diff options
1267 files changed, 20159 insertions, 15994 deletions
diff --git a/Documentation/00-INDEX b/Documentation/00-INDEX index 299615d..c3014df 100644 --- a/Documentation/00-INDEX +++ b/Documentation/00-INDEX @@ -262,6 +262,8 @@ mtrr.txt - how to use PPro Memory Type Range Registers to increase performance. mutex-design.txt - info on the generic mutex subsystem. +namespaces/ + - directory with various information about namespaces nbd.txt - info on a TCP implementation of a network block device. netlabel/ diff --git a/Documentation/DocBook/Makefile b/Documentation/DocBook/Makefile index 054a7ec..4953bc2 100644 --- a/Documentation/DocBook/Makefile +++ b/Documentation/DocBook/Makefile @@ -11,7 +11,7 @@ DOCBOOKS := wanbook.xml z8530book.xml mcabook.xml videobook.xml \ procfs-guide.xml writing_usb_driver.xml \ kernel-api.xml filesystems.xml lsm.xml usb.xml \ gadget.xml libata.xml mtdnand.xml librs.xml rapidio.xml \ - genericirq.xml s390-drivers.xml + genericirq.xml s390-drivers.xml uio-howto.xml ### # The build process is as follows (targets): diff --git a/Documentation/DocBook/uio-howto.tmpl b/Documentation/DocBook/uio-howto.tmpl index c119484..fdd7f4f 100644 --- a/Documentation/DocBook/uio-howto.tmpl +++ b/Documentation/DocBook/uio-howto.tmpl @@ -30,6 +30,12 @@ <revhistory> <revision> + <revnumber>0.4</revnumber> + <date>2007-11-26</date> + <authorinitials>hjk</authorinitials> + <revremark>Removed section about uio_dummy.</revremark> + </revision> + <revision> <revnumber>0.3</revnumber> <date>2007-04-29</date> <authorinitials>hjk</authorinitials> @@ -94,6 +100,26 @@ interested in translating it, please email me user space. This simplifies development and reduces the risk of serious bugs within a kernel module. </para> + <para> + Please note that UIO is not an universal driver interface. Devices + that are already handled well by other kernel subsystems (like + networking or serial or USB) are no candidates for an UIO driver. + Hardware that is ideally suited for an UIO driver fulfills all of + the following: + </para> +<itemizedlist> +<listitem> + <para>The device has memory that can be mapped. The device can be + controlled completely by writing to this memory.</para> +</listitem> +<listitem> + <para>The device usually generates interrupts.</para> +</listitem> +<listitem> + <para>The device does not fit into one of the standard kernel + subsystems.</para> +</listitem> +</itemizedlist> </sect1> <sect1 id="thanks"> @@ -174,8 +200,9 @@ interested in translating it, please email me For cards that don't generate interrupts but need to be polled, there is the possibility to set up a timer that triggers the interrupt handler at configurable time intervals. - See <filename>drivers/uio/uio_dummy.c</filename> for an - example of this technique. + This interrupt simulation is done by calling + <function>uio_event_notify()</function> + from the timer's event handler. </para> <para> @@ -263,63 +290,11 @@ offset = N * getpagesize(); </sect1> </chapter> -<chapter id="using-uio_dummy" xreflabel="Using uio_dummy"> -<?dbhtml filename="using-uio_dummy.html"?> -<title>Using uio_dummy</title> - <para> - Well, there is no real use for uio_dummy. Its only purpose is - to test most parts of the UIO system (everything except - hardware interrupts), and to serve as an example for the - kernel module that you will have to write yourself. - </para> - -<sect1 id="what_uio_dummy_does"> -<title>What uio_dummy does</title> - <para> - The kernel module <filename>uio_dummy.ko</filename> creates a - device that uses a timer to generate periodic interrupts. The - interrupt handler does nothing but increment a counter. The - driver adds two custom attributes, <varname>count</varname> - and <varname>freq</varname>, that appear under - <filename>/sys/devices/platform/uio_dummy/</filename>. - </para> - - <para> - The attribute <varname>count</varname> can be read and - written. The associated file - <filename>/sys/devices/platform/uio_dummy/count</filename> - appears as a normal text file and contains the total number of - timer interrupts. If you look at it (e.g. using - <function>cat</function>), you'll notice it is slowly counting - up. - </para> - - <para> - The attribute <varname>freq</varname> can be read and written. - The content of - <filename>/sys/devices/platform/uio_dummy/freq</filename> - represents the number of system timer ticks between two timer - interrupts. The default value of <varname>freq</varname> is - the value of the kernel variable <varname>HZ</varname>, which - gives you an interval of one second. Lower values will - increase the frequency. Try the following: - </para> -<programlisting format="linespecific"> -cd /sys/devices/platform/uio_dummy/ -echo 100 > freq -</programlisting> - <para> - Use <function>cat count</function> to see how the interrupt - frequency changes. - </para> -</sect1> -</chapter> - <chapter id="custom_kernel_module" xreflabel="Writing your own kernel module"> <?dbhtml filename="custom_kernel_module.html"?> <title>Writing your own kernel module</title> <para> - Please have a look at <filename>uio_dummy.c</filename> as an + Please have a look at <filename>uio_cif.c</filename> as an example. The following paragraphs explain the different sections of this file. </para> @@ -354,9 +329,8 @@ See the description below for details. interrupt, it's your modules task to determine the irq number during initialization. If you don't have a hardware generated interrupt but want to trigger the interrupt handler in some other way, set -<varname>irq</varname> to <varname>UIO_IRQ_CUSTOM</varname>. The -uio_dummy module does this as it triggers the event mechanism in a timer -routine. If you had no interrupt at all, you could set +<varname>irq</varname> to <varname>UIO_IRQ_CUSTOM</varname>. +If you had no interrupt at all, you could set <varname>irq</varname> to <varname>UIO_IRQ_NONE</varname>, though this rarely makes sense. </para></listitem> diff --git a/Documentation/accounting/getdelays.c b/Documentation/accounting/getdelays.c index ab82b7f..d6cb1a8 100644 --- a/Documentation/accounting/getdelays.c +++ b/Documentation/accounting/getdelays.c @@ -25,6 +25,7 @@ #include <linux/genetlink.h> #include <linux/taskstats.h> +#include <linux/cgroupstats.h> /* * Generic macros for dealing with netlink sockets. Might be duplicated @@ -78,6 +79,7 @@ static void usage(void) fprintf(stderr, " -i: print IO accounting (works only with -p)\n"); fprintf(stderr, " -l: listen forever\n"); fprintf(stderr, " -v: debug on\n"); + fprintf(stderr, " -C: container path\n"); } /* @@ -212,6 +214,14 @@ void task_context_switch_counts(struct taskstats *t) t->nvcsw, t->nivcsw); } +void print_cgroupstats(struct cgroupstats *c) +{ + printf("sleeping %llu, blocked %llu, running %llu, stopped %llu, " + "uninterruptible %llu\n", c->nr_sleeping, c->nr_io_wait, + c->nr_running, c->nr_stopped, c->nr_uninterruptible); +} + + void print_ioacct(struct taskstats *t) { printf("%s: read=%llu, write=%llu, cancelled_write=%llu\n", @@ -239,11 +249,14 @@ int main(int argc, char *argv[]) int maskset = 0; char *logfile = NULL; int loop = 0; + int containerset = 0; + char containerpath[1024]; + int cfd = 0; struct msgtemplate msg; while (1) { - c = getopt(argc, argv, "qdiw:r:m:t:p:vl"); + c = getopt(argc, argv, "qdiw:r:m:t:p:vlC:"); if (c < 0) break; @@ -260,6 +273,10 @@ int main(int argc, char *argv[]) printf("printing task/process context switch rates\n"); print_task_context_switch_counts = 1; break; + case 'C': + containerset = 1; + strncpy(containerpath, optarg, strlen(optarg) + 1); + break; case 'w': logfile = strdup(optarg); printf("write to file %s\n", logfile); @@ -334,6 +351,11 @@ int main(int argc, char *argv[]) } } + if (tid && containerset) { + fprintf(stderr, "Select either -t or -C, not both\n"); + goto err; + } + if (tid) { rc = send_cmd(nl_sd, id, mypid, TASKSTATS_CMD_GET, cmd_type, &tid, sizeof(__u32)); @@ -344,6 +366,20 @@ int main(int argc, char *argv[]) } } + if (containerset) { + cfd = open(containerpath, O_RDONLY); + if (cfd < 0) { + perror("error opening container file"); + goto err; + } + rc = send_cmd(nl_sd, id, mypid, CGROUPSTATS_CMD_GET, + CGROUPSTATS_CMD_ATTR_FD, &cfd, sizeof(__u32)); + if (rc < 0) { + perror("error sending cgroupstats command"); + goto err; + } + } + do { int i; @@ -422,6 +458,9 @@ int main(int argc, char *argv[]) } break; + case CGROUPSTATS_TYPE_CGROUP_STATS: + print_cgroupstats(NLA_DATA(na)); + break; default: fprintf(stderr, "Unknown nla_type %d\n", na->nla_type); @@ -443,5 +482,7 @@ err: close(nl_sd); if (fd) close(fd); + if (cfd) + close(cfd); return 0; } diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt index 6bb9be5..20c4c8b 100644 --- a/Documentation/feature-removal-schedule.txt +++ b/Documentation/feature-removal-schedule.txt @@ -181,15 +181,6 @@ Who: Nick Piggin <npiggin@suse.de> --------------------------- -What: Interrupt only SA_* flags -When: September 2007 -Why: The interrupt related SA_* flags are replaced by IRQF_* to move them - out of the signal namespace. - -Who: Thomas Gleixner <tglx@linutronix.de> - ---------------------------- - What: PHYSDEVPATH, PHYSDEVBUS, PHYSDEVDRIVER in the uevent environment When: October 2008 Why: The stacking of class devices makes these values misleading and diff --git a/Documentation/hwmon/sysfs-interface b/Documentation/hwmon/sysfs-interface index a17b692..f4a8ebc 100644 --- a/Documentation/hwmon/sysfs-interface +++ b/Documentation/hwmon/sysfs-interface @@ -328,6 +328,37 @@ curr[1-*]_input Current input value Unit: milliampere RO +********* +* Power * +********* + +power[1-*]_average Average power use + Unit: microWatt + RO + +power[1-*]_average_highest Historical average maximum power use + Unit: microWatt + RO + +power[1-*]_average_lowest Historical average minimum power use + Unit: microWatt + RO + +power[1-*]_input Instantaneous power use + Unit: microWatt + RO + +power[1-*]_input_highest Historical maximum power use + Unit: microWatt + RO + +power[1-*]_input_lowest Historical minimum power use + Unit: microWatt + RO + +power[1-*]_reset_history Reset input_highest, input_lowest, + average_highest and average_lowest. + WO ********** * Alarms * diff --git a/Documentation/lguest/lguest.c b/Documentation/lguest/lguest.c index f266839..9b0e322 100644 --- a/Documentation/lguest/lguest.c +++ b/Documentation/lguest/lguest.c @@ -62,8 +62,8 @@ typedef uint8_t u8; #endif /* We can have up to 256 pages for devices. */ #define DEVICE_PAGES 256 -/* This fits nicely in a single 4096-byte page. */ -#define VIRTQUEUE_NUM 127 +/* This will occupy 2 pages: it must be a power of 2. */ +#define VIRTQUEUE_NUM 128 /*L:120 verbose is both a global flag and a macro. The C preprocessor allows * this, and although I wouldn't recommend it, it works quite nicely here. */ @@ -1036,16 +1036,22 @@ static void add_virtqueue(struct device *dev, unsigned int num_descs, void *p; /* First we need some pages for this virtqueue. */ - pages = (vring_size(num_descs) + getpagesize() - 1) / getpagesize(); + pages = (vring_size(num_descs, getpagesize()) + getpagesize() - 1) + / getpagesize(); p = get_pages(pages); + /* Initialize the virtqueue */ + vq->next = NULL; + vq->last_avail_idx = 0; + vq->dev = dev; + /* Initialize the configuration. */ vq->config.num = num_descs; vq->config.irq = devices.next_irq++; vq->config.pfn = to_guest_phys(p) / getpagesize(); /* Initialize the vring. */ - vring_init(&vq->vring, num_descs, p); + vring_init(&vq->vring, num_descs, p, getpagesize()); /* Add the configuration information to this device's descriptor. */ add_desc_field(dev, VIRTIO_CONFIG_F_VIRTQUEUE, @@ -1056,9 +1062,6 @@ static void add_virtqueue(struct device *dev, unsigned int num_descs, for (i = &dev->vq; *i; i = &(*i)->next); *i = vq; - /* Link virtqueue back to device. */ - vq->dev = dev; - /* Set the routine to call when the Guest does something to this * virtqueue. */ vq->handle_output = handle_output; @@ -1092,6 +1095,7 @@ static struct device *new_device(const char *name, u16 type, int fd, dev->desc = new_dev_desc(type); dev->handle_input = handle_input; dev->name = name; + dev->vq = NULL; return dev; } @@ -1342,7 +1346,7 @@ static bool service_io(struct device *dev) if (out->type & VIRTIO_BLK_T_SCSI_CMD) { fprintf(stderr, "Scsi commands unsupported\n"); in->status = VIRTIO_BLK_S_UNSUPP; - wlen = sizeof(in); + wlen = sizeof(*in); } else if (out->type & VIRTIO_BLK_T_OUT) { /* Write */ @@ -1363,7 +1367,7 @@ static bool service_io(struct device *dev) /* Die, bad Guest, die. */ errx(1, "Write past end %llu+%u", off, ret); } - wlen = sizeof(in); + wlen = sizeof(*in); in->status = (ret >= 0 ? VIRTIO_BLK_S_OK : VIRTIO_BLK_S_IOERR); } else { /* Read */ @@ -1376,10 +1380,10 @@ static bool service_io(struct device *dev) ret = readv(vblk->fd, iov+1, in_num-1); verbose("READ from sector %llu: %i\n", out->sector, ret); if (ret >= 0) { - wlen = sizeof(in) + ret; + wlen = sizeof(*in) + ret; in->status = VIRTIO_BLK_S_OK; } else { - wlen = sizeof(in); + wlen = sizeof(*in); in->status = VIRTIO_BLK_S_IOERR; } } diff --git a/Documentation/markers.txt b/Documentation/markers.txt index 295a71b..d9f50a1 100644 --- a/Documentation/markers.txt +++ b/Documentation/markers.txt @@ -35,12 +35,14 @@ In order to use the macro trace_mark, you should include linux/marker.h. And, -trace_mark(subsystem_event, "%d %s", someint, somestring); +trace_mark(subsystem_event, "myint %d mystring %s", someint, somestring); Where : - subsystem_event is an identifier unique to your event - subsystem is the name of your subsystem. - event is the name of the event to mark. -- "%d %s" is the formatted string for the serializer. +- "myint %d mystring %s" is the formatted string for the serializer. "myint" and + "mystring" are repectively the field names associated with the first and + second parameter. - someint is an integer. - somestring is a char pointer. diff --git a/Documentation/namespaces/compatibility-list.txt b/Documentation/namespaces/compatibility-list.txt new file mode 100644 index 0000000..defc558 --- /dev/null +++ b/Documentation/namespaces/compatibility-list.txt @@ -0,0 +1,39 @@ + Namespaces compatibility list + +This document contains the information about the problems user +may have when creating tasks living in different namespaces. + +Here's the summary. This matrix shows the known problems, that +occur when tasks share some namespace (the columns) while living +in different other namespaces (the rows): + + UTS IPC VFS PID User Net +UTS X +IPC X 1 +VFS X +PID 1 1 X +User 2 2 X +Net X + +1. Both the IPC and the PID namespaces provide IDs to address + object inside the kernel. E.g. semaphore with IPCID or + process group with pid. + + In both cases, tasks shouldn't try exposing this ID to some + other task living in a different namespace via a shared filesystem + or IPC shmem/message. The fact is that this ID is only valid + within the namespace it was obtained in and may refer to some + other object in another namespace. + +2. Intentionally, two equal user IDs in different user namespaces + should not be equal from the VFS point of view. In other + words, user 10 in one user namespace shouldn't have the same + access permissions to files, belonging to user 10 in another + namespace. + + The same is true for the IPC namespaces being shared - two users + from different user namespaces should not access the same IPC objects + even having equal UIDs. + + But currently this is not so. + diff --git a/Documentation/networking/00-INDEX b/Documentation/networking/00-INDEX index f5a5e6d..563e442 100644 --- a/Documentation/networking/00-INDEX +++ b/Documentation/networking/00-INDEX @@ -4,8 +4,6 @@ - information on the 3Com EtherLink Plus (3c505) driver. 6pack.txt - info on the 6pack protocol, an alternative to KISS for AX.25 -Configurable - - info on some of the configurable network parameters DLINK.txt - info on the D-Link DE-600/DE-620 parallel port pocket adapters PLIP.txt @@ -26,8 +24,6 @@ baycom.txt - info on the driver for Baycom style amateur radio modems bridge.txt - where to get user space programs for ethernet bridging with Linux. -comx.txt - - info on drivers for COMX line of synchronous serial adapters. cops.txt - info on the COPS LocalTalk Linux driver cs89x0.txt @@ -78,20 +74,14 @@ ltpc.txt - the Apple or Farallon LocalTalk PC card driver multicast.txt - Behaviour of cards under Multicast -ncsa-telnet - - notes on how NCSA telnet (DOS) breaks with MTU discovery enabled. netdevices.txt - info on network device driver functions exported to the kernel. olympic.txt - IBM PCI Pit/Pit-Phy/Olympic Token Ring driver info. policy-routing.txt - IP policy-based routing -pt.txt - - the Gracilis Packetwin AX.25 device driver ray_cs.txt - Raylink Wireless LAN card driver info. -routing.txt - - the new routing mechanism shaper.txt - info on the module that can shape/limit transmitted traffic. sk98lin.txt diff --git a/Documentation/networking/3c505.txt b/Documentation/networking/3c505.txt index b9d5b72..72f38b1 100644 --- a/Documentation/networking/3c505.txt +++ b/Documentation/networking/3c505.txt @@ -14,8 +14,7 @@ If no base address is given at boot time, the driver will autoprobe ports 0x300, 0x280 and 0x310 (in that order). If no IRQ is given, the driver will try to probe for it. -The driver can be used as a loadable module. See net-modules.txt for details -of the parameters it can take. +The driver can be used as a loadable module. Theoretically, one instance of the driver can now run multiple cards, in the standard way (when loading a module, say "modprobe 3c505 diff --git a/Documentation/networking/Configurable b/Documentation/networking/Configurable deleted file mode 100644 index 69c0dd4..0000000 --- a/Documentation/networking/Configurable +++ /dev/null @@ -1,34 +0,0 @@ - -There are a few network parameters that can be tuned to better match -the kernel to your system hardware and intended usage. The defaults -are usually a good choice for 99% of the people 99% of the time, but -you should be aware they do exist and can be changed. - -The current list of parameters can be found in the files: - - linux/net/TUNABLE - Documentation/networking/ip-sysctl.txt - -Some of these are accessible via the sysctl interface, and many more are -scheduled to be added in this way. For example, some parameters related -to Address Resolution Protocol (ARP) are very easily viewed and altered. - - # cat /proc/sys/net/ipv4/arp_timeout - 6000 - # echo 7000 > /proc/sys/net/ipv4/arp_timeout - # cat /proc/sys/net/ipv4/arp_timeout - 7000 - -Others are already accessible via the related user space programs. -For example, MAX_WINDOW has a default of 32 k which is a good choice for -modern hardware, but if you have a slow (8 bit) Ethernet card and/or a slow -machine, then this will be far too big for the card to keep up with fast -machines transmitting on the same net, resulting in overruns and receive errors. -A value of about 4 k would be more appropriate, which can be set via: - - # route add -net 192.168.3.0 window 4096 - -The remainder of these can only be presently changed by altering a #define -in the related header file. This means an edit and recompile cycle. - - Paul Gortmaker 06/96 diff --git a/Documentation/networking/comx.txt b/Documentation/networking/comx.txt deleted file mode 100644 index d1526eb..0000000 --- a/Documentation/networking/comx.txt +++ /dev/null @@ -1,248 +0,0 @@ - - COMX drivers for the 2.2 kernel - -Originally written by: Tivadar Szemethy, <tiv@itc.hu> -Currently maintained by: Gergely Madarasz <gorgo@itc.hu> - -Last change: 21/06/1999. - -INTRODUCTION - -This document describes the software drivers and their use for the -COMX line of synchronous serial adapters for Linux version 2.2.0 and -above. -The cards are produced and sold by ITC-Pro Ltd. Budapest, Hungary -For further info contact <info@itc.hu> -or http://www.itc.hu (mostly in Hungarian). -The firmware files and software are available from ftp://ftp.itc.hu - -Currently, the drivers support the following cards and protocols: - -COMX (2x64 kbps intelligent board) -CMX (1x256 + 1x128 kbps intelligent board) -HiCOMX (2x2Mbps intelligent board) -LoCOMX (1x512 kbps passive board) -MixCOM (1x512 or 2x512kbps passive board with a hardware watchdog an - optional BRI interface and optional flashROM (1-32M)) -SliceCOM (1x2Mbps channelized E1 board) -PciCOM (X21) - -At the moment of writing this document, the (Cisco)-HDLC, LAPB, SyncPPP and -Frame Relay (DTE, rfc1294 IP encapsulation with partially implemented Q933a -LMI) protocols are available as link-level protocol. -X.25 support is being worked on. - -USAGE - -Load the comx.o module and the hardware-specific and protocol-specific -modules you'll need into the running kernel using the insmod utility. -This creates the /proc/comx directory. -See the example scripts in the 'etc' directory. - -/proc INTERFACE INTRO - -The COMX driver set has a new type of user interface based on the /proc -filesystem which eliminates the need for external user-land software doing -IOCTL calls. -Each network interface or device (i.e. those ones you configure with 'ifconfig' -and 'route' etc.) has a corresponding directory under /proc/comx. You can -dynamically create a new interface by saying 'mkdir /proc/comx/comx0' (or you -can name it whatever you want up to 8 characters long, comx[n] is just a -convention). -Generally the files contained in these directories are text files, which can -be viewed by 'cat filename' and you can write a string to such a file by -saying 'echo _string_ >filename'. This is very similar to the sysctl interface. -Don't use a text editor to edit these files, always use 'echo' (or 'cat' -where appropriate). -When you've created the comx[n] directory, two files are created automagically -in it: 'boardtype' and 'protocol'. You have to fill in these files correctly -for your board and protocol you intend to use (see the board and protocol -descriptions in this file below or the example scripts in the 'etc' directory). -After filling in these files, other files will appear in the directory for -setting the various hardware- and protocol-related informations (for example -irq and io addresses, keepalive values etc.) These files are set to default -values upon creation, so you don't necessarily have to change all of them. - -When you're ready with filling in the files in the comx[n] directory, you can -configure the corresponding network interface with the standard network -configuration utilities. If you're unable to bring the interfaces up, look up -the various kernel log files on your system, and consult the messages for -a probable reason. - -EXAMPLE - -To create the interface 'comx0' which is the first channel of a COMX card: - -insmod comx -# insmod comx-hw-comx ; insmod comx-proto-ppp (these are usually -autoloaded if you use the kernel module loader) - -mkdir /proc/comx/comx0 -echo comx >/proc/comx/comx0/boardtype -echo 0x360 >/proc/comx/comx0/io <- jumper-selectable I/O port -echo 0x0a >/proc/comx/comx0/irq <- jumper-selectable IRQ line -echo 0xd000 >/proc/comx/comx0/memaddr <- software-configurable memory - address. COMX uses 64 KB, and this - can be: 0xa000, 0xb000, 0xc000, - 0xd000, 0xe000. Avoid conflicts - with other hardware. -cat </etc/siol1.rom >/proc/comx/comx0/firmware <- the firmware for the card -echo HDLC >/proc/comx/comx0/protocol <- the data-link protocol -echo 10 >/proc/comx/comx0/keepalive <- the keepalive for the protocol -ifconfig comx0 1.2.3.4 pointopoint 5.6.7.8 netmask 255.255.255.255 <- - finally configure it with ifconfig -Check its status: -cat /proc/comx/comx0/status - -If you want to use the second channel of this board: - -mkdir /proc/comx/comx1 -echo comx >/proc/comx/comx1/boardtype -echo 0x360 >/proc/comx/comx1/io -echo 10 >/proc/comx/comx1/irq -echo 0xd000 >/proc/comx/comx1/memaddr -echo 1 >/proc/comx/comx1/channel <- channels are numbered - as 0 (default) and 1 - -Now, check if the driver recognized that you're going to use the other -channel of the same adapter: - -cat /proc/comx/comx0/twin -comx1 -cat /proc/comx/comx1/twin -comx0 - -You don't have to load the firmware twice, if you use both channels of -an adapter, just write it into the channel 0's /proc firmware file. - -Default values: io 0x360 for COMX, 0x320 (HICOMX), irq 10, memaddr 0xd0000 - -THE LOCOMX HARDWARE DRIVER - -The LoCOMX driver doesn't require firmware, and it doesn't use memory either, -but it uses DMA channels 1 and 3. You can set the clock rate (if enabled by -jumpers on the board) by writing the kbps value into the file named 'clock'. -Set it to 'external' (it is the default) if you have external clock source. - -(Note: currently the LoCOMX driver does not support the internal clock) - -THE COMX, CMX AND HICOMX DRIVERS - -On the HICOMX, COMX and CMX, you have to load the firmware (it is different for -the three cards!). All these adapters can share the same memory -address (we usually use 0xd0000). On the CMX you can set the internal -clock rate (if enabled by jumpers on the small adapter boards) by writing -the kbps value into the 'clock' file. You have to do this before initializing -the card. If you use both HICOMX and CMX/COMX cards, initialize the HICOMX -first. The I/O address of the HICOMX board is not configurable by any -method available to the user: it is hardwired to 0x320, and if you have to -change it, consult ITC-Pro Ltd. - -THE MIXCOM DRIVER - -The MixCOM board doesn't require firmware, the driver communicates with -it through I/O ports. You can have three of these cards in one machine. - -THE SLICECOM DRIVER - -The SliceCOM board doesn't require firmware. You can have 4 of these cards -in one machine. The driver doesn't (yet) support shared interrupts, so -you will need a separate IRQ line for every board. -Read Documentation/networking/slicecom.txt for help on configuring -this adapter. - -THE HDLC/PPP LINE PROTOCOL DRIVER - -The HDLC/SyncPPP line protocol driver uses the kernel's built-in syncppp -driver (syncppp.o). You don't have to manually select syncppp.o when building -the kernel, the dependencies compile it in automatically. - - - - -EXAMPLE -(setting up hw parameters, see above) - -# using HDLC: -echo hdlc >/proc/comx/comx0/protocol -echo 10 >/proc/comx/comx0/keepalive <- not necessary, 10 is the default -ifconfig comx0 1.2.3.4 pointopoint 5.6.7.8 netmask 255.255.255.255 - -(setting up hw parameters, see above) - -# using PPP: -echo ppp >/proc/comx/comx0/protocol -ifconfig comx0 up -ifconfig comx0 1.2.3.4 pointopoint 5.6.7.8 netmask 255.255.255.255 - - -THE LAPB LINE PROTOCOL DRIVER - -For this, you'll need to configure LAPB support (See 'LAPB Data Link Driver' in -'Network options' section) into your kernel (thanks to Jonathan Naylor for his -excellent implementation). -comx-proto-lapb.o provides the following files in the appropriate directory -(the default values in parens): t1 (5), t2 (1), n2 (20), mode (DTE, STD) and -window (7). Agree with the administrator of your peer router on these -settings (most people use defaults, but you have to know if you are DTE or -DCE). - -EXAMPLE - -(setting up hw parameters, see above) -echo lapb >/proc/comx/comx0/protocol -echo dce >/proc/comx/comx0/mode <- DCE interface in this example -ifconfig comx0 1.2.3.4 pointopoint 5.6.7.8 netmask 255.255.255.255 - - -THE FRAME RELAY PROTOCOL DRIVER - -You DON'T need any other frame relay related modules from the kernel to use -COMX-Frame Relay. This protocol is a bit more complicated than the others, -because it allows to use 'subinterfaces' or DLCIs within one physical device. -First you have to create the 'master' device (the actual physical interface) -as you would do for other protocols. Specify 'frad' as protocol type. -Now you can bring this interface up by saying 'ifconfig comx0 up' (or whatever -you've named the interface). Do not assign any IP address to this interface -and do not set any routes through it. -Then, set up your DLCIs the following way: create a comx interface for each -DLCI you intend to use (with mkdir), and write 'dlci' to the 'boardtype' file, -and 'ietf-ip' to the 'protocol' file. Currently, the only supported -encapsulation type is this (also called as RFC1294/1490 IP encapsulation). -Write the DLCI number to the 'dlci' file, and write the name of the physical -COMX device to the file called 'master'. -Now you can assign an IP address to this interface and set routes using it. -See the example file for further info and example config script. -Notes: this driver implements a DTE interface with partially implemented -Q933a LMI. -You can find an extensively commented example in the 'etc' directory. - -FURTHER /proc FILES - -boardtype: -Type of the hardware. Valid values are: - 'comx', 'hicomx', 'locomx', 'cmx', 'slicecom'. - -protocol: -Data-link protocol on this channel. Can be: HDLC, LAPB, PPP, FRAD - -status: -You can read the channel's actual status from the 'status' file, for example -'cat /proc/comx/comx3/status'. - -lineup_delay: -Interpreted in seconds (default is 1). Used to avoid line jitter: the system -will consider the line status 'UP' only if it is up for at least this number -of seconds. - -debug: -You can set various debug options through this file. Valid options are: -'comx_events', 'comx_tx', 'comx_rx', 'hw_events', 'hw_tx', 'hw_rx'. -You can enable a debug options by writing its name prepended by a '+' into -the debug file, for example 'echo +comx_rx >comx0/debug'. -Disabling an option happens similarly, use the '-' prefix -(e.g. 'echo -hw_rx >debug'). -Debug results can be read from the debug file, for example: -tail -f /proc/comx/comx2/debug - - diff --git a/Documentation/networking/ncsa-telnet b/Documentation/networking/ncsa-telnet deleted file mode 100644 index d77d28b..0000000 --- a/Documentation/networking/ncsa-telnet +++ /dev/null @@ -1,16 +0,0 @@ -NCSA telnet doesn't work with path MTU discovery enabled. This is due to a -bug in NCSA that also stops it working with other modern networking code -such as Solaris. - -The following information is courtesy of -Marek <marekm@i17linuxb.ists.pwr.wroc.pl> - -There is a fixed version somewhere on ftp.upe.ac.za (sorry, I don't -remember the exact pathname, and this site is very slow from here). -It may or may not be faster for you to get it from -ftp://ftp.ists.pwr.wroc.pl/pub/msdos/telnet/ncsa_upe/tel23074.zip -(source is in v230704s.zip). I have tested it with 1.3.79 (with -path mtu discovery enabled - ncsa 2.3.08 didn't work) and it seems -to work. I don't know if anyone is working on this code - this -version is over a year old. Too bad - it's faster and often more -stable than these windoze telnets, and runs on almost anything... diff --git a/Documentation/networking/pt.txt b/Documentation/networking/pt.txt deleted file mode 100644 index 72e888c..0000000 --- a/Documentation/networking/pt.txt +++ /dev/null @@ -1,58 +0,0 @@ -This is the README for the Gracilis Packetwin device driver, version 0.5 -ALPHA for Linux 1.3.43. - -These files will allow you to talk to the PackeTwin (now know as PT) and -connect through it just like a pair of TNCs. To do this you will also -require the AX.25 code in the kernel enabled. - -There are four files in this archive; this readme, a patch file, a .c file -and finally a .h file. The two program files need to be put into the -drivers/net directory in the Linux source tree, for me this is the -directory /usr/src/linux/drivers/net. The patch file needs to be patched in -at the top of the Linux source tree (/usr/src/linux in my case). - -You will most probably have to edit the pt.c file to suit your own setup, -this should just involve changing some of the defines at the top of the file. -Please note that if you run an external modem you must specify a speed of 0. - -The program is currently setup to run a 4800 baud external modem on port A -and a Kantronics DE-9600 daughter board on port B so if you have this (or -something similar) then you're right. - -To compile in the driver, put the files in the correct place and patch in -the diff. You will have to re-configure the kernel again before you -recompile it. - -The driver is not real good at the moment for finding the card. You can -'help' it by changing the order of the potential addresses in the structure -found in the pt_init() function so the address of where the card is is put -first. - -After compiling, you have to get them going, they are pretty well like any -other net device and just need ifconfig to get them going. -As an example, here is my /etc/rc.net --------------------------- - -# -# Configure the PackeTwin, port A. -/sbin/ifconfig pt0a 44.136.8.87 hw ax25 vk2xlz mtu 512 -/sbin/ifconfig pt0a 44.136.8.87 broadcast 44.136.8.255 netmask 255.255.255.0 -/sbin/route add -net 44.136.8.0 netmask 255.255.255.0 dev pt0a -/sbin/route add -net 44.0.0.0 netmask 255.0.0.0 gw 44.136.8.68 dev pt0a -/sbin/route add -net 138.25.16.0 netmask 255.255.240.0 dev pt0a -/sbin/route add -host 44.136.8.255 dev pt0a -# -# Configure the PackeTwin, port B. -/sbin/ifconfig pt0b 44.136.8.87 hw ax25 vk2xlz-1 mtu 512 -/sbin/ifconfig pt0b 44.136.8.87 broadcast 44.255.255.255 netmask 255.0.0.0 -/sbin/route add -host 44.136.8.216 dev pt0b -/sbin/route add -host 44.136.8.95 dev pt0b -/sbin/route add -host 44.255.255.255 dev pt0b - -This version of the driver comes under the GNU GPL. If you have one of my -previous (non-GPL) versions of the driver, please update to this one. - -I hope that this all works well for you. I would be pleased to hear how -many people use the driver and if it does its job. - - - Craig vk2xlz <csmall@small.dropbear.id.au> diff --git a/Documentation/networking/routing.txt b/Documentation/networking/routing.txt deleted file mode 100644 index a26838b..0000000 --- a/Documentation/networking/routing.txt +++ /dev/null @@ -1,46 +0,0 @@ -The directory ftp.inr.ac.ru:/ip-routing contains: - -- iproute.c - "professional" routing table maintenance utility. - -- rdisc.tar.gz - rdisc daemon, ported from Sun. - STRONGLY RECOMMENDED FOR ALL HOSTS. - -- routing.tgz - original Mike McLagan's route by source patch. - Currently it is obsolete. - -- gated.dif-ss<NEWEST>.gz - gated-R3_6Alpha_2 fixes. - Look at README.gated - -- mrouted-3.8.dif.gz - mrouted-3.8 fixes. - -- rtmon.c - trivial debugging utility: reads and stores netlink. - - -NEWS for user. - -- Policy based routing. Routing decisions are made on the basis - not only of destination address, but also source address, - TOS and incoming interface. -- Complete set of IP level control messages. - Now Linux is the only OS in the world complying to RFC requirements. - Great win 8) -- New interface addressing paradigm. - Assignment of address ranges to interface, - multiple prefixes etc. etc. - Do not bother, it is compatible with the old one. Moreover: -- You don't need to do "route add aaa.bbb.ccc... eth0" anymore, - it is done automatically. -- "Abstract" UNIX sockets and security enhancements. - This is necessary to use TIRPC and TLI emulation library. - -NEWS for hacker. - -- New destination cache. Flexible, robust and just beautiful. -- Network stack is reordered, simplified, optimized, a lot of bugs fixed. - (well, and new bugs were introduced, but I haven't seen them yet 8)) - It is difficult to describe all the changes, look into source. - -If you see this file, then this patch works 8) - -Alexey Kuznetsov. -kuznet@ms2.inr.ac.ru diff --git a/Documentation/networking/slicecom.hun b/Documentation/networking/slicecom.hun deleted file mode 100644 index bed2f04..0000000 --- a/Documentation/networking/slicecom.hun +++ /dev/null @@ -1,371 +0,0 @@ - -SliceCOM adapter felhasznaloi dokumentacioja - 0.51 verziohoz - -Bartók István <bartoki@itc.hu> -Utolso modositas: Wed Aug 29 17:26:58 CEST 2001 - ------------------------------------------------------------------ - -Hasznalata: - -Forditas: - -Code maturity level options - [*] Prompt for development and/or incomplete code/drivers - -Network device support - Wan interfaces - <M> MultiGate (COMX) synchronous - <M> Support for MUNICH based boards: SliceCOM, PCICOM (NEW) - <M> Support for HDLC and syncPPP... - - -A modulok betoltese: - -modprobe comx - -modprobe comx-proto-ppp # a Cisco-HDLC es a SyncPPP protokollt is - # ez a modul adja - -modprobe comx-hw-munich # a modul betoltodeskor azonnal jelent a - # syslogba a detektalt kartyakrol - - -Konfiguralas: - -# Ezen az interfeszen Cisco-HDLC vonali protokoll fog futni -# Az interfeszhez rendelt idoszeletek: 1,2 (128 kbit/sec-es vonal) -# (a G.703 keretben az elso adatot vivo idoszelet az 1-es) -# -mkdir /proc/comx/comx0.1/ -echo slicecom >/proc/comx/comx0.1/boardtype -echo hdlc >/proc/comx/comx0.1/protocol -echo 1 2 >/proc/comx/comx0.1/timeslots - - -# Ezen az interfeszen SyncPPP vonali protokoll fog futni -# Az interfeszhez rendelt idoszelet: 3 (64 kbit/sec-es vonal) -# -mkdir /proc/comx/comx0.2/ -echo slicecom >/proc/comx/comx0.2/boardtype -echo ppp >/proc/comx/comx0.2/protocol -echo 3 >/proc/comx/comx0.2/timeslots - -... - -ifconfig comx0.1 up -ifconfig comx0.2 up - ------------------------------------------------------------------ - -A COMX driverek default 20 csomagnyi transmit queue-t rendelnek a halozati -interfeszekhez. WAN halozatokban ennel hosszabbat is szokas hasznalni -(20 es 100 kozott), hogy a vonal kihasznaltsaga nagy terheles eseten jobb -legyen (bar ezzel megno a varhato kesleltetes a csomagok sorban allasa miatt): - -# ifconfig comx0 txqueuelen 50 - -Ezt a beallitasi lehetoseget csak az ujabb disztribuciok ifconfig parancsa -tamogatja (amik mar a 2.2 kernelekhez keszultek, mint a RedHat 6.1 vagy a -Debian 2.2). - -A 2.1-es Debian disztribuciohoz a http://www.debian.org/~rcw/2.2/netbase/ -cimrol toltheto le ujabb netbase csomag, ami mar ilyet tamogato ifconfig -parancsot tartalmaz. Bovebben a 2.2 kernel hasznalatarol Debian 2.1 alatt: -http://www.debian.org/releases/stable/running-kernel-2.2 - ------------------------------------------------------------------ - -A kartya LED-jeinek jelentese: - -piros - eg, ha Remote Alarm-ot kuld a tuloldal -zold - eg, ha a vett jelben megtalalja a keretszinkront - -Reszletesebben: - -piros: zold: jelentes: - -- - nincs keretszinkron (nincs jel, vagy rossz a jel) -- eg "minden rendben" -eg eg a vetel OK, de a tuloldal Remote Alarm-ot kuld -eg - ez nincs ertelmezve, egyelore funkcio nelkul - ------------------------------------------------------------------ - -Reszletesebb leiras a hardver beallitasi lehetosegeirol: - -Az altalanos,- es a protokoll-retegek beallitasi lehetosegeirol a 'comx.txt' -fajlban leirtak SliceCOM kartyanal is ervenyesek, itt csak a hardver-specifikus -beallitasi lehetosegek vannak osszefoglalva: - -Konfiguralasi interfesz a /proc/comx/ alatt: - -Minden timeslot-csoportnak kulon comx* interfeszt kell letrehozni mkdir-rel: -comx0, comx1, .. stb. Itt beallithato, hogy az adott interfesz hanyadik kartya -melyik timeslotja(i)bol alljon ossze. A Cisco-fele serial3:1 elnevezesek -(serial3:1 = a 3. kartyaban az 1-es idoszelet-csoport) Linuxon aliasing-ot -jelentenenek, ezert mi nem tudunk ilyen elnevezest hasznalni. - -Tobb kartya eseten a comx0.1, comx0.2, ... vagy slice0.1, slice0.2 nevek -hasznalhatoak. - -Tobb SliceCOM kartya is lehet egy gepben, de sajat interrupt kell mindegyiknek, -nem tud meg megosztott interruptot kezelni. - -Az egesz kartyat erinto beallitasok: - -Az ioport es irq beallitas nincs: amit a PCI BIOS kioszt a rendszernek, -azt hasznalja a driver. - - -comx0/boardnum - hanyadik SliceCOM kartya a gepben (a 'termeszetes' PCI - sorrendben ertve: ahogyan a /proc/pci-ban vagy az 'lspci' - kimeneteben megjelenik, altalaban az alaplapi PCI meghajto - aramkorokhoz kozelebb eso kartyak a kisebb sorszamuak) - - Default: 0 (0-tol kezdodik a szamolas) - - -Bar a kovetkezoket csak egy-egy interfeszen allitjuk at, megis az egesz kartya -mukodeset egyszerre allitjak. A megkotes hogy csak UP-ban levo interfeszen -hasznalhatoak, azert van, mert kulonben nem vart eredmenyekre vezetne egy ilyen -paranccsorozat: - - echo 0 >boardnum - echo internal >clock_source - echo 1 >boardnum - -- Ez a 0-s board clock_source-at allitana at. - -Ezek a beallitasok megmaradnak az osszes interfesz torlesekor, de torlodnek -a driver modul ki/betoltesekor. - - -comx0/clock_source - A Tx orajelforrasa, a Cisco-val hasonlatosra keszult. - Hasznalata: - - papaya:# echo line >/proc/comx/comx0/clock_source - papaya:# echo internal >/proc/comx/comx0/clock_source - - line - A Tx orajelet a vett adatfolyambol dekodolja, igyekszik - igazodni hozza. Ha nem lat orajelet az inputon, akkor - atall a sajat orajelgeneratorara. - internal - A Tx orajelet a sajat orajelgeneratora szolgaltatja. - - Default: line - - Normal osszeallitas eseten a tavkozlesi szolgaltato eszkoze - (pl. HDSL modem) adja az orajelet, ezert ez a default. - - -comx0/framing - A CRC4 ki/be kapcsolasa - - A CRC4: 16 PCM keretet (A PCM keret az, amibe a 32 darab 64 - kilobites csatorna van bemultiplexalva. Nem osszetevesztendo a HDLC - kerettel.) 2x8 -as csoportokra osztanak, es azokhoz 4-4 bites CRC-t - szamolnak. Elsosorban a vonal minosegenek a monitorozasara szolgal. - - papaya:~# echo crc4 >/proc/comx/comx0/framing - papaya:~# echo no-crc4 >/proc/comx/comx0/framing - - Default a 'crc4', a MATAV vonalak altalaban igy futnak. De ha nem - egyforma is a beallitas a vonal ket vegen, attol a forgalom altalaban - at tud menni. - - -comx0/linecode - A vonali kodolas beallitasa - - papaya:~# echo hdb3 >/proc/comx/comx0/linecode - papaya:~# echo ami >/proc/comx/comx0/linecode - - Default a 'hdb3', a MATAV vonalak igy futnak. - - (az AMI kodolas igen ritka E1-es vonalaknal). Ha ez a beallitas nem - egyezik a vonal ket vegen, akkor elofordulhat hogy a keretszinkron - osszejon, de CRC4-hibak es a vonalakon atvitt adatokban is hibak - keletkeznek (amit a HDLC/SyncPPP szinten CRC-hibaval jelez) - - -comx0/reg - a kartya aramkoreinek, a MUNICH (reg) es a FALC (lbireg) -comx0/lbireg regisztereinek kozvetlen elerese. Hasznalata: - - echo >reg 0x04 0x0 - a 4-es regiszterbe 0-t ir - echo >reg 0x104 - printk()-val kiirja a 4-es regiszter - tartalmat a syslogba. - - WARNING: ezek csak a fejleszteshez keszultek, sok galibat - lehet veluk okozni! - - -comx0/loopback - A kartya G.703 jelenek a visszahurkolasara is van lehetoseg: - - papaya:# echo none >/proc/comx/comx0/loopback - papaya:# echo local >/proc/comx/comx0/loopback - papaya:# echo remote >/proc/comx/comx0/loopback - - none - nincs visszahurkolas, normal mukodes - local - a kartya a sajat maga altal adott jelet kapja vissza - remote - a kartya a kivulrol vett jelet adja kifele - - Default: none - ------------------------------------------------------------------ - -Az interfeszhez (Cisco terminologiaban 'channel-group') kapcsolodo beallitasok: - -comx0/timeslots - mely timeslotok (idoszeletek) tartoznak az adott interfeszhez. - - papaya:~# cat /proc/comx/comx0/timeslots - 1 3 4 5 6 - papaya:~# - - Egy timeslot megkeresese (hanyas interfeszbe tartozik nalunk): - - papaya:~# grep ' 4' /proc/comx/comx*/timeslots - /proc/comx/comx0/timeslots:1 3 4 5 6 - papaya:~# - - Beallitasa: - papaya:~# echo '1 5 2 6 7 8' >/proc/comx/comx0/timeslots - - A timeslotok sorrendje nem szamit, '1 3 2' ugyanaz mint az '1 2 3'. - - Beallitashoz az adott interfesznek DOWN-ban kell lennie - (ifconfig comx0 down), de ugyanannak a kartyanak a tobbi interfesze - uzemelhet kozben. - - Beallitaskor leellenorzi, hogy az uj timeslotok nem utkoznek-e egy - masik interfesz timeslotjaival. Ha utkoznek, akkor nem allitja at. - - Mindig 10-es szamrendszerben tortenik a timeslotok ertelmezese, nehogy - a 08, 09 alaku felirast rosszul ertelmezze. - ------------------------------------------------------------------ - -Az interfeszek es a kartya allapotanak lekerdezese: - -- A ' '-szel kezdodo sorok az eredeti kimenetet, a //-rel kezdodo sorok a -magyarazatot jelzik. - - papaya:~$ cat /proc/comx/comx1/status - Interface administrative status is UP, modem status is UP, protocol is UP - Modem status changes: 0, Transmitter status is IDLE, tbusy: 0 - Interface load (input): 978376 / 947808 / 951024 bits/s (5s/5m/15m) - (output): 978376 / 947848 / 951024 bits/s (5s/5m/15m) - Debug flags: none - RX errors: len: 22, overrun: 1, crc: 0, aborts: 0 - buffer overrun: 0, pbuffer overrun: 0 - TX errors: underrun: 0 - Line keepalive (value: 10) status UP [0] - -// Itt kezdodik a hardver-specifikus resz: - Controller status: - No alarms - -// Alarm: hibajelzes: -// -// No alarms - minden rendben -// -// LOS - Loss Of Signal - nem erzekel jelet a bemeneten. -// AIS - Alarm Indication Signal - csak egymas utani 1-esek jonnek -// a bemeneten, a tuloldal igy is jelezheti hogy meghibasodott vagy -// nincs inicializalva. -// AUXP - Auxiliary Pattern Indication - 01010101.. sorozat jon a bemeneten. -// LFA - Loss of Frame Alignment - nincs keretszinkron -// RRA - Receive Remote Alarm - a tuloldal el, de hibat jelez. -// LMFA - Loss of CRC4 Multiframe Alignment - nincs CRC4-multikeret-szinkron -// NMF - No Multiframe alignment Found after 400 msec - ilyen alarm a no-crc4 -// es crc4 keretezesek eseten nincs, lasd lentebb -// -// Egyeb lehetseges hibajelzesek: -// -// Transmit Line Short - a kartya ugy erzi hogy az adasi kimenete rovidre -// van zarva, ezert kikapcsolta az adast. (nem feltetlenul veszi eszre -// a kulso rovidzarat) - -// A veteli oldal csomagjainak lancolt listai, debug celokra: - - Rx ring: - rafutott: 0 - lastcheck: 50845731, jiffies: 51314281 - base: 017b1858 - rx_desc_ptr: 0 - rx_desc_ptr: 017b1858 - hw_curr_ptr: 017b1858 - 06040000 017b1868 017b1898 c016ff00 - 06040000 017b1878 017b1e9c c016ff00 - 46040000 017b1888 017b24a0 c016ff00 - 06040000 017b1858 017b2aa4 c016ff00 - -// A kartyat hasznalo tobbi interfesz: a 0-s channel-group a comx1 interfesz, -// es az 1,2,...,16 timeslotok tartoznak hozza: - - Interfaces using this board: (channel-group, interface, timeslots) - 0 comx1: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 - 1 comx2: 17 - 2 comx3: 18 - 3 comx4: 19 - 4 comx5: 20 - 5 comx6: 21 - 6 comx7: 22 - 7 comx8: 23 - 8 comx9: 24 - 9 comx10: 25 - 10 comx11: 26 - 11 comx12: 27 - 12 comx13: 28 - 13 comx14: 29 - 14 comx15: 30 - 15 comx16: 31 - -// Hany esemenyt kezelt le a driver egy-egy hardver-interrupt kiszolgalasanal: - - Interrupt work histogram: - hist[ 0]: 0 hist[ 1]: 2 hist[ 2]: 18574 hist[ 3]: 79 - hist[ 4]: 14 hist[ 5]: 1 hist[ 6]: 0 hist[ 7]: 1 - hist[ 8]: 0 hist[ 9]: 7 - -// Hany kikuldendo csomag volt mar a Tx-ringben amikor ujabb lett irva bele: - - Tx ring histogram: - hist[ 0]: 2329 hist[ 1]: 0 hist[ 2]: 0 hist[ 3]: 0 - -// Az E1-interfesz hiba-szamlaloi, az rfc2495-nek megfeleloen: -// (kb. a Cisco routerek "show controllers e1" formatumaban: http://www.cisco.com/univercd/cc/td/doc/product/software/ios11/rbook/rinterfc.htm#xtocid25669126) - -Data in current interval (91 seconds elapsed): - 9516 Line Code Violations, 65 Path Code Violations, 2 E-Bit Errors - 0 Slip Secs, 2 Fr Loss Secs, 2 Line Err Secs, 0 Degraded Mins - 0 Errored Secs, 0 Bursty Err Secs, 0 Severely Err Secs, 11 Unavail Secs -Data in Interval 1 (15 minutes): - 0 Line Code Violations, 0 Path Code Violations, 0 E-Bit Errors - 0 Slip Secs, 0 Fr Loss Secs, 0 Line Err Secs, 0 Degraded Mins - 0 Errored Secs, 0 Bursty Err Secs, 0 Severely Err Secs, 0 Unavail Secs -Data in last 4 intervals (1 hour): - 0 Line Code Violations, 0 Path Code Violations, 0 E-Bit Errors - 0 Slip Secs, 0 Fr Loss Secs, 0 Line Err Secs, 0 Degraded Mins - 0 Errored Secs, 0 Bursty Err Secs, 0 Severely Err Secs, 0 Unavail Secs -Data in last 96 intervals (24 hours): - 0 Line Code Violations, 0 Path Code Violations, 0 E-Bit Errors - 0 Slip Secs, 0 Fr Loss Secs, 0 Line Err Secs, 0 Degraded Mins - 0 Errored Secs, 0 Bursty Err Secs, 0 Severely Err Secs, 0 Unavail Secs - ------------------------------------------------------------------ - -Nehany kulonlegesebb beallitasi lehetoseg (idovel beepulhetnek majd a driverbe): -Ezekkel sok galibat lehet okozni, nagyon ovatosan kell oket hasznalni! - - modified CRC-4, for improved interworking of CRC-4 and non-CRC-4 - devices: (lasd page 107 es g706 Annex B) - lbireg[ 0x1b ] |= 0x08 - lbireg[ 0x1c ] |= 0xc0 - - ilyenkor ertelmezett az NMF - 'No Multiframe alignment Found after - 400 msec' alarm. - - FALC - a vonali meghajto IC - local loop - a sajat adasomat halljam vissza - remote loop - a kivulrol jovo adast adom vissza - - Egy hibakeresesre hasznalhato dolog: - - 1-es timeslot local loop a FALC-ban: echo >lbireg 0x1d 0x21 - - local loop kikapcsolasa: echo >lbireg 0x1d 0x00 diff --git a/Documentation/networking/slicecom.txt b/Documentation/networking/slicecom.txt deleted file mode 100644 index c82c0cf..0000000 --- a/Documentation/networking/slicecom.txt +++ /dev/null @@ -1,369 +0,0 @@ - -SliceCOM adapter user's documentation - for the 0.51 driver version - -Written by Bartók István <bartoki@itc.hu> - -English translation: Lakatos György <gyuri@itc.hu> -Mon Dec 11 15:28:42 CET 2000 - -Last modified: Wed Aug 29 17:25:37 CEST 2001 - ------------------------------------------------------------------ - -Usage: - -Compiling the kernel: - -Code maturity level options - [*] Prompt for development and/or incomplete code/drivers - -Network device support - Wan interfaces - <M> MultiGate (COMX) synchronous - <M> Support for MUNICH based boards: SliceCOM, PCICOM (NEW) - <M> Support for HDLC and syncPPP... - - -Loading the modules: - -modprobe comx - -modprobe comx-proto-ppp # module for Cisco-HDLC and SyncPPP protocols - -modprobe comx-hw-munich # the module logs information by the kernel - # about the detected boards - - -Configuring the board: - -# This interface will use the Cisco-HDLC line protocol, -# the timeslices assigned are 1,2 (128 KiBit line speed) -# (the first data timeslice in the G.703 frame is no. 1) -# -mkdir /proc/comx/comx0.1/ -echo slicecom >/proc/comx/comx0.1/boardtype -echo hdlc >/proc/comx/comx0.1/protocol -echo 1 2 >/proc/comx/comx0.1/timeslots - - -# This interface uses SyncPPP line protocol, the assigned -# is no. 3 (64 KiBit line speed) -# -mkdir /proc/comx/comx0.2/ -echo slicecom >/proc/comx/comx0.2/boardtype -echo ppp >/proc/comx/comx0.2/protocol -echo 3 >/proc/comx/comx0.2/timeslots - -... - -ifconfig comx0.1 up -ifconfig comx0.2 up - ------------------------------------------------------------------ - -The COMX interfaces use a 10 packet transmit queue by default, however WAN -networks sometimes use bigger values (20 to 100), to utilize the line better -by large traffic (though the line delay increases because of more packets -join the queue). - -# ifconfig comx0 txqueuelen 50 - -This option is only supported by the ifconfig command of the later -distributions, which came with 2.2 kernels, such as RedHat 6.1 or Debian 2.2. - -You can download a newer netbase packet from -http://www.debian.org/~rcw/2.2/netbase/ for Debian 2.1, which has a new -ifconfig. You can get further information about using 2.2 kernel with -Debian 2.1 from http://www.debian.org/releases/stable/running-kernel-2.2 - ------------------------------------------------------------------ - -The SliceCom LEDs: - -red - on, if the interface is unconfigured, or it gets Remote Alarm-s -green - on, if the board finds frame-sync in the received signal - -A bit more detailed: - -red: green: meaning: - -- - no frame-sync, no signal received, or signal SNAFU. -- on "Everything is OK" -on on Reception is ok, but the remote end sends Remote Alarm -on - The interface is unconfigured - ------------------------------------------------------------------ - -A more detailed description of the hardware setting options: - -The general and the protocol layer options described in the 'comx.txt' file -apply to the SliceCom as well, I only summarize the SliceCom hardware specific -settings below. - -The '/proc/comx' configuring interface: - -An interface directory should be created for every timeslot group with -'mkdir', e,g: 'comx0', 'comx1' etc. The timeslots can be assigned here to the -specific interface. The Cisco-like naming convention (serial3:1 - first -timeslot group of the 3rd. board) can't be used here, because these mean IP -aliasing in Linux. - -You can give any meaningful name to keep the configuration clear; -e.g: 'comx0.1', 'comx0.2', 'comx1.1', comx1.2', if you have two boards -with two interfaces each. - -Settings, which apply to the board: - -Neither 'io' nor 'irq' settings required, the driver uses the resources -given by the PCI BIOS. - -comx0/boardnum - board number of the SliceCom in the PC (using the 'natural' - PCI order) as listed in '/proc/pci' or the output of the - 'lspci' command, generally the slots nearer to the motherboard - PCI driver chips have the lower numbers. - - Default: 0 (the counting starts with 0) - -Though the options below are to be set on a single interface, they apply to the -whole board. The restriction, to use them on 'UP' interfaces, is because the -command sequence below could lead to unpredictable results. - - # echo 0 >boardnum - # echo internal >clock_source - # echo 1 >boardnum - -The sequence would set the clock source of board 0. - -These settings will persist after all the interfaces are cleared, but are -cleared when the driver module is unloaded and loaded again. - -comx0/clock_source - source of the transmit clock - Usage: - - # echo line >/proc/comx/comx0/clock_source - # echo internal >/proc/comx/comx0/clock_source - - line - The Tx clock is being decoded if the input data stream, - if no clock seen on the input, then the board will use it's - own clock generator. - - internal - The Tx clock is supplied by the builtin clock generator. - - Default: line - - Normally, the telecommunication company's end device (the HDSL - modem) provides the Tx clock, that's why 'line' is the default. - -comx0/framing - Switching CRC4 off/on - - CRC4: 16 PCM frames (The 32 64Kibit channels are multiplexed into a - PCM frame, nothing to do with HDLC frames) are divided into 2x8 - groups, each group has a 4 bit CRC. - - # echo crc4 >/proc/comx/comx0/framing - # echo no-crc4 >/proc/comx/comx0/framing - - Default is 'crc4', the Hungarian MATAV lines behave like this. - The traffic generally passes if this setting on both ends don't match. - -comx0/linecode - Setting the line coding - - # echo hdb3 >/proc/comx/comx0/linecode - # echo ami >/proc/comx/comx0/linecode - - Default a 'hdb3', MATAV lines use this. - - (AMI coding is rarely used with E1 lines). Frame sync may occur, if - this setting doesn't match the other end's, but CRC4 and data errors - will come, which will result in CRC errors on HDLC/SyncPPP level. - -comx0/reg - direct access to the board's MUNICH (reg) and FALC (lbireg) -comx0/lbireg circuit's registers - - # echo >reg 0x04 0x0 - write 0 to register 4 - # echo >reg 0x104 - write the contents of register 4 with - printk() to syslog - -WARNING! These are only for development purposes, messing with this will - result much trouble! - -comx0/loopback - Places a loop to the board's G.703 signals - - # echo none >/proc/comx/comx0/loopback - # echo local >/proc/comx/comx0/loopback - # echo remote >/proc/comx/comx0/loopback - - none - normal operation, no loop - local - the board receives it's own output - remote - the board sends the received data to the remote side - - Default: none - ------------------------------------------------------------------ - -Interface (channel group in Cisco terms) settings: - -comx0/timeslots - which timeslots belong to the given interface - - Setting: - - # echo '1 5 2 6 7 8' >/proc/comx/comx0/timeslots - - # cat /proc/comx/comx0/timeslots - 1 2 5 6 7 8 - # - - Finding a timeslot: - - # grep ' 4' /proc/comx/comx*/timeslots - /proc/comx/comx0/timeslots:1 3 4 5 6 - # - - The timeslots can be in any order, '1 2 3' is the same as '1 3 2'. - - The interface has to be DOWN during the setting ('ifconfig comx0 - down'), but the other interfaces could operate normally. - - The driver checks if the assigned timeslots are vacant, if not, then - the setting won't be applied. - - The timeslot values are treated as decimal numbers, not to misunderstand - values of 08, 09 form. - ------------------------------------------------------------------ - -Checking the interface and board status: - -- Lines beginning with ' ' (space) belong to the original output, the lines -which begin with '//' are the comments. - - papaya:~$ cat /proc/comx/comx1/status - Interface administrative status is UP, modem status is UP, protocol is UP - Modem status changes: 0, Transmitter status is IDLE, tbusy: 0 - Interface load (input): 978376 / 947808 / 951024 bits/s (5s/5m/15m) - (output): 978376 / 947848 / 951024 bits/s (5s/5m/15m) - Debug flags: none - RX errors: len: 22, overrun: 1, crc: 0, aborts: 0 - buffer overrun: 0, pbuffer overrun: 0 - TX errors: underrun: 0 - Line keepalive (value: 10) status UP [0] - -// The hardware specific part starts here: - Controller status: - No alarms - -// Alarm: -// -// No alarms - Everything OK -// -// LOS - Loss Of Signal - No signal sensed on the input -// AIS - Alarm Indication Signal - The remote side sends '11111111'-s, -// it tells, that there's an error condition, or it's not -// initialised. -// AUXP - Auxiliary Pattern Indication - 01010101.. received. -// LFA - Loss of Frame Alignment - no frame sync received. -// RRA - Receive Remote Alarm - the remote end's OK, but signals error cond. -// LMFA - Loss of CRC4 Multiframe Alignment - no CRC4 multiframe sync. -// NMF - No Multiframe alignment Found after 400 msec - no such alarm using -// no-crc4 or crc4 framing, see below. -// -// Other possible error messages: -// -// Transmit Line Short - the board felt, that it's output is short-circuited, -// so it switched the transmission off. (The board can't definitely tell, -// that it's output is short-circuited.) - -// Chained list of the received packets, for debug purposes: - - Rx ring: - rafutott: 0 - lastcheck: 50845731, jiffies: 51314281 - base: 017b1858 - rx_desc_ptr: 0 - rx_desc_ptr: 017b1858 - hw_curr_ptr: 017b1858 - 06040000 017b1868 017b1898 c016ff00 - 06040000 017b1878 017b1e9c c016ff00 - 46040000 017b1888 017b24a0 c016ff00 - 06040000 017b1858 017b2aa4 c016ff00 - -// All the interfaces using the board: comx1, using the 1,2,...16 timeslots, -// comx2, using timeslot 17, etc. - - Interfaces using this board: (channel-group, interface, timeslots) - 0 comx1: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 - 1 comx2: 17 - 2 comx3: 18 - 3 comx4: 19 - 4 comx5: 20 - 5 comx6: 21 - 6 comx7: 22 - 7 comx8: 23 - 8 comx9: 24 - 9 comx10: 25 - 10 comx11: 26 - 11 comx12: 27 - 12 comx13: 28 - 13 comx14: 29 - 14 comx15: 30 - 15 comx16: 31 - -// The number of events handled by the driver during an interrupt cycle: - - Interrupt work histogram: - hist[ 0]: 0 hist[ 1]: 2 hist[ 2]: 18574 hist[ 3]: 79 - hist[ 4]: 14 hist[ 5]: 1 hist[ 6]: 0 hist[ 7]: 1 - hist[ 8]: 0 hist[ 9]: 7 - -// The number of packets to send in the Tx ring, when a new one arrived: - - Tx ring histogram: - hist[ 0]: 2329 hist[ 1]: 0 hist[ 2]: 0 hist[ 3]: 0 - -// The error counters of the E1 interface, according to the RFC2495, -// (similar to the Cisco "show controllers e1" command's output: -// http://www.cisco.com/univercd/cc/td/doc/product/software/ios11/rbook/rinterfc.htm#xtocid25669126) - -Data in current interval (91 seconds elapsed): - 9516 Line Code Violations, 65 Path Code Violations, 2 E-Bit Errors - 0 Slip Secs, 2 Fr Loss Secs, 2 Line Err Secs, 0 Degraded Mins - 0 Errored Secs, 0 Bursty Err Secs, 0 Severely Err Secs, 11 Unavail Secs -Data in Interval 1 (15 minutes): - 0 Line Code Violations, 0 Path Code Violations, 0 E-Bit Errors - 0 Slip Secs, 0 Fr Loss Secs, 0 Line Err Secs, 0 Degraded Mins - 0 Errored Secs, 0 Bursty Err Secs, 0 Severely Err Secs, 0 Unavail Secs -Data in last 4 intervals (1 hour): - 0 Line Code Violations, 0 Path Code Violations, 0 E-Bit Errors - 0 Slip Secs, 0 Fr Loss Secs, 0 Line Err Secs, 0 Degraded Mins - 0 Errored Secs, 0 Bursty Err Secs, 0 Severely Err Secs, 0 Unavail Secs -Data in last 96 intervals (24 hours): - 0 Line Code Violations, 0 Path Code Violations, 0 E-Bit Errors - 0 Slip Secs, 0 Fr Loss Secs, 0 Line Err Secs, 0 Degraded Mins - 0 Errored Secs, 0 Bursty Err Secs, 0 Severely Err Secs, 0 Unavail Secs - ------------------------------------------------------------------ - -Some unique options, (may get into the driver later): -Treat them very carefully, these can cause much trouble! - - modified CRC-4, for improved interworking of CRC-4 and non-CRC-4 - devices: (see page 107 and g706 Annex B) - lbireg[ 0x1b ] |= 0x08 - lbireg[ 0x1c ] |= 0xc0 - - - The NMF - 'No Multiframe alignment Found after 400 msec' alarm - comes into account. - - FALC - the line driver chip. - local loop - I hear my transmission back. - remote loop - I echo the remote transmission back. - - Something useful for finding errors: - - - local loop for timeslot 1 in the FALC chip: - - # echo >lbireg 0x1d 0x21 - - - Switching the loop off: - - # echo >lbireg 0x1d 0x00 diff --git a/Documentation/parport-lowlevel.txt b/Documentation/parport-lowlevel.txt index 265fcdc..120eb20 100644 --- a/Documentation/parport-lowlevel.txt +++ b/Documentation/parport-lowlevel.txt @@ -339,6 +339,10 @@ Use this function to register your device driver on a parallel port ('port'). Once you have done that, you will be able to use parport_claim and parport_release in order to use the port. +The ('name') argument is the name of the device that appears in /proc +filesystem. The string must be valid for the whole lifetime of the +device (until parport_unregister_device is called). + This function will register three callbacks into your driver: 'preempt', 'wakeup' and 'irq'. Each of these may be NULL in order to indicate that you do not want a callback. diff --git a/Documentation/powerpc/booting-without-of.txt b/Documentation/powerpc/booting-without-of.txt index a96e853..e9a3cb1 100644 --- a/Documentation/powerpc/booting-without-of.txt +++ b/Documentation/powerpc/booting-without-of.txt @@ -52,6 +52,7 @@ Table of Contents i) Freescale QUICC Engine module (QE) j) CFI or JEDEC memory-mapped NOR flash k) Global Utilities Block + l) Xilinx IP cores VII - Specifying interrupt information for devices 1) interrupts property @@ -851,12 +852,18 @@ address which can extend beyond that limit. /cpus/PowerPC,970FX@0 /cpus/PowerPC,970FX@1 (unit addresses do not require leading zeroes) - - d-cache-line-size : one cell, L1 data cache line size in bytes - - i-cache-line-size : one cell, L1 instruction cache line size in + - d-cache-block-size : one cell, L1 data cache block size in bytes (*) + - i-cache-block-size : one cell, L1 instruction cache block size in bytes - d-cache-size : one cell, size of L1 data cache in bytes - i-cache-size : one cell, size of L1 instruction cache in bytes +(*) The cache "block" size is the size on which the cache management +instructions operate. Historically, this document used the cache +"line" size here which is incorrect. The kernel will prefer the cache +block size and will fallback to cache line size for backward +compatibility. + Recommended properties: - timebase-frequency : a cell indicating the frequency of the @@ -870,6 +877,10 @@ address which can extend beyond that limit. for the above, the common code doesn't use that property, but you are welcome to re-use the pSeries or Maple one. A future kernel version might provide a common function for this. + - d-cache-line-size : one cell, L1 data cache line size in bytes + if different from the block size + - i-cache-line-size : one cell, L1 instruction cache line size in + bytes if different from the block size You are welcome to add any property you find relevant to your board, like some information about the mechanism used to soft-reset the @@ -1634,8 +1645,9 @@ platforms are moved over to use the flattened-device-tree model. MAC addresses passed by the firmware when no information other than indices is available to associate an address with a device. - phy-connection-type : a string naming the controller/PHY interface type, - i.e., "mii" (default), "rmii", "gmii", "rgmii", "rgmii-id", "tbi", - or "rtbi". + i.e., "mii" (default), "rmii", "gmii", "rgmii", "rgmii-id" (Internal + Delay), "rgmii-txid" (delay on TX only), "rgmii-rxid" (delay on RX only), + "tbi", or "rtbi". Example: ucc@2000 { @@ -2242,6 +2254,266 @@ platforms are moved over to use the flattened-device-tree model. available. For Axon: 0x0000012a + l) Xilinx IP cores + + The Xilinx EDK toolchain ships with a set of IP cores (devices) for use + in Xilinx Spartan and Virtex FPGAs. The devices cover the whole range + of standard device types (network, serial, etc.) and miscellanious + devices (gpio, LCD, spi, etc). Also, since these devices are + implemented within the fpga fabric every instance of the device can be + synthesised with different options that change the behaviour. + + Each IP-core has a set of parameters which the FPGA designer can use to + control how the core is synthesized. Historically, the EDK tool would + extract the device parameters relevant to device drivers and copy them + into an 'xparameters.h' in the form of #define symbols. This tells the + device drivers how the IP cores are configured, but it requres the kernel + to be recompiled every time the FPGA bitstream is resynthesized. + + The new approach is to export the parameters into the device tree and + generate a new device tree each time the FPGA bitstream changes. The + parameters which used to be exported as #defines will now become + properties of the device node. In general, device nodes for IP-cores + will take the following form: + + (name)@(base-address) { + compatible = "xlnx,(ip-core-name)-(HW_VER)" + [, (list of compatible devices), ...]; + reg = <(baseaddr) (size)>; + interrupt-parent = <&interrupt-controller-phandle>; + interrupts = < ... >; + xlnx,(parameter1) = "(string-value)"; + xlnx,(parameter2) = <(int-value)>; + }; + + (ip-core-name): the name of the ip block (given after the BEGIN + directive in system.mhs). Should be in lowercase + and all underscores '_' converted to dashes '-'. + (name): is derived from the "PARAMETER INSTANCE" value. + (parameter#): C_* parameters from system.mhs. The C_ prefix is + dropped from the parameter name, the name is converted + to lowercase and all underscore '_' characters are + converted to dashes '-'. + (baseaddr): the C_BASEADDR parameter. + (HW_VER): from the HW_VER parameter. + (size): equals C_HIGHADDR - C_BASEADDR + 1 + + Typically, the compatible list will include the exact IP core version + followed by an older IP core version which implements the same + interface or any other device with the same interface. + + 'reg', 'interrupt-parent' and 'interrupts' are all optional properties. + + For example, the following block from system.mhs: + + BEGIN opb_uartlite + PARAMETER INSTANCE = opb_uartlite_0 + PARAMETER HW_VER = 1.00.b + PARAMETER C_BAUDRATE = 115200 + PARAMETER C_DATA_BITS = 8 + PARAMETER C_ODD_PARITY = 0 + PARAMETER C_USE_PARITY = 0 + PARAMETER C_CLK_FREQ = 50000000 + PARAMETER C_BASEADDR = 0xEC100000 + PARAMETER C_HIGHADDR = 0xEC10FFFF + BUS_INTERFACE SOPB = opb_7 + PORT OPB_Clk = CLK_50MHz + PORT Interrupt = opb_uartlite_0_Interrupt + PORT RX = opb_uartlite_0_RX + PORT TX = opb_uartlite_0_TX + PORT OPB_Rst = sys_bus_reset_0 + END + + becomes the following device tree node: + + opb-uartlite-0@ec100000 { + device_type = "serial"; + compatible = "xlnx,opb-uartlite-1.00.b"; + reg = <ec100000 10000>; + interrupt-parent = <&opb-intc>; + interrupts = <1 0>; // got this from the opb_intc parameters + current-speed = <d#115200>; // standard serial device prop + clock-frequency = <d#50000000>; // standard serial device prop + xlnx,data-bits = <8>; + xlnx,odd-parity = <0>; + xlnx,use-parity = <0>; + }; + + Some IP cores actually implement 2 or more logical devices. In this case, + the device should still describe the whole IP core with a single node + and add a child node for each logical device. The ranges property can + be used to translate from parent IP-core to the registers of each device. + (Note: this makes the assumption that both logical devices have the same + bus binding. If this is not true, then separate nodes should be used for + each logical device). The 'cell-index' property can be used to enumerate + logical devices within an IP core. For example, the following is the + system.mhs entry for the dual ps2 controller found on the ml403 reference + design. + + BEGIN opb_ps2_dual_ref + PARAMETER INSTANCE = opb_ps2_dual_ref_0 + PARAMETER HW_VER = 1.00.a + PARAMETER C_BASEADDR = 0xA9000000 + PARAMETER C_HIGHADDR = 0xA9001FFF + BUS_INTERFACE SOPB = opb_v20_0 + PORT Sys_Intr1 = ps2_1_intr + PORT Sys_Intr2 = ps2_2_intr + PORT Clkin1 = ps2_clk_rx_1 + PORT Clkin2 = ps2_clk_rx_2 + PORT Clkpd1 = ps2_clk_tx_1 + PORT Clkpd2 = ps2_clk_tx_2 + PORT Rx1 = ps2_d_rx_1 + PORT Rx2 = ps2_d_rx_2 + PORT Txpd1 = ps2_d_tx_1 + PORT Txpd2 = ps2_d_tx_2 + END + + It would result in the following device tree nodes: + + opb_ps2_dual_ref_0@a9000000 { + ranges = <0 a9000000 2000>; + // If this device had extra parameters, then they would + // go here. + ps2@0 { + compatible = "xlnx,opb-ps2-dual-ref-1.00.a"; + reg = <0 40>; + interrupt-parent = <&opb-intc>; + interrupts = <3 0>; + cell-index = <0>; + }; + ps2@1000 { + compatible = "xlnx,opb-ps2-dual-ref-1.00.a"; + reg = <1000 40>; + interrupt-parent = <&opb-intc>; + interrupts = <3 0>; + cell-index = <0>; + }; + }; + + Also, the system.mhs file defines bus attachments from the processor + to the devices. The device tree structure should reflect the bus + attachments. Again an example; this system.mhs fragment: + + BEGIN ppc405_virtex4 + PARAMETER INSTANCE = ppc405_0 + PARAMETER HW_VER = 1.01.a + BUS_INTERFACE DPLB = plb_v34_0 + BUS_INTERFACE IPLB = plb_v34_0 + END + + BEGIN opb_intc + PARAMETER INSTANCE = opb_intc_0 + PARAMETER HW_VER = 1.00.c + PARAMETER C_BASEADDR = 0xD1000FC0 + PARAMETER C_HIGHADDR = 0xD1000FDF + BUS_INTERFACE SOPB = opb_v20_0 + END + + BEGIN opb_uart16550 + PARAMETER INSTANCE = opb_uart16550_0 + PARAMETER HW_VER = 1.00.d + PARAMETER C_BASEADDR = 0xa0000000 + PARAMETER C_HIGHADDR = 0xa0001FFF + BUS_INTERFACE SOPB = opb_v20_0 + END + + BEGIN plb_v34 + PARAMETER INSTANCE = plb_v34_0 + PARAMETER HW_VER = 1.02.a + END + + BEGIN plb_bram_if_cntlr + PARAMETER INSTANCE = plb_bram_if_cntlr_0 + PARAMETER HW_VER = 1.00.b + PARAMETER C_BASEADDR = 0xFFFF0000 + PARAMETER C_HIGHADDR = 0xFFFFFFFF + BUS_INTERFACE SPLB = plb_v34_0 + END + + BEGIN plb2opb_bridge + PARAMETER INSTANCE = plb2opb_bridge_0 + PARAMETER HW_VER = 1.01.a + PARAMETER C_RNG0_BASEADDR = 0x20000000 + PARAMETER C_RNG0_HIGHADDR = 0x3FFFFFFF + PARAMETER C_RNG1_BASEADDR = 0x60000000 + PARAMETER C_RNG1_HIGHADDR = 0x7FFFFFFF + PARAMETER C_RNG2_BASEADDR = 0x80000000 + PARAMETER C_RNG2_HIGHADDR = 0xBFFFFFFF + PARAMETER C_RNG3_BASEADDR = 0xC0000000 + PARAMETER C_RNG3_HIGHADDR = 0xDFFFFFFF + BUS_INTERFACE SPLB = plb_v34_0 + BUS_INTERFACE MOPB = opb_v20_0 + END + + Gives this device tree (some properties removed for clarity): + + plb-v34-0 { + #address-cells = <1>; + #size-cells = <1>; + device_type = "ibm,plb"; + ranges; // 1:1 translation + + plb-bram-if-cntrl-0@ffff0000 { + reg = <ffff0000 10000>; + } + + opb-v20-0 { + #address-cells = <1>; + #size-cells = <1>; + ranges = <20000000 20000000 20000000 + 60000000 60000000 20000000 + 80000000 80000000 40000000 + c0000000 c0000000 20000000>; + + opb-uart16550-0@a0000000 { + reg = <a00000000 2000>; + }; + + opb-intc-0@d1000fc0 { + reg = <d1000fc0 20>; + }; + }; + }; + + That covers the general approach to binding xilinx IP cores into the + device tree. The following are bindings for specific devices: + + i) Xilinx ML300 Framebuffer + + Simple framebuffer device from the ML300 reference design (also on the + ML403 reference design as well as others). + + Optional properties: + - resolution = <xres yres> : pixel resolution of framebuffer. Some + implementations use a different resolution. + Default is <d#640 d#480> + - virt-resolution = <xvirt yvirt> : Size of framebuffer in memory. + Default is <d#1024 d#480>. + - rotate-display (empty) : rotate display 180 degrees. + + ii) Xilinx SystemACE + + The Xilinx SystemACE device is used to program FPGAs from an FPGA + bitstream stored on a CF card. It can also be used as a generic CF + interface device. + + Optional properties: + - 8-bit (empty) : Set this property for SystemACE in 8 bit mode + + iii) Xilinx EMAC and Xilinx TEMAC + + Xilinx Ethernet devices. In addition to general xilinx properties + listed above, nodes for these devices should include a phy-handle + property, and may include other common network device properties + like local-mac-address. + + iv) Xilinx Uartlite + + Xilinx uartlite devices are simple fixed speed serial ports. + + Requred properties: + - current-speed : Baud rate of uartlite + More devices will be defined as this spec matures. VII - Specifying interrupt information for devices diff --git a/Documentation/rtc.txt b/Documentation/rtc.txt index c931d61..e20b19c 100644 --- a/Documentation/rtc.txt +++ b/Documentation/rtc.txt @@ -180,9 +180,10 @@ driver returns ENOIOCTLCMD. Some common examples: * RTC_IRQP_SET, RTC_IRQP_READ: the irq_set_freq function will be called to set the frequency while the framework will handle the read for you since the frequency is stored in the irq_freq member of the rtc_device - structure. Also make sure you set the max_user_freq member in your - initialization routines so the framework can sanity check the user - input for you. + structure. Your driver needs to initialize the irq_freq member during + init. Make sure you check the requested frequency is in range of your + hardware in the irq_set_freq function. If you cannot actually change + the frequency, just return -ENOTTY. If all else fails, check out the rtc-test.c driver! diff --git a/Documentation/thinkpad-acpi.txt b/Documentation/thinkpad-acpi.txt index ec49926..10c041c 100644 --- a/Documentation/thinkpad-acpi.txt +++ b/Documentation/thinkpad-acpi.txt @@ -1,7 +1,7 @@ ThinkPad ACPI Extras Driver - Version 0.16 - August 2nd, 2007 + Version 0.17 + October 04th, 2007 Borislav Deianov <borislav@users.sf.net> Henrique de Moraes Holschuh <hmh@hmh.eng.br> @@ -923,19 +923,34 @@ sysfs backlight device "thinkpad_screen" This feature allows software control of the LCD brightness on ThinkPad models which don't have a hardware brightness slider. -It has some limitations: the LCD backlight cannot be actually turned on or off -by this interface, and in many ThinkPad models, the "dim while on battery" -functionality will be enabled by the BIOS when this interface is used, and -cannot be controlled. - -The backlight control has eight levels, ranging from 0 to 7. Some of the -levels may not be distinct. - -There are two interfaces to the firmware for brightness control, EC and CMOS. -To select which one should be used, use the brightness_mode module parameter: -brightness_mode=1 selects EC mode, brightness_mode=2 selects CMOS mode, -brightness_mode=3 selects both EC and CMOS. The driver tries to autodetect -which interface to use. +It has some limitations: the LCD backlight cannot be actually turned on or +off by this interface, and in many ThinkPad models, the "dim while on +battery" functionality will be enabled by the BIOS when this interface is +used, and cannot be controlled. + +On IBM (and some of the earlier Lenovo) ThinkPads, the backlight control +has eight brightness levels, ranging from 0 to 7. Some of the levels +may not be distinct. Later Lenovo models that implement the ACPI +display backlight brightness control methods have 16 levels, ranging +from 0 to 15. + +There are two interfaces to the firmware for direct brightness control, +EC and CMOS. To select which one should be used, use the +brightness_mode module parameter: brightness_mode=1 selects EC mode, +brightness_mode=2 selects CMOS mode, brightness_mode=3 selects both EC +and CMOS. The driver tries to autodetect which interface to use. + +When display backlight brightness controls are available through the +standard ACPI interface, it is best to use it instead of this direct +ThinkPad-specific interface. The driver will disable its native +backlight brightness control interface if it detects that the standard +ACPI interface is available in the ThinkPad. + +The brightness_enable module parameter can be used to control whether +the LCD brightness control feature will be enabled when available. +brightness_enable=0 forces it to be disabled. brightness_enable=1 +forces it to be enabled when available, even if the standard ACPI +interface is also available. Procfs notes: @@ -947,11 +962,11 @@ Procfs notes: Sysfs notes: -The interface is implemented through the backlight sysfs class, which is poorly -documented at this time. +The interface is implemented through the backlight sysfs class, which is +poorly documented at this time. -Locate the thinkpad_screen device under /sys/class/backlight, and inside it -there will be the following attributes: +Locate the thinkpad_screen device under /sys/class/backlight, and inside +it there will be the following attributes: max_brightness: Reads the maximum brightness the hardware can be set to. @@ -961,17 +976,19 @@ there will be the following attributes: Reads what brightness the screen is set to at this instant. brightness: - Writes request the driver to change brightness to the given - value. Reads will tell you what brightness the driver is trying - to set the display to when "power" is set to zero and the display - has not been dimmed by a kernel power management event. + Writes request the driver to change brightness to the + given value. Reads will tell you what brightness the + driver is trying to set the display to when "power" is set + to zero and the display has not been dimmed by a kernel + power management event. power: - power management mode, where 0 is "display on", and 1 to 3 will - dim the display backlight to brightness level 0 because - thinkpad-acpi cannot really turn the backlight off. Kernel - power management events can temporarily increase the current - power management level, i.e. they can dim the display. + power management mode, where 0 is "display on", and 1 to 3 + will dim the display backlight to brightness level 0 + because thinkpad-acpi cannot really turn the backlight + off. Kernel power management events can temporarily + increase the current power management level, i.e. they can + dim the display. Volume control -- /proc/acpi/ibm/volume diff --git a/Documentation/tty.txt b/Documentation/tty.txt index 048a876..8e65c44 100644 --- a/Documentation/tty.txt +++ b/Documentation/tty.txt @@ -132,6 +132,14 @@ set_termios() Notify the tty driver that the device's termios tty->termios. Previous settings should be passed in the "old" argument. + The API is defined such that the driver should return + the actual modes selected. This means that the + driver function is responsible for modifying any + bits in the request it cannot fulfill to indicate + the actual modes being used. A device with no + hardware capability for change (eg a USB dongle or + virtual port) can provide NULL for this method. + throttle() Notify the tty driver that input buffers for the line discipline are close to full, and it should somehow signal that no more characters should be diff --git a/Documentation/usb/power-management.txt b/Documentation/usb/power-management.txt index 97842de..b2fc4d4 100644 --- a/Documentation/usb/power-management.txt +++ b/Documentation/usb/power-management.txt @@ -278,6 +278,14 @@ optional. The methods' jobs are quite simple: (although the interfaces will be in the same altsettings as before the suspend). +If the device is disconnected or powered down while it is suspended, +the disconnect method will be called instead of the resume or +reset_resume method. This is also quite likely to happen when +waking up from hibernation, as many systems do not maintain suspend +current to the USB host controllers during hibernation. (It's +possible to work around the hibernation-forces-disconnect problem by +using the USB Persist facility.) + The reset_resume method is used by the USB Persist facility (see Documentation/usb/persist.txt) and it can also be used under certain circumstances when CONFIG_USB_PERSIST is not enabled. Currently, if a diff --git a/Documentation/x86_64/uefi.txt b/Documentation/x86_64/uefi.txt new file mode 100644 index 0000000..91a98ed --- /dev/null +++ b/Documentation/x86_64/uefi.txt @@ -0,0 +1,29 @@ +General note on [U]EFI x86_64 support +------------------------------------- + +The nomenclature EFI and UEFI are used interchangeably in this document. + +Although the tools below are _not_ needed for building the kernel, +the needed bootloader support and associated tools for x86_64 platforms +with EFI firmware and specifications are listed below. + +1. UEFI specification: http://www.uefi.org + +2. Booting Linux kernel on UEFI x86_64 platform requires bootloader + support. Elilo with x86_64 support can be used. + +3. x86_64 platform with EFI/UEFI firmware. + +Mechanics: +--------- +- Build the kernel with the following configuration. + CONFIG_FB_EFI=y + CONFIG_FRAMEBUFFER_CONSOLE=y +- Create a VFAT partition on the disk +- Copy the following to the VFAT partition: + elilo bootloader with x86_64 support, elilo configuration file, + kernel image built in first step and corresponding + initrd. Instructions on building elilo and its dependencies + can be found in the elilo sourceforge project. +- Boot to EFI shell and invoke elilo choosing the kernel image built + in first step. diff --git a/MAINTAINERS b/MAINTAINERS index 1c7c229..2bbe40e 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -323,8 +323,7 @@ S: Maintained ALCATEL SPEEDTOUCH USB DRIVER P: Duncan Sands M: duncan.sands@free.fr -L: linux-usb-users@lists.sourceforge.net -L: linux-usb-devel@lists.sourceforge.net +L: linux-usb@vger.kernel.org W: http://www.linux-usb.org/SpeedTouch/ S: Maintained @@ -440,7 +439,7 @@ S: Maintained ARM/ATMEL AT91RM9200 ARM ARCHITECTURE P: Andrew Victor -M: andrew@sanpeople.com +M: linux@maxim.org.za L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only) W: http://maxim.org.za/at91_26.html S: Maintained @@ -787,23 +786,25 @@ B43 WIRELESS DRIVER P: Michael Buesch M: mb@bu3sch.de P: Stefano Brivio -M: st3@riseup.net +M: stefano.brivio@polimi.it L: linux-wireless@vger.kernel.org -W: http://bcm43xx.berlios.de/ +W: http://linuxwireless.org/en/users/Drivers/b43 S: Maintained B43LEGACY WIRELESS DRIVER P: Larry Finger M: Larry.Finger@lwfinger.net +P: Stefano Brivio +M: stefano.brivio@polimi.it L: linux-wireless@vger.kernel.org -W: http://bcm43xx.berlios.de/ +W: http://linuxwireless.org/en/users/Drivers/b43 S: Maintained BCM43XX WIRELESS DRIVER (SOFTMAC BASED VERSION) P: Larry Finger M: Larry.Finger@lwfinger.net P: Stefano Brivio -M: st3@riseup.net +M: stefano.brivio@polimi.it L: linux-wireless@vger.kernel.org W: http://bcm43xx.berlios.de/ S: Maintained @@ -1041,7 +1042,7 @@ S: Maintained CIRRUS LOGIC EP93XX OHCI USB HOST DRIVER P: Lennert Buytenhek M: kernel@wantstofly.org -L: linux-usb-devel@lists.sourceforge.net +L: linux-usb@vger.kernel.org S: Maintained CIRRUS LOGIC CS4280/CS461x SOUNDDRIVER @@ -1550,7 +1551,7 @@ S: Maintained FREESCALE HIGHSPEED USB DEVICE DRIVER P: Li Yang M: leoli@freescale.com -L: linux-usb-devel@lists.sourceforge.net +L: linux-usb@vger.kernel.org L: linuxppc-dev@ozlabs.org S: Maintained @@ -1912,10 +1913,8 @@ L: linux1394-devel@lists.sourceforge.net S: Maintained IMS TWINTURBO FRAMEBUFFER DRIVER -P: Paul Mundt -M: lethal@chaoticdreams.org L: linux-fbdev-devel@lists.sourceforge.net (subscribers-only) -S: Maintained +S: Orphan INFINIBAND SUBSYSTEM P: Roland Dreier @@ -2111,6 +2110,14 @@ L: irda-users@lists.sourceforge.net (subscribers-only) W: http://irda.sourceforge.net/ S: Maintained +ISCSI +P: Mike Christie +M: michaelc@cs.wisc.edu +L: open-iscsi@googlegroups.com +W: www.open-iscsi.org +T: git kernel.org:/pub/scm/linux/kernel/mnc/linux-2.6-iscsi.git +S: Maintained + ISAPNP P: Jaroslav Kysela M: perex@perex.cz @@ -2166,7 +2173,7 @@ S: Maintained KDUMP P: Vivek Goyal -M: vgoyal@in.ibm.com +M: vgoyal@redhat.com P: Haren Myneni M: hbabu@us.ibm.com L: kexec@lists.infradead.org @@ -2444,7 +2451,7 @@ M68K ON APPLE MACINTOSH P: Joshua Thompson M: funaho@jurai.org W: http://www.mac.linux-m68k.org/ -L: linux-mac68k@mac.linux-m68k.org +L: linux-m68k@lists.linux-m68k.org S: Maintained M68K ON HP9000/300 @@ -3452,15 +3459,10 @@ L: lm-sensors@lm-sensors.org S: Maintained SOFTMAC LAYER (IEEE 802.11) -P: Johannes Berg -M: johannes@sipsolutions.net -P: Joe Jezak -M: josejx@gentoo.org P: Daniel Drake M: dsd@gentoo.org -W: http://softmac.sipsolutions.net/ L: linux-wireless@vger.kernel.org -S: Maintained +S: Obsolete SOFTWARE RAID (Multiple Disks) SUPPORT P: Ingo Molnar @@ -3639,18 +3641,12 @@ M: laredo@gnu.org W: http://www.stradis.com/ S: Maintained -SUPERH (sh) -P: Paul Mundt -M: lethal@linux-sh.org -L: linuxsh-dev@lists.sourceforge.net (subscribers-only) -W: http://www.linux-sh.org -S: Maintained - -SUPERH64 (sh64) +SUPERH P: Paul Mundt M: lethal@linux-sh.org -L: linuxsh-shmedia-dev@lists.sourceforge.net +L: linux-sh@vger.kernel.org W: http://www.linux-sh.org +T: git kernel.org:/pub/scm/linux/kernel/git/lethal/sh-2.6.git S: Maintained SUN3/3X @@ -3736,7 +3732,7 @@ S: Maintained TLAN NETWORK DRIVER P: Samuel Chessman M: chessman@tux.org -L: tlan-devel@lists.sourceforge.net +L: tlan-devel@lists.sourceforge.net (subscribers-only) W: http://sourceforge.net/projects/tlan/ S: Maintained @@ -3821,22 +3817,20 @@ S: Maintained USB ACM DRIVER P: Oliver Neukum M: oliver@neukum.name -L: linux-usb-users@lists.sourceforge.net -L: linux-usb-devel@lists.sourceforge.net +L: linux-usb@vger.kernel.org S: Maintained USB BLOCK DRIVER (UB ub) P: Pete Zaitcev M: zaitcev@redhat.com L: linux-kernel@vger.kernel.org -L: linux-usb-devel@lists.sourceforge.net +L: linux-usb@vger.kernel.org S: Supported USB CDC ETHERNET DRIVER P: Greg Kroah-Hartman M: greg@kroah.com -L: linux-usb-users@lists.sourceforge.net -L: linux-usb-devel@lists.sourceforge.net +L: linux-usb@vger.kernel.org S: Maintained W: http://www.kroah.com/linux-usb/ @@ -3850,13 +3844,13 @@ S: Maintained USB EHCI DRIVER P: David Brownell M: dbrownell@users.sourceforge.net -L: linux-usb-devel@lists.sourceforge.net +L: linux-usb@vger.kernel.org S: Odd Fixes USB ET61X[12]51 DRIVER P: Luca Risolia M: luca.risolia@studio.unibo.it -L: linux-usb-devel@lists.sourceforge.net +L: linux-usb@vger.kernel.org L: video4linux-list@redhat.com W: http://www.linux-projects.org S: Maintained @@ -3864,41 +3858,33 @@ S: Maintained USB GADGET/PERIPHERAL SUBSYSTEM P: David Brownell M: dbrownell@users.sourceforge.net -L: linux-usb-devel@lists.sourceforge.net +L: linux-usb@vger.kernel.org W: http://www.linux-usb.org/gadget S: Maintained USB HID/HIDBP DRIVERS (USB KEYBOARDS, MICE, REMOTE CONTROLS, ...) P: Jiri Kosina M: jkosina@suse.cz -L: linux-usb-devel@lists.sourceforge.net +L: linux-usb@vger.kernel.org T: git kernel.org:/pub/scm/linux/kernel/git/jikos/hid.git S: Maintained -USB HUB DRIVER -P: Johannes Erdfelt -M: johannes@erdfelt.com -L: linux-usb-users@lists.sourceforge.net -L: linux-usb-devel@lists.sourceforge.net -S: Maintained - USB ISP116X DRIVER P: Olav Kongas M: ok@artecdesign.ee -L: linux-usb-devel@lists.sourceforge.net +L: linux-usb@vger.kernel.org S: Maintained USB KAWASAKI LSI DRIVER P: Oliver Neukum M: oliver@neukum.name -L: linux-usb-users@lists.sourceforge.net -L: linux-usb-devel@lists.sourceforge.net +L: linux-usb@vger.kernel.org S: Maintained USB MASS STORAGE DRIVER P: Matthew Dharm M: mdharm-usb@one-eyed-alien.net -L: linux-usb-users@lists.sourceforge.net +L: linux-usb@vger.kernel.org L: usb-storage@lists.one-eyed-alien.net S: Maintained W: http://www.one-eyed-alien.net/~mdharm/linux-usb/ @@ -3906,28 +3892,26 @@ W: http://www.one-eyed-alien.net/~mdharm/linux-usb/ USB OHCI DRIVER P: David Brownell M: dbrownell@users.sourceforge.net -L: linux-usb-users@lists.sourceforge.net -L: linux-usb-devel@lists.sourceforge.net +L: linux-usb@vger.kernel.org S: Odd Fixes USB OPTION-CARD DRIVER P: Matthias Urlichs M: smurf@smurf.noris.de -L: linux-usb-devel@lists.sourceforge.net +L: linux-usb@vger.kernel.org S: Maintained USB OV511 DRIVER P: Mark McClelland M: mmcclell@bigfoot.com -L: linux-usb-users@lists.sourceforge.net -L: linux-usb-devel@lists.sourceforge.net +L: linux-usb@vger.kernel.org W: http://alpha.dyndns.org/ov511/ S: Maintained USB PEGASUS DRIVER P: Petko Manolov M: petkan@users.sourceforge.net -L: linux-usb-devel@lists.sourceforge.net +L: linux-usb@vger.kernel.org L: netdev@vger.kernel.org W: http://pegasus2.sourceforge.net/ S: Maintained @@ -3935,14 +3919,13 @@ S: Maintained USB PRINTER DRIVER (usblp) P: Pete Zaitcev M: zaitcev@redhat.com -L: linux-usb-users@lists.sourceforge.net -L: linux-usb-devel@lists.sourceforge.net +L: linux-usb@vger.kernel.org S: Supported USB RTL8150 DRIVER P: Petko Manolov M: petkan@users.sourceforge.net -L: linux-usb-devel@lists.sourceforge.net +L: linux-usb@vger.kernel.org L: netdev@vger.kernel.org W: http://pegasus2.sourceforge.net/ S: Maintained @@ -3950,8 +3933,7 @@ S: Maintained USB SE401 DRIVER P: Jeroen Vreeken M: pe1rxq@amsat.org -L: linux-usb-users@lists.sourceforge.net -L: linux-usb-devel@lists.sourceforge.net +L: linux-usb@vger.kernel.org W: http://www.chello.nl/~j.vreeken/se401/ S: Maintained @@ -3965,72 +3947,59 @@ USB SERIAL DIGI ACCELEPORT DRIVER P: Peter Berger and Al Borchers M: pberger@brimson.com M: alborchers@steinerpoint.com -L: linux-usb-users@lists.sourceforge.net -L: linux-usb-devel@lists.sourceforge.net +L: linux-usb@vger.kernel.org S: Maintained USB SERIAL DRIVER P: Greg Kroah-Hartman M: gregkh@suse.de -L: linux-usb-users@lists.sourceforge.net -L: linux-usb-devel@lists.sourceforge.net +L: linux-usb@vger.kernel.org S: Supported USB SERIAL BELKIN F5U103 DRIVER P: William Greathouse M: wgreathouse@smva.com -L: linux-usb-users@lists.sourceforge.net -L: linux-usb-devel@lists.sourceforge.net +L: linux-usb@vger.kernel.org S: Maintained USB SERIAL CYPRESS M8 DRIVER P: Lonnie Mendez M: dignome@gmail.com -L: linux-usb-users@lists.sourceforge.net -L: linux-usb-devel@lists.sourceforge.net +L: linux-usb@vger.kernel.org S: Maintained W: http://geocities.com/i0xox0i W: http://firstlight.net/cvs -USB SERIAL CYBERJACK PINPAD/E-COM DRIVER -L: linux-usb-users@lists.sourceforge.net -L: linux-usb-devel@lists.sourceforge.net -S: Maintained - USB AUERSWALD DRIVER P: Wolfgang Muees M: wolfgang@iksw-muees.de -L: linux-usb-users@lists.sourceforge.net -L: linux-usb-devel@lists.sourceforge.net +L: linux-usb@vger.kernel.org S: Maintained USB SERIAL EMPEG EMPEG-CAR MARK I/II DRIVER P: Gary Brubaker M: xavyer@ix.netcom.com -L: linux-usb-users@lists.sourceforge.net -L: linux-usb-devel@lists.sourceforge.net +L: linux-usb@vger.kernel.org S: Maintained USB SERIAL KEYSPAN DRIVER P: Greg Kroah-Hartman M: greg@kroah.com -L: linux-usb-users@lists.sourceforge.net -L: linux-usb-devel@lists.sourceforge.net +L: linux-usb@vger.kernel.org W: http://www.kroah.com/linux/ S: Maintained USB SERIAL WHITEHEAT DRIVER P: Support Department M: support@connecttech.com -L: linux-usb-users@lists.sourceforge.net -L: linux-usb-devel@lists.sourceforge.net +L: linux-usb@vger.kernel.org W: http://www.connecttech.com S: Supported USB SN9C1xx DRIVER P: Luca Risolia M: luca.risolia@studio.unibo.it -L: linux-usb-devel@lists.sourceforge.net +L: linux-usb@vger.kernel.org L: video4linux-list@redhat.com W: http://www.linux-projects.org S: Maintained @@ -4038,8 +4007,7 @@ S: Maintained USB SUBSYSTEM P: Greg Kroah-Hartman M: gregkh@suse.de -L: linux-usb-users@lists.sourceforge.net -L: linux-usb-devel@lists.sourceforge.net +L: linux-usb@vger.kernel.org W: http://www.linux-usb.org T: quilt kernel.org/pub/linux/kernel/people/gregkh/gregkh-2.6/ S: Supported @@ -4047,8 +4015,7 @@ S: Supported USB UHCI DRIVER P: Alan Stern M: stern@rowland.harvard.edu -L: linux-usb-users@lists.sourceforge.net -L: linux-usb-devel@lists.sourceforge.net +L: linux-usb@vger.kernel.org S: Maintained USB "USBNET" DRIVER FRAMEWORK @@ -4061,7 +4028,7 @@ S: Maintained USB W996[87]CF DRIVER P: Luca Risolia M: luca.risolia@studio.unibo.it -L: linux-usb-devel@lists.sourceforge.net +L: linux-usb@vger.kernel.org L: video4linux-list@redhat.com W: http://www.linux-projects.org S: Maintained @@ -4069,7 +4036,7 @@ S: Maintained USB ZC0301 DRIVER P: Luca Risolia M: luca.risolia@studio.unibo.it -L: linux-usb-devel@lists.sourceforge.net +L: linux-usb@vger.kernel.org L: video4linux-list@redhat.com W: http://www.linux-projects.org S: Maintained @@ -4077,15 +4044,14 @@ S: Maintained USB ZD1201 DRIVER P: Jeroen Vreeken M: pe1rxq@amsat.org -L: linux-usb-users@lists.sourceforge.net -L: linux-usb-devel@lists.sourceforge.net +L: linux-usb@vger.kernel.org W: http://linux-lc100020.sourceforge.net S: Maintained USB ZR364XX DRIVER P: Antoine Jacquet M: royale@zerezo.com -L: linux-usb-devel@lists.sourceforge.net +L: linux-usb@vger.kernel.org L: video4linux-list@redhat.com W: http://royale.zerezo.com/zr364xx/ S: Maintained @@ -1,7 +1,7 @@ VERSION = 2 PATCHLEVEL = 6 SUBLEVEL = 24 -EXTRAVERSION = -rc2 +EXTRAVERSION = -rc3 NAME = Arr Matey! A Hairy Bilge Rat! # *DOCUMENTATION* @@ -197,8 +197,13 @@ CROSS_COMPILE ?= UTS_MACHINE := $(ARCH) SRCARCH := $(ARCH) -# for i386 and x86_64 we use SRCARCH equal to x86 -SRCARCH := $(if $(filter x86_64 i386,$(SRCARCH)),x86,$(SRCARCH)) +# Additional ARCH settings for x86 +ifeq ($(ARCH),i386) + SRCARCH := x86 +endif +ifeq ($(ARCH),x86_64) + SRCARCH := x86 +endif KCONFIG_CONFIG ?= .config @@ -1327,12 +1332,7 @@ else ALLINCLUDE_ARCHS := $(ALLSOURCE_ARCHS) endif -# Take care of arch/x86 -ifeq ($(ARCH), $(SRCARCH)) -ALLSOURCE_ARCHS := $(ARCH) -else -ALLSOURCE_ARCHS := $(ARCH) $(SRCARCH) -endif +ALLSOURCE_ARCHS := $(SRCARCH) define find-sources ( for arch in $(ALLSOURCE_ARCHS) ; do \ diff --git a/arch/alpha/kernel/pci-noop.c b/arch/alpha/kernel/pci-noop.c index 174b729..468b76c 100644 --- a/arch/alpha/kernel/pci-noop.c +++ b/arch/alpha/kernel/pci-noop.c @@ -12,6 +12,7 @@ #include <linux/errno.h> #include <linux/sched.h> #include <linux/dma-mapping.h> +#include <linux/scatterlist.h> #include "proto.h" @@ -172,18 +173,19 @@ dma_alloc_coherent(struct device *dev, size_t size, EXPORT_SYMBOL(dma_alloc_coherent); int -dma_map_sg(struct device *dev, struct scatterlist *sg, int nents, +dma_map_sg(struct device *dev, struct scatterlist *sgl, int nents, enum dma_data_direction direction) { int i; + struct scatterlist *sg; - for (i = 0; i < nents; i++ ) { + for_each_sg(sgl, sg, nents, i) { void *va; - BUG_ON(!sg[i].page); - va = page_address(sg[i].page) + sg[i].offset; - sg_dma_address(sg + i) = (dma_addr_t)virt_to_bus(va); - sg_dma_len(sg + i) = sg[i].length; + BUG_ON(!sg_page(sg)); + va = sg_virt(sg); + sg_dma_address(sg) = (dma_addr_t)virt_to_bus(va); + sg_dma_len(sg) = sg->length; } return nents; diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index a0cdaaf..a7e9fea 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -1040,6 +1040,8 @@ source "drivers/power/Kconfig" source "drivers/hwmon/Kconfig" +source "drivers/watchdog/Kconfig" + source "drivers/ssb/Kconfig" #source "drivers/l3/Kconfig" diff --git a/arch/arm/common/uengine.c b/arch/arm/common/uengine.c index 95c8508..117cab3 100644 --- a/arch/arm/common/uengine.c +++ b/arch/arm/common/uengine.c @@ -374,8 +374,8 @@ static int set_initial_registers(int uengine, struct ixp2000_uengine_code *c) u8 *ucode; int i; - gpr_a = kmalloc(128 * sizeof(u32), GFP_KERNEL); - gpr_b = kmalloc(128 * sizeof(u32), GFP_KERNEL); + gpr_a = kzalloc(128 * sizeof(u32), GFP_KERNEL); + gpr_b = kzalloc(128 * sizeof(u32), GFP_KERNEL); ucode = kmalloc(513 * 5, GFP_KERNEL); if (gpr_a == NULL || gpr_b == NULL || ucode == NULL) { kfree(ucode); @@ -388,8 +388,6 @@ static int set_initial_registers(int uengine, struct ixp2000_uengine_code *c) if (c->uengine_parameters & IXP2000_UENGINE_4_CONTEXTS) per_ctx_regs = 32; - memset(gpr_a, 0, sizeof(gpr_a)); - memset(gpr_b, 0, sizeof(gpr_b)); for (i = 0; i < 256; i++) { struct ixp2000_reg_value *r = c->initial_reg_values + i; u32 *bank; diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S index d645897..29dec08 100644 --- a/arch/arm/kernel/entry-armv.S +++ b/arch/arm/kernel/entry-armv.S @@ -339,16 +339,6 @@ __pabt_svc: str r1, [sp] @ save the "real" r0 copied @ from the exception stack -#if __LINUX_ARM_ARCH__ < 6 && !defined(CONFIG_NEEDS_SYSCALL_FOR_CMPXCHG) -#ifndef CONFIG_MMU -#warning "NPTL on non MMU needs fixing" -#else - @ make sure our user space atomic helper is aborted - cmp r2, #TASK_SIZE - bichs r3, r3, #PSR_Z_BIT -#endif -#endif - @ @ We are now ready to fill in the remaining blanks on the stack: @ @@ -372,9 +362,25 @@ __pabt_svc: zero_fp .endm + .macro kuser_cmpxchg_check +#if __LINUX_ARM_ARCH__ < 6 && !defined(CONFIG_NEEDS_SYSCALL_FOR_CMPXCHG) +#ifndef CONFIG_MMU +#warning "NPTL on non MMU needs fixing" +#else + @ Make sure our user space atomic helper is restarted + @ if it was interrupted in a critical region. Here we + @ perform a quick test inline since it should be false + @ 99.9999% of the time. The rest is done out of line. + cmp r2, #TASK_SIZE + blhs kuser_cmpxchg_fixup +#endif +#endif + .endm + .align 5 __dabt_usr: usr_entry + kuser_cmpxchg_check @ @ Call the processor-specific abort handler: @@ -404,6 +410,7 @@ __dabt_usr: .align 5 __irq_usr: usr_entry + kuser_cmpxchg_check #ifdef CONFIG_TRACE_IRQFLAGS bl trace_hardirqs_off @@ -446,9 +453,9 @@ __und_usr: @ @ r0 - instruction @ -1: ldrt r0, [r4] adr r9, ret_from_exception adr lr, __und_usr_unknown +1: ldrt r0, [r4] @ @ fallthrough to call_fpe @ @@ -669,7 +676,7 @@ __kuser_helper_start: * * Clobbered: * - * the Z flag might be lost + * none * * Definition and user space usage example: * @@ -730,9 +737,6 @@ __kuser_memory_barrier: @ 0xffff0fa0 * * - This routine already includes memory barriers as needed. * - * - A failure might be transient, i.e. it is possible, although unlikely, - * that "failure" be returned even if *ptr == oldval. - * * For example, a user space atomic_add implementation could look like this: * * #define atomic_add(ptr, val) \ @@ -769,46 +773,62 @@ __kuser_cmpxchg: @ 0xffff0fc0 #elif __LINUX_ARM_ARCH__ < 6 +#ifdef CONFIG_MMU + /* - * Theory of operation: - * - * We set the Z flag before loading oldval. If ever an exception - * occurs we can not be sure the loaded value will still be the same - * when the exception returns, therefore the user exception handler - * will clear the Z flag whenever the interrupted user code was - * actually from the kernel address space (see the usr_entry macro). - * - * The post-increment on the str is used to prevent a race with an - * exception happening just after the str instruction which would - * clear the Z flag although the exchange was done. + * The only thing that can break atomicity in this cmpxchg + * implementation is either an IRQ or a data abort exception + * causing another process/thread to be scheduled in the middle + * of the critical sequence. To prevent this, code is added to + * the IRQ and data abort exception handlers to set the pc back + * to the beginning of the critical section if it is found to be + * within that critical section (see kuser_cmpxchg_fixup). */ -#ifdef CONFIG_MMU - teq ip, ip @ set Z flag - ldr ip, [r2] @ load current val - add r3, r2, #1 @ prepare store ptr - teqeq ip, r0 @ compare with oldval if still allowed - streq r1, [r3, #-1]! @ store newval if still allowed - subs r0, r2, r3 @ if r2 == r3 the str occured +1: ldr r3, [r2] @ load current val + subs r3, r3, r0 @ compare with oldval +2: streq r1, [r2] @ store newval if eq + rsbs r0, r3, #0 @ set return val and C flag + usr_ret lr + + .text +kuser_cmpxchg_fixup: + @ Called from kuser_cmpxchg_check macro. + @ r2 = address of interrupted insn (must be preserved). + @ sp = saved regs. r7 and r8 are clobbered. + @ 1b = first critical insn, 2b = last critical insn. + @ If r2 >= 1b and r2 <= 2b then saved pc_usr is set to 1b. + mov r7, #0xffff0fff + sub r7, r7, #(0xffff0fff - (0xffff0fc0 + (1b - __kuser_cmpxchg))) + subs r8, r2, r7 + rsbcss r8, r8, #(2b - 1b) + strcs r7, [sp, #S_PC] + mov pc, lr + .previous + #else #warning "NPTL on non MMU needs fixing" mov r0, #-1 adds r0, r0, #0 -#endif usr_ret lr +#endif #else #ifdef CONFIG_SMP mcr p15, 0, r0, c7, c10, 5 @ dmb #endif - ldrex r3, [r2] +1: ldrex r3, [r2] subs r3, r3, r0 strexeq r3, r1, [r2] + teqeq r3, #1 + beq 1b rsbs r0, r3, #0 + /* beware -- each __kuser slot must be 8 instructions max */ #ifdef CONFIG_SMP - mcr p15, 0, r0, c7, c10, 5 @ dmb -#endif + b __kuser_memory_barrier +#else usr_ret lr +#endif #endif @@ -829,7 +849,7 @@ __kuser_cmpxchg: @ 0xffff0fc0 * * Clobbered: * - * the Z flag might be lost + * none * * Definition and user space usage example: * diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c index 4764bd9..c34db4e 100644 --- a/arch/arm/kernel/traps.c +++ b/arch/arm/kernel/traps.c @@ -327,7 +327,7 @@ asmlinkage void __exception do_undefinstr(struct pt_regs *regs) if ((instr & hook->instr_mask) == hook->instr_val && (regs->ARM_cpsr & hook->cpsr_mask) == hook->cpsr_val) { if (hook->fn(regs, instr) == 0) { - spin_unlock_irq(&undef_lock); + spin_unlock_irqrestore(&undef_lock, flags); return; } } @@ -509,7 +509,7 @@ asmlinkage int arm_syscall(int no, struct pt_regs *regs) * existence. Don't ever use this from user code. */ case 0xfff0: - { + for (;;) { extern void do_DataAbort(unsigned long addr, unsigned int fsr, struct pt_regs *regs); unsigned long val; @@ -545,7 +545,6 @@ asmlinkage int arm_syscall(int no, struct pt_regs *regs) up_read(&mm->mmap_sem); /* simulate a write access fault */ do_DataAbort(addr, 15 + (1 << 11), regs); - return -1; } #endif diff --git a/arch/arm/mach-at91/at91rm9200_devices.c b/arch/arm/mach-at91/at91rm9200_devices.c index 0417c16..9296833 100644 --- a/arch/arm/mach-at91/at91rm9200_devices.c +++ b/arch/arm/mach-at91/at91rm9200_devices.c @@ -14,6 +14,7 @@ #include <asm/mach/map.h> #include <linux/platform_device.h> +#include <linux/i2c-gpio.h> #include <asm/arch/board.h> #include <asm/arch/gpio.h> @@ -435,7 +436,40 @@ void __init at91_add_device_nand(struct at91_nand_data *data) {} * TWI (i2c) * -------------------------------------------------------------------- */ -#if defined(CONFIG_I2C_AT91) || defined(CONFIG_I2C_AT91_MODULE) +/* + * Prefer the GPIO code since the TWI controller isn't robust + * (gets overruns and underruns under load) and can only issue + * repeated STARTs in one scenario (the driver doesn't yet handle them). + */ +#if defined(CONFIG_I2C_GPIO) || defined(CONFIG_I2C_GPIO_MODULE) + +static struct i2c_gpio_platform_data pdata = { + .sda_pin = AT91_PIN_PA25, + .sda_is_open_drain = 1, + .scl_pin = AT91_PIN_PA26, + .scl_is_open_drain = 1, + .udelay = 2, /* ~100 kHz */ +}; + +static struct platform_device at91rm9200_twi_device = { + .name = "i2c-gpio", + .id = -1, + .dev.platform_data = &pdata, +}; + +void __init at91_add_device_i2c(struct i2c_board_info *devices, int nr_devices) +{ + at91_set_GPIO_periph(AT91_PIN_PA25, 1); /* TWD (SDA) */ + at91_set_multi_drive(AT91_PIN_PA25, 1); + + at91_set_GPIO_periph(AT91_PIN_PA26, 1); /* TWCK (SCL) */ + at91_set_multi_drive(AT91_PIN_PA26, 1); + + i2c_register_board_info(0, devices, nr_devices); + platform_device_register(&at91rm9200_twi_device); +} + +#elif defined(CONFIG_I2C_AT91) || defined(CONFIG_I2C_AT91_MODULE) static struct resource twi_resources[] = { [0] = { @@ -457,7 +491,7 @@ static struct platform_device at91rm9200_twi_device = { .num_resources = ARRAY_SIZE(twi_resources), }; -void __init at91_add_device_i2c(void) +void __init at91_add_device_i2c(struct i2c_board_info *devices, int nr_devices) { /* pins used for TWI interface */ at91_set_A_periph(AT91_PIN_PA25, 0); /* TWD */ @@ -466,10 +500,11 @@ void __init at91_add_device_i2c(void) at91_set_A_periph(AT91_PIN_PA26, 0); /* TWCK */ at91_set_multi_drive(AT91_PIN_PA26, 1); + i2c_register_board_info(0, devices, nr_devices); platform_device_register(&at91rm9200_twi_device); } #else -void __init at91_add_device_i2c(void) {} +void __init at91_add_device_i2c(struct i2c_board_info *devices, int nr_devices) {} #endif diff --git a/arch/arm/mach-at91/at91sam9260_devices.c b/arch/arm/mach-at91/at91sam9260_devices.c index ffd3154..3091bf4 100644 --- a/arch/arm/mach-at91/at91sam9260_devices.c +++ b/arch/arm/mach-at91/at91sam9260_devices.c @@ -13,6 +13,7 @@ #include <asm/mach/map.h> #include <linux/platform_device.h> +#include <linux/i2c-gpio.h> #include <asm/arch/board.h> #include <asm/arch/gpio.h> @@ -352,7 +353,41 @@ void __init at91_add_device_nand(struct at91_nand_data *data) {} * TWI (i2c) * -------------------------------------------------------------------- */ -#if defined(CONFIG_I2C_AT91) || defined(CONFIG_I2C_AT91_MODULE) +/* + * Prefer the GPIO code since the TWI controller isn't robust + * (gets overruns and underruns under load) and can only issue + * repeated STARTs in one scenario (the driver doesn't yet handle them). + */ + +#if defined(CONFIG_I2C_GPIO) || defined(CONFIG_I2C_GPIO_MODULE) + +static struct i2c_gpio_platform_data pdata = { + .sda_pin = AT91_PIN_PA23, + .sda_is_open_drain = 1, + .scl_pin = AT91_PIN_PA24, + .scl_is_open_drain = 1, + .udelay = 2, /* ~100 kHz */ +}; + +static struct platform_device at91sam9260_twi_device = { + .name = "i2c-gpio", + .id = -1, + .dev.platform_data = &pdata, +}; + +void __init at91_add_device_i2c(struct i2c_board_info *devices, int nr_devices) +{ + at91_set_GPIO_periph(AT91_PIN_PA23, 1); /* TWD (SDA) */ + at91_set_multi_drive(AT91_PIN_PA23, 1); + + at91_set_GPIO_periph(AT91_PIN_PA24, 1); /* TWCK (SCL) */ + at91_set_multi_drive(AT91_PIN_PA24, 1); + + i2c_register_board_info(0, devices, nr_devices); + platform_device_register(&at91sam9260_twi_device); +} + +#elif defined(CONFIG_I2C_AT91) || defined(CONFIG_I2C_AT91_MODULE) static struct resource twi_resources[] = { [0] = { @@ -374,7 +409,7 @@ static struct platform_device at91sam9260_twi_device = { .num_resources = ARRAY_SIZE(twi_resources), }; -void __init at91_add_device_i2c(void) +void __init at91_add_device_i2c(struct i2c_board_info *devices, int nr_devices) { /* pins used for TWI interface */ at91_set_A_periph(AT91_PIN_PA23, 0); /* TWD */ @@ -383,10 +418,11 @@ void __init at91_add_device_i2c(void) at91_set_A_periph(AT91_PIN_PA24, 0); /* TWCK */ at91_set_multi_drive(AT91_PIN_PA24, 1); + i2c_register_board_info(0, devices, nr_devices); platform_device_register(&at91sam9260_twi_device); } #else -void __init at91_add_device_i2c(void) {} +void __init at91_add_device_i2c(struct i2c_board_info *devices, int nr_devices) {} #endif diff --git a/arch/arm/mach-at91/at91sam9261_devices.c b/arch/arm/mach-at91/at91sam9261_devices.c index 3576595..64979a9 100644 --- a/arch/arm/mach-at91/at91sam9261_devices.c +++ b/arch/arm/mach-at91/at91sam9261_devices.c @@ -14,7 +14,9 @@ #include <asm/mach/map.h> #include <linux/platform_device.h> +#include <linux/i2c-gpio.h> +#include <linux/fb.h> #include <video/atmel_lcdc.h> #include <asm/arch/board.h> @@ -275,7 +277,40 @@ void __init at91_add_device_nand(struct at91_nand_data *data) {} * TWI (i2c) * -------------------------------------------------------------------- */ -#if defined(CONFIG_I2C_AT91) || defined(CONFIG_I2C_AT91_MODULE) +/* + * Prefer the GPIO code since the TWI controller isn't robust + * (gets overruns and underruns under load) and can only issue + * repeated STARTs in one scenario (the driver doesn't yet handle them). + */ +#if defined(CONFIG_I2C_GPIO) || defined(CONFIG_I2C_GPIO_MODULE) + +static struct i2c_gpio_platform_data pdata = { + .sda_pin = AT91_PIN_PA7, + .sda_is_open_drain = 1, + .scl_pin = AT91_PIN_PA8, + .scl_is_open_drain = 1, + .udelay = 2, /* ~100 kHz */ +}; + +static struct platform_device at91sam9261_twi_device = { + .name = "i2c-gpio", + .id = -1, + .dev.platform_data = &pdata, +}; + +void __init at91_add_device_i2c(struct i2c_board_info *devices, int nr_devices) +{ + at91_set_GPIO_periph(AT91_PIN_PA7, 1); /* TWD (SDA) */ + at91_set_multi_drive(AT91_PIN_PA7, 1); + + at91_set_GPIO_periph(AT91_PIN_PA8, 1); /* TWCK (SCL) */ + at91_set_multi_drive(AT91_PIN_PA8, 1); + + i2c_register_board_info(0, devices, nr_devices); + platform_device_register(&at91sam9261_twi_device); +} + +#elif defined(CONFIG_I2C_AT91) || defined(CONFIG_I2C_AT91_MODULE) static struct resource twi_resources[] = { [0] = { @@ -297,7 +332,7 @@ static struct platform_device at91sam9261_twi_device = { .num_resources = ARRAY_SIZE(twi_resources), }; -void __init at91_add_device_i2c(void) +void __init at91_add_device_i2c(struct i2c_board_info *devices, int nr_devices) { /* pins used for TWI interface */ at91_set_A_periph(AT91_PIN_PA7, 0); /* TWD */ @@ -306,10 +341,11 @@ void __init at91_add_device_i2c(void) at91_set_A_periph(AT91_PIN_PA8, 0); /* TWCK */ at91_set_multi_drive(AT91_PIN_PA8, 1); + i2c_register_board_info(0, devices, nr_devices); platform_device_register(&at91sam9261_twi_device); } #else -void __init at91_add_device_i2c(void) {} +void __init at91_add_device_i2c(struct i2c_board_info *devices, int nr_devices) {} #endif diff --git a/arch/arm/mach-at91/at91sam9263_devices.c b/arch/arm/mach-at91/at91sam9263_devices.c index f924bd5..ac329a9 100644 --- a/arch/arm/mach-at91/at91sam9263_devices.c +++ b/arch/arm/mach-at91/at91sam9263_devices.c @@ -13,7 +13,9 @@ #include <asm/mach/map.h> #include <linux/platform_device.h> +#include <linux/i2c-gpio.h> +#include <linux/fb.h> #include <video/atmel_lcdc.h> #include <asm/arch/board.h> @@ -421,7 +423,40 @@ void __init at91_add_device_nand(struct at91_nand_data *data) {} * TWI (i2c) * -------------------------------------------------------------------- */ -#if defined(CONFIG_I2C_AT91) || defined(CONFIG_I2C_AT91_MODULE) +/* + * Prefer the GPIO code since the TWI controller isn't robust + * (gets overruns and underruns under load) and can only issue + * repeated STARTs in one scenario (the driver doesn't yet handle them). + */ +#if defined(CONFIG_I2C_GPIO) || defined(CONFIG_I2C_GPIO_MODULE) + +static struct i2c_gpio_platform_data pdata = { + .sda_pin = AT91_PIN_PB4, + .sda_is_open_drain = 1, + .scl_pin = AT91_PIN_PB5, + .scl_is_open_drain = 1, + .udelay = 2, /* ~100 kHz */ +}; + +static struct platform_device at91sam9263_twi_device = { + .name = "i2c-gpio", + .id = -1, + .dev.platform_data = &pdata, +}; + +void __init at91_add_device_i2c(struct i2c_board_info *devices, int nr_devices) +{ + at91_set_GPIO_periph(AT91_PIN_PB4, 1); /* TWD (SDA) */ + at91_set_multi_drive(AT91_PIN_PB4, 1); + + at91_set_GPIO_periph(AT91_PIN_PB5, 1); /* TWCK (SCL) */ + at91_set_multi_drive(AT91_PIN_PB5, 1); + + i2c_register_board_info(0, devices, nr_devices); + platform_device_register(&at91sam9263_twi_device); +} + +#elif defined(CONFIG_I2C_AT91) || defined(CONFIG_I2C_AT91_MODULE) static struct resource twi_resources[] = { [0] = { @@ -443,7 +478,7 @@ static struct platform_device at91sam9263_twi_device = { .num_resources = ARRAY_SIZE(twi_resources), }; -void __init at91_add_device_i2c(void) +void __init at91_add_device_i2c(struct i2c_board_info *devices, int nr_devices) { /* pins used for TWI interface */ at91_set_A_periph(AT91_PIN_PB4, 0); /* TWD */ @@ -452,10 +487,11 @@ void __init at91_add_device_i2c(void) at91_set_A_periph(AT91_PIN_PB5, 0); /* TWCK */ at91_set_multi_drive(AT91_PIN_PB5, 1); + i2c_register_board_info(0, devices, nr_devices); platform_device_register(&at91sam9263_twi_device); } #else -void __init at91_add_device_i2c(void) {} +void __init at91_add_device_i2c(struct i2c_board_info *devices, int nr_devices) {} #endif diff --git a/arch/arm/mach-at91/at91sam9rl_devices.c b/arch/arm/mach-at91/at91sam9rl_devices.c index cd7532b..2bd60a3 100644 --- a/arch/arm/mach-at91/at91sam9rl_devices.c +++ b/arch/arm/mach-at91/at91sam9rl_devices.c @@ -10,8 +10,9 @@ #include <asm/mach/map.h> #include <linux/platform_device.h> -#include <linux/fb.h> +#include <linux/i2c-gpio.h> +#include <linux/fb.h> #include <video/atmel_lcdc.h> #include <asm/arch/board.h> @@ -169,7 +170,40 @@ void __init at91_add_device_nand(struct at91_nand_data *data) {} * TWI (i2c) * -------------------------------------------------------------------- */ -#if defined(CONFIG_I2C_AT91) || defined(CONFIG_I2C_AT91_MODULE) +/* + * Prefer the GPIO code since the TWI controller isn't robust + * (gets overruns and underruns under load) and can only issue + * repeated STARTs in one scenario (the driver doesn't yet handle them). + */ +#if defined(CONFIG_I2C_GPIO) || defined(CONFIG_I2C_GPIO_MODULE) + +static struct i2c_gpio_platform_data pdata = { + .sda_pin = AT91_PIN_PA23, + .sda_is_open_drain = 1, + .scl_pin = AT91_PIN_PA24, + .scl_is_open_drain = 1, + .udelay = 2, /* ~100 kHz */ +}; + +static struct platform_device at91sam9rl_twi_device = { + .name = "i2c-gpio", + .id = -1, + .dev.platform_data = &pdata, +}; + +void __init at91_add_device_i2c(struct i2c_board_info *devices, int nr_devices) +{ + at91_set_GPIO_periph(AT91_PIN_PA23, 1); /* TWD (SDA) */ + at91_set_multi_drive(AT91_PIN_PA23, 1); + + at91_set_GPIO_periph(AT91_PIN_PA24, 1); /* TWCK (SCL) */ + at91_set_multi_drive(AT91_PIN_PA24, 1); + + i2c_register_board_info(0, devices, nr_devices); + platform_device_register(&at91sam9rl_twi_device); +} + +#elif defined(CONFIG_I2C_AT91) || defined(CONFIG_I2C_AT91_MODULE) static struct resource twi_resources[] = { [0] = { @@ -191,7 +225,7 @@ static struct platform_device at91sam9rl_twi_device = { .num_resources = ARRAY_SIZE(twi_resources), }; -void __init at91_add_device_i2c(void) +void __init at91_add_device_i2c(struct i2c_board_info *devices, int nr_devices) { /* pins used for TWI interface */ at91_set_A_periph(AT91_PIN_PA23, 0); /* TWD */ @@ -200,10 +234,11 @@ void __init at91_add_device_i2c(void) at91_set_A_periph(AT91_PIN_PA24, 0); /* TWCK */ at91_set_multi_drive(AT91_PIN_PA24, 1); + i2c_register_board_info(0, devices, nr_devices); platform_device_register(&at91sam9rl_twi_device); } #else -void __init at91_add_device_i2c(void) {} +void __init at91_add_device_i2c(struct i2c_board_info *devices, int nr_devices) {} #endif diff --git a/arch/arm/mach-at91/board-carmeva.c b/arch/arm/mach-at91/board-carmeva.c index 76ec856..0f08782 100644 --- a/arch/arm/mach-at91/board-carmeva.c +++ b/arch/arm/mach-at91/board-carmeva.c @@ -128,7 +128,7 @@ static void __init carmeva_board_init(void) /* USB Device */ at91_add_device_udc(&carmeva_udc_data); /* I2C */ - at91_add_device_i2c(); + at91_add_device_i2c(NULL, 0); /* SPI */ at91_add_device_spi(carmeva_spi_devices, ARRAY_SIZE(carmeva_spi_devices)); /* Compact Flash */ diff --git a/arch/arm/mach-at91/board-csb337.c b/arch/arm/mach-at91/board-csb337.c index dde0899..d0aa20c 100644 --- a/arch/arm/mach-at91/board-csb337.c +++ b/arch/arm/mach-at91/board-csb337.c @@ -23,7 +23,6 @@ #include <linux/mm.h> #include <linux/module.h> #include <linux/platform_device.h> -#include <linux/i2c.h> #include <linux/spi/spi.h> #include <linux/mtd/physmap.h> @@ -85,12 +84,12 @@ static struct at91_udc_data __initdata csb337_udc_data = { }; static struct i2c_board_info __initdata csb337_i2c_devices[] = { - { I2C_BOARD_INFO("rtc-ds1307", 0x68), - .type = "ds1307", + { + I2C_BOARD_INFO("rtc-ds1307", 0x68), + .type = "ds1307", }, }; - static struct at91_cf_data __initdata csb337_cf_data = { /* * connector P4 on the CSB 337 mates to @@ -168,9 +167,7 @@ static void __init csb337_board_init(void) /* USB Device */ at91_add_device_udc(&csb337_udc_data); /* I2C */ - at91_add_device_i2c(); - i2c_register_board_info(0, csb337_i2c_devices, - ARRAY_SIZE(csb337_i2c_devices)); + at91_add_device_i2c(csb337_i2c_devices, ARRAY_SIZE(csb337_i2c_devices)); /* Compact Flash */ at91_set_gpio_input(AT91_PIN_PB22, 1); /* IOIS16 */ at91_add_device_cf(&csb337_cf_data); diff --git a/arch/arm/mach-at91/board-csb637.c b/arch/arm/mach-at91/board-csb637.c index 77f04b9..c5c721d 100644 --- a/arch/arm/mach-at91/board-csb637.c +++ b/arch/arm/mach-at91/board-csb637.c @@ -129,7 +129,7 @@ static void __init csb637_board_init(void) /* USB Device */ at91_add_device_udc(&csb637_udc_data); /* I2C */ - at91_add_device_i2c(); + at91_add_device_i2c(NULL, 0); /* SPI */ at91_add_device_spi(NULL, 0); /* NOR flash */ diff --git a/arch/arm/mach-at91/board-dk.c b/arch/arm/mach-at91/board-dk.c index af49789..40c9e43 100644 --- a/arch/arm/mach-at91/board-dk.c +++ b/arch/arm/mach-at91/board-dk.c @@ -124,6 +124,19 @@ static struct spi_board_info dk_spi_devices[] = { #endif }; +static struct i2c_board_info __initdata dk_i2c_devices[] = { + { + I2C_BOARD_INFO("ics1523", 0x26), + }, + { + I2C_BOARD_INFO("x9429", 0x28), + }, + { + I2C_BOARD_INFO("at24c", 0x50), + .type = "24c1024", + } +}; + static struct mtd_partition __initdata dk_nand_partition[] = { { .name = "NAND Partition 1", @@ -185,7 +198,7 @@ static void __init dk_board_init(void) /* Compact Flash */ at91_add_device_cf(&dk_cf_data); /* I2C */ - at91_add_device_i2c(); + at91_add_device_i2c(dk_i2c_devices, ARRAY_SIZE(dk_i2c_devices)); /* SPI */ at91_add_device_spi(dk_spi_devices, ARRAY_SIZE(dk_spi_devices)); #ifdef CONFIG_MTD_AT91_DATAFLASH_CARD diff --git a/arch/arm/mach-at91/board-eb9200.c b/arch/arm/mach-at91/board-eb9200.c index 20458b5..b7b79bb 100644 --- a/arch/arm/mach-at91/board-eb9200.c +++ b/arch/arm/mach-at91/board-eb9200.c @@ -91,6 +91,14 @@ static struct at91_mmc_data __initdata eb9200_mmc_data = { .wire4 = 1, }; +static struct i2c_board_info __initdata eb9200_i2c_devices[] = { + { + I2C_BOARD_INFO("at24c", 0x50), + .type = "24c512", + }, +}; + + static void __init eb9200_board_init(void) { /* Serial */ @@ -102,7 +110,7 @@ static void __init eb9200_board_init(void) /* USB Device */ at91_add_device_udc(&eb9200_udc_data); /* I2C */ - at91_add_device_i2c(); + at91_add_device_i2c(eb9200_i2c_devices, ARRAY_SIZE(eb9200_i2c_devices)); /* Compact Flash */ at91_add_device_cf(&eb9200_cf_data); /* SPI */ diff --git a/arch/arm/mach-at91/board-ek.c b/arch/arm/mach-at91/board-ek.c index 322fdd7..d05b1b2 100644 --- a/arch/arm/mach-at91/board-ek.c +++ b/arch/arm/mach-at91/board-ek.c @@ -145,7 +145,7 @@ static void __init ek_board_init(void) at91_add_device_udc(&ek_udc_data); at91_set_multi_drive(ek_udc_data.pullup_pin, 1); /* pullup_pin is connected to reset */ /* I2C */ - at91_add_device_i2c(); + at91_add_device_i2c(ek_i2c_devices, ARRAY_SIZE(ek_i2c_devices)); /* SPI */ at91_add_device_spi(ek_spi_devices, ARRAY_SIZE(ek_spi_devices)); #ifdef CONFIG_MTD_AT91_DATAFLASH_CARD diff --git a/arch/arm/mach-at91/board-kafa.c b/arch/arm/mach-at91/board-kafa.c index c77d84c..cf1b7b2 100644 --- a/arch/arm/mach-at91/board-kafa.c +++ b/arch/arm/mach-at91/board-kafa.c @@ -92,7 +92,7 @@ static void __init kafa_board_init(void) /* USB Device */ at91_add_device_udc(&kafa_udc_data); /* I2C */ - at91_add_device_i2c(); + at91_add_device_i2c(NULL, 0); /* SPI */ at91_add_device_spi(NULL, 0); } diff --git a/arch/arm/mach-at91/board-kb9202.c b/arch/arm/mach-at91/board-kb9202.c index 7d9b1a2..4b39b9c 100644 --- a/arch/arm/mach-at91/board-kb9202.c +++ b/arch/arm/mach-at91/board-kb9202.c @@ -124,7 +124,7 @@ static void __init kb9202_board_init(void) /* MMC */ at91_add_device_mmc(0, &kb9202_mmc_data); /* I2C */ - at91_add_device_i2c(); + at91_add_device_i2c(NULL, 0); /* SPI */ at91_add_device_spi(NULL, 0); /* NAND */ diff --git a/arch/arm/mach-at91/board-picotux200.c b/arch/arm/mach-at91/board-picotux200.c index 49cfe7a..6acb55c 100644 --- a/arch/arm/mach-at91/board-picotux200.c +++ b/arch/arm/mach-at91/board-picotux200.c @@ -139,7 +139,7 @@ static void __init picotux200_board_init(void) // at91_add_device_udc(&picotux200_udc_data); // at91_set_multi_drive(picotux200_udc_data.pullup_pin, 1); /* pullup_pin is connected to reset */ /* I2C */ - at91_add_device_i2c(); + at91_add_device_i2c(NULL, 0); /* SPI */ // at91_add_device_spi(picotux200_spi_devices, ARRAY_SIZE(picotux200_spi_devices)); #ifdef CONFIG_MTD_AT91_DATAFLASH_CARD diff --git a/arch/arm/mach-at91/board-sam9260ek.c b/arch/arm/mach-at91/board-sam9260ek.c index 65fa532..b343a6c 100644 --- a/arch/arm/mach-at91/board-sam9260ek.c +++ b/arch/arm/mach-at91/board-sam9260ek.c @@ -189,7 +189,7 @@ static void __init ek_board_init(void) /* MMC */ at91_add_device_mmc(0, &ek_mmc_data); /* I2C */ - at91_add_device_i2c(); + at91_add_device_i2c(NULL, 0); } MACHINE_START(AT91SAM9260EK, "Atmel AT91SAM9260-EK") diff --git a/arch/arm/mach-at91/board-sam9261ek.c b/arch/arm/mach-at91/board-sam9261ek.c index 42e172c..550ae59 100644 --- a/arch/arm/mach-at91/board-sam9261ek.c +++ b/arch/arm/mach-at91/board-sam9261ek.c @@ -382,14 +382,14 @@ static struct platform_device ek_button_device = { static void __init ek_add_device_buttons(void) { - at91_set_gpio_input(AT91_PIN_PB27, 0); /* btn0 */ - at91_set_deglitch(AT91_PIN_PB27, 1); - at91_set_gpio_input(AT91_PIN_PB26, 0); /* btn1 */ - at91_set_deglitch(AT91_PIN_PB26, 1); - at91_set_gpio_input(AT91_PIN_PB25, 0); /* btn2 */ - at91_set_deglitch(AT91_PIN_PB25, 1); - at91_set_gpio_input(AT91_PIN_PB24, 0); /* btn3 */ - at91_set_deglitch(AT91_PIN_PB24, 1); + at91_set_gpio_input(AT91_PIN_PA27, 0); /* btn0 */ + at91_set_deglitch(AT91_PIN_PA27, 1); + at91_set_gpio_input(AT91_PIN_PA26, 0); /* btn1 */ + at91_set_deglitch(AT91_PIN_PA26, 1); + at91_set_gpio_input(AT91_PIN_PA25, 0); /* btn2 */ + at91_set_deglitch(AT91_PIN_PA25, 1); + at91_set_gpio_input(AT91_PIN_PA24, 0); /* btn3 */ + at91_set_deglitch(AT91_PIN_PA24, 1); platform_device_register(&ek_button_device); } @@ -406,7 +406,7 @@ static void __init ek_board_init(void) /* USB Device */ at91_add_device_udc(&ek_udc_data); /* I2C */ - at91_add_device_i2c(); + at91_add_device_i2c(NULL, 0); /* NAND */ at91_add_device_nand(&ek_nand_data); /* DM9000 ethernet */ diff --git a/arch/arm/mach-at91/board-sam9263ek.c b/arch/arm/mach-at91/board-sam9263ek.c index 2a1cc73..ab9dcc0 100644 --- a/arch/arm/mach-at91/board-sam9263ek.c +++ b/arch/arm/mach-at91/board-sam9263ek.c @@ -291,7 +291,7 @@ static void __init ek_board_init(void) /* NAND */ at91_add_device_nand(&ek_nand_data); /* I2C */ - at91_add_device_i2c(); + at91_add_device_i2c(NULL, 0); /* LCD Controller */ at91_add_device_lcdc(&ek_lcdc_data); /* AC97 */ diff --git a/arch/arm/mach-at91/board-sam9rlek.c b/arch/arm/mach-at91/board-sam9rlek.c index 9b61320..bc0546d 100644 --- a/arch/arm/mach-at91/board-sam9rlek.c +++ b/arch/arm/mach-at91/board-sam9rlek.c @@ -181,7 +181,7 @@ static void __init ek_board_init(void) /* Serial */ at91_add_device_serial(); /* I2C */ - at91_add_device_i2c(); + at91_add_device_i2c(NULL, 0); /* NAND */ at91_add_device_nand(&ek_nand_data); /* SPI */ diff --git a/arch/arm/mach-at91/clock.c b/arch/arm/mach-at91/clock.c index 848efb2..57c3b64 100644 --- a/arch/arm/mach-at91/clock.c +++ b/arch/arm/mach-at91/clock.c @@ -351,7 +351,7 @@ static void init_programmable_clock(struct clk *clk) pckr = at91_sys_read(AT91_PMC_PCKR(clk->id)); parent = at91_css_to_clk(pckr & AT91_PMC_CSS); clk->parent = parent; - clk->rate_hz = parent->rate_hz / (1 << ((pckr >> 2) & 3)); + clk->rate_hz = parent->rate_hz / (1 << ((pckr & AT91_PMC_PRES) >> 2)); } #endif /* CONFIG_AT91_PROGRAMMABLE_CLOCKS */ @@ -587,8 +587,11 @@ int __init at91_clock_init(unsigned long main_clock) mckr = at91_sys_read(AT91_PMC_MCKR); mck.parent = at91_css_to_clk(mckr & AT91_PMC_CSS); freq = mck.parent->rate_hz; - freq /= (1 << ((mckr >> 2) & 3)); /* prescale */ - mck.rate_hz = freq / (1 + ((mckr >> 8) & 3)); /* mdiv */ + freq /= (1 << ((mckr & AT91_PMC_PRES) >> 2)); /* prescale */ + if (cpu_is_at91rm9200()) + mck.rate_hz = freq / (1 + ((mckr & AT91_PMC_MDIV) >> 8)); /* mdiv */ + else + mck.rate_hz = freq / (1 << ((mckr & AT91_PMC_MDIV) >> 8)); /* mdiv */ /* Register the PMC's standard clocks */ for (i = 0; i < ARRAY_SIZE(standard_pmc_clocks); i++) diff --git a/arch/arm/mach-imx/irq.c b/arch/arm/mach-imx/irq.c index 0791b56..a7465db 100644 --- a/arch/arm/mach-imx/irq.c +++ b/arch/arm/mach-imx/irq.c @@ -43,12 +43,46 @@ * */ -#define INTENNUM_OFF 0x8 -#define INTDISNUM_OFF 0xC +#define INTCNTL_OFF 0x00 +#define NIMASK_OFF 0x04 +#define INTENNUM_OFF 0x08 +#define INTDISNUM_OFF 0x0C +#define INTENABLEH_OFF 0x10 +#define INTENABLEL_OFF 0x14 +#define INTTYPEH_OFF 0x18 +#define INTTYPEL_OFF 0x1C +#define NIPRIORITY_OFF(x) (0x20+4*(7-(x))) +#define NIVECSR_OFF 0x40 +#define FIVECSR_OFF 0x44 +#define INTSRCH_OFF 0x48 +#define INTSRCL_OFF 0x4C +#define INTFRCH_OFF 0x50 +#define INTFRCL_OFF 0x54 +#define NIPNDH_OFF 0x58 +#define NIPNDL_OFF 0x5C +#define FIPNDH_OFF 0x60 +#define FIPNDL_OFF 0x64 #define VA_AITC_BASE IO_ADDRESS(IMX_AITC_BASE) -#define IMX_AITC_INTDISNUM (VA_AITC_BASE + INTDISNUM_OFF) +#define IMX_AITC_INTCNTL (VA_AITC_BASE + INTCNTL_OFF) +#define IMX_AITC_NIMASK (VA_AITC_BASE + NIMASK_OFF) #define IMX_AITC_INTENNUM (VA_AITC_BASE + INTENNUM_OFF) +#define IMX_AITC_INTDISNUM (VA_AITC_BASE + INTDISNUM_OFF) +#define IMX_AITC_INTENABLEH (VA_AITC_BASE + INTENABLEH_OFF) +#define IMX_AITC_INTENABLEL (VA_AITC_BASE + INTENABLEL_OFF) +#define IMX_AITC_INTTYPEH (VA_AITC_BASE + INTTYPEH_OFF) +#define IMX_AITC_INTTYPEL (VA_AITC_BASE + INTTYPEL_OFF) +#define IMX_AITC_NIPRIORITY(x) (VA_AITC_BASE + NIPRIORITY_OFF(x)) +#define IMX_AITC_NIVECSR (VA_AITC_BASE + NIVECSR_OFF) +#define IMX_AITC_FIVECSR (VA_AITC_BASE + FIVECSR_OFF) +#define IMX_AITC_INTSRCH (VA_AITC_BASE + INTSRCH_OFF) +#define IMX_AITC_INTSRCL (VA_AITC_BASE + INTSRCL_OFF) +#define IMX_AITC_INTFRCH (VA_AITC_BASE + INTFRCH_OFF) +#define IMX_AITC_INTFRCL (VA_AITC_BASE + INTFRCL_OFF) +#define IMX_AITC_NIPNDH (VA_AITC_BASE + NIPNDH_OFF) +#define IMX_AITC_NIPNDL (VA_AITC_BASE + NIPNDL_OFF) +#define IMX_AITC_FIPNDH (VA_AITC_BASE + FIPNDH_OFF) +#define IMX_AITC_FIPNDL (VA_AITC_BASE + FIPNDL_OFF) #if 0 #define DEBUG_IRQ(fmt...) printk(fmt) @@ -222,7 +256,12 @@ imx_init_irq(void) DEBUG_IRQ("Initializing imx interrupts\n"); - /* Mask all interrupts initially */ + /* Disable all interrupts initially. */ + /* Do not rely on the bootloader. */ + __raw_writel(0, IMX_AITC_INTENABLEH); + __raw_writel(0, IMX_AITC_INTENABLEL); + + /* Mask all GPIO interrupts as well */ IMR(0) = 0; IMR(1) = 0; IMR(2) = 0; @@ -245,6 +284,6 @@ imx_init_irq(void) set_irq_chained_handler(GPIO_INT_PORTC, imx_gpioc_demux_handler); set_irq_chained_handler(GPIO_INT_PORTD, imx_gpiod_demux_handler); - /* Disable all interrupts initially. */ - /* In IMX this is done in the bootloader. */ + /* Release masking of interrupts according to priority */ + __raw_writel(-1, IMX_AITC_NIMASK); } diff --git a/arch/arm/mach-iop32x/n2100.c b/arch/arm/mach-iop32x/n2100.c index 1873bd8..bc91d6e 100644 --- a/arch/arm/mach-iop32x/n2100.c +++ b/arch/arm/mach-iop32x/n2100.c @@ -16,6 +16,7 @@ #include <linux/mm.h> #include <linux/init.h> +#include <linux/f75375s.h> #include <linux/delay.h> #include <linux/kernel.h> #include <linux/pci.h> @@ -200,11 +201,21 @@ static struct platform_device n2100_serial_device = { .resource = &n2100_uart_resource, }; +static struct f75375s_platform_data n2100_f75375s = { + .pwm = { 255, 255 }, + .pwm_enable = { 0, 0 }, +}; + static struct i2c_board_info __initdata n2100_i2c_devices[] = { { I2C_BOARD_INFO("rtc-rs5c372", 0x32), .type = "rs5c372b", }, + { + I2C_BOARD_INFO("f75375", 0x2e), + .type = "f75375", + .platform_data = &n2100_f75375s, + }, }; /* diff --git a/arch/arm/mach-netx/xc.c b/arch/arm/mach-netx/xc.c index bd5184f..ca9c5b6 100644 --- a/arch/arm/mach-netx/xc.c +++ b/arch/arm/mach-netx/xc.c @@ -190,15 +190,15 @@ struct xc *request_xc(int xcno, struct device *dev) goto exit; if (!request_mem_region - (NETX_PA_XPEC(xcno), XPEC_MEM_SIZE, kobject_name(dev->kobj))) + (NETX_PA_XPEC(xcno), XPEC_MEM_SIZE, kobject_name(&dev->kobj))) goto exit_free; if (!request_mem_region - (NETX_PA_XMAC(xcno), XMAC_MEM_SIZE, kobject_name(dev->kobj))) + (NETX_PA_XMAC(xcno), XMAC_MEM_SIZE, kobject_name(&dev->kobj))) goto exit_release_1; if (!request_mem_region - (SRAM_INTERNAL_PHYS(xcno), SRAM_MEM_SIZE, kobject_name(dev->kobj))) + (SRAM_INTERNAL_PHYS(xcno), SRAM_MEM_SIZE, kobject_name(&dev->kobj))) goto exit_release_2; x->xpec_base = (void * __iomem)io_p2v(NETX_PA_XPEC(xcno)); diff --git a/arch/arm/mach-pxa/pxa27x.c b/arch/arm/mach-pxa/pxa27x.c index d0f2b59..8e126e6 100644 --- a/arch/arm/mach-pxa/pxa27x.c +++ b/arch/arm/mach-pxa/pxa27x.c @@ -146,7 +146,7 @@ static struct clk pxa27x_clks[] = { INIT_CKEN("MMCCLK", MMC, 19500000, 0, &pxa_device_mci.dev), INIT_CKEN("FICPCLK", FICP, 48000000, 0, &pxa_device_ficp.dev), - INIT_CKEN("USBCLK", USB, 48000000, 0, &pxa27x_device_ohci.dev), + INIT_CKEN("USBCLK", USBHOST, 48000000, 0, &pxa27x_device_ohci.dev), INIT_CKEN("I2CCLK", PWRI2C, 13000000, 0, &pxa27x_device_i2c_power.dev), INIT_CKEN("KBDCLK", KEYPAD, 32768, 0, NULL), diff --git a/arch/arm/mach-pxa/pxa320.c b/arch/arm/mach-pxa/pxa320.c index 1010f77..74128eb 100644 --- a/arch/arm/mach-pxa/pxa320.c +++ b/arch/arm/mach-pxa/pxa320.c @@ -23,8 +23,11 @@ static struct pxa3xx_mfp_addr_map pxa320_mfp_addr_map[] __initdata = { MFP_ADDR_X(GPIO0, GPIO4, 0x0124), - MFP_ADDR_X(GPIO5, GPIO26, 0x028C), - MFP_ADDR_X(GPIO27, GPIO62, 0x0400), + MFP_ADDR_X(GPIO5, GPIO9, 0x028C), + MFP_ADDR(GPIO10, 0x0458), + MFP_ADDR_X(GPIO11, GPIO26, 0x02A0), + MFP_ADDR_X(GPIO27, GPIO48, 0x0400), + MFP_ADDR_X(GPIO49, GPIO62, 0x045C), MFP_ADDR_X(GPIO63, GPIO73, 0x04B4), MFP_ADDR_X(GPIO74, GPIO98, 0x04F0), MFP_ADDR_X(GPIO99, GPIO127, 0x0600), diff --git a/arch/arm/mach-pxa/pxa3xx.c b/arch/arm/mach-pxa/pxa3xx.c index 5da7982..61d9c9d 100644 --- a/arch/arm/mach-pxa/pxa3xx.c +++ b/arch/arm/mach-pxa/pxa3xx.c @@ -150,22 +150,45 @@ static void clk_pxa3xx_cken_disable(struct clk *clk) local_irq_enable(); } +static const struct clkops clk_pxa3xx_cken_ops = { + .enable = clk_pxa3xx_cken_enable, + .disable = clk_pxa3xx_cken_disable, +}; + static const struct clkops clk_pxa3xx_hsio_ops = { .enable = clk_pxa3xx_cken_enable, .disable = clk_pxa3xx_cken_disable, .getrate = clk_pxa3xx_hsio_getrate, }; +#define PXA3xx_CKEN(_name, _cken, _rate, _delay, _dev) \ + { \ + .name = _name, \ + .dev = _dev, \ + .ops = &clk_pxa3xx_cken_ops, \ + .rate = _rate, \ + .cken = CKEN_##_cken, \ + .delay = _delay, \ + } + +#define PXA3xx_CK(_name, _cken, _ops, _dev) \ + { \ + .name = _name, \ + .dev = _dev, \ + .ops = _ops, \ + .cken = CKEN_##_cken, \ + } + static struct clk pxa3xx_clks[] = { - INIT_CK("LCDCLK", LCD, &clk_pxa3xx_hsio_ops, &pxa_device_fb.dev), - INIT_CK("CAMCLK", CAMERA, &clk_pxa3xx_hsio_ops, NULL), + PXA3xx_CK("LCDCLK", LCD, &clk_pxa3xx_hsio_ops, &pxa_device_fb.dev), + PXA3xx_CK("CAMCLK", CAMERA, &clk_pxa3xx_hsio_ops, NULL), - INIT_CKEN("UARTCLK", FFUART, 14857000, 1, &pxa_device_ffuart.dev), - INIT_CKEN("UARTCLK", BTUART, 14857000, 1, &pxa_device_btuart.dev), - INIT_CKEN("UARTCLK", STUART, 14857000, 1, NULL), + PXA3xx_CKEN("UARTCLK", FFUART, 14857000, 1, &pxa_device_ffuart.dev), + PXA3xx_CKEN("UARTCLK", BTUART, 14857000, 1, &pxa_device_btuart.dev), + PXA3xx_CKEN("UARTCLK", STUART, 14857000, 1, NULL), - INIT_CKEN("I2CCLK", I2C, 32842000, 0, &pxa_device_i2c.dev), - INIT_CKEN("UDCCLK", UDC, 48000000, 5, &pxa_device_udc.dev), + PXA3xx_CKEN("I2CCLK", I2C, 32842000, 0, &pxa_device_i2c.dev), + PXA3xx_CKEN("UDCCLK", UDC, 48000000, 5, &pxa_device_udc.dev), }; void __init pxa3xx_init_irq(void) diff --git a/arch/arm/mach-pxa/ssp.c b/arch/arm/mach-pxa/ssp.c index 71766ac..422afee 100644 --- a/arch/arm/mach-pxa/ssp.c +++ b/arch/arm/mach-pxa/ssp.c @@ -309,6 +309,7 @@ void ssp_exit(struct ssp_dev *dev) if (dev->port > PXA_SSP_PORTS || dev->port == 0) { printk(KERN_WARNING "SSP: tried to close invalid port\n"); + mutex_unlock(&mutex); return; } diff --git a/arch/arm/mach-pxa/time.c b/arch/arm/mach-pxa/time.c index a2d45d7..fbfa192 100644 --- a/arch/arm/mach-pxa/time.c +++ b/arch/arm/mach-pxa/time.c @@ -68,6 +68,7 @@ pxa_ost0_interrupt(int irq, void *dev_id) if (c->mode == CLOCK_EVT_MODE_ONESHOT) { /* Disarm the compare/match, signal the event. */ OIER &= ~OIER_E0; + OSSR = OSSR_M0; c->event_handler(c); } else if (c->mode == CLOCK_EVT_MODE_PERIODIC) { /* Call the event handler as many times as necessary @@ -100,9 +101,9 @@ pxa_ost0_interrupt(int irq, void *dev_id) * anything that might put us "very close". */ #define MIN_OSCR_DELTA 16 - do { + do { OSSR = OSSR_M0; - next_match = (OSMR0 += LATCH); + next_match = (OSMR0 += LATCH); c->event_handler(c); } while (((signed long)(next_match - OSCR) <= MIN_OSCR_DELTA) && (c->mode == CLOCK_EVT_MODE_PERIODIC)); @@ -114,14 +115,16 @@ pxa_ost0_interrupt(int irq, void *dev_id) static int pxa_osmr0_set_next_event(unsigned long delta, struct clock_event_device *dev) { - unsigned long irqflags; + unsigned long flags, next, oscr; - raw_local_irq_save(irqflags); - OSMR0 = OSCR + delta; - OSSR = OSSR_M0; + raw_local_irq_save(flags); OIER |= OIER_E0; - raw_local_irq_restore(irqflags); - return 0; + next = OSCR + delta; + OSMR0 = next; + oscr = OSCR; + raw_local_irq_restore(flags); + + return (signed)(next - oscr) <= MIN_OSCR_DELTA ? -ETIME : 0; } static void @@ -132,15 +135,16 @@ pxa_osmr0_set_mode(enum clock_event_mode mode, struct clock_event_device *dev) switch (mode) { case CLOCK_EVT_MODE_PERIODIC: raw_local_irq_save(irqflags); - OSMR0 = OSCR + LATCH; OSSR = OSSR_M0; OIER |= OIER_E0; + OSMR0 = OSCR + LATCH; raw_local_irq_restore(irqflags); break; case CLOCK_EVT_MODE_ONESHOT: raw_local_irq_save(irqflags); OIER &= ~OIER_E0; + OSSR = OSSR_M0; raw_local_irq_restore(irqflags); break; @@ -149,6 +153,7 @@ pxa_osmr0_set_mode(enum clock_event_mode mode, struct clock_event_device *dev) /* initializing, released, or preparing for suspend */ raw_local_irq_save(irqflags); OIER &= ~OIER_E0; + OSSR = OSSR_M0; raw_local_irq_restore(irqflags); break; diff --git a/arch/arm/mm/consistent.c b/arch/arm/mm/consistent.c index cefdf2f..333a82a 100644 --- a/arch/arm/mm/consistent.c +++ b/arch/arm/mm/consistent.c @@ -322,7 +322,6 @@ static int dma_mmap(struct device *dev, struct vm_area_struct *vma, if (off < kern_size && user_size <= (kern_size - off)) { - vma->vm_flags |= VM_RESERVED; ret = remap_pfn_range(vma, vma->vm_start, page_to_pfn(c->vm_pages) + off, user_size << PAGE_SHIFT, diff --git a/arch/arm/plat-omap/fb.c b/arch/arm/plat-omap/fb.c index 4493bcf..ee40c1a0 100644 --- a/arch/arm/plat-omap/fb.c +++ b/arch/arm/plat-omap/fb.c @@ -171,7 +171,7 @@ static int check_fbmem_region(int region_idx, struct omapfb_mem_region *rg, * Called from map_io. We need to call to this early enough so that we * can reserve the fixed SDRAM regions before VM could get hold of them. */ -void omapfb_reserve_sdram(void) +void __init omapfb_reserve_sdram(void) { struct bootmem_data *bdata; unsigned long sdram_start, sdram_size; diff --git a/arch/avr32/Kconfig b/arch/avr32/Kconfig index bbecbd8..4f402c9 100644 --- a/arch/avr32/Kconfig +++ b/arch/avr32/Kconfig @@ -19,9 +19,6 @@ config AVR32 There is an AVR32 Linux project with a web page at http://avr32linux.org/. -config UID16 - bool - config GENERIC_GPIO bool default y diff --git a/arch/avr32/mach-at32ap/at32ap7000.c b/arch/avr32/mach-at32ap/at32ap7000.c index a9d9ec0..7c4388f 100644 --- a/arch/avr32/mach-at32ap/at32ap7000.c +++ b/arch/avr32/mach-at32ap/at32ap7000.c @@ -474,7 +474,7 @@ static struct resource at32ap700x_rtc0_resource[] = { static struct resource at32_wdt0_resource[] = { { .start = 0xfff000b0, - .end = 0xfff000bf, + .end = 0xfff000cf, .flags = IORESOURCE_MEM, }, }; @@ -690,7 +690,7 @@ static struct resource atmel_usart0_resource[] = { IRQ(6), }; DEFINE_DEV_DATA(atmel_usart, 0); -DEV_CLK(usart, atmel_usart0, pba, 4); +DEV_CLK(usart, atmel_usart0, pba, 3); static struct atmel_uart_data atmel_usart1_data = { .use_dma_tx = 1, diff --git a/arch/avr32/mach-at32ap/hsmc.c b/arch/avr32/mach-at32ap/hsmc.c index 704607f..fa427ed 100644 --- a/arch/avr32/mach-at32ap/hsmc.c +++ b/arch/avr32/mach-at32ap/hsmc.c @@ -7,7 +7,6 @@ * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. */ -#define DEBUG #include <linux/clk.h> #include <linux/err.h> #include <linux/init.h> diff --git a/arch/avr32/mach-at32ap/intc.c b/arch/avr32/mach-at32ap/intc.c index dd5c009..0b286cd 100644 --- a/arch/avr32/mach-at32ap/intc.c +++ b/arch/avr32/mach-at32ap/intc.c @@ -13,6 +13,7 @@ #include <linux/irq.h> #include <linux/platform_device.h> +#include <asm/intc.h> #include <asm/io.h> #include "intc.h" @@ -136,7 +137,8 @@ fail: panic("Interrupt controller initialization failed!\n"); } -unsigned long intc_get_pending(int group) +unsigned long intc_get_pending(unsigned int group) { return intc_readl(&intc0, INTREQ0 + 4 * group); } +EXPORT_SYMBOL_GPL(intc_get_pending); diff --git a/arch/blackfin/Kconfig b/arch/blackfin/Kconfig index 9f9de3e..2a3a7ea 100644 --- a/arch/blackfin/Kconfig +++ b/arch/blackfin/Kconfig @@ -3,7 +3,7 @@ # see Documentation/kbuild/kconfig-language.txt. # -mainmenu "uClinux/Blackfin (w/o MMU) Kernel Configuration" +mainmenu "Blackfin Kernel Configuration" config MMU bool @@ -29,10 +29,6 @@ config ZONE_DMA bool default y -config BFIN - bool - default y - config SEMAPHORE_SLEEPERS bool default y @@ -50,7 +46,7 @@ config GENERIC_HARDIRQS default y config GENERIC_IRQ_PROBE - bool + bool default y config GENERIC_TIME @@ -69,11 +65,6 @@ config GENERIC_CALIBRATE_DELAY bool default y -config IRQCHIP_DEMUX_GPIO - bool - depends on (BF52x || BF53x || BF561 || BF54x) - default y - source "init/Kconfig" source "kernel/Kconfig.preempt" @@ -140,6 +131,11 @@ config BF544 help BF544 Processor Support. +config BF547 + bool "BF547" + help + BF547 Processor Support. + config BF548 bool "BF548" help @@ -166,11 +162,11 @@ choice config BF_REV_0_0 bool "0.0" - depends on (BF549 || BF527) + depends on (BF52x || BF54x) config BF_REV_0_1 - bool "0.2" - depends on (BF549 || BF527) + bool "0.1" + depends on (BF52x || BF54x) config BF_REV_0_2 bool "0.2" @@ -208,7 +204,7 @@ config BF53x config BF54x bool - depends on (BF542 || BF544 || BF548 || BF549) + depends on (BF542 || BF544 || BF547 || BF548 || BF549) default y config BFIN_DUAL_CORE @@ -221,95 +217,6 @@ config BFIN_SINGLE_CORE depends on !BFIN_DUAL_CORE default y -choice - prompt "System type" - default BFIN533_STAMP - help - Do NOT change the board here. Please use the top level - configuration to ensure that all the other settings are - correct. - -config BFIN527_EZKIT - bool "BF527-EZKIT" - depends on (BF522 || BF525 || BF527) - help - BF533-EZKIT-LITE board Support. - -config BFIN533_EZKIT - bool "BF533-EZKIT" - depends on (BF533 || BF532 || BF531) - help - BF533-EZKIT-LITE board Support. - -config BFIN533_STAMP - bool "BF533-STAMP" - depends on (BF533 || BF532 || BF531) - help - BF533-STAMP board Support. - -config BFIN537_STAMP - bool "BF537-STAMP" - depends on (BF537 || BF536 || BF534) - help - BF537-STAMP board Support. - -config BFIN533_BLUETECHNIX_CM - bool "Bluetechnix CM-BF533" - depends on (BF533) - help - CM-BF533 support for EVAL- and DEV-Board. - -config BFIN537_BLUETECHNIX_CM - bool "Bluetechnix CM-BF537" - depends on (BF537) - help - CM-BF537 support for EVAL- and DEV-Board. - -config BFIN548_EZKIT - bool "BF548-EZKIT" - depends on (BF548 || BF549) - help - BFIN548-EZKIT board Support. - -config BFIN561_BLUETECHNIX_CM - bool "Bluetechnix CM-BF561" - depends on (BF561) - help - CM-BF561 support for EVAL- and DEV-Board. - -config BFIN561_EZKIT - bool "BF561-EZKIT" - depends on (BF561) - help - BF561-EZKIT-LITE board Support. - -config BFIN561_TEPLA - bool "BF561-TEPLA" - depends on (BF561) - help - BF561-TEPLA board Support. - -config PNAV10 - bool "PNAV 1.0 board" - depends on (BF537) - help - PNAV 1.0 board Support. - -config H8606_HVSISTEMAS - bool "HV Sistemas H8606" - depends on (BF532) - help - HV Sistemas H8606 board support. - -config GENERIC_BOARD - bool "Custom" - depends on (BF537 || BF536 \ - || BF534 || BF561 || BF535 || BF533 || BF532 || BF531) - help - GENERIC or Custom board Support. - -endchoice - config MEM_GENERIC_BOARD bool depends on GENERIC_BOARD @@ -389,9 +296,9 @@ config BFIN_KERNEL_CLOCK configuration. config PLL_BYPASS - bool "Bypass PLL" - depends on BFIN_KERNEL_CLOCK - default n + bool "Bypass PLL" + depends on BFIN_KERNEL_CLOCK + default n config CLKIN_HALF bool "Half Clock In" @@ -468,11 +375,11 @@ config MAX_VCO_HZ default 500000000 if BF534 default 400000000 if BF536 default 600000000 if BF537 - default 533000000 if BF538 - default 533000000 if BF539 + default 533333333 if BF538 + default 533333333 if BF539 default 600000000 if BF542 - default 533000000 if BF544 - default 533000000 if BF549 + default 533333333 if BF544 + default 533333333 if BF549 default 600000000 if BF561 config MIN_VCO_HZ @@ -481,7 +388,7 @@ config MIN_VCO_HZ config MAX_SCLK_HZ int - default 133000000 + default 133333333 config MIN_SCLK_HZ int @@ -959,6 +866,20 @@ config BANK_3 default 0x99B3 endmenu +config EBIU_MBSCTLVAL + hex "EBIU Bank Select Control Register" + depends on BF54x + default 0 + +config EBIU_MODEVAL + hex "Flash Memory Mode Control Register" + depends on BF54x + default 1 + +config EBIU_FCTLVAL + hex "Flash Memory Bank Control Register" + depends on BF54x + default 6 endmenu ############################################################################# @@ -1075,174 +996,7 @@ source "fs/Kconfig" source "kernel/Kconfig.instrumentation" -menu "Kernel hacking" - -source "lib/Kconfig.debug" - -config DEBUG_HWERR - bool "Hardware error interrupt debugging" - depends on DEBUG_KERNEL - help - When enabled, the hardware error interrupt is never disabled, and - will happen immediately when an error condition occurs. This comes - at a slight cost in code size, but is necessary if you are getting - hardware error interrupts and need to know where they are coming - from. - -config DEBUG_ICACHE_CHECK - bool "Check Instruction cache coherency" - depends on DEBUG_KERNEL - depends on DEBUG_HWERR - help - Say Y here if you are getting weird unexplained errors. This will - ensure that icache is what SDRAM says it should be by doing a - byte wise comparison between SDRAM and instruction cache. This - also relocates the irq_panic() function to L1 memory, (which is - un-cached). - -config DEBUG_HUNT_FOR_ZERO - bool "Catch NULL pointer reads/writes" - default y - help - Say Y here to catch reads/writes to anywhere in the memory range - from 0x0000 - 0x0FFF (the first 4k) of memory. This is useful in - catching common programming errors such as NULL pointer dereferences. - - Misbehaving applications will be killed (generate a SEGV) while the - kernel will trigger a panic. - - Enabling this option will take up an extra entry in CPLB table. - Otherwise, there is no extra overhead. - -config DEBUG_BFIN_HWTRACE_ON - bool "Turn on Blackfin's Hardware Trace" - default y - help - All Blackfins include a Trace Unit which stores a history of the last - 16 changes in program flow taken by the program sequencer. The history - allows the user to recreate the program sequencer’s recent path. This - can be handy when an application dies - we print out the execution - path of how it got to the offending instruction. - - By turning this off, you may save a tiny amount of power. - -choice - prompt "Omit loop Tracing" - default DEBUG_BFIN_HWTRACE_COMPRESSION_OFF - depends on DEBUG_BFIN_HWTRACE_ON - help - The trace buffer can be configured to omit recording of changes in - program flow that match either the last entry or one of the last - two entries. Omitting one of these entries from the record prevents - the trace buffer from overflowing because of any sort of loop (for, do - while, etc) in the program. - - Because zero-overhead Hardware loops are not recorded in the trace buffer, - this feature can be used to prevent trace overflow from loops that - are nested four deep. - -config DEBUG_BFIN_HWTRACE_COMPRESSION_OFF - bool "Trace all Loops" - help - The trace buffer records all changes of flow - -config DEBUG_BFIN_HWTRACE_COMPRESSION_ONE - bool "Compress single-level loops" - help - The trace buffer does not record single loops - helpful if trace - is spinning on a while or do loop. - -config DEBUG_BFIN_HWTRACE_COMPRESSION_TWO - bool "Compress two-level loops" - help - The trace buffer does not record loops two levels deep. Helpful if - the trace is spinning in a nested loop - -endchoice - -config DEBUG_BFIN_HWTRACE_COMPRESSION - int - depends on DEBUG_BFIN_HWTRACE_ON - default 0 if DEBUG_BFIN_HWTRACE_COMPRESSION_OFF - default 1 if DEBUG_BFIN_HWTRACE_COMPRESSION_ONE - default 2 if DEBUG_BFIN_HWTRACE_COMPRESSION_TWO - - -config DEBUG_BFIN_HWTRACE_EXPAND - bool "Expand Trace Buffer greater than 16 entries" - depends on DEBUG_BFIN_HWTRACE_ON - default n - help - By selecting this option, every time the 16 hardware entries in - the Blackfin's HW Trace buffer are full, the kernel will move them - into a software buffer, for dumping when there is an issue. This - has a great impact on performance, (an interrupt every 16 change of - flows) and should normally be turned off, except in those nasty - debugging sessions - -config DEBUG_BFIN_HWTRACE_EXPAND_LEN - int "Size of Trace buffer (in power of 2k)" - range 0 4 - depends on DEBUG_BFIN_HWTRACE_EXPAND - default 1 - help - This sets the size of the software buffer that the trace information - is kept in. - 0 for (2^0) 1k, or 256 entries, - 1 for (2^1) 2k, or 512 entries, - 2 for (2^2) 4k, or 1024 entries, - 3 for (2^3) 8k, or 2048 entries, - 4 for (2^4) 16k, or 4096 entries - -config DEBUG_BFIN_NO_KERN_HWTRACE - bool "Trace user apps (turn off hwtrace in kernel)" - depends on DEBUG_BFIN_HWTRACE_ON - default n - help - Some pieces of the kernel contain a lot of flow changes which can - quickly fill up the hardware trace buffer. When debugging crashes, - the hardware trace may indicate that the problem lies in kernel - space when in reality an application is buggy. - - Say Y here to disable hardware tracing in some known "jumpy" pieces - of code so that the trace buffer will extend further back. - -config EARLY_PRINTK - bool "Early printk" - default n - help - This option enables special console drivers which allow the kernel - to print messages very early in the bootup process. - - This is useful for kernel debugging when your machine crashes very - early before the console code is initialized. After enabling this - feature, you must add "earlyprintk=serial,uart0,57600" to the - command line (bootargs). It is safe to say Y here in all cases, as - all of this lives in the init section and is thrown away after the - kernel boots completely. - -config DUAL_CORE_TEST_MODULE - tristate "Dual Core Test Module" - depends on (BF561) - default n - help - Say Y here to build-in dual core test module for dual core test. - -config CPLB_INFO - bool "Display the CPLB information" - help - Display the CPLB information. - -config ACCESS_CHECK - bool "Check the user pointer address" - default y - help - Usually the pointer transfer from user space is checked to see if its - address is in the kernel space. - - Say N here to disable that check to improve the performance. - -endmenu +source "arch/blackfin/Kconfig.debug" source "security/Kconfig" diff --git a/arch/blackfin/Kconfig.debug b/arch/blackfin/Kconfig.debug new file mode 100644 index 0000000..59b87a4 --- /dev/null +++ b/arch/blackfin/Kconfig.debug @@ -0,0 +1,178 @@ +menu "Kernel hacking" + +source "lib/Kconfig.debug" + +config DEBUG_MMRS + bool "Generate Blackfin MMR tree" + select DEBUG_FS + help + Create a tree of Blackfin MMRs via the debugfs tree. If + you enable this, you will find all MMRs laid out in the + /sys/kernel/debug/blackfin/ directory where you can read/write + MMRs directly from userspace. This is obviously just a debug + feature. + +config DEBUG_HWERR + bool "Hardware error interrupt debugging" + depends on DEBUG_KERNEL + help + When enabled, the hardware error interrupt is never disabled, and + will happen immediately when an error condition occurs. This comes + at a slight cost in code size, but is necessary if you are getting + hardware error interrupts and need to know where they are coming + from. + +config DEBUG_ICACHE_CHECK + bool "Check Instruction cache coherency" + depends on DEBUG_KERNEL + depends on DEBUG_HWERR + help + Say Y here if you are getting weird unexplained errors. This will + ensure that icache is what SDRAM says it should be by doing a + byte wise comparison between SDRAM and instruction cache. This + also relocates the irq_panic() function to L1 memory, (which is + un-cached). + +config DEBUG_HUNT_FOR_ZERO + bool "Catch NULL pointer reads/writes" + default y + help + Say Y here to catch reads/writes to anywhere in the memory range + from 0x0000 - 0x0FFF (the first 4k) of memory. This is useful in + catching common programming errors such as NULL pointer dereferences. + + Misbehaving applications will be killed (generate a SEGV) while the + kernel will trigger a panic. + + Enabling this option will take up an extra entry in CPLB table. + Otherwise, there is no extra overhead. + +config DEBUG_BFIN_HWTRACE_ON + bool "Turn on Blackfin's Hardware Trace" + default y + help + All Blackfins include a Trace Unit which stores a history of the last + 16 changes in program flow taken by the program sequencer. The history + allows the user to recreate the program sequencer’s recent path. This + can be handy when an application dies - we print out the execution + path of how it got to the offending instruction. + + By turning this off, you may save a tiny amount of power. + +choice + prompt "Omit loop Tracing" + default DEBUG_BFIN_HWTRACE_COMPRESSION_OFF + depends on DEBUG_BFIN_HWTRACE_ON + help + The trace buffer can be configured to omit recording of changes in + program flow that match either the last entry or one of the last + two entries. Omitting one of these entries from the record prevents + the trace buffer from overflowing because of any sort of loop (for, do + while, etc) in the program. + + Because zero-overhead Hardware loops are not recorded in the trace buffer, + this feature can be used to prevent trace overflow from loops that + are nested four deep. + +config DEBUG_BFIN_HWTRACE_COMPRESSION_OFF + bool "Trace all Loops" + help + The trace buffer records all changes of flow + +config DEBUG_BFIN_HWTRACE_COMPRESSION_ONE + bool "Compress single-level loops" + help + The trace buffer does not record single loops - helpful if trace + is spinning on a while or do loop. + +config DEBUG_BFIN_HWTRACE_COMPRESSION_TWO + bool "Compress two-level loops" + help + The trace buffer does not record loops two levels deep. Helpful if + the trace is spinning in a nested loop + +endchoice + +config DEBUG_BFIN_HWTRACE_COMPRESSION + int + depends on DEBUG_BFIN_HWTRACE_ON + default 0 if DEBUG_BFIN_HWTRACE_COMPRESSION_OFF + default 1 if DEBUG_BFIN_HWTRACE_COMPRESSION_ONE + default 2 if DEBUG_BFIN_HWTRACE_COMPRESSION_TWO + + +config DEBUG_BFIN_HWTRACE_EXPAND + bool "Expand Trace Buffer greater than 16 entries" + depends on DEBUG_BFIN_HWTRACE_ON + default n + help + By selecting this option, every time the 16 hardware entries in + the Blackfin's HW Trace buffer are full, the kernel will move them + into a software buffer, for dumping when there is an issue. This + has a great impact on performance, (an interrupt every 16 change of + flows) and should normally be turned off, except in those nasty + debugging sessions + +config DEBUG_BFIN_HWTRACE_EXPAND_LEN + int "Size of Trace buffer (in power of 2k)" + range 0 4 + depends on DEBUG_BFIN_HWTRACE_EXPAND + default 1 + help + This sets the size of the software buffer that the trace information + is kept in. + 0 for (2^0) 1k, or 256 entries, + 1 for (2^1) 2k, or 512 entries, + 2 for (2^2) 4k, or 1024 entries, + 3 for (2^3) 8k, or 2048 entries, + 4 for (2^4) 16k, or 4096 entries + +config DEBUG_BFIN_NO_KERN_HWTRACE + bool "Trace user apps (turn off hwtrace in kernel)" + depends on DEBUG_BFIN_HWTRACE_ON + default n + help + Some pieces of the kernel contain a lot of flow changes which can + quickly fill up the hardware trace buffer. When debugging crashes, + the hardware trace may indicate that the problem lies in kernel + space when in reality an application is buggy. + + Say Y here to disable hardware tracing in some known "jumpy" pieces + of code so that the trace buffer will extend further back. + +config EARLY_PRINTK + bool "Early printk" + default n + help + This option enables special console drivers which allow the kernel + to print messages very early in the bootup process. + + This is useful for kernel debugging when your machine crashes very + early before the console code is initialized. After enabling this + feature, you must add "earlyprintk=serial,uart0,57600" to the + command line (bootargs). It is safe to say Y here in all cases, as + all of this lives in the init section and is thrown away after the + kernel boots completely. + +config DUAL_CORE_TEST_MODULE + tristate "Dual Core Test Module" + depends on (BF561) + default n + help + Say Y here to build-in dual core test module for dual core test. + +config CPLB_INFO + bool "Display the CPLB information" + help + Display the CPLB information. + +config ACCESS_CHECK + bool "Check the user pointer address" + default y + help + Usually the pointer transfer from user space is checked to see if its + address is in the kernel space. + + Say N here to disable that check to improve the performance. + +endmenu diff --git a/arch/blackfin/Makefile b/arch/blackfin/Makefile index f7cac7c..c47e000 100644 --- a/arch/blackfin/Makefile +++ b/arch/blackfin/Makefile @@ -31,6 +31,7 @@ machine-$(CONFIG_BF536) := bf537 machine-$(CONFIG_BF537) := bf537 machine-$(CONFIG_BF542) := bf548 machine-$(CONFIG_BF544) := bf548 +machine-$(CONFIG_BF547) := bf548 machine-$(CONFIG_BF548) := bf548 machine-$(CONFIG_BF549) := bf548 machine-$(CONFIG_BF561) := bf561 @@ -48,6 +49,7 @@ cpu-$(CONFIG_BF536) := bf536 cpu-$(CONFIG_BF537) := bf537 cpu-$(CONFIG_BF542) := bf542 cpu-$(CONFIG_BF544) := bf544 +cpu-$(CONFIG_BF547) := bf547 cpu-$(CONFIG_BF548) := bf548 cpu-$(CONFIG_BF549) := bf549 cpu-$(CONFIG_BF561) := bf561 diff --git a/arch/blackfin/configs/BF527-EZKIT_defconfig b/arch/blackfin/configs/BF527-EZKIT_defconfig index 1f6a93d..fa6eb4e 100644 --- a/arch/blackfin/configs/BF527-EZKIT_defconfig +++ b/arch/blackfin/configs/BF527-EZKIT_defconfig @@ -1,6 +1,6 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.22.9 +# Linux kernel version: 2.6.22.12 # # CONFIG_MMU is not set # CONFIG_FPU is not set @@ -8,7 +8,6 @@ CONFIG_RWSEM_GENERIC_SPINLOCK=y # CONFIG_RWSEM_XCHGADD_ALGORITHM is not set CONFIG_BLACKFIN=y CONFIG_ZONE_DMA=y -CONFIG_BFIN=y CONFIG_SEMAPHORE_SLEEPERS=y CONFIG_GENERIC_FIND_NEXT_BIT=y CONFIG_GENERIC_HWEIGHT=y @@ -18,7 +17,6 @@ CONFIG_GENERIC_IRQ_PROBE=y CONFIG_GENERIC_GPIO=y CONFIG_FORCE_MAX_ZONEORDER=14 CONFIG_GENERIC_CALIBRATE_DELAY=y -CONFIG_IRQCHIP_DEMUX_GPIO=y CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" # @@ -127,6 +125,7 @@ CONFIG_BF527=y # CONFIG_BF537 is not set # CONFIG_BF542 is not set # CONFIG_BF544 is not set +# CONFIG_BF547 is not set # CONFIG_BF548 is not set # CONFIG_BF549 is not set # CONFIG_BF561 is not set @@ -140,19 +139,8 @@ CONFIG_BF_REV_0_0=y # CONFIG_BF_REV_NONE is not set CONFIG_BF52x=y CONFIG_BFIN_SINGLE_CORE=y -CONFIG_BFIN527_EZKIT=y -# CONFIG_BFIN533_EZKIT is not set -# CONFIG_BFIN533_STAMP is not set -# CONFIG_BFIN537_STAMP is not set -# CONFIG_BFIN533_BLUETECHNIX_CM is not set -# CONFIG_BFIN537_BLUETECHNIX_CM is not set -# CONFIG_BFIN548_EZKIT is not set -# CONFIG_BFIN561_BLUETECHNIX_CM is not set -# CONFIG_BFIN561_EZKIT is not set -# CONFIG_BFIN561_TEPLA is not set -# CONFIG_PNAV10 is not set -# CONFIG_GENERIC_BOARD is not set CONFIG_MEM_MT48LC32M16A2TG_75=y +CONFIG_BFIN527_EZKIT=y # # BF527 Specific Configuration @@ -244,7 +232,7 @@ CONFIG_CLKIN_HZ=25000000 # CONFIG_BFIN_KERNEL_CLOCK is not set CONFIG_MAX_VCO_HZ=600000000 CONFIG_MIN_VCO_HZ=50000000 -CONFIG_MAX_SCLK_HZ=133333333 +CONFIG_MAX_SCLK_HZ=133000000 CONFIG_MIN_SCLK_HZ=27000000 # @@ -301,6 +289,7 @@ CONFIG_SPLIT_PTLOCK_CPUS=4 # CONFIG_RESOURCES_64BIT is not set CONFIG_ZONE_DMA_FLAG=1 CONFIG_LARGE_ALLOCS=y +# CONFIG_BFIN_GPTIMERS is not set CONFIG_BFIN_DMA_5XX=y # CONFIG_DMA_UNCACHED_2M is not set CONFIG_DMA_UNCACHED_1M=y @@ -322,7 +311,7 @@ CONFIG_L1_MAX_PIECE=16 # # -# EBIU_AMBCTL Global Control +# EBIU_AMGCTL Global Control # CONFIG_C_AMCKEN=y CONFIG_C_CDPRIO=y @@ -548,6 +537,7 @@ CONFIG_BFIN_NAND_CLE=2 CONFIG_BFIN_NAND_ALE=1 CONFIG_BFIN_NAND_READY=3 CONFIG_MTD_NAND_IDS=m +# CONFIG_MTD_NAND_BF5XX is not set # CONFIG_MTD_NAND_DISKONCHIP is not set # CONFIG_MTD_NAND_NANDSIM is not set # CONFIG_MTD_NAND_PLATFORM is not set @@ -637,6 +627,7 @@ CONFIG_BFIN_MAC_RMII=y # CONFIG_DM9000 is not set CONFIG_NETDEV_1000=y CONFIG_NETDEV_10000=y +# CONFIG_AX88180 is not set # # Wireless LAN @@ -708,7 +699,7 @@ CONFIG_INPUT_MISC=y # CONFIG_SPI_ADC_BF533 is not set # CONFIG_BF5xx_PFLAGS is not set # CONFIG_BF5xx_PPIFCD is not set -# CONFIG_BF5xx_TIMERS is not set +# CONFIG_BFIN_SIMPLE_TIMER is not set # CONFIG_BF5xx_PPI is not set # CONFIG_BFIN_SPORT is not set # CONFIG_BFIN_TIMER_LATENCY is not set diff --git a/arch/blackfin/configs/BF533-EZKIT_defconfig b/arch/blackfin/configs/BF533-EZKIT_defconfig index 9e9b420..4fdb493 100644 --- a/arch/blackfin/configs/BF533-EZKIT_defconfig +++ b/arch/blackfin/configs/BF533-EZKIT_defconfig @@ -1,6 +1,6 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.22.6 +# Linux kernel version: 2.6.22.12 # # CONFIG_MMU is not set # CONFIG_FPU is not set @@ -8,7 +8,6 @@ CONFIG_RWSEM_GENERIC_SPINLOCK=y # CONFIG_RWSEM_XCHGADD_ALGORITHM is not set CONFIG_BLACKFIN=y CONFIG_ZONE_DMA=y -CONFIG_BFIN=y CONFIG_SEMAPHORE_SLEEPERS=y CONFIG_GENERIC_FIND_NEXT_BIT=y CONFIG_GENERIC_HWEIGHT=y @@ -18,7 +17,6 @@ CONFIG_GENERIC_IRQ_PROBE=y CONFIG_GENERIC_GPIO=y CONFIG_FORCE_MAX_ZONEORDER=14 CONFIG_GENERIC_CALIBRATE_DELAY=y -CONFIG_IRQCHIP_DEMUX_GPIO=y CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" # @@ -64,7 +62,6 @@ CONFIG_FUTEX=y CONFIG_ANON_INODES=y CONFIG_EPOLL=y CONFIG_SIGNALFD=y -CONFIG_TIMERFD=y CONFIG_EVENTFD=y CONFIG_VM_EVENT_COUNTERS=y CONFIG_BIG_ORDER_ALLOC_NOFAIL_MAGIC=3 @@ -117,6 +114,9 @@ CONFIG_PREEMPT_VOLUNTARY=y # # Processor and Board Settings # +# CONFIG_BF522 is not set +# CONFIG_BF525 is not set +# CONFIG_BF527 is not set # CONFIG_BF531 is not set # CONFIG_BF532 is not set CONFIG_BF533=y @@ -125,10 +125,12 @@ CONFIG_BF533=y # CONFIG_BF537 is not set # CONFIG_BF542 is not set # CONFIG_BF544 is not set +# CONFIG_BF547 is not set # CONFIG_BF548 is not set # CONFIG_BF549 is not set # CONFIG_BF561 is not set # CONFIG_BF_REV_0_0 is not set +# CONFIG_BF_REV_0_1 is not set # CONFIG_BF_REV_0_2 is not set CONFIG_BF_REV_0_3=y # CONFIG_BF_REV_0_4 is not set @@ -137,18 +139,12 @@ CONFIG_BF_REV_0_3=y # CONFIG_BF_REV_NONE is not set CONFIG_BF53x=y CONFIG_BFIN_SINGLE_CORE=y +CONFIG_MEM_MT48LC16M16A2TG_75=y CONFIG_BFIN533_EZKIT=y # CONFIG_BFIN533_STAMP is not set -# CONFIG_BFIN537_STAMP is not set # CONFIG_BFIN533_BLUETECHNIX_CM is not set -# CONFIG_BFIN537_BLUETECHNIX_CM is not set -# CONFIG_BFIN548_EZKIT is not set -# CONFIG_BFIN561_BLUETECHNIX_CM is not set -# CONFIG_BFIN561_EZKIT is not set -# CONFIG_BFIN561_TEPLA is not set -# CONFIG_PNAV10 is not set -# CONFIG_GENERIC_BOARD is not set -CONFIG_MEM_MT48LC16M16A2TG_75=y +# CONFIG_H8606_HVSISTEMAS is not set +# CONFIG_GENERIC_BF533_BOARD is not set # # BF533/2/1 Specific Configuration @@ -198,7 +194,7 @@ CONFIG_CLKIN_HZ=27000000 # CONFIG_BFIN_KERNEL_CLOCK is not set CONFIG_MAX_VCO_HZ=750000000 CONFIG_MIN_VCO_HZ=50000000 -CONFIG_MAX_SCLK_HZ=133333333 +CONFIG_MAX_SCLK_HZ=133000000 CONFIG_MIN_SCLK_HZ=27000000 # @@ -255,6 +251,7 @@ CONFIG_SPLIT_PTLOCK_CPUS=4 # CONFIG_RESOURCES_64BIT is not set CONFIG_ZONE_DMA_FLAG=1 CONFIG_LARGE_ALLOCS=y +# CONFIG_BFIN_GPTIMERS is not set CONFIG_BFIN_DMA_5XX=y # CONFIG_DMA_UNCACHED_2M is not set CONFIG_DMA_UNCACHED_1M=y @@ -276,7 +273,7 @@ CONFIG_L1_MAX_PIECE=16 # # -# EBIU_AMBCTL Global Control +# EBIU_AMGCTL Global Control # CONFIG_C_AMCKEN=y CONFIG_C_CDPRIO=y @@ -526,14 +523,6 @@ CONFIG_MTD_COMPLEX_MAPPINGS=y CONFIG_MTD_BF5xx=m CONFIG_BFIN_FLASH_SIZE=0x400000 CONFIG_EBIU_FLASH_BASE=0x20000000 - -# -# FLASH_EBIU_AMBCTL Control -# -CONFIG_BFIN_FLASH_BANK_0=0x7BB0 -CONFIG_BFIN_FLASH_BANK_1=0x7BB0 -CONFIG_BFIN_FLASH_BANK_2=0x7BB0 -CONFIG_BFIN_FLASH_BANK_3=0x7BB0 # CONFIG_MTD_UCLINUX is not set # CONFIG_MTD_PLATRAM is not set @@ -622,6 +611,7 @@ CONFIG_SMC91X=y # CONFIG_DM9000 is not set CONFIG_NETDEV_1000=y CONFIG_NETDEV_10000=y +# CONFIG_AX88180 is not set # # Wireless LAN @@ -683,9 +673,9 @@ CONFIG_INPUT_EVDEV=m # # CONFIG_AD9960 is not set # CONFIG_SPI_ADC_BF533 is not set -# CONFIG_BFIN_PFLAGS is not set +# CONFIG_BF5xx_PFLAGS is not set # CONFIG_BF5xx_PPIFCD is not set -# CONFIG_BF5xx_TIMERS is not set +# CONFIG_BFIN_SIMPLE_TIMER is not set # CONFIG_BF5xx_PPI is not set CONFIG_BFIN_SPORT=y # CONFIG_BFIN_TIMER_LATENCY is not set @@ -708,6 +698,7 @@ CONFIG_SERIAL_BFIN_DMA=y # CONFIG_SERIAL_BFIN_PIO is not set CONFIG_SERIAL_BFIN_UART0=y # CONFIG_BFIN_UART0_CTSRTS is not set +# CONFIG_SERIAL_BFIN_UART1 is not set CONFIG_SERIAL_CORE=y CONFIG_SERIAL_CORE_CONSOLE=y # CONFIG_SERIAL_BFIN_SPORT is not set diff --git a/arch/blackfin/configs/BF533-STAMP_defconfig b/arch/blackfin/configs/BF533-STAMP_defconfig index f59ade9..b04e8e5 100644 --- a/arch/blackfin/configs/BF533-STAMP_defconfig +++ b/arch/blackfin/configs/BF533-STAMP_defconfig @@ -1,6 +1,6 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.22.6 +# Linux kernel version: 2.6.22.12 # # CONFIG_MMU is not set # CONFIG_FPU is not set @@ -8,7 +8,6 @@ CONFIG_RWSEM_GENERIC_SPINLOCK=y # CONFIG_RWSEM_XCHGADD_ALGORITHM is not set CONFIG_BLACKFIN=y CONFIG_ZONE_DMA=y -CONFIG_BFIN=y CONFIG_SEMAPHORE_SLEEPERS=y CONFIG_GENERIC_FIND_NEXT_BIT=y CONFIG_GENERIC_HWEIGHT=y @@ -18,7 +17,6 @@ CONFIG_GENERIC_IRQ_PROBE=y CONFIG_GENERIC_GPIO=y CONFIG_FORCE_MAX_ZONEORDER=14 CONFIG_GENERIC_CALIBRATE_DELAY=y -CONFIG_IRQCHIP_DEMUX_GPIO=y CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" # @@ -64,7 +62,6 @@ CONFIG_FUTEX=y CONFIG_ANON_INODES=y CONFIG_EPOLL=y CONFIG_SIGNALFD=y -CONFIG_TIMERFD=y CONFIG_EVENTFD=y CONFIG_VM_EVENT_COUNTERS=y CONFIG_BIG_ORDER_ALLOC_NOFAIL_MAGIC=3 @@ -117,6 +114,9 @@ CONFIG_PREEMPT_VOLUNTARY=y # # Processor and Board Settings # +# CONFIG_BF522 is not set +# CONFIG_BF525 is not set +# CONFIG_BF527 is not set # CONFIG_BF531 is not set # CONFIG_BF532 is not set CONFIG_BF533=y @@ -125,10 +125,12 @@ CONFIG_BF533=y # CONFIG_BF537 is not set # CONFIG_BF542 is not set # CONFIG_BF544 is not set +# CONFIG_BF547 is not set # CONFIG_BF548 is not set # CONFIG_BF549 is not set # CONFIG_BF561 is not set # CONFIG_BF_REV_0_0 is not set +# CONFIG_BF_REV_0_1 is not set # CONFIG_BF_REV_0_2 is not set CONFIG_BF_REV_0_3=y # CONFIG_BF_REV_0_4 is not set @@ -137,19 +139,13 @@ CONFIG_BF_REV_0_3=y # CONFIG_BF_REV_NONE is not set CONFIG_BF53x=y CONFIG_BFIN_SINGLE_CORE=y +CONFIG_MEM_MT48LC64M4A2FB_7E=y +CONFIG_BFIN_SHARED_FLASH_ENET=y # CONFIG_BFIN533_EZKIT is not set CONFIG_BFIN533_STAMP=y -# CONFIG_BFIN537_STAMP is not set # CONFIG_BFIN533_BLUETECHNIX_CM is not set -# CONFIG_BFIN537_BLUETECHNIX_CM is not set -# CONFIG_BFIN548_EZKIT is not set -# CONFIG_BFIN561_BLUETECHNIX_CM is not set -# CONFIG_BFIN561_EZKIT is not set -# CONFIG_BFIN561_TEPLA is not set -# CONFIG_PNAV10 is not set -# CONFIG_GENERIC_BOARD is not set -CONFIG_MEM_MT48LC64M4A2FB_7E=y -CONFIG_BFIN_SHARED_FLASH_ENET=y +# CONFIG_H8606_HVSISTEMAS is not set +# CONFIG_GENERIC_BF533_BOARD is not set # # BF533/2/1 Specific Configuration @@ -199,7 +195,7 @@ CONFIG_CLKIN_HZ=11059200 # CONFIG_BFIN_KERNEL_CLOCK is not set CONFIG_MAX_VCO_HZ=750000000 CONFIG_MIN_VCO_HZ=50000000 -CONFIG_MAX_SCLK_HZ=133333333 +CONFIG_MAX_SCLK_HZ=133000000 CONFIG_MIN_SCLK_HZ=27000000 # @@ -267,6 +263,7 @@ CONFIG_SPLIT_PTLOCK_CPUS=4 # CONFIG_RESOURCES_64BIT is not set CONFIG_ZONE_DMA_FLAG=1 CONFIG_LARGE_ALLOCS=y +# CONFIG_BFIN_GPTIMERS is not set CONFIG_BFIN_DMA_5XX=y # CONFIG_DMA_UNCACHED_2M is not set CONFIG_DMA_UNCACHED_1M=y @@ -288,7 +285,7 @@ CONFIG_L1_MAX_PIECE=16 # # -# EBIU_AMBCTL Global Control +# EBIU_AMGCTL Global Control # CONFIG_C_AMCKEN=y CONFIG_C_CDPRIO=y @@ -634,6 +631,7 @@ CONFIG_SMC91X=y # CONFIG_DM9000 is not set CONFIG_NETDEV_1000=y CONFIG_NETDEV_10000=y +# CONFIG_AX88180 is not set # # Wireless LAN @@ -704,9 +702,9 @@ CONFIG_BFIN_TWIKEYPAD_IRQ_PFX=39 # # CONFIG_AD9960 is not set # CONFIG_SPI_ADC_BF533 is not set -# CONFIG_BFIN_PFLAGS is not set +# CONFIG_BF5xx_PFLAGS is not set # CONFIG_BF5xx_PPIFCD is not set -# CONFIG_BF5xx_TIMERS is not set +# CONFIG_BFIN_SIMPLE_TIMER is not set # CONFIG_BF5xx_PPI is not set CONFIG_BFIN_SPORT=y # CONFIG_BFIN_TIMER_LATENCY is not set @@ -732,6 +730,7 @@ CONFIG_SERIAL_BFIN_DMA=y # CONFIG_SERIAL_BFIN_PIO is not set CONFIG_SERIAL_BFIN_UART0=y # CONFIG_BFIN_UART0_CTSRTS is not set +# CONFIG_SERIAL_BFIN_UART1 is not set CONFIG_SERIAL_CORE=y CONFIG_SERIAL_CORE_CONSOLE=y # CONFIG_SERIAL_BFIN_SPORT is not set @@ -925,6 +924,7 @@ CONFIG_NTSC=y # CONFIG_PAL_YCBCR is not set CONFIG_ADV7393_1XMEM=y # CONFIG_ADV7393_2XMEM is not set +# CONFIG_FB_BFIN_T350MCQB is not set # CONFIG_FB_S1D13XXX is not set # CONFIG_FB_VIRTUAL is not set # CONFIG_LOGO is not set @@ -979,11 +979,6 @@ CONFIG_SND_BFIN_AD73311_SE=4 # CONFIG_SND_SOC is not set # -# SoC Audio for the ADI Blackfin -# -# CONFIG_SND_BF5XX_HAVE_COLD_RESET is not set - -# # Open Sound System # # CONFIG_SOUND_PRIME is not set diff --git a/arch/blackfin/configs/BF537-STAMP_defconfig b/arch/blackfin/configs/BF537-STAMP_defconfig index 07eb63d..f812b66 100644 --- a/arch/blackfin/configs/BF537-STAMP_defconfig +++ b/arch/blackfin/configs/BF537-STAMP_defconfig @@ -1,6 +1,6 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.22.6 +# Linux kernel version: 2.6.22.12 # # CONFIG_MMU is not set # CONFIG_FPU is not set @@ -8,7 +8,6 @@ CONFIG_RWSEM_GENERIC_SPINLOCK=y # CONFIG_RWSEM_XCHGADD_ALGORITHM is not set CONFIG_BLACKFIN=y CONFIG_ZONE_DMA=y -CONFIG_BFIN=y CONFIG_SEMAPHORE_SLEEPERS=y CONFIG_GENERIC_FIND_NEXT_BIT=y CONFIG_GENERIC_HWEIGHT=y @@ -18,7 +17,6 @@ CONFIG_GENERIC_IRQ_PROBE=y CONFIG_GENERIC_GPIO=y CONFIG_FORCE_MAX_ZONEORDER=14 CONFIG_GENERIC_CALIBRATE_DELAY=y -CONFIG_IRQCHIP_DEMUX_GPIO=y CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" # @@ -64,7 +62,6 @@ CONFIG_FUTEX=y CONFIG_ANON_INODES=y CONFIG_EPOLL=y CONFIG_SIGNALFD=y -CONFIG_TIMERFD=y CONFIG_EVENTFD=y CONFIG_VM_EVENT_COUNTERS=y CONFIG_BIG_ORDER_ALLOC_NOFAIL_MAGIC=3 @@ -117,6 +114,9 @@ CONFIG_PREEMPT_VOLUNTARY=y # # Processor and Board Settings # +# CONFIG_BF522 is not set +# CONFIG_BF525 is not set +# CONFIG_BF527 is not set # CONFIG_BF531 is not set # CONFIG_BF532 is not set # CONFIG_BF533 is not set @@ -125,10 +125,12 @@ CONFIG_PREEMPT_VOLUNTARY=y CONFIG_BF537=y # CONFIG_BF542 is not set # CONFIG_BF544 is not set +# CONFIG_BF547 is not set # CONFIG_BF548 is not set # CONFIG_BF549 is not set # CONFIG_BF561 is not set # CONFIG_BF_REV_0_0 is not set +# CONFIG_BF_REV_0_1 is not set CONFIG_BF_REV_0_2=y # CONFIG_BF_REV_0_3 is not set # CONFIG_BF_REV_0_4 is not set @@ -137,33 +139,8 @@ CONFIG_BF_REV_0_2=y # CONFIG_BF_REV_NONE is not set CONFIG_BF53x=y CONFIG_BFIN_SINGLE_CORE=y -# CONFIG_BFIN533_EZKIT is not set -# CONFIG_BFIN533_STAMP is not set -CONFIG_BFIN537_STAMP=y -# CONFIG_BFIN533_BLUETECHNIX_CM is not set -# CONFIG_BFIN537_BLUETECHNIX_CM is not set -# CONFIG_BFIN548_EZKIT is not set -# CONFIG_BFIN561_BLUETECHNIX_CM is not set -# CONFIG_BFIN561_EZKIT is not set -# CONFIG_BFIN561_TEPLA is not set -# CONFIG_PNAV10 is not set -# CONFIG_GENERIC_BOARD is not set CONFIG_MEM_MT48LC32M8A2_75=y CONFIG_IRQ_PLL_WAKEUP=7 - -# -# BF537 Specific Configuration -# - -# -# Interrupt Priority Assignment -# - -# -# Priority -# -CONFIG_IRQ_DMA_ERROR=7 -CONFIG_IRQ_ERROR=7 CONFIG_IRQ_RTC=8 CONFIG_IRQ_PPI=8 CONFIG_IRQ_SPORT0_RX=9 @@ -176,8 +153,6 @@ CONFIG_IRQ_UART0_RX=10 CONFIG_IRQ_UART0_TX=10 CONFIG_IRQ_UART1_RX=10 CONFIG_IRQ_UART1_TX=10 -CONFIG_IRQ_CAN_RX=11 -CONFIG_IRQ_CAN_TX=11 CONFIG_IRQ_MAC_RX=11 CONFIG_IRQ_MAC_TX=11 CONFIG_IRQ_TMR0=12 @@ -188,11 +163,31 @@ CONFIG_IRQ_TMR4=12 CONFIG_IRQ_TMR5=12 CONFIG_IRQ_TMR6=12 CONFIG_IRQ_TMR7=12 -CONFIG_IRQ_PROG_INTA=12 CONFIG_IRQ_PORTG_INTB=12 CONFIG_IRQ_MEM_DMA0=13 CONFIG_IRQ_MEM_DMA1=13 CONFIG_IRQ_WATCH=13 +CONFIG_BFIN537_STAMP=y +# CONFIG_BFIN537_BLUETECHNIX_CM is not set +# CONFIG_PNAV10 is not set +# CONFIG_GENERIC_BF537_BOARD is not set + +# +# BF537 Specific Configuration +# + +# +# Interrupt Priority Assignment +# + +# +# Priority +# +CONFIG_IRQ_DMA_ERROR=7 +CONFIG_IRQ_ERROR=7 +CONFIG_IRQ_CAN_RX=11 +CONFIG_IRQ_CAN_TX=11 +CONFIG_IRQ_PROG_INTA=12 # # Board customizations @@ -206,7 +201,7 @@ CONFIG_CLKIN_HZ=25000000 # CONFIG_BFIN_KERNEL_CLOCK is not set CONFIG_MAX_VCO_HZ=600000000 CONFIG_MIN_VCO_HZ=50000000 -CONFIG_MAX_SCLK_HZ=133333333 +CONFIG_MAX_SCLK_HZ=133000000 CONFIG_MIN_SCLK_HZ=27000000 # @@ -263,6 +258,7 @@ CONFIG_SPLIT_PTLOCK_CPUS=4 # CONFIG_RESOURCES_64BIT is not set CONFIG_ZONE_DMA_FLAG=1 CONFIG_LARGE_ALLOCS=y +# CONFIG_BFIN_GPTIMERS is not set CONFIG_BFIN_DMA_5XX=y # CONFIG_DMA_UNCACHED_2M is not set CONFIG_DMA_UNCACHED_1M=y @@ -284,7 +280,7 @@ CONFIG_L1_MAX_PIECE=16 # # -# EBIU_AMBCTL Global Control +# EBIU_AMGCTL Global Control # CONFIG_C_AMCKEN=y CONFIG_C_CDPRIO=y @@ -534,14 +530,6 @@ CONFIG_MTD_COMPLEX_MAPPINGS=y CONFIG_MTD_BF5xx=m CONFIG_BFIN_FLASH_SIZE=0x400000 CONFIG_EBIU_FLASH_BASE=0x20000000 - -# -# FLASH_EBIU_AMBCTL Control -# -CONFIG_BFIN_FLASH_BANK_0=0x7BB0 -CONFIG_BFIN_FLASH_BANK_1=0x7BB0 -CONFIG_BFIN_FLASH_BANK_2=0x7BB0 -CONFIG_BFIN_FLASH_BANK_3=0x7BB0 # CONFIG_MTD_UCLINUX is not set # CONFIG_MTD_PLATRAM is not set @@ -660,6 +648,7 @@ CONFIG_BFIN_RX_DESC_NUM=20 # CONFIG_DM9000 is not set CONFIG_NETDEV_1000=y CONFIG_NETDEV_10000=y +# CONFIG_AX88180 is not set # # Wireless LAN @@ -730,9 +719,9 @@ CONFIG_BFIN_TWIKEYPAD_IRQ_PFX=72 # # CONFIG_AD9960 is not set # CONFIG_SPI_ADC_BF533 is not set -# CONFIG_BFIN_PFLAGS is not set +# CONFIG_BF5xx_PFLAGS is not set # CONFIG_BF5xx_PPIFCD is not set -# CONFIG_BF5xx_TIMERS is not set +# CONFIG_BFIN_SIMPLE_TIMER is not set # CONFIG_BF5xx_PPI is not set CONFIG_BFIN_SPORT=y # CONFIG_BFIN_TIMER_LATENCY is not set @@ -967,6 +956,7 @@ CONFIG_FB_BF537_LQ035=m CONFIG_LQ035_SLAVE_ADDR=0x58 # CONFIG_FB_BFIN_LANDSCAPE is not set # CONFIG_FB_BFIN_BGR is not set +# CONFIG_FB_BFIN_T350MCQB is not set # CONFIG_FB_S1D13XXX is not set # CONFIG_FB_VIRTUAL is not set # CONFIG_LOGO is not set @@ -1021,11 +1011,6 @@ CONFIG_SND_BFIN_AD73311_SE=4 # CONFIG_SND_SOC is not set # -# SoC Audio for the ADI Blackfin -# -# CONFIG_SND_BF5XX_HAVE_COLD_RESET is not set - -# # Open Sound System # # CONFIG_SOUND_PRIME is not set diff --git a/arch/blackfin/configs/BF548-EZKIT_defconfig b/arch/blackfin/configs/BF548-EZKIT_defconfig index 0dd3d22..48367cc9 100644 --- a/arch/blackfin/configs/BF548-EZKIT_defconfig +++ b/arch/blackfin/configs/BF548-EZKIT_defconfig @@ -1,7 +1,6 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.22.10 -# Sat Oct 27 02:34:07 2007 +# Linux kernel version: 2.6.22.12 # # CONFIG_MMU is not set # CONFIG_FPU is not set @@ -9,7 +8,6 @@ CONFIG_RWSEM_GENERIC_SPINLOCK=y # CONFIG_RWSEM_XCHGADD_ALGORITHM is not set CONFIG_BLACKFIN=y CONFIG_ZONE_DMA=y -CONFIG_BFIN=y CONFIG_SEMAPHORE_SLEEPERS=y CONFIG_GENERIC_FIND_NEXT_BIT=y CONFIG_GENERIC_HWEIGHT=y @@ -19,7 +17,6 @@ CONFIG_GENERIC_IRQ_PROBE=y CONFIG_GENERIC_GPIO=y CONFIG_FORCE_MAX_ZONEORDER=14 CONFIG_GENERIC_CALIBRATE_DELAY=y -CONFIG_IRQCHIP_DEMUX_GPIO=y CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" # @@ -128,6 +125,7 @@ CONFIG_PREEMPT_VOLUNTARY=y # CONFIG_BF537 is not set # CONFIG_BF542 is not set # CONFIG_BF544 is not set +# CONFIG_BF547 is not set # CONFIG_BF548 is not set CONFIG_BF549=y # CONFIG_BF561 is not set @@ -141,19 +139,6 @@ CONFIG_BF_REV_0_0=y # CONFIG_BF_REV_NONE is not set CONFIG_BF54x=y CONFIG_BFIN_SINGLE_CORE=y -# CONFIG_BFIN527_EZKIT is not set -# CONFIG_BFIN533_EZKIT is not set -# CONFIG_BFIN533_STAMP is not set -# CONFIG_BFIN537_STAMP is not set -# CONFIG_BFIN533_BLUETECHNIX_CM is not set -# CONFIG_BFIN537_BLUETECHNIX_CM is not set -CONFIG_BFIN548_EZKIT=y -# CONFIG_BFIN561_BLUETECHNIX_CM is not set -# CONFIG_BFIN561_EZKIT is not set -# CONFIG_BFIN561_TEPLA is not set -# CONFIG_PNAV10 is not set -# CONFIG_H8606_HVSISTEMAS is not set -# CONFIG_GENERIC_BOARD is not set CONFIG_IRQ_PLL_WAKEUP=7 CONFIG_IRQ_RTC=8 CONFIG_IRQ_SPORT0_RX=9 @@ -180,6 +165,7 @@ CONFIG_IRQ_TIMER7=11 CONFIG_IRQ_TIMER8=11 CONFIG_IRQ_TIMER9=11 CONFIG_IRQ_TIMER10=11 +CONFIG_BFIN548_EZKIT=y # # BF548 Specific Configuration @@ -279,9 +265,9 @@ CONFIG_PINT3_ASSIGN=0x02020303 # CONFIG_CLKIN_HZ=25000000 # CONFIG_BFIN_KERNEL_CLOCK is not set -CONFIG_MAX_VCO_HZ=533333333 +CONFIG_MAX_VCO_HZ=533000000 CONFIG_MIN_VCO_HZ=50000000 -CONFIG_MAX_SCLK_HZ=133333333 +CONFIG_MAX_SCLK_HZ=133000000 CONFIG_MIN_SCLK_HZ=27000000 # @@ -376,6 +362,9 @@ CONFIG_BANK_0=0x7BB0 CONFIG_BANK_1=0x5554 CONFIG_BANK_2=0x7BB0 CONFIG_BANK_3=0x99B3 +CONFIG_EBUI_MBSCTLVAL=0x0 +CONFIG_EBUI_MODEVAL=0x1 +CONFIG_EBUI_FCTLVAL=0x6 # # Bus options (PCI, PCMCIA, EISA, MCA, ISA) @@ -702,6 +691,7 @@ CONFIG_SMSC911X=y # CONFIG_DM9000 is not set CONFIG_NETDEV_1000=y CONFIG_NETDEV_10000=y +# CONFIG_AX88180 is not set # # Wireless LAN @@ -1058,6 +1048,8 @@ CONFIG_SND_SOC=y CONFIG_SND_BF5XX_SOC=y CONFIG_SND_BF5XX_SOC_AC97=y CONFIG_SND_BF5XX_SOC_BF548_EZKIT=y +# CONFIG_SND_BF5XX_SOC_WM8750 is not set +# CONFIG_SND_BF5XX_SOC_WM8731 is not set CONFIG_SND_BF5XX_SPORT_NUM=0 # CONFIG_SND_BF5XX_HAVE_COLD_RESET is not set CONFIG_SND_SOC_AD1980=y diff --git a/arch/blackfin/configs/BF561-EZKIT_defconfig b/arch/blackfin/configs/BF561-EZKIT_defconfig index 277d72d..e9f100b 100644 --- a/arch/blackfin/configs/BF561-EZKIT_defconfig +++ b/arch/blackfin/configs/BF561-EZKIT_defconfig @@ -1,6 +1,6 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.22.6 +# Linux kernel version: 2.6.22.12 # # CONFIG_MMU is not set # CONFIG_FPU is not set @@ -8,7 +8,6 @@ CONFIG_RWSEM_GENERIC_SPINLOCK=y # CONFIG_RWSEM_XCHGADD_ALGORITHM is not set CONFIG_BLACKFIN=y CONFIG_ZONE_DMA=y -CONFIG_BFIN=y CONFIG_SEMAPHORE_SLEEPERS=y CONFIG_GENERIC_FIND_NEXT_BIT=y CONFIG_GENERIC_HWEIGHT=y @@ -18,7 +17,6 @@ CONFIG_GENERIC_IRQ_PROBE=y CONFIG_GENERIC_GPIO=y CONFIG_FORCE_MAX_ZONEORDER=14 CONFIG_GENERIC_CALIBRATE_DELAY=y -CONFIG_IRQCHIP_DEMUX_GPIO=y CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" # @@ -64,7 +62,6 @@ CONFIG_FUTEX=y CONFIG_ANON_INODES=y CONFIG_EPOLL=y CONFIG_SIGNALFD=y -CONFIG_TIMERFD=y CONFIG_EVENTFD=y CONFIG_VM_EVENT_COUNTERS=y CONFIG_BIG_ORDER_ALLOC_NOFAIL_MAGIC=3 @@ -117,6 +114,9 @@ CONFIG_PREEMPT_VOLUNTARY=y # # Processor and Board Settings # +# CONFIG_BF522 is not set +# CONFIG_BF525 is not set +# CONFIG_BF527 is not set # CONFIG_BF531 is not set # CONFIG_BF532 is not set # CONFIG_BF533 is not set @@ -125,10 +125,12 @@ CONFIG_PREEMPT_VOLUNTARY=y # CONFIG_BF537 is not set # CONFIG_BF542 is not set # CONFIG_BF544 is not set +# CONFIG_BF547 is not set # CONFIG_BF548 is not set # CONFIG_BF549 is not set CONFIG_BF561=y # CONFIG_BF_REV_0_0 is not set +# CONFIG_BF_REV_0_1 is not set # CONFIG_BF_REV_0_2 is not set CONFIG_BF_REV_0_3=y # CONFIG_BF_REV_0_4 is not set @@ -136,18 +138,15 @@ CONFIG_BF_REV_0_3=y # CONFIG_BF_REV_ANY is not set # CONFIG_BF_REV_NONE is not set CONFIG_BFIN_DUAL_CORE=y -# CONFIG_BFIN533_EZKIT is not set -# CONFIG_BFIN533_STAMP is not set -# CONFIG_BFIN537_STAMP is not set -# CONFIG_BFIN533_BLUETECHNIX_CM is not set -# CONFIG_BFIN537_BLUETECHNIX_CM is not set -# CONFIG_BFIN548_EZKIT is not set -# CONFIG_BFIN561_BLUETECHNIX_CM is not set +CONFIG_MEM_MT48LC16M16A2TG_75=y +CONFIG_IRQ_PLL_WAKEUP=7 +CONFIG_IRQ_SPORT0_ERROR=7 +CONFIG_IRQ_SPORT1_ERROR=7 +CONFIG_IRQ_SPI_ERROR=7 CONFIG_BFIN561_EZKIT=y # CONFIG_BFIN561_TEPLA is not set -# CONFIG_PNAV10 is not set -# CONFIG_GENERIC_BOARD is not set -CONFIG_MEM_MT48LC16M16A2TG_75=y +# CONFIG_BFIN561_BLUETECHNIX_CM is not set +# CONFIG_GENERIC_BF561_BOARD is not set # # BF561 Specific Configuration @@ -170,15 +169,11 @@ CONFIG_BF561_COREB_RESET=y # # Priority # -CONFIG_IRQ_PLL_WAKEUP=7 CONFIG_IRQ_DMA1_ERROR=7 CONFIG_IRQ_DMA2_ERROR=7 CONFIG_IRQ_IMDMA_ERROR=7 CONFIG_IRQ_PPI0_ERROR=7 CONFIG_IRQ_PPI1_ERROR=7 -CONFIG_IRQ_SPORT0_ERROR=7 -CONFIG_IRQ_SPORT1_ERROR=7 -CONFIG_IRQ_SPI_ERROR=7 CONFIG_IRQ_UART_ERROR=7 CONFIG_IRQ_RESERVED_ERROR=7 CONFIG_IRQ_DMA1_0=8 @@ -243,7 +238,7 @@ CONFIG_CLKIN_HZ=30000000 # CONFIG_BFIN_KERNEL_CLOCK is not set CONFIG_MAX_VCO_HZ=600000000 CONFIG_MIN_VCO_HZ=50000000 -CONFIG_MAX_SCLK_HZ=133333333 +CONFIG_MAX_SCLK_HZ=133000000 CONFIG_MIN_SCLK_HZ=27000000 # @@ -300,6 +295,7 @@ CONFIG_SPLIT_PTLOCK_CPUS=4 # CONFIG_RESOURCES_64BIT is not set CONFIG_ZONE_DMA_FLAG=1 CONFIG_LARGE_ALLOCS=y +# CONFIG_BFIN_GPTIMERS is not set CONFIG_BFIN_DMA_5XX=y # CONFIG_DMA_UNCACHED_2M is not set CONFIG_DMA_UNCACHED_1M=y @@ -321,7 +317,7 @@ CONFIG_L1_MAX_PIECE=16 # # -# EBIU_AMBCTL Global Control +# EBIU_AMGCTL Global Control # CONFIG_C_AMCKEN=y CONFIG_C_CDPRIO=y @@ -564,14 +560,6 @@ CONFIG_MTD_COMPLEX_MAPPINGS=y CONFIG_MTD_BF5xx=m CONFIG_BFIN_FLASH_SIZE=0x0400000 CONFIG_EBIU_FLASH_BASE=0x20000000 - -# -# FLASH_EBIU_AMBCTL Control -# -CONFIG_BFIN_FLASH_BANK_0=0x7BB0 -CONFIG_BFIN_FLASH_BANK_1=0x7BB0 -CONFIG_BFIN_FLASH_BANK_2=0x7BB0 -CONFIG_BFIN_FLASH_BANK_3=0x7BB0 # CONFIG_MTD_UCLINUX is not set # CONFIG_MTD_PLATRAM is not set @@ -660,6 +648,7 @@ CONFIG_SMC91X=y # CONFIG_DM9000 is not set CONFIG_NETDEV_1000=y CONFIG_NETDEV_10000=y +# CONFIG_AX88180 is not set # # Wireless LAN @@ -721,9 +710,9 @@ CONFIG_INPUT_EVDEV=m # # CONFIG_AD9960 is not set # CONFIG_SPI_ADC_BF533 is not set -# CONFIG_BFIN_PFLAGS is not set +# CONFIG_BF5xx_PFLAGS is not set # CONFIG_BF5xx_PPIFCD is not set -# CONFIG_BF5xx_TIMERS is not set +# CONFIG_BFIN_SIMPLE_TIMER is not set # CONFIG_BF5xx_PPI is not set # CONFIG_BFIN_SPORT is not set # CONFIG_BFIN_TIMER_LATENCY is not set diff --git a/arch/blackfin/configs/H8606_defconfig b/arch/blackfin/configs/H8606_defconfig new file mode 100644 index 0000000..18cbb8c --- /dev/null +++ b/arch/blackfin/configs/H8606_defconfig @@ -0,0 +1,1160 @@ +# +# Automatically generated make config: don't edit +# Linux kernel version: 2.6.22.12 +# +# CONFIG_MMU is not set +# CONFIG_FPU is not set +CONFIG_RWSEM_GENERIC_SPINLOCK=y +# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set +CONFIG_BLACKFIN=y +CONFIG_ZONE_DMA=y +CONFIG_SEMAPHORE_SLEEPERS=y +CONFIG_GENERIC_FIND_NEXT_BIT=y +CONFIG_GENERIC_HWEIGHT=y +CONFIG_GENERIC_HARDIRQS=y +CONFIG_GENERIC_IRQ_PROBE=y +# CONFIG_GENERIC_TIME is not set +CONFIG_GENERIC_GPIO=y +CONFIG_FORCE_MAX_ZONEORDER=14 +CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y +CONFIG_BROKEN_ON_SMP=y +CONFIG_INIT_ENV_ARG_LIMIT=32 + +# +# General setup +# +CONFIG_LOCALVERSION="" +CONFIG_LOCALVERSION_AUTO=y +CONFIG_SYSVIPC=y +# CONFIG_IPC_NS is not set +CONFIG_SYSVIPC_SYSCTL=y +# CONFIG_POSIX_MQUEUE is not set +# CONFIG_BSD_PROCESS_ACCT is not set +# CONFIG_TASKSTATS is not set +# CONFIG_UTS_NS is not set +# CONFIG_AUDIT is not set +# CONFIG_IKCONFIG is not set +CONFIG_LOG_BUF_SHIFT=14 +CONFIG_SYSFS_DEPRECATED=y +# CONFIG_RELAY is not set +# CONFIG_BLK_DEV_INITRD is not set +# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set +CONFIG_SYSCTL=y +CONFIG_EMBEDDED=y +CONFIG_UID16=y +CONFIG_SYSCTL_SYSCALL=y +CONFIG_KALLSYMS=y +# CONFIG_KALLSYMS_EXTRA_PASS is not set +CONFIG_HOTPLUG=y +CONFIG_PRINTK=y +CONFIG_BUG=y +CONFIG_ELF_CORE=y +CONFIG_BASE_FULL=y +CONFIG_FUTEX=y +CONFIG_ANON_INODES=y +CONFIG_EPOLL=y +CONFIG_SIGNALFD=y +CONFIG_EVENTFD=y +CONFIG_VM_EVENT_COUNTERS=y +CONFIG_BIG_ORDER_ALLOC_NOFAIL_MAGIC=3 +# CONFIG_NP2 is not set +CONFIG_SLAB=y +# CONFIG_SLUB is not set +# CONFIG_SLOB is not set +CONFIG_RT_MUTEXES=y +CONFIG_TINY_SHMEM=y +CONFIG_BASE_SMALL=0 + +# +# Loadable module support +# +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +# CONFIG_MODULE_FORCE_UNLOAD is not set +# CONFIG_MODVERSIONS is not set +# CONFIG_MODULE_SRCVERSION_ALL is not set +CONFIG_KMOD=y + +# +# Block layer +# +CONFIG_BLOCK=y +# CONFIG_LBD is not set +# CONFIG_BLK_DEV_IO_TRACE is not set +# CONFIG_LSF is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +# CONFIG_IOSCHED_DEADLINE is not set +CONFIG_IOSCHED_CFQ=y +CONFIG_DEFAULT_AS=y +# CONFIG_DEFAULT_DEADLINE is not set +# CONFIG_DEFAULT_CFQ is not set +# CONFIG_DEFAULT_NOOP is not set +CONFIG_DEFAULT_IOSCHED="anticipatory" +CONFIG_PREEMPT_NONE=y +# CONFIG_PREEMPT_VOLUNTARY is not set +# CONFIG_PREEMPT is not set + +# +# Blackfin Processor Options +# + +# +# Processor and Board Settings +# +# CONFIG_BF522 is not set +# CONFIG_BF525 is not set +# CONFIG_BF527 is not set +# CONFIG_BF531 is not set +CONFIG_BF532=y +# CONFIG_BF533 is not set +# CONFIG_BF534 is not set +# CONFIG_BF536 is not set +# CONFIG_BF537 is not set +# CONFIG_BF542 is not set +# CONFIG_BF544 is not set +# CONFIG_BF547 is not set +# CONFIG_BF548 is not set +# CONFIG_BF549 is not set +# CONFIG_BF561 is not set +# CONFIG_BF_REV_0_0 is not set +# CONFIG_BF_REV_0_1 is not set +# CONFIG_BF_REV_0_2 is not set +# CONFIG_BF_REV_0_3 is not set +# CONFIG_BF_REV_0_4 is not set +CONFIG_BF_REV_0_5=y +# CONFIG_BF_REV_ANY is not set +# CONFIG_BF_REV_NONE is not set +CONFIG_BF53x=y +CONFIG_BFIN_SINGLE_CORE=y +CONFIG_MEM_MT48LC16M16A2TG_75=y +# CONFIG_BFIN533_EZKIT is not set +# CONFIG_BFIN533_STAMP is not set +# CONFIG_BFIN533_BLUETECHNIX_CM is not set +CONFIG_H8606_HVSISTEMAS=y +# CONFIG_GENERIC_BF533_BOARD is not set + +# +# BF533/2/1 Specific Configuration +# + +# +# Interrupt Priority Assignment +# + +# +# Priority +# +CONFIG_UART_ERROR=7 +CONFIG_SPORT0_ERROR=7 +CONFIG_SPI_ERROR=7 +CONFIG_SPORT1_ERROR=7 +CONFIG_PPI_ERROR=7 +CONFIG_DMA_ERROR=7 +CONFIG_PLLWAKE_ERROR=7 +CONFIG_RTC_ERROR=8 +CONFIG_DMA0_PPI=8 +CONFIG_DMA1_SPORT0RX=9 +CONFIG_DMA2_SPORT0TX=9 +CONFIG_DMA3_SPORT1RX=9 +CONFIG_DMA4_SPORT1TX=9 +CONFIG_DMA5_SPI=10 +CONFIG_DMA6_UARTRX=10 +CONFIG_DMA7_UARTTX=10 +CONFIG_TIMER0=11 +CONFIG_TIMER1=11 +CONFIG_TIMER2=11 +CONFIG_PFA=12 +CONFIG_PFB=12 +CONFIG_MEMDMA0=13 +CONFIG_MEMDMA1=13 +CONFIG_WDTIMER=13 + +# +# Board customizations +# +# CONFIG_CMDLINE_BOOL is not set + +# +# Clock/PLL Setup +# +CONFIG_CLKIN_HZ=25000000 +# CONFIG_BFIN_KERNEL_CLOCK is not set +CONFIG_MAX_VCO_HZ=400000000 +CONFIG_MIN_VCO_HZ=50000000 +CONFIG_MAX_SCLK_HZ=133000000 +CONFIG_MIN_SCLK_HZ=27000000 + +# +# Kernel Timer/Scheduler +# +# CONFIG_HZ_100 is not set +CONFIG_HZ_250=y +# CONFIG_HZ_300 is not set +# CONFIG_HZ_1000 is not set +CONFIG_HZ=250 + +# +# Memory Setup +# +CONFIG_MEM_SIZE=32 +CONFIG_MEM_ADD_WIDTH=9 +CONFIG_BOOT_LOAD=0x1000 +CONFIG_BFIN_SCRATCH_REG_RETN=y +# CONFIG_BFIN_SCRATCH_REG_RETE is not set +# CONFIG_BFIN_SCRATCH_REG_CYCLES is not set + +# +# Blackfin Kernel Optimizations +# + +# +# Memory Optimizations +# +CONFIG_I_ENTRY_L1=y +CONFIG_EXCPT_IRQ_SYSC_L1=y +CONFIG_DO_IRQ_L1=y +CONFIG_CORE_TIMER_IRQ_L1=y +CONFIG_IDLE_L1=y +CONFIG_SCHEDULE_L1=y +CONFIG_ARITHMETIC_OPS_L1=y +CONFIG_ACCESS_OK_L1=y +CONFIG_MEMSET_L1=y +CONFIG_MEMCPY_L1=y +CONFIG_SYS_BFIN_SPINLOCK_L1=y +# CONFIG_IP_CHECKSUM_L1 is not set +# CONFIG_CACHELINE_ALIGNED_L1 is not set +# CONFIG_SYSCALL_TAB_L1 is not set +# CONFIG_CPLB_SWITCH_TAB_L1 is not set +CONFIG_RAMKERNEL=y +# CONFIG_ROMKERNEL is not set +CONFIG_SELECT_MEMORY_MODEL=y +CONFIG_FLATMEM_MANUAL=y +# CONFIG_DISCONTIGMEM_MANUAL is not set +# CONFIG_SPARSEMEM_MANUAL is not set +CONFIG_FLATMEM=y +CONFIG_FLAT_NODE_MEM_MAP=y +# CONFIG_SPARSEMEM_STATIC is not set +CONFIG_SPLIT_PTLOCK_CPUS=4 +# CONFIG_RESOURCES_64BIT is not set +CONFIG_ZONE_DMA_FLAG=1 +CONFIG_LARGE_ALLOCS=y +CONFIG_BFIN_GPTIMERS=y +CONFIG_BFIN_DMA_5XX=y +# CONFIG_DMA_UNCACHED_2M is not set +CONFIG_DMA_UNCACHED_1M=y +# CONFIG_DMA_UNCACHED_NONE is not set + +# +# Cache Support +# +CONFIG_BFIN_ICACHE=y +CONFIG_BFIN_DCACHE=y +# CONFIG_BFIN_DCACHE_BANKA is not set +CONFIG_BFIN_ICACHE_LOCK=y +CONFIG_BFIN_WB=y +# CONFIG_BFIN_WT is not set +CONFIG_L1_MAX_PIECE=16 + +# +# Asynchonous Memory Configuration +# + +# +# EBIU_AMGCTL Global Control +# +CONFIG_C_AMCKEN=y +CONFIG_C_CDPRIO=y +# CONFIG_C_AMBEN is not set +# CONFIG_C_AMBEN_B0 is not set +# CONFIG_C_AMBEN_B0_B1 is not set +# CONFIG_C_AMBEN_B0_B1_B2 is not set +CONFIG_C_AMBEN_ALL=y + +# +# EBIU_AMBCTL Control +# +CONFIG_BANK_0=0x7BB0 +CONFIG_BANK_1=0x7BB0 +CONFIG_BANK_2=0x7BB0 +CONFIG_BANK_3=0x99B3 + +# +# Bus options (PCI, PCMCIA, EISA, MCA, ISA) +# +# CONFIG_PCI is not set +# CONFIG_ARCH_SUPPORTS_MSI is not set + +# +# PCCARD (PCMCIA/CardBus) support +# +# CONFIG_PCCARD is not set + +# +# Executable file formats +# +CONFIG_BINFMT_ELF_FDPIC=y +CONFIG_BINFMT_FLAT=y +CONFIG_BINFMT_ZFLAT=y +# CONFIG_BINFMT_SHARED_FLAT is not set +# CONFIG_BINFMT_MISC is not set + +# +# Power management options +# +CONFIG_PM=y +CONFIG_PM_LEGACY=y +# CONFIG_PM_DEBUG is not set +# CONFIG_PM_SYSFS_DEPRECATED is not set +CONFIG_PM_WAKEUP_GPIO_BY_SIC_IWR=y +# CONFIG_PM_WAKEUP_BY_GPIO is not set +# CONFIG_PM_WAKEUP_GPIO_API is not set +CONFIG_PM_WAKEUP_SIC_IWR=0x100000 + +# +# Networking +# +CONFIG_NET=y + +# +# Networking options +# +CONFIG_PACKET=y +# CONFIG_PACKET_MMAP is not set +CONFIG_UNIX=y +CONFIG_XFRM=y +# CONFIG_XFRM_USER is not set +# CONFIG_XFRM_SUB_POLICY is not set +# CONFIG_XFRM_MIGRATE is not set +# CONFIG_NET_KEY is not set +CONFIG_INET=y +# CONFIG_IP_MULTICAST is not set +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_FIB_HASH=y +CONFIG_IP_PNP=y +# CONFIG_IP_PNP_DHCP is not set +# CONFIG_IP_PNP_BOOTP is not set +# CONFIG_IP_PNP_RARP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_ARPD is not set +CONFIG_SYN_COOKIES=y +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_INET_XFRM_TUNNEL is not set +# CONFIG_INET_TUNNEL is not set +CONFIG_INET_XFRM_MODE_TRANSPORT=y +CONFIG_INET_XFRM_MODE_TUNNEL=y +CONFIG_INET_XFRM_MODE_BEET=y +CONFIG_INET_DIAG=y +CONFIG_INET_TCP_DIAG=y +# CONFIG_TCP_CONG_ADVANCED is not set +CONFIG_TCP_CONG_CUBIC=y +CONFIG_DEFAULT_TCP_CONG="cubic" +# CONFIG_TCP_MD5SIG is not set +# CONFIG_IPV6 is not set +# CONFIG_INET6_XFRM_TUNNEL is not set +# CONFIG_INET6_TUNNEL is not set +# CONFIG_NETLABEL is not set +# CONFIG_NETWORK_SECMARK is not set +# CONFIG_NETFILTER is not set +# CONFIG_IP_DCCP is not set +# CONFIG_IP_SCTP is not set +# CONFIG_TIPC is not set +# CONFIG_ATM is not set +# CONFIG_BRIDGE is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_DECNET is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set + +# +# QoS and/or fair queueing +# +# CONFIG_NET_SCHED is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +# CONFIG_HAMRADIO is not set +CONFIG_IRDA=m + +# +# IrDA protocols +# +CONFIG_IRLAN=m +CONFIG_IRCOMM=m +# CONFIG_IRDA_ULTRA is not set + +# +# IrDA options +# +CONFIG_IRDA_CACHE_LAST_LSAP=y +# CONFIG_IRDA_FAST_RR is not set +# CONFIG_IRDA_DEBUG is not set + +# +# Infrared-port device drivers +# + +# +# SIR device drivers +# +CONFIG_IRTTY_SIR=m + +# +# Dongle support +# +# CONFIG_DONGLE is not set + +# +# Old SIR device drivers +# +# CONFIG_IRPORT_SIR is not set + +# +# Old Serial dongle support +# + +# +# FIR device drivers +# +# CONFIG_BT is not set +# CONFIG_AF_RXRPC is not set + +# +# Wireless +# +# CONFIG_CFG80211 is not set +# CONFIG_WIRELESS_EXT is not set +# CONFIG_MAC80211 is not set +# CONFIG_IEEE80211 is not set +# CONFIG_RFKILL is not set + +# +# Device Drivers +# + +# +# Generic Driver Options +# +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y +# CONFIG_FW_LOADER is not set +# CONFIG_SYS_HYPERVISOR is not set + +# +# Connector - unified userspace <-> kernelspace linker +# +# CONFIG_CONNECTOR is not set +CONFIG_MTD=y +# CONFIG_MTD_DEBUG is not set +# CONFIG_MTD_CONCAT is not set +CONFIG_MTD_PARTITIONS=y +# CONFIG_MTD_REDBOOT_PARTS is not set +# CONFIG_MTD_CMDLINE_PARTS is not set + +# +# User Modules And Translation Layers +# +CONFIG_MTD_CHAR=y +CONFIG_MTD_BLKDEVS=y +CONFIG_MTD_BLOCK=y +# CONFIG_FTL is not set +# CONFIG_NFTL is not set +# CONFIG_INFTL is not set +# CONFIG_RFD_FTL is not set +# CONFIG_SSFDC is not set + +# +# RAM/ROM/Flash chip drivers +# +# CONFIG_MTD_CFI is not set +# CONFIG_MTD_JEDECPROBE is not set +CONFIG_MTD_MAP_BANK_WIDTH_1=y +CONFIG_MTD_MAP_BANK_WIDTH_2=y +CONFIG_MTD_MAP_BANK_WIDTH_4=y +# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set +CONFIG_MTD_CFI_I1=y +CONFIG_MTD_CFI_I2=y +# CONFIG_MTD_CFI_I4 is not set +# CONFIG_MTD_CFI_I8 is not set +CONFIG_MTD_RAM=y +CONFIG_MTD_ROM=y +# CONFIG_MTD_ABSENT is not set + +# +# Mapping drivers for chip access +# +CONFIG_MTD_COMPLEX_MAPPINGS=y +# CONFIG_MTD_PHYSMAP is not set +# CONFIG_MTD_BF5xx is not set +# CONFIG_MTD_UCLINUX is not set +# CONFIG_MTD_PLATRAM is not set + +# +# Self-contained MTD device drivers +# +# CONFIG_MTD_DATAFLASH is not set +CONFIG_MTD_M25P80=y +CONFIG_M25PXX_USE_FAST_READ=y +# CONFIG_MTD_SLRAM is not set +# CONFIG_MTD_PHRAM is not set +# CONFIG_MTD_MTDRAM is not set +# CONFIG_MTD_BLOCK2MTD is not set + +# +# Disk-On-Chip Device Drivers +# +# CONFIG_MTD_DOC2000 is not set +# CONFIG_MTD_DOC2001 is not set +# CONFIG_MTD_DOC2001PLUS is not set +# CONFIG_MTD_NAND is not set +# CONFIG_MTD_ONENAND is not set + +# +# UBI - Unsorted block images +# +# CONFIG_MTD_UBI is not set + +# +# Parallel port support +# +# CONFIG_PARPORT is not set + +# +# Plug and Play support +# +# CONFIG_PNPACPI is not set + +# +# Block devices +# +# CONFIG_BLK_DEV_COW_COMMON is not set +# CONFIG_BLK_DEV_LOOP is not set +# CONFIG_BLK_DEV_NBD is not set +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_COUNT=16 +CONFIG_BLK_DEV_RAM_SIZE=4096 +CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024 +# CONFIG_CDROM_PKTCDVD is not set +# CONFIG_ATA_OVER_ETH is not set + +# +# Misc devices +# +# CONFIG_IDE is not set + +# +# SCSI device support +# +# CONFIG_RAID_ATTRS is not set +# CONFIG_SCSI is not set +# CONFIG_SCSI_NETLINK is not set +# CONFIG_ATA is not set + +# +# Multi-device support (RAID and LVM) +# +# CONFIG_MD is not set + +# +# Network device support +# +CONFIG_NETDEVICES=y +# CONFIG_DUMMY is not set +# CONFIG_BONDING is not set +# CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set +# CONFIG_PHYLIB is not set + +# +# Ethernet (10 or 100Mbit) +# +CONFIG_NET_ETHERNET=y +CONFIG_MII=y +# CONFIG_SMC91X is not set +# CONFIG_SMSC911X is not set +CONFIG_DM9000=y +CONFIG_NETDEV_1000=y +CONFIG_NETDEV_10000=y +# CONFIG_AX88180 is not set + +# +# Wireless LAN +# +# CONFIG_WLAN_PRE80211 is not set +# CONFIG_WLAN_80211 is not set +# CONFIG_WAN is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set +# CONFIG_SHAPER is not set +# CONFIG_NETCONSOLE is not set +# CONFIG_NETPOLL is not set +# CONFIG_NET_POLL_CONTROLLER is not set + +# +# ISDN subsystem +# +# CONFIG_ISDN is not set + +# +# Telephony Support +# +# CONFIG_PHONE is not set + +# +# Input device support +# +CONFIG_INPUT=y +# CONFIG_INPUT_FF_MEMLESS is not set +# CONFIG_INPUT_POLLDEV is not set + +# +# Userland interfaces +# +# CONFIG_INPUT_MOUSEDEV is not set +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_TSDEV is not set +CONFIG_INPUT_EVDEV=m +# CONFIG_INPUT_EVBUG is not set + +# +# Input Device Drivers +# +# CONFIG_INPUT_KEYBOARD is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TABLET is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +CONFIG_INPUT_MISC=y +# CONFIG_INPUT_ATI_REMOTE is not set +# CONFIG_INPUT_ATI_REMOTE2 is not set +# CONFIG_INPUT_KEYSPAN_REMOTE is not set +# CONFIG_INPUT_POWERMATE is not set +# CONFIG_INPUT_YEALINK is not set +# CONFIG_INPUT_UINPUT is not set +# CONFIG_BF53X_PFBUTTONS is not set + +# +# Hardware I/O ports +# +# CONFIG_SERIO is not set +# CONFIG_GAMEPORT is not set + +# +# Character devices +# +# CONFIG_AD9960 is not set +# CONFIG_SPI_ADC_BF533 is not set +CONFIG_BF5xx_PFLAGS=y +# CONFIG_BF5xx_PFLAGS_PROC is not set +# CONFIG_BF5xx_PPIFCD is not set +CONFIG_BFIN_SIMPLE_TIMER=y +# CONFIG_BF5xx_PPI is not set +CONFIG_BFIN_SPORT=y +CONFIG_BFIN_TIMER_LATENCY=y +# CONFIG_AD5304 is not set +# CONFIG_BF5xx_FBDMA is not set +# CONFIG_VT is not set +# CONFIG_SERIAL_NONSTANDARD is not set + +# +# Serial drivers +# +# CONFIG_SERIAL_8250 is not set + +# +# Non-8250 serial port support +# +CONFIG_SERIAL_BFIN=y +CONFIG_SERIAL_BFIN_CONSOLE=y +CONFIG_SERIAL_BFIN_DMA=y +# CONFIG_SERIAL_BFIN_PIO is not set +CONFIG_SERIAL_BFIN_UART0=y +# CONFIG_BFIN_UART0_CTSRTS is not set +# CONFIG_SERIAL_BFIN_UART1 is not set +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +# CONFIG_SERIAL_BFIN_SPORT is not set +CONFIG_UNIX98_PTYS=y +# CONFIG_LEGACY_PTYS is not set + +# +# CAN, the car bus and industrial fieldbus +# +# CONFIG_CAN4LINUX is not set + +# +# IPMI +# +# CONFIG_IPMI_HANDLER is not set +CONFIG_WATCHDOG=y +# CONFIG_WATCHDOG_NOWAYOUT is not set + +# +# Watchdog Device Drivers +# +# CONFIG_SOFT_WATCHDOG is not set +# CONFIG_BFIN_WDT is not set +# CONFIG_HW_RANDOM is not set +# CONFIG_GEN_RTC is not set +CONFIG_BLACKFIN_DPMC=y +# CONFIG_R3964 is not set +# CONFIG_RAW_DRIVER is not set + +# +# TPM devices +# +# CONFIG_TCG_TPM is not set +# CONFIG_I2C is not set + +# +# SPI support +# +CONFIG_SPI=y +CONFIG_SPI_MASTER=y + +# +# SPI Master Controller Drivers +# +CONFIG_SPI_BFIN=y +# CONFIG_SPI_BITBANG is not set + +# +# SPI Protocol Masters +# +CONFIG_SPI_AT25=y +CONFIG_SPI_SPIDEV=y + +# +# Dallas's 1-wire bus +# +# CONFIG_W1 is not set +CONFIG_HWMON=y +# CONFIG_HWMON_VID is not set +# CONFIG_SENSORS_ABITUGURU is not set +# CONFIG_SENSORS_F71805F is not set +# CONFIG_SENSORS_LM70 is not set +# CONFIG_SENSORS_PC87427 is not set +# CONFIG_SENSORS_SMSC47M1 is not set +# CONFIG_SENSORS_SMSC47B397 is not set +# CONFIG_SENSORS_VT1211 is not set +# CONFIG_SENSORS_W83627HF is not set +# CONFIG_HWMON_DEBUG_CHIP is not set + +# +# Multifunction device drivers +# +# CONFIG_MFD_SM501 is not set + +# +# Multimedia devices +# +# CONFIG_VIDEO_DEV is not set +# CONFIG_DVB_CORE is not set +CONFIG_DAB=y + +# +# Graphics support +# +# CONFIG_BACKLIGHT_LCD_SUPPORT is not set + +# +# Display device support +# +# CONFIG_DISPLAY_SUPPORT is not set +# CONFIG_VGASTATE is not set +# CONFIG_FB is not set + +# +# Sound +# +CONFIG_SOUND=m + +# +# Advanced Linux Sound Architecture +# +CONFIG_SND=m +CONFIG_SND_TIMER=m +CONFIG_SND_PCM=m +# CONFIG_SND_SEQUENCER is not set +CONFIG_SND_OSSEMUL=y +CONFIG_SND_MIXER_OSS=m +CONFIG_SND_PCM_OSS=m +CONFIG_SND_PCM_OSS_PLUGINS=y +# CONFIG_SND_DYNAMIC_MINORS is not set +CONFIG_SND_SUPPORT_OLD_API=y +CONFIG_SND_VERBOSE_PROCFS=y +# CONFIG_SND_VERBOSE_PRINTK is not set +# CONFIG_SND_DEBUG is not set + +# +# Generic devices +# +# CONFIG_SND_DUMMY is not set +# CONFIG_SND_MTPAV is not set +# CONFIG_SND_SERIAL_U16550 is not set +# CONFIG_SND_MPU401 is not set + +# +# ALSA Blackfin devices +# +CONFIG_SND_BLACKFIN_AD1836=m +CONFIG_SND_BLACKFIN_AD1836_TDM=y +# CONFIG_SND_BLACKFIN_AD1836_I2S is not set +CONFIG_SND_BLACKFIN_AD1836_MULSUB=y +# CONFIG_SND_BLACKFIN_AD1836_5P1 is not set +CONFIG_SND_BLACKFIN_SPORT=0 +CONFIG_SND_BLACKFIN_SPI_PFBIT=4 +# CONFIG_SND_BFIN_AD73311 is not set + +# +# System on Chip audio support +# +# CONFIG_SND_SOC is not set + +# +# Open Sound System +# +# CONFIG_SOUND_PRIME is not set + +# +# HID Devices +# +CONFIG_HID=y +# CONFIG_HID_DEBUG is not set + +# +# USB support +# +CONFIG_USB_ARCH_HAS_HCD=y +# CONFIG_USB_ARCH_HAS_OHCI is not set +# CONFIG_USB_ARCH_HAS_EHCI is not set +# CONFIG_USB is not set + +# +# Enable Host or Gadget support to see Inventra options +# + +# +# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' +# + +# +# USB Gadget Support +# +# CONFIG_USB_GADGET is not set +# CONFIG_MMC is not set + +# +# LED devices +# +# CONFIG_NEW_LEDS is not set + +# +# LED drivers +# + +# +# LED Triggers +# + +# +# InfiniBand support +# + +# +# EDAC - error detection and reporting (RAS) (EXPERIMENTAL) +# + +# +# Real Time Clock +# +CONFIG_RTC_LIB=y +CONFIG_RTC_CLASS=y +CONFIG_RTC_HCTOSYS=y +CONFIG_RTC_HCTOSYS_DEVICE="rtc0" +# CONFIG_RTC_DEBUG is not set + +# +# RTC interfaces +# +CONFIG_RTC_INTF_SYSFS=y +CONFIG_RTC_INTF_PROC=y +CONFIG_RTC_INTF_DEV=y +CONFIG_RTC_INTF_DEV_UIE_EMUL=y +# CONFIG_RTC_DRV_TEST is not set + +# +# I2C RTC drivers +# + +# +# SPI RTC drivers +# +# CONFIG_RTC_DRV_RS5C348 is not set +# CONFIG_RTC_DRV_MAX6902 is not set + +# +# Platform RTC drivers +# +# CONFIG_RTC_DRV_DS1553 is not set +# CONFIG_RTC_DRV_DS1742 is not set +# CONFIG_RTC_DRV_M48T86 is not set +# CONFIG_RTC_DRV_V3020 is not set + +# +# on-CPU RTC drivers +# +CONFIG_RTC_DRV_BFIN=y + +# +# DMA Engine support +# +# CONFIG_DMA_ENGINE is not set + +# +# DMA Clients +# + +# +# DMA Devices +# + +# +# PBX support +# +# CONFIG_PBX is not set + +# +# File systems +# +CONFIG_EXT2_FS=y +CONFIG_EXT2_FS_XATTR=y +# CONFIG_EXT2_FS_POSIX_ACL is not set +# CONFIG_EXT2_FS_SECURITY is not set +# CONFIG_EXT3_FS is not set +# CONFIG_EXT4DEV_FS is not set +CONFIG_FS_MBCACHE=y +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +# CONFIG_FS_POSIX_ACL is not set +# CONFIG_XFS_FS is not set +# CONFIG_GFS2_FS is not set +# CONFIG_OCFS2_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_ROMFS_FS is not set +CONFIG_INOTIFY=y +CONFIG_INOTIFY_USER=y +# CONFIG_QUOTA is not set +CONFIG_DNOTIFY=y +# CONFIG_AUTOFS_FS is not set +# CONFIG_AUTOFS4_FS is not set +# CONFIG_FUSE_FS is not set + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +# CONFIG_MSDOS_FS is not set +# CONFIG_VFAT_FS is not set +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_SYSCTL=y +CONFIG_SYSFS=y +# CONFIG_TMPFS is not set +# CONFIG_HUGETLB_PAGE is not set +CONFIG_RAMFS=y +# CONFIG_CONFIGFS_FS is not set + +# +# Miscellaneous filesystems +# +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_HFSPLUS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +# CONFIG_YAFFS_FS is not set +CONFIG_JFFS2_FS=y +CONFIG_JFFS2_FS_DEBUG=0 +CONFIG_JFFS2_FS_WRITEBUFFER=y +# CONFIG_JFFS2_SUMMARY is not set +# CONFIG_JFFS2_FS_XATTR is not set +# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set +CONFIG_JFFS2_ZLIB=y +CONFIG_JFFS2_RTIME=y +# CONFIG_JFFS2_RUBIN is not set +# CONFIG_CRAMFS is not set +# CONFIG_VXFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set + +# +# Network File Systems +# +CONFIG_NFS_FS=m +CONFIG_NFS_V3=y +# CONFIG_NFS_V3_ACL is not set +# CONFIG_NFS_V4 is not set +# CONFIG_NFS_DIRECTIO is not set +# CONFIG_NFSD is not set +CONFIG_LOCKD=m +CONFIG_LOCKD_V4=y +CONFIG_NFS_COMMON=y +CONFIG_SUNRPC=m +# CONFIG_SUNRPC_BIND34 is not set +# CONFIG_RPCSEC_GSS_KRB5 is not set +# CONFIG_RPCSEC_GSS_SPKM3 is not set +# CONFIG_SMB_FS is not set +# CONFIG_CIFS is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_AFS_FS is not set +# CONFIG_9P_FS is not set + +# +# Partition Types +# +# CONFIG_PARTITION_ADVANCED is not set +CONFIG_MSDOS_PARTITION=y + +# +# Native Language Support +# +CONFIG_NLS=m +CONFIG_NLS_DEFAULT="iso8859-1" +# CONFIG_NLS_CODEPAGE_437 is not set +# CONFIG_NLS_CODEPAGE_737 is not set +# CONFIG_NLS_CODEPAGE_775 is not set +# CONFIG_NLS_CODEPAGE_850 is not set +# CONFIG_NLS_CODEPAGE_852 is not set +# CONFIG_NLS_CODEPAGE_855 is not set +# CONFIG_NLS_CODEPAGE_857 is not set +# CONFIG_NLS_CODEPAGE_860 is not set +# CONFIG_NLS_CODEPAGE_861 is not set +# CONFIG_NLS_CODEPAGE_862 is not set +# CONFIG_NLS_CODEPAGE_863 is not set +# CONFIG_NLS_CODEPAGE_864 is not set +# CONFIG_NLS_CODEPAGE_865 is not set +# CONFIG_NLS_CODEPAGE_866 is not set +# CONFIG_NLS_CODEPAGE_869 is not set +# CONFIG_NLS_CODEPAGE_936 is not set +# CONFIG_NLS_CODEPAGE_950 is not set +# CONFIG_NLS_CODEPAGE_932 is not set +# CONFIG_NLS_CODEPAGE_949 is not set +# CONFIG_NLS_CODEPAGE_874 is not set +# CONFIG_NLS_ISO8859_8 is not set +# CONFIG_NLS_CODEPAGE_1250 is not set +# CONFIG_NLS_CODEPAGE_1251 is not set +# CONFIG_NLS_ASCII is not set +# CONFIG_NLS_ISO8859_1 is not set +# CONFIG_NLS_ISO8859_2 is not set +# CONFIG_NLS_ISO8859_3 is not set +# CONFIG_NLS_ISO8859_4 is not set +# CONFIG_NLS_ISO8859_5 is not set +# CONFIG_NLS_ISO8859_6 is not set +# CONFIG_NLS_ISO8859_7 is not set +# CONFIG_NLS_ISO8859_9 is not set +# CONFIG_NLS_ISO8859_13 is not set +# CONFIG_NLS_ISO8859_14 is not set +# CONFIG_NLS_ISO8859_15 is not set +# CONFIG_NLS_KOI8_R is not set +# CONFIG_NLS_KOI8_U is not set +# CONFIG_NLS_UTF8 is not set + +# +# Distributed Lock Manager +# +# CONFIG_DLM is not set + +# +# Profiling support +# +# CONFIG_PROFILING is not set + +# +# Kernel hacking +# +# CONFIG_PRINTK_TIME is not set +CONFIG_ENABLE_MUST_CHECK=y +# CONFIG_MAGIC_SYSRQ is not set +# CONFIG_UNUSED_SYMBOLS is not set +# CONFIG_DEBUG_FS is not set +# CONFIG_HEADERS_CHECK is not set +# CONFIG_DEBUG_KERNEL is not set +# CONFIG_DEBUG_BUGVERBOSE is not set +# CONFIG_DEBUG_MMRS is not set +CONFIG_DEBUG_HUNT_FOR_ZERO=y +CONFIG_DEBUG_BFIN_HWTRACE_ON=y +CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_OFF=y +# CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_ONE is not set +# CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_TWO is not set +CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION=0 +# CONFIG_DEBUG_BFIN_HWTRACE_EXPAND is not set +# CONFIG_DEBUG_BFIN_NO_KERN_HWTRACE is not set +# CONFIG_EARLY_PRINTK is not set +CONFIG_CPLB_INFO=y +CONFIG_ACCESS_CHECK=y + +# +# Security options +# +# CONFIG_KEYS is not set +CONFIG_SECURITY=y +# CONFIG_SECURITY_NETWORK is not set +CONFIG_SECURITY_CAPABILITIES=y + +# +# Cryptographic options +# +# CONFIG_CRYPTO is not set + +# +# Library routines +# +CONFIG_BITREVERSE=y +CONFIG_CRC_CCITT=m +# CONFIG_CRC16 is not set +# CONFIG_CRC_ITU_T is not set +CONFIG_CRC32=y +# CONFIG_LIBCRC32C is not set +CONFIG_ZLIB_INFLATE=y +CONFIG_ZLIB_DEFLATE=y +CONFIG_PLIST=y +CONFIG_HAS_IOMEM=y +CONFIG_HAS_IOPORT=y +CONFIG_HAS_DMA=y diff --git a/arch/blackfin/configs/PNAV-10_defconfig b/arch/blackfin/configs/PNAV-10_defconfig index 3d403e0..25709f5 100644 --- a/arch/blackfin/configs/PNAV-10_defconfig +++ b/arch/blackfin/configs/PNAV-10_defconfig @@ -1,6 +1,6 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.22.6 +# Linux kernel version: 2.6.22.12 # # CONFIG_MMU is not set # CONFIG_FPU is not set @@ -8,7 +8,6 @@ CONFIG_RWSEM_GENERIC_SPINLOCK=y # CONFIG_RWSEM_XCHGADD_ALGORITHM is not set CONFIG_BLACKFIN=y CONFIG_ZONE_DMA=y -CONFIG_BFIN=y CONFIG_SEMAPHORE_SLEEPERS=y CONFIG_GENERIC_FIND_NEXT_BIT=y CONFIG_GENERIC_HWEIGHT=y @@ -18,7 +17,6 @@ CONFIG_GENERIC_IRQ_PROBE=y CONFIG_GENERIC_GPIO=y CONFIG_FORCE_MAX_ZONEORDER=14 CONFIG_GENERIC_CALIBRATE_DELAY=y -CONFIG_IRQCHIP_DEMUX_GPIO=y CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" # @@ -62,7 +60,6 @@ CONFIG_FUTEX=y CONFIG_ANON_INODES=y CONFIG_EPOLL=y CONFIG_SIGNALFD=y -CONFIG_TIMERFD=y CONFIG_EVENTFD=y CONFIG_VM_EVENT_COUNTERS=y CONFIG_BIG_ORDER_ALLOC_NOFAIL_MAGIC=9 @@ -115,6 +112,9 @@ CONFIG_PREEMPT_VOLUNTARY=y # # Processor and Board Settings # +# CONFIG_BF522 is not set +# CONFIG_BF525 is not set +# CONFIG_BF527 is not set # CONFIG_BF531 is not set # CONFIG_BF532 is not set # CONFIG_BF533 is not set @@ -123,10 +123,12 @@ CONFIG_PREEMPT_VOLUNTARY=y CONFIG_BF537=y # CONFIG_BF542 is not set # CONFIG_BF544 is not set +# CONFIG_BF547 is not set # CONFIG_BF548 is not set # CONFIG_BF549 is not set # CONFIG_BF561 is not set # CONFIG_BF_REV_0_0 is not set +# CONFIG_BF_REV_0_1 is not set CONFIG_BF_REV_0_2=y # CONFIG_BF_REV_0_3 is not set # CONFIG_BF_REV_0_4 is not set @@ -135,33 +137,8 @@ CONFIG_BF_REV_0_2=y # CONFIG_BF_REV_NONE is not set CONFIG_BF53x=y CONFIG_BFIN_SINGLE_CORE=y -# CONFIG_BFIN533_EZKIT is not set -# CONFIG_BFIN533_STAMP is not set -# CONFIG_BFIN537_STAMP is not set -# CONFIG_BFIN533_BLUETECHNIX_CM is not set -# CONFIG_BFIN537_BLUETECHNIX_CM is not set -# CONFIG_BFIN548_EZKIT is not set -# CONFIG_BFIN561_BLUETECHNIX_CM is not set -# CONFIG_BFIN561_EZKIT is not set -# CONFIG_BFIN561_TEPLA is not set -CONFIG_PNAV10=y -# CONFIG_GENERIC_BOARD is not set CONFIG_MEM_MT48LC32M8A2_75=y CONFIG_IRQ_PLL_WAKEUP=7 - -# -# BF537 Specific Configuration -# - -# -# Interrupt Priority Assignment -# - -# -# Priority -# -CONFIG_IRQ_DMA_ERROR=7 -CONFIG_IRQ_ERROR=7 CONFIG_IRQ_RTC=8 CONFIG_IRQ_PPI=8 CONFIG_IRQ_SPORT0_RX=9 @@ -174,8 +151,6 @@ CONFIG_IRQ_UART0_RX=10 CONFIG_IRQ_UART0_TX=10 CONFIG_IRQ_UART1_RX=10 CONFIG_IRQ_UART1_TX=10 -CONFIG_IRQ_CAN_RX=11 -CONFIG_IRQ_CAN_TX=11 CONFIG_IRQ_MAC_RX=11 CONFIG_IRQ_MAC_TX=11 CONFIG_IRQ_TMR0=12 @@ -186,11 +161,31 @@ CONFIG_IRQ_TMR4=12 CONFIG_IRQ_TMR5=12 CONFIG_IRQ_TMR6=12 CONFIG_IRQ_TMR7=12 -CONFIG_IRQ_PROG_INTA=12 CONFIG_IRQ_PORTG_INTB=12 CONFIG_IRQ_MEM_DMA0=13 CONFIG_IRQ_MEM_DMA1=13 CONFIG_IRQ_WATCH=13 +# CONFIG_BFIN537_STAMP is not set +# CONFIG_BFIN537_BLUETECHNIX_CM is not set +CONFIG_PNAV10=y +# CONFIG_GENERIC_BF537_BOARD is not set + +# +# BF537 Specific Configuration +# + +# +# Interrupt Priority Assignment +# + +# +# Priority +# +CONFIG_IRQ_DMA_ERROR=7 +CONFIG_IRQ_ERROR=7 +CONFIG_IRQ_CAN_RX=11 +CONFIG_IRQ_CAN_TX=11 +CONFIG_IRQ_PROG_INTA=12 # # Board customizations @@ -204,7 +199,7 @@ CONFIG_CLKIN_HZ=24576000 # CONFIG_BFIN_KERNEL_CLOCK is not set CONFIG_MAX_VCO_HZ=600000000 CONFIG_MIN_VCO_HZ=50000000 -CONFIG_MAX_SCLK_HZ=133333333 +CONFIG_MAX_SCLK_HZ=133000000 CONFIG_MIN_SCLK_HZ=27000000 # @@ -261,6 +256,7 @@ CONFIG_SPLIT_PTLOCK_CPUS=4 # CONFIG_RESOURCES_64BIT is not set CONFIG_ZONE_DMA_FLAG=1 CONFIG_LARGE_ALLOCS=y +# CONFIG_BFIN_GPTIMERS is not set CONFIG_BFIN_DMA_5XX=y # CONFIG_DMA_UNCACHED_2M is not set CONFIG_DMA_UNCACHED_1M=y @@ -282,7 +278,7 @@ CONFIG_L1_MAX_PIECE=16 # # -# EBIU_AMBCTL Global Control +# EBIU_AMGCTL Global Control # CONFIG_C_AMCKEN=y CONFIG_C_CDPRIO=y @@ -593,6 +589,7 @@ CONFIG_BFIN_MAC_RMII=y # CONFIG_DM9000 is not set CONFIG_NETDEV_1000=y CONFIG_NETDEV_10000=y +# CONFIG_AX88180 is not set # # Wireless LAN @@ -675,9 +672,9 @@ CONFIG_INPUT_UINPUT=y # # CONFIG_AD9960 is not set # CONFIG_SPI_ADC_BF533 is not set -# CONFIG_BFIN_PFLAGS is not set +# CONFIG_BF5xx_PFLAGS is not set # CONFIG_BF5xx_PPIFCD is not set -# CONFIG_BF5xx_TIMERS is not set +# CONFIG_BFIN_SIMPLE_TIMER is not set # CONFIG_BF5xx_PPI is not set CONFIG_BFIN_SPORT=y # CONFIG_BFIN_TIMER_LATENCY is not set @@ -897,6 +894,7 @@ CONFIG_FB_BF537_LQ035=y CONFIG_LQ035_SLAVE_ADDR=0x58 CONFIG_FB_BFIN_LANDSCAPE=y # CONFIG_FB_BFIN_BGR is not set +# CONFIG_FB_BFIN_T350MCQB is not set # CONFIG_FB_S1D13XXX is not set # CONFIG_FB_VIRTUAL is not set # CONFIG_LOGO is not set @@ -939,11 +937,6 @@ CONFIG_SND=m # CONFIG_SND_SOC is not set # -# SoC Audio for the ADI Blackfin -# -# CONFIG_SND_BF5XX_HAVE_COLD_RESET is not set - -# # Open Sound System # CONFIG_SOUND_PRIME=y diff --git a/arch/blackfin/kernel/bfin_dma_5xx.c b/arch/blackfin/kernel/bfin_dma_5xx.c index 503eef4..b544460 100644 --- a/arch/blackfin/kernel/bfin_dma_5xx.c +++ b/arch/blackfin/kernel/bfin_dma_5xx.c @@ -436,6 +436,7 @@ unsigned long get_dma_curr_desc_ptr(unsigned int channel) return dma_ch[channel].regs->curr_desc_ptr; } +EXPORT_SYMBOL(get_dma_curr_desc_ptr); unsigned long get_dma_curr_addr(unsigned int channel) { diff --git a/arch/blackfin/kernel/bfin_ksyms.c b/arch/blackfin/kernel/bfin_ksyms.c index 2198afe..0bfbb26 100644 --- a/arch/blackfin/kernel/bfin_ksyms.c +++ b/arch/blackfin/kernel/bfin_ksyms.c @@ -37,9 +37,6 @@ /* platform dependent support */ EXPORT_SYMBOL(__ioremap); -EXPORT_SYMBOL(strcmp); -EXPORT_SYMBOL(strncmp); -EXPORT_SYMBOL(dump_thread); EXPORT_SYMBOL(ip_fast_csum); @@ -51,6 +48,7 @@ EXPORT_SYMBOL(__down_trylock); EXPORT_SYMBOL(__down_interruptible); EXPORT_SYMBOL(is_in_rom); +EXPORT_SYMBOL(bfin_return_from_exception); /* Networking helper routines. */ EXPORT_SYMBOL(csum_partial_copy); @@ -60,13 +58,11 @@ EXPORT_SYMBOL(csum_partial_copy); * their interface isn't gonna change any time soon now, so * it's OK to leave it out of version control. */ -EXPORT_SYMBOL(strcpy); EXPORT_SYMBOL(memcpy); EXPORT_SYMBOL(memset); EXPORT_SYMBOL(memcmp); EXPORT_SYMBOL(memmove); EXPORT_SYMBOL(memchr); -EXPORT_SYMBOL(get_wchan); /* * libgcc functions - functions that are used internally by the @@ -102,6 +98,7 @@ EXPORT_SYMBOL(outsw); EXPORT_SYMBOL(insw); EXPORT_SYMBOL(outsl); EXPORT_SYMBOL(insl); +EXPORT_SYMBOL(insl_16); EXPORT_SYMBOL(irq_flags); EXPORT_SYMBOL(iounmap); EXPORT_SYMBOL(blackfin_dcache_invalidate_range); diff --git a/arch/blackfin/kernel/cplbinit.c b/arch/blackfin/kernel/cplbinit.c index f2db6a5..6320bc4 100644 --- a/arch/blackfin/kernel/cplbinit.c +++ b/arch/blackfin/kernel/cplbinit.c @@ -26,29 +26,22 @@ #include <asm/cplb.h> #include <asm/cplbinit.h> -u_long icplb_table[MAX_CPLBS+1]; -u_long dcplb_table[MAX_CPLBS+1]; +u_long icplb_table[MAX_CPLBS + 1]; +u_long dcplb_table[MAX_CPLBS + 1]; #ifdef CONFIG_CPLB_SWITCH_TAB_L1 -u_long ipdt_table[MAX_SWITCH_I_CPLBS+1]__attribute__((l1_data)); -u_long dpdt_table[MAX_SWITCH_D_CPLBS+1]__attribute__((l1_data)); - -#ifdef CONFIG_CPLB_INFO -u_long ipdt_swapcount_table[MAX_SWITCH_I_CPLBS]__attribute__((l1_data)); -u_long dpdt_swapcount_table[MAX_SWITCH_D_CPLBS]__attribute__((l1_data)); -#endif /* CONFIG_CPLB_INFO */ - +# define PDT_ATTR __attribute__((l1_data)) #else +# define PDT_ATTR +#endif -u_long ipdt_table[MAX_SWITCH_I_CPLBS+1]; -u_long dpdt_table[MAX_SWITCH_D_CPLBS+1]; +u_long ipdt_table[MAX_SWITCH_I_CPLBS + 1] PDT_ATTR; +u_long dpdt_table[MAX_SWITCH_D_CPLBS + 1] PDT_ATTR; #ifdef CONFIG_CPLB_INFO -u_long ipdt_swapcount_table[MAX_SWITCH_I_CPLBS]; -u_long dpdt_swapcount_table[MAX_SWITCH_D_CPLBS]; -#endif /* CONFIG_CPLB_INFO */ - -#endif /*CONFIG_CPLB_SWITCH_TAB_L1*/ +u_long ipdt_swapcount_table[MAX_SWITCH_I_CPLBS] PDT_ATTR; +u_long dpdt_swapcount_table[MAX_SWITCH_D_CPLBS] PDT_ATTR; +#endif struct s_cplb { struct cplb_tab init_i; @@ -71,7 +64,7 @@ static struct cplb_desc cplb_data[] = { #else .valid = 0, #endif - .name = "ZERO Pointer Saveguard", + .name = "Zero Pointer Guard Page", }, { .start = L1_CODE_START, @@ -102,20 +95,20 @@ static struct cplb_desc cplb_data[] = { .end = 0, /* dynamic */ .psize = 0, .attr = INITIAL_T | SWITCH_T | I_CPLB | D_CPLB, - .i_conf = SDRAM_IGENERIC, - .d_conf = SDRAM_DGENERIC, + .i_conf = SDRAM_IGENERIC, + .d_conf = SDRAM_DGENERIC, .valid = 1, - .name = "SDRAM Kernel", + .name = "Kernel Memory", }, { .start = 0, /* dynamic */ .end = 0, /* dynamic */ .psize = 0, .attr = INITIAL_T | SWITCH_T | D_CPLB, - .i_conf = SDRAM_IGENERIC, - .d_conf = SDRAM_DNON_CHBL, + .i_conf = SDRAM_IGENERIC, + .d_conf = SDRAM_DNON_CHBL, .valid = 1, - .name = "SDRAM RAM MTD", + .name = "uClinux MTD Memory", }, { .start = 0, /* dynamic */ @@ -124,7 +117,7 @@ static struct cplb_desc cplb_data[] = { .attr = INITIAL_T | SWITCH_T | D_CPLB, .d_conf = SDRAM_DNON_CHBL, .valid = 1, - .name = "SDRAM Uncached DMA ZONE", + .name = "Uncached DMA Zone", }, { .start = 0, /* dynamic */ @@ -134,7 +127,7 @@ static struct cplb_desc cplb_data[] = { .i_conf = 0, /* dynamic */ .d_conf = 0, /* dynamic */ .valid = 1, - .name = "SDRAM Reserved Memory", + .name = "Reserved Memory", }, { .start = ASYNC_BANK0_BASE, @@ -143,14 +136,14 @@ static struct cplb_desc cplb_data[] = { .attr = SWITCH_T | D_CPLB, .d_conf = SDRAM_EBIU, .valid = 1, - .name = "ASYNC Memory", + .name = "Asynchronous Memory Banks", }, { -#if defined(CONFIG_BF561) - .start = L2_SRAM, - .end = L2_SRAM_END, +#ifdef L2_START + .start = L2_START, + .end = L2_START + L2_LENGTH, .psize = SIZE_1M, - .attr = SWITCH_T | D_CPLB, + .attr = SWITCH_T | I_CPLB | D_CPLB, .i_conf = L2_MEMORY, .d_conf = L2_MEMORY, .valid = 1, @@ -158,13 +151,23 @@ static struct cplb_desc cplb_data[] = { .valid = 0, #endif .name = "L2 Memory", - } + }, + { + .start = BOOT_ROM_START, + .end = BOOT_ROM_START + BOOT_ROM_LENGTH, + .psize = SIZE_1M, + .attr = SWITCH_T | I_CPLB | D_CPLB, + .i_conf = SDRAM_IGENERIC, + .d_conf = SDRAM_DGENERIC, + .valid = 1, + .name = "On-Chip BootROM", + }, }; static u16 __init lock_kernel_check(u32 start, u32 end) { - if ((start <= (u32) _stext && end >= (u32) _end) - || (start >= (u32) _stext && end <= (u32) _end)) + if ((end <= (u32) _end && end >= (u32)_stext) || + (start <= (u32) _end && start >= (u32)_stext)) return IN_KERNEL; return 0; } @@ -350,7 +353,7 @@ void __init generate_cpl_tables(void) else cplb_data[RES_MEM].i_conf = SDRAM_INON_CHBL; - for (i = ZERO_P; i <= L2_MEM; i++) { + for (i = ZERO_P; i < ARRAY_SIZE(cplb_data); ++i) { if (!cplb_data[i].valid) continue; diff --git a/arch/blackfin/kernel/early_printk.c b/arch/blackfin/kernel/early_printk.c index 6ec518a..724f4a5 100644 --- a/arch/blackfin/kernel/early_printk.c +++ b/arch/blackfin/kernel/early_printk.c @@ -205,7 +205,8 @@ asmlinkage void __init early_trap_c(struct pt_regs *fp, void *retaddr) if (likely(early_console == NULL)) setup_early_printk(DEFAULT_EARLY_PORT); - dump_bfin_regs(fp, retaddr); + dump_bfin_mem((void *)fp->retx); + show_regs(fp); dump_bfin_trace_buffer(); panic("Died early"); diff --git a/arch/blackfin/kernel/process.c b/arch/blackfin/kernel/process.c index 9124467..5bf1512 100644 --- a/arch/blackfin/kernel/process.c +++ b/arch/blackfin/kernel/process.c @@ -134,27 +134,6 @@ void cpu_idle(void) } } -void show_regs(struct pt_regs *regs) -{ - printk(KERN_NOTICE "\n"); - printk(KERN_NOTICE - "PC: %08lu Status: %04lu SysStatus: %04lu RETS: %08lu\n", - regs->pc, regs->astat, regs->seqstat, regs->rets); - printk(KERN_NOTICE - "A0.x: %08lx A0.w: %08lx A1.x: %08lx A1.w: %08lx\n", - regs->a0x, regs->a0w, regs->a1x, regs->a1w); - printk(KERN_NOTICE "P0: %08lx P1: %08lx P2: %08lx P3: %08lx\n", - regs->p0, regs->p1, regs->p2, regs->p3); - printk(KERN_NOTICE "P4: %08lx P5: %08lx\n", regs->p4, regs->p5); - printk(KERN_NOTICE "R0: %08lx R1: %08lx R2: %08lx R3: %08lx\n", - regs->r0, regs->r1, regs->r2, regs->r3); - printk(KERN_NOTICE "R4: %08lx R5: %08lx R6: %08lx R7: %08lx\n", - regs->r4, regs->r5, regs->r6, regs->r7); - - if (!regs->ipend) - printk(KERN_NOTICE "USP: %08lx\n", rdusp()); -} - /* Fill in the fpu structure for a core dump. */ int dump_fpu(struct pt_regs *regs, elf_fpregset_t * fpregs) @@ -239,51 +218,6 @@ copy_thread(int nr, unsigned long clone_flags, } /* - * fill in the user structure for a core dump.. - */ -void dump_thread(struct pt_regs *regs, struct user *dump) -{ - dump->magic = CMAGIC; - dump->start_code = 0; - dump->start_stack = rdusp() & ~(PAGE_SIZE - 1); - dump->u_tsize = ((unsigned long)current->mm->end_code) >> PAGE_SHIFT; - dump->u_dsize = ((unsigned long)(current->mm->brk + - (PAGE_SIZE - 1))) >> PAGE_SHIFT; - dump->u_dsize -= dump->u_tsize; - dump->u_ssize = 0; - - if (dump->start_stack < TASK_SIZE) - dump->u_ssize = - ((unsigned long)(TASK_SIZE - - dump->start_stack)) >> PAGE_SHIFT; - - dump->u_ar0 = (struct user_regs_struct *)((int)&dump->regs - (int)dump); - - dump->regs.r0 = regs->r0; - dump->regs.r1 = regs->r1; - dump->regs.r2 = regs->r2; - dump->regs.r3 = regs->r3; - dump->regs.r4 = regs->r4; - dump->regs.r5 = regs->r5; - dump->regs.r6 = regs->r6; - dump->regs.r7 = regs->r7; - dump->regs.p0 = regs->p0; - dump->regs.p1 = regs->p1; - dump->regs.p2 = regs->p2; - dump->regs.p3 = regs->p3; - dump->regs.p4 = regs->p4; - dump->regs.p5 = regs->p5; - dump->regs.orig_p0 = regs->orig_p0; - dump->regs.a0w = regs->a0w; - dump->regs.a1w = regs->a1w; - dump->regs.a0x = regs->a0x; - dump->regs.a1x = regs->a1x; - dump->regs.rets = regs->rets; - dump->regs.astat = regs->astat; - dump->regs.pc = regs->pc; -} - -/* * sys_execve() executes a new program. */ diff --git a/arch/blackfin/kernel/setup.c b/arch/blackfin/kernel/setup.c index 934234f..d282201 100644 --- a/arch/blackfin/kernel/setup.c +++ b/arch/blackfin/kernel/setup.c @@ -43,6 +43,7 @@ #include <asm/cacheflush.h> #include <asm/blackfin.h> #include <asm/cplbinit.h> +#include <asm/div64.h> #include <asm/fixed_code.h> #include <asm/early_printk.h> @@ -504,13 +505,17 @@ EXPORT_SYMBOL(get_sclk); unsigned long sclk_to_usecs(unsigned long sclk) { - return (USEC_PER_SEC * (u64)sclk) / get_sclk(); + u64 tmp = USEC_PER_SEC * (u64)sclk; + do_div(tmp, get_sclk()); + return tmp; } EXPORT_SYMBOL(sclk_to_usecs); unsigned long usecs_to_sclk(unsigned long usecs) { - return (get_sclk() * (u64)usecs) / USEC_PER_SEC; + u64 tmp = get_sclk() * (u64)usecs; + do_div(tmp, USEC_PER_SEC); + return tmp; } EXPORT_SYMBOL(usecs_to_sclk); diff --git a/arch/blackfin/kernel/traps.c b/arch/blackfin/kernel/traps.c index cfa05436..21a55ef 100644 --- a/arch/blackfin/kernel/traps.c +++ b/arch/blackfin/kernel/traps.c @@ -158,7 +158,7 @@ static void decode_address(char *buf, unsigned long address) } /* we were unable to find this address anywhere */ - sprintf(buf, "[<0x%p>]", (void *)address); + sprintf(buf, "<0x%p> /* unknown address */", (void *)address); done: write_unlock_irqrestore(&tasklist_lock, flags); @@ -169,7 +169,9 @@ asmlinkage void double_fault_c(struct pt_regs *fp) console_verbose(); oops_in_progress = 1; printk(KERN_EMERG "\n" KERN_EMERG "Double Fault\n"); - dump_bfin_regs(fp, (void *)fp->retx); + dump_bfin_process(fp); + dump_bfin_mem((void *)fp->retx); + show_regs(fp); panic("Double Fault - unrecoverable event\n"); } @@ -250,7 +252,7 @@ asmlinkage void trap_c(struct pt_regs *fp) case VEC_EXCPT03: info.si_code = SEGV_STACKFLOW; sig = SIGSEGV; - printk(KERN_NOTICE EXC_0x03); + printk(KERN_NOTICE EXC_0x03(KERN_NOTICE)); CHK_DEBUGGER_TRAP(); break; /* 0x04 - User Defined, Caught by default */ @@ -279,7 +281,7 @@ asmlinkage void trap_c(struct pt_regs *fp) case VEC_OVFLOW: info.si_code = TRAP_TRACEFLOW; sig = SIGTRAP; - printk(KERN_NOTICE EXC_0x11); + printk(KERN_NOTICE EXC_0x11(KERN_NOTICE)); CHK_DEBUGGER_TRAP(); break; /* 0x12 - Reserved, Caught by default */ @@ -301,36 +303,35 @@ asmlinkage void trap_c(struct pt_regs *fp) case VEC_UNDEF_I: info.si_code = ILL_ILLOPC; sig = SIGILL; - printk(KERN_NOTICE EXC_0x21); + printk(KERN_NOTICE EXC_0x21(KERN_NOTICE)); CHK_DEBUGGER_TRAP(); break; /* 0x22 - Illegal Instruction Combination, handled here */ case VEC_ILGAL_I: info.si_code = ILL_ILLPARAOP; sig = SIGILL; - printk(KERN_NOTICE EXC_0x22); + printk(KERN_NOTICE EXC_0x22(KERN_NOTICE)); CHK_DEBUGGER_TRAP(); break; - /* 0x23 - Data CPLB Protection Violation, - normal case is handled in _cplb_hdr */ + /* 0x23 - Data CPLB protection violation, handled here */ case VEC_CPLB_VL: info.si_code = ILL_CPLB_VI; - sig = SIGILL; - printk(KERN_NOTICE EXC_0x23); + sig = SIGBUS; + printk(KERN_NOTICE EXC_0x23(KERN_NOTICE)); CHK_DEBUGGER_TRAP(); break; /* 0x24 - Data access misaligned, handled here */ case VEC_MISALI_D: info.si_code = BUS_ADRALN; sig = SIGBUS; - printk(KERN_NOTICE EXC_0x24); + printk(KERN_NOTICE EXC_0x24(KERN_NOTICE)); CHK_DEBUGGER_TRAP(); break; /* 0x25 - Unrecoverable Event, handled here */ case VEC_UNCOV: info.si_code = ILL_ILLEXCPT; sig = SIGILL; - printk(KERN_NOTICE EXC_0x25); + printk(KERN_NOTICE EXC_0x25(KERN_NOTICE)); CHK_DEBUGGER_TRAP(); break; /* 0x26 - Data CPLB Miss, normal case is handled in _cplb_hdr, @@ -338,7 +339,7 @@ asmlinkage void trap_c(struct pt_regs *fp) case VEC_CPLB_M: info.si_code = BUS_ADRALN; sig = SIGBUS; - printk(KERN_NOTICE EXC_0x26); + printk(KERN_NOTICE EXC_0x26(KERN_NOTICE)); CHK_DEBUGGER_TRAP(); break; /* 0x27 - Data CPLB Multiple Hits - Linux Trap Zero, handled here */ @@ -349,7 +350,7 @@ asmlinkage void trap_c(struct pt_regs *fp) printk(KERN_NOTICE "NULL pointer access (probably)\n"); #else sig = SIGILL; - printk(KERN_NOTICE EXC_0x27); + printk(KERN_NOTICE EXC_0x27(KERN_NOTICE)); #endif CHK_DEBUGGER_TRAP(); break; @@ -357,7 +358,7 @@ asmlinkage void trap_c(struct pt_regs *fp) case VEC_WATCH: info.si_code = TRAP_WATCHPT; sig = SIGTRAP; - pr_debug(EXC_0x28); + pr_debug(EXC_0x28(KERN_DEBUG)); CHK_DEBUGGER_TRAP_MAYBE(); /* Check if this is a watchpoint in kernel space */ if (fp->ipend & 0xffc0) @@ -379,22 +380,21 @@ asmlinkage void trap_c(struct pt_regs *fp) case VEC_MISALI_I: info.si_code = BUS_ADRALN; sig = SIGBUS; - printk(KERN_NOTICE EXC_0x2A); + printk(KERN_NOTICE EXC_0x2A(KERN_NOTICE)); CHK_DEBUGGER_TRAP(); break; - /* 0x2B - Instruction CPLB protection Violation, - handled in _cplb_hdr */ + /* 0x2B - Instruction CPLB protection violation, handled here */ case VEC_CPLB_I_VL: info.si_code = ILL_CPLB_VI; - sig = SIGILL; - printk(KERN_NOTICE EXC_0x2B); + sig = SIGBUS; + printk(KERN_NOTICE EXC_0x2B(KERN_NOTICE)); CHK_DEBUGGER_TRAP(); break; /* 0x2C - Instruction CPLB miss, handled in _cplb_hdr */ case VEC_CPLB_I_M: info.si_code = ILL_CPLB_MISS; sig = SIGBUS; - printk(KERN_NOTICE EXC_0x2C); + printk(KERN_NOTICE EXC_0x2C(KERN_NOTICE)); CHK_DEBUGGER_TRAP(); break; /* 0x2D - Instruction CPLB Multiple Hits, handled here */ @@ -405,7 +405,7 @@ asmlinkage void trap_c(struct pt_regs *fp) printk(KERN_NOTICE "Jump to address 0 - 0x0fff\n"); #else sig = SIGILL; - printk(KERN_NOTICE EXC_0x2D); + printk(KERN_NOTICE EXC_0x2D(KERN_NOTICE)); #endif CHK_DEBUGGER_TRAP(); break; @@ -413,7 +413,7 @@ asmlinkage void trap_c(struct pt_regs *fp) case VEC_ILL_RES: info.si_code = ILL_PRVOPC; sig = SIGILL; - printk(KERN_NOTICE EXC_0x2E); + printk(KERN_NOTICE EXC_0x2E(KERN_NOTICE)); CHK_DEBUGGER_TRAP(); break; /* 0x2F - Reserved, Caught by default */ @@ -446,7 +446,9 @@ asmlinkage void trap_c(struct pt_regs *fp) if (sig != SIGTRAP) { unsigned long stack; - dump_bfin_regs(fp, (void *)fp->retx); + dump_bfin_process(fp); + dump_bfin_mem((void *)fp->retx); + show_regs(fp); /* Print out the trace buffer if it makes sense */ #ifndef CONFIG_DEBUG_BFIN_NO_KERN_HWTRACE @@ -460,22 +462,25 @@ asmlinkage void trap_c(struct pt_regs *fp) show_stack(current, &stack); if (oops_in_progress) { #ifndef CONFIG_ACCESS_CHECK - printk(KERN_EMERG "Hey - dork - please turn on " - "CONFIG_ACCESS_CHECK\n"); + printk(KERN_EMERG "Please turn on " + "CONFIG_ACCESS_CHECK\n"); #endif panic("Kernel exception"); } - - /* Ensure that bad return addresses don't end up in an infinite - * loop, due to speculative loads/reads - */ - fp->pc = SAFE_USER_INSTRUCTION; } + info.si_signo = sig; info.si_errno = 0; info.si_addr = (void *)fp->pc; force_sig_info(sig, &info, current); + /* Ensure that bad return addresses don't end up in an infinite + * loop, due to speculative loads/reads. This needs to be done after + * the signal has been sent. + */ + if (trapnr == VEC_CPLB_I_M && sig != SIGTRAP) + fp->pc = SAFE_USER_INSTRUCTION; + trace_buffer_restore(j); return; } @@ -600,37 +605,48 @@ void dump_stack(void) show_stack(current, &stack); trace_buffer_restore(tflags); } - EXPORT_SYMBOL(dump_stack); -void dump_bfin_regs(struct pt_regs *fp, void *retaddr) +void dump_bfin_process(struct pt_regs *fp) { - char buf [150]; + /* We should be able to look at fp->ipend, but we don't push it on the + * stack all the time, so do this until we fix that */ + unsigned int context = bfin_read_IPEND(); + + if (oops_in_progress) + printk(KERN_EMERG "Kernel OOPS in progress\n"); + + if (context & 0x0020) + printk(KERN_NOTICE "Deferred excecption or HW Error context\n"); + else if (context & 0x3FC0) + printk(KERN_NOTICE "Interrupt context\n"); + else if (context & 0x4000) + printk(KERN_NOTICE "Deferred Interrupt context\n"); + else if (context & 0x8000) + printk(KERN_NOTICE "Kernel process context\n"); + + if (current->pid && current->mm) { + printk(KERN_NOTICE "CURRENT PROCESS:\n"); + printk(KERN_NOTICE "COMM=%s PID=%d\n", + current->comm, current->pid); + + printk(KERN_NOTICE "TEXT = 0x%p-0x%p DATA = 0x%p-0x%p\n" + KERN_NOTICE "BSS = 0x%p-0x%p USER-STACK = 0x%p\n" + KERN_NOTICE "\n", + (void *)current->mm->start_code, + (void *)current->mm->end_code, + (void *)current->mm->start_data, + (void *)current->mm->end_data, + (void *)current->mm->end_data, + (void *)current->mm->brk, + (void *)current->mm->start_stack); + } else + printk(KERN_NOTICE "\n" KERN_NOTICE + "No Valid process in current context\n"); +} - if (!oops_in_progress) { - if (current->pid && current->mm) { - printk(KERN_NOTICE "\n" KERN_NOTICE "CURRENT PROCESS:\n"); - printk(KERN_NOTICE "COMM=%s PID=%d\n", - current->comm, current->pid); - - printk(KERN_NOTICE "TEXT = 0x%p-0x%p DATA = 0x%p-0x%p\n" - KERN_NOTICE "BSS = 0x%p-0x%p USER-STACK = 0x%p\n" - KERN_NOTICE "\n", - (void *)current->mm->start_code, - (void *)current->mm->end_code, - (void *)current->mm->start_data, - (void *)current->mm->end_data, - (void *)current->mm->end_data, - (void *)current->mm->brk, - (void *)current->mm->start_stack); - } else { - printk (KERN_NOTICE "\n" KERN_NOTICE - "No Valid pid - Either things are really messed up," - " or you are in the kernel\n"); - } - } else { - printk(KERN_NOTICE "Kernel or interrupt exception\n"); - } +void dump_bfin_mem(void *retaddr) +{ if (retaddr >= (void *)FIXED_CODE_START && retaddr < (void *)physical_mem_end #if L1_CODE_LENGTH != 0 @@ -671,8 +687,13 @@ void dump_bfin_regs(struct pt_regs *fp, void *retaddr) printk("\n"); } else printk("\n" KERN_NOTICE - "Cannot look at the [PC] for it is" - " in unreadable memory - sorry\n"); + "Cannot look at the [PC] <%p> for it is" + " in unreadable memory - sorry\n", retaddr); +} + +void show_regs(struct pt_regs *fp) +{ + char buf [150]; printk(KERN_NOTICE "\n" KERN_NOTICE "SEQUENCER STATUS:\n"); printk(KERN_NOTICE " SEQSTAT: %08lx IPEND: %04lx SYSCFG: %04lx\n", @@ -686,6 +707,8 @@ void dump_bfin_regs(struct pt_regs *fp, void *retaddr) printk(KERN_NOTICE " RETX: %s\n", buf); decode_address(buf, fp->rets); printk(KERN_NOTICE " RETS: %s\n", buf); + decode_address(buf, fp->pc); + printk(KERN_NOTICE " PC: %s\n", buf); if ((long)fp->seqstat & SEQSTAT_EXCAUSE) { decode_address(buf, bfin_read_DCPLB_FAULT_ADDR()); @@ -800,7 +823,9 @@ void panic_cplb_error(int cplb_panic, struct pt_regs *fp) printk(KERN_EMERG "DCPLB_FAULT_ADDR=%p\n", (void *)bfin_read_DCPLB_FAULT_ADDR()); printk(KERN_EMERG "ICPLB_FAULT_ADDR=%p\n", (void *)bfin_read_ICPLB_FAULT_ADDR()); - dump_bfin_regs(fp, (void *)fp->retx); + dump_bfin_process(fp); + dump_bfin_mem((void *)fp->retx); + show_regs(fp); dump_stack(); panic("Unrecoverable event\n"); } diff --git a/arch/blackfin/lib/Makefile b/arch/blackfin/lib/Makefile index bfdad52..635288f 100644 --- a/arch/blackfin/lib/Makefile +++ b/arch/blackfin/lib/Makefile @@ -4,7 +4,7 @@ lib-y := \ ashldi3.o ashrdi3.o lshrdi3.o \ - muldi3.o divsi3.o udivsi3.o udivdi3.o modsi3.o umodsi3.o \ + muldi3.o divsi3.o udivsi3.o modsi3.o umodsi3.o \ checksum.o memcpy.o memset.o memcmp.o memchr.o memmove.o \ strcmp.o strcpy.o strncmp.o strncpy.o \ umulsi3_highpart.o smulsi3_highpart.o \ diff --git a/arch/blackfin/lib/ins.S b/arch/blackfin/lib/ins.S index a17cc77..df7b883 100644 --- a/arch/blackfin/lib/ins.S +++ b/arch/blackfin/lib/ins.S @@ -77,3 +77,22 @@ ENTRY(_insb) sti R3; RTS; ENDPROC(_insb) + + + +ENTRY(_insl_16) + P0 = R0; /* P0 = port */ + cli R3; + P1 = R1; /* P1 = address */ + P2 = R2; /* P2 = count */ + SSYNC; + LSETUP( .Llong16_loop_s, .Llong16_loop_e) LC0 = P2; +.Llong16_loop_s: R0 = [P0]; + W[P1++] = R0; + R0 = R0 >> 16; + W[P1++] = R0; + NOP; +.Llong16_loop_e: NOP; + sti R3; + RTS; +ENDPROC(_insl_16) diff --git a/arch/blackfin/lib/strcmp.c b/arch/blackfin/lib/strcmp.c index 4eeefd8..fde39a1 100644 --- a/arch/blackfin/lib/strcmp.c +++ b/arch/blackfin/lib/strcmp.c @@ -1,10 +1,19 @@ -#include <linux/types.h> +/* + * Provide symbol in case str func is not inlined. + * + * Copyright (c) 2006-2007 Analog Devices Inc. + * + * Licensed under the GPL-2 or later. + */ #define strcmp __inline_strcmp #include <asm/string.h> #undef strcmp +#include <linux/module.h> + int strcmp(const char *dest, const char *src) { return __inline_strcmp(dest, src); } +EXPORT_SYMBOL(strcmp); diff --git a/arch/blackfin/lib/strcpy.c b/arch/blackfin/lib/strcpy.c index 534589d..2a8836b 100644 --- a/arch/blackfin/lib/strcpy.c +++ b/arch/blackfin/lib/strcpy.c @@ -1,10 +1,19 @@ -#include <linux/types.h> +/* + * Provide symbol in case str func is not inlined. + * + * Copyright (c) 2006-2007 Analog Devices Inc. + * + * Licensed under the GPL-2 or later. + */ #define strcpy __inline_strcpy #include <asm/string.h> #undef strcpy +#include <linux/module.h> + char *strcpy(char *dest, const char *src) { return __inline_strcpy(dest, src); } +EXPORT_SYMBOL(strcpy); diff --git a/arch/blackfin/lib/strncmp.c b/arch/blackfin/lib/strncmp.c index d791f12..2aaae78 100644 --- a/arch/blackfin/lib/strncmp.c +++ b/arch/blackfin/lib/strncmp.c @@ -1,10 +1,19 @@ -#include <linux/types.h> +/* + * Provide symbol in case str func is not inlined. + * + * Copyright (c) 2006-2007 Analog Devices Inc. + * + * Licensed under the GPL-2 or later. + */ #define strncmp __inline_strncmp #include <asm/string.h> #undef strncmp +#include <linux/module.h> + int strncmp(const char *cs, const char *ct, size_t count) { return __inline_strncmp(cs, ct, count); } +EXPORT_SYMBOL(strncmp); diff --git a/arch/blackfin/lib/strncpy.c b/arch/blackfin/lib/strncpy.c index 1fecb5c..ea1dc6b 100644 --- a/arch/blackfin/lib/strncpy.c +++ b/arch/blackfin/lib/strncpy.c @@ -1,10 +1,19 @@ -#include <linux/types.h> +/* + * Provide symbol in case str func is not inlined. + * + * Copyright (c) 2006-2007 Analog Devices Inc. + * + * Licensed under the GPL-2 or later. + */ #define strncpy __inline_strncpy #include <asm/string.h> #undef strncpy +#include <linux/module.h> + char *strncpy(char *dest, const char *src, size_t n) { return __inline_strncpy(dest, src, n); } +EXPORT_SYMBOL(strncpy); diff --git a/arch/blackfin/lib/udivdi3.S b/arch/blackfin/lib/udivdi3.S deleted file mode 100644 index ad1ebee..0000000 --- a/arch/blackfin/lib/udivdi3.S +++ /dev/null @@ -1,375 +0,0 @@ -/* - * udivdi3.S - unsigned long long division - * - * Copyright 2003-2007 Analog Devices Inc. - * Enter bugs at http://blackfin.uclinux.org/ - * - * Licensed under the GPLv2 or later. - */ - -#include <linux/linkage.h> - -#define CARRY AC0 - -#ifdef CONFIG_ARITHMETIC_OPS_L1 -.section .l1.text -#else -.text -#endif - - -ENTRY(___udivdi3) - R3 = [SP + 12]; - [--SP] = (R7:4, P5:3); - - /* Attempt to use divide primitive first; these will handle - ** most cases, and they're quick - avoids stalls incurred by - ** testing for identities. - */ - - R4 = R2 | R3; - CC = R4 == 0; - IF CC JUMP .LDIV_BY_ZERO; - - R4.H = 0x8000; - R4 >>>= 16; // R4 now 0xFFFF8000 - R5 = R0 | R2; // If either dividend or - R4 = R5 & R4; // divisor have bits in - CC = R4; // top half or low half's sign - IF CC JUMP .LIDENTS; // bit, skip builtins. - R4 = R1 | R3; // Also check top halves - CC = R4; - IF CC JUMP .LIDENTS; - - /* Can use the builtins. */ - - AQ = CC; // Clear AQ (CC==0) - DIVQ(R0, R2); - DIVQ(R0, R2); - DIVQ(R0, R2); - DIVQ(R0, R2); - DIVQ(R0, R2); - DIVQ(R0, R2); - DIVQ(R0, R2); - DIVQ(R0, R2); - DIVQ(R0, R2); - DIVQ(R0, R2); - DIVQ(R0, R2); - DIVQ(R0, R2); - DIVQ(R0, R2); - DIVQ(R0, R2); - DIVQ(R0, R2); - DIVQ(R0, R2); - DIVQ(R0, R2); - R0 = R0.L (Z); - R1 = 0; - (R7:4, P5:3) = [SP++]; - RTS; - -.LIDENTS: - /* Test for common identities. Value to be returned is - ** placed in R6,R7. - */ - // Check for 0/y, return 0 - R4 = R0 | R1; - CC = R4 == 0; - IF CC JUMP .LRETURN_R0; - - // Check for x/x, return 1 - R6 = R0 - R2; // If x == y, then both R6 and R7 will be zero - R7 = R1 - R3; - R4 = R6 | R7; // making R4 zero. - R6 += 1; // which would now make R6:R7==1. - CC = R4 == 0; - IF CC JUMP .LRETURN_IDENT; - - // Check for x/1, return x - R6 = R0; - R7 = R1; - CC = R3 == 0; - IF !CC JUMP .Lnexttest; - CC = R2 == 1; - IF CC JUMP .LRETURN_IDENT; - -.Lnexttest: - R4.L = ONES R2; // check for div by power of two which - R5.L = ONES R3; // can be done using a shift - R6 = PACK (R5.L, R4.L); - CC = R6 == 1; - IF CC JUMP .Lpower_of_two_upper_zero; - R6 = PACK (R4.L, R5.L); - CC = R6 == 1; - IF CC JUMP .Lpower_of_two_lower_zero; - - // Check for x < y, return 0 - R6 = 0; - R7 = R6; - CC = R1 < R3 (IU); - IF CC JUMP .LRETURN_IDENT; - CC = R1 == R3; - IF !CC JUMP .Lno_idents; - CC = R0 < R2 (IU); - IF CC JUMP .LRETURN_IDENT; - -.Lno_idents: // Idents don't match. Go for the full operation - - - // If X, or X and Y have high bit set, it'll affect the - // results, so shift right one to stop this. Note: we've already - // checked that X >= Y, so Y's msb won't be set unless X's - // is. - - R4 = 0; - CC = R1 < 0; - IF !CC JUMP .Lx_msb_clear; - CC = !CC; // 1 -> 0; - R1 = ROT R1 BY -1; // Shift X >> 1 - R0 = ROT R0 BY -1; // lsb -> CC - BITSET(R4,31); // to record only x msb was set - CC = R3 < 0; - IF !CC JUMP .Ly_msb_clear; - CC = !CC; - R3 = ROT R3 BY -1; // Shift Y >> 1 - R2 = ROT R2 BY -1; - BITCLR(R4,31); // clear bit to record only x msb was set - -.Ly_msb_clear: -.Lx_msb_clear: - // Bit 31 in R4 indicates X msb set, but Y msb wasn't, and no bits - // were lost, so we should shift result left by one. - - [--SP] = R4; // save for later - - // In the loop that follows, each iteration we add - // either Y' or -Y' to the Remainder. We compute the - // negated Y', and store, for convenience. Y' goes - // into P0:P1, while -Y' goes into P2:P3. - - P0 = R2; - P1 = R3; - R2 = -R2; - CC = CARRY; - CC = !CC; - R4 = CC; - R3 = -R3; - R3 = R3 - R4; - - R6 = 0; // remainder = 0 - R7 = R6; - - [--SP] = R2; P2 = SP; - [--SP] = R3; P3 = SP; - [--SP] = R6; P5 = SP; // AQ = 0 - [--SP] = P1; - - /* In the loop that follows, we use the following - ** register assignments: - ** R0,R1 X, workspace - ** R2,R3 Y, workspace - ** R4,R5 partial Div - ** R6,R7 partial remainder - ** P5 AQ - ** The remainder and div form a 128-bit number, with - ** the remainder in the high 64-bits. - */ - R4 = R0; // Div = X' - R5 = R1; - R3 = 0; - - P4 = 64; // Iterate once per bit - LSETUP(.LULST,.LULEND) LC0 = P4; -.LULST: - /* Shift Div and remainder up by one. The bit shifted - ** out of the top of the quotient is shifted into the bottom - ** of the remainder. - */ - CC = R3; - R4 = ROT R4 BY 1; - R5 = ROT R5 BY 1 || // low q to high q - R2 = [P5]; // load saved AQ - R6 = ROT R6 BY 1 || // high q to low r - R0 = [P2]; // load -Y' - R7 = ROT R7 BY 1 || // low r to high r - R1 = [P3]; - - // Assume add -Y' - CC = R2 < 0; // But if AQ is set... - IF CC R0 = P0; // then add Y' instead - IF CC R1 = P1; - - R6 = R6 + R0; // Rem += (Y' or -Y') - CC = CARRY; - R0 = CC; - R7 = R7 + R1; - R7 = R7 + R0 (NS) || - R1 = [SP]; - // Set the next AQ bit - R1 = R7 ^ R1; // from Remainder and Y' - R1 = R1 >> 31 || // Negate AQ's value, and - [P5] = R1; // save next AQ - BITTGL(R1, 0); // add neg AQ to the Div -.LULEND: R4 = R4 + R1; - - R6 = [SP + 16]; - - R0 = R4; - R1 = R5; - CC = BITTST(R6,30); // Just set CC=0 - R4 = ROT R0 BY 1; // but if we had to shift X, - R5 = ROT R1 BY 1; // and didn't shift any bits out, - CC = BITTST(R6,31); // then the result will be half as - IF CC R0 = R4; // much as required, so shift left - IF CC R1 = R5; // one space. - - SP += 20; - (R7:4, P5:3) = [SP++]; - RTS; - -.Lpower_of_two: - /* Y has a single bit set, which means it's a power of two. - ** That means we can perform the division just by shifting - ** X to the right the appropriate number of bits - */ - - /* signbits returns the number of sign bits, minus one. - ** 1=>30, 2=>29, ..., 0x40000000=>0. Which means we need - ** to shift right n-signbits spaces. It also means 0x80000000 - ** is a special case, because that *also* gives a signbits of 0 - */ -.Lpower_of_two_lower_zero: - R7 = 0; - R6 = R1 >> 31; - CC = R3 < 0; - IF CC JUMP .LRETURN_IDENT; - - R2.L = SIGNBITS R3; - R2 = R2.L (Z); - R2 += -62; - (R7:4, P5:3) = [SP++]; - JUMP ___lshftli; - -.Lpower_of_two_upper_zero: - CC = R2 < 0; - IF CC JUMP .Lmaxint_shift; - - R2.L = SIGNBITS R2; - R2 = R2.L (Z); - R2 += -30; - (R7:4, P5:3) = [SP++]; - JUMP ___lshftli; - -.Lmaxint_shift: - R2 = -31; - (R7:4, P5:3) = [SP++]; - JUMP ___lshftli; - -.LRETURN_IDENT: - R0 = R6; - R1 = R7; -.LRETURN_R0: - (R7:4, P5:3) = [SP++]; - RTS; -.LDIV_BY_ZERO: - R0 = ~R2; - R1 = R0; - (R7:4, P5:3) = [SP++]; - RTS; - -ENDPROC(___udivdi3) - - -ENTRY(___lshftli) - CC = R2 == 0; - IF CC JUMP .Lfinished; // nothing to do - CC = R2 < 0; - IF CC JUMP .Lrshift; - R3 = 64; - CC = R2 < R3; - IF !CC JUMP .Lretzero; - - // We're shifting left, and it's less than 64 bits, so - // a valid result will be returned. - - R3 >>= 1; // R3 now 32 - CC = R2 < R3; - - IF !CC JUMP .Lzerohalf; - - // We're shifting left, between 1 and 31 bits, which means - // some of the low half will be shifted into the high half. - // Work out how much. - - R3 = R3 - R2; - - // Save that much data from the bottom half. - - P1 = R7; - R7 = R0; - R7 >>= R3; - - // Adjust both parts of the parameter. - - R0 <<= R2; - R1 <<= R2; - - // And include the bits moved across. - - R1 = R1 | R7; - R7 = P1; - RTS; - -.Lzerohalf: - // We're shifting left, between 32 and 63 bits, so the - // bottom half will become zero, and the top half will - // lose some bits. How many? - - R2 = R2 - R3; // N - 32 - R1 = LSHIFT R0 BY R2.L; - R0 = R0 - R0; - RTS; - -.Lretzero: - R0 = R0 - R0; - R1 = R0; -.Lfinished: - RTS; - -.Lrshift: - // We're shifting right, but by how much? - R2 = -R2; - R3 = 64; - CC = R2 < R3; - IF !CC JUMP .Lretzero; - - // Shifting right less than 64 bits, so some result bits will - // be retained. - - R3 >>= 1; // R3 now 32 - CC = R2 < R3; - IF !CC JUMP .Lsignhalf; - - // Shifting right between 1 and 31 bits, so need to copy - // data across words. - - P1 = R7; - R3 = R3 - R2; - R7 = R1; - R7 <<= R3; - R1 >>= R2; - R0 >>= R2; - R0 = R7 | R0; - R7 = P1; - RTS; - -.Lsignhalf: - // Shifting right between 32 and 63 bits, so the top half - // will become all zero-bits, and the bottom half is some - // of the top half. But how much? - - R2 = R2 - R3; - R0 = R1; - R0 >>= R2; - R1 = 0; - RTS; - -ENDPROC(___lshftli) diff --git a/arch/blackfin/mach-bf527/Kconfig b/arch/blackfin/mach-bf527/Kconfig index 50321f7..5c73683 100644 --- a/arch/blackfin/mach-bf527/Kconfig +++ b/arch/blackfin/mach-bf527/Kconfig @@ -1,5 +1,7 @@ if (BF52x) +source "arch/blackfin/mach-bf527/boards/Kconfig" + menu "BF527 Specific Configuration" comment "Alternative Multiplexing Scheme" diff --git a/arch/blackfin/mach-bf527/boards/Kconfig b/arch/blackfin/mach-bf527/boards/Kconfig new file mode 100644 index 0000000..6a570ad --- /dev/null +++ b/arch/blackfin/mach-bf527/boards/Kconfig @@ -0,0 +1,12 @@ +choice + prompt "System type" + default BFIN527_EZKIT + help + Select your board! + +config BFIN527_EZKIT + bool "BF527-EZKIT" + help + BF527-EZKIT-LITE board support. + +endchoice diff --git a/arch/blackfin/mach-bf527/boards/Makefile b/arch/blackfin/mach-bf527/boards/Makefile index 912ac8e..7277d35 100644 --- a/arch/blackfin/mach-bf527/boards/Makefile +++ b/arch/blackfin/mach-bf527/boards/Makefile @@ -1,7 +1,5 @@ # -# arch/blackfin/mach-bf532/boards/Makefile +# arch/blackfin/mach-bf527/boards/Makefile # -obj-y += eth_mac.o -obj-$(CONFIG_BFIN527_EZKIT) += ezkit.o - +obj-$(CONFIG_BFIN527_EZKIT) += ezkit.o diff --git a/arch/blackfin/mach-bf527/boards/eth_mac.c b/arch/blackfin/mach-bf527/boards/eth_mac.c deleted file mode 100644 index a725cc8..0000000 --- a/arch/blackfin/mach-bf527/boards/eth_mac.c +++ /dev/null @@ -1,50 +0,0 @@ -/* - * arch/blackfin/mach-bf537/board/eth_mac.c - * - * Copyright (C) 2007 Analog Devices, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -#include <linux/module.h> -#include <asm/blackfin.h> - -#if defined(CONFIG_GENERIC_BOARD) || defined(CONFIG_BFIN537_STAMP) - -/* - * Currently the MAC address is saved in Flash by U-Boot - */ -#define FLASH_MAC 0x203f0000 - -void get_bf537_ether_addr(char *addr) -{ - unsigned int flash_mac = (unsigned int) FLASH_MAC; - *(u32 *)(&(addr[0])) = bfin_read32(flash_mac); - flash_mac += 4; - *(u16 *)(&(addr[4])) = bfin_read16(flash_mac); -} - -#else - -/* - * Provide MAC address function for other specific board setting - */ -void get_bf537_ether_addr(char *addr) -{ - printk(KERN_WARNING "%s: No valid Ethernet MAC address found\n", __FILE__); -} - -#endif - -EXPORT_SYMBOL(get_bf537_ether_addr); diff --git a/arch/blackfin/mach-bf527/boards/ezkit.c b/arch/blackfin/mach-bf527/boards/ezkit.c index bf1bedc..003e2ac 100644 --- a/arch/blackfin/mach-bf527/boards/ezkit.c +++ b/arch/blackfin/mach-bf527/boards/ezkit.c @@ -35,17 +35,18 @@ #include <linux/spi/spi.h> #include <linux/spi/flash.h> #if defined(CONFIG_USB_ISP1362_HCD) || defined(CONFIG_USB_ISP1362_HCD_MODULE) -#include <linux/usb_isp1362.h> +#include <linux/usb/isp1362.h> #endif #include <linux/pata_platform.h> #include <linux/irq.h> #include <linux/interrupt.h> -#include <linux/usb_sl811.h> +#include <linux/usb/sl811.h> #include <asm/cplb.h> #include <asm/dma.h> #include <asm/bfin5xx_spi.h> #include <asm/reboot.h> #include <asm/nand.h> +#include <asm/portmux.h> #include <linux/spi/ad7877.h> /* @@ -450,6 +451,13 @@ static const struct ad7877_platform_data bfin_ad7877_ts_info = { }; #endif +#if defined(CONFIG_SND_SOC_WM8731) || defined(CONFIG_SND_SOC_WM8731_MODULE) \ + && defined(CONFIG_SND_SOC_WM8731_SPI) +static struct bfin5xx_spi_chip spi_wm8731_chip_info = { + .enable_dma = 0, + .bits_per_word = 16, +}; +#endif static struct spi_board_info bfin_spi_board_info[] __initdata = { #if defined(CONFIG_MTD_M25P80) \ || defined(CONFIG_MTD_M25P80_MODULE) @@ -551,17 +559,29 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = { .platform_data = &bfin_ad7877_ts_info, .irq = IRQ_PF6, .max_speed_hz = 12500000, /* max spi clock (SCK) speed in HZ */ - .bus_num = 1, + .bus_num = 0, .chip_select = 1, .controller_data = &spi_ad7877_chip_info, }, #endif +#if defined(CONFIG_SND_SOC_WM8731) || defined(CONFIG_SND_SOC_WM8731_MODULE) \ + && defined(CONFIG_SND_SOC_WM8731_SPI) + { + .modalias = "wm8731", + .max_speed_hz = 3125000, /* max spi clock (SCK) speed in HZ */ + .bus_num = 0, + .chip_select = 5, + .controller_data = &spi_wm8731_chip_info, + .mode = SPI_MODE_0, + }, +#endif }; /* SPI controller data */ static struct bfin5xx_spi_master bfin_spi0_info = { .num_chipselect = 8, .enable_dma = 1, /* master has the ability to do dma transfer */ + .pin_req = {P_SPI0_SCK, P_SPI0_MISO, P_SPI0_MOSI, 0}, }; /* SPI (0) */ @@ -788,3 +808,14 @@ void native_machine_restart(char *cmd) if ((bfin_read_SYSCR() & 0x7) == 0x3) bfin_gpio_reset_spi0_ssel1(); } + +/* + * Currently the MAC address is saved in Flash by U-Boot + */ +#define FLASH_MAC 0x203f0000 +void bfin_get_ether_addr(char *addr) +{ + *(u32 *)(&(addr[0])) = bfin_read32(FLASH_MAC); + *(u16 *)(&(addr[4])) = bfin_read16(FLASH_MAC + 4); +} +EXPORT_SYMBOL(bfin_get_ether_addr); diff --git a/arch/blackfin/mach-bf533/Kconfig b/arch/blackfin/mach-bf533/Kconfig index 14297b3..76beb75 100644 --- a/arch/blackfin/mach-bf533/Kconfig +++ b/arch/blackfin/mach-bf533/Kconfig @@ -1,5 +1,7 @@ if (BF533 || BF532 || BF531) +source "arch/blackfin/mach-bf533/boards/Kconfig" + menu "BF533/2/1 Specific Configuration" comment "Interrupt Priority Assignment" diff --git a/arch/blackfin/mach-bf533/boards/H8606.c b/arch/blackfin/mach-bf533/boards/H8606.c index b941550..6bcf404 100644 --- a/arch/blackfin/mach-bf533/boards/H8606.c +++ b/arch/blackfin/mach-bf533/boards/H8606.c @@ -36,20 +36,21 @@ #include <linux/spi/spi.h> #include <linux/spi/flash.h> #if defined(CONFIG_USB_ISP1362_HCD) || defined(CONFIG_USB_ISP1362_HCD_MODULE) -#include <linux/usb_isp1362.h> +#include <linux/usb/isp1362.h> #endif #include <linux/pata_platform.h> #include <linux/irq.h> #include <asm/dma.h> #include <asm/bfin5xx_spi.h> #include <asm/reboot.h> +#include <asm/portmux.h> /* * Name the Board for the /proc/cpuinfo */ const char bfin_board_name[] = "HV Sistemas H8606"; -#if defined(CONFIG_RTC_DRV_BFIN) || defined(CONFIG_RTC_BFIN_MODULE) +#if defined(CONFIG_RTC_DRV_BFIN) || defined(CONFIG_RTC_DRV_BFIN_MODULE) static struct platform_device rtc_device = { .name = "rtc-bfin", .id = -1, @@ -93,10 +94,6 @@ static struct resource smc91x_resources[] = { .end = IRQ_PROG_INTB, .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL, }, { - /* - * denotes the flag pin and is used directly if - * CONFIG_IRQCHIP_DEMUX_GPIO is defined. - */ .start = IRQ_PF7, .end = IRQ_PF7, .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL, @@ -269,6 +266,7 @@ static struct resource bfin_spi0_resource[] = { static struct bfin5xx_spi_master bfin_spi0_info = { .num_chipselect = 8, .enable_dma = 1, /* master has the ability to do dma transfer */ + .pin_req = {P_SPI0_SCK, P_SPI0_MISO, P_SPI0_MOSI, 0}, }; static struct platform_device bfin_spi0_device = { @@ -342,4 +340,4 @@ static int __init H8606_init(void) return 0; } -arch_initcall(H8606_init);
\ No newline at end of file +arch_initcall(H8606_init); diff --git a/arch/blackfin/mach-bf533/boards/Kconfig b/arch/blackfin/mach-bf533/boards/Kconfig new file mode 100644 index 0000000..751de51 --- /dev/null +++ b/arch/blackfin/mach-bf533/boards/Kconfig @@ -0,0 +1,34 @@ +choice + prompt "System type" + default BFIN533_STAMP + help + Select your board! + +config BFIN533_EZKIT + bool "BF533-EZKIT" + help + BF533-EZKIT-LITE board support. + +config BFIN533_STAMP + bool "BF533-STAMP" + help + BF533-STAMP board support. + +config BFIN533_BLUETECHNIX_CM + bool "Bluetechnix CM-BF533" + depends on (BF533) + help + CM-BF533 support for EVAL- and DEV-Board. + +config H8606_HVSISTEMAS + bool "HV Sistemas H8606" + depends on (BF532) + help + HV Sistemas H8606 board support. + +config GENERIC_BF533_BOARD + bool "Generic" + help + Generic or Custom board support. + +endchoice diff --git a/arch/blackfin/mach-bf533/boards/Makefile b/arch/blackfin/mach-bf533/boards/Makefile index 2452b45..54f57fb 100644 --- a/arch/blackfin/mach-bf533/boards/Makefile +++ b/arch/blackfin/mach-bf533/boards/Makefile @@ -2,7 +2,7 @@ # arch/blackfin/mach-bf533/boards/Makefile # -obj-$(CONFIG_GENERIC_BOARD) += generic_board.o +obj-$(CONFIG_GENERIC_BF533_BOARD) += generic_board.o obj-$(CONFIG_BFIN533_STAMP) += stamp.o obj-$(CONFIG_BFIN533_EZKIT) += ezkit.o obj-$(CONFIG_BFIN533_BLUETECHNIX_CM) += cm_bf533.o diff --git a/arch/blackfin/mach-bf533/boards/cm_bf533.c b/arch/blackfin/mach-bf533/boards/cm_bf533.c index a863522..21df2f3 100644 --- a/arch/blackfin/mach-bf533/boards/cm_bf533.c +++ b/arch/blackfin/mach-bf533/boards/cm_bf533.c @@ -33,11 +33,12 @@ #include <linux/mtd/partitions.h> #include <linux/spi/spi.h> #include <linux/spi/flash.h> -#include <linux/usb_isp1362.h> +#include <linux/usb/isp1362.h> #include <linux/pata_platform.h> #include <linux/irq.h> #include <asm/dma.h> #include <asm/bfin5xx_spi.h> +#include <asm/portmux.h> /* * Name the Board for the /proc/cpuinfo @@ -175,6 +176,7 @@ static struct resource bfin_spi0_resource[] = { static struct bfin5xx_spi_master bfin_spi0_info = { .num_chipselect = 8, .enable_dma = 1, /* master has the ability to do dma transfer */ + .pin_req = {P_SPI0_SCK, P_SPI0_MISO, P_SPI0_MOSI, 0}, }; static struct platform_device bfin_spi0_device = { diff --git a/arch/blackfin/mach-bf533/boards/ezkit.c b/arch/blackfin/mach-bf533/boards/ezkit.c index 34b6392..be85203 100644 --- a/arch/blackfin/mach-bf533/boards/ezkit.c +++ b/arch/blackfin/mach-bf533/boards/ezkit.c @@ -34,11 +34,12 @@ #include <linux/mtd/partitions.h> #include <linux/spi/spi.h> #include <linux/spi/flash.h> -#include <linux/usb_isp1362.h> +#include <linux/usb/isp1362.h> #include <linux/pata_platform.h> #include <linux/irq.h> #include <asm/dma.h> #include <asm/bfin5xx_spi.h> +#include <asm/portmux.h> /* * Name the Board for the /proc/cpuinfo @@ -187,6 +188,7 @@ static struct resource bfin_spi0_resource[] = { static struct bfin5xx_spi_master bfin_spi0_info = { .num_chipselect = 8, .enable_dma = 1, /* master has the ability to do dma transfer */ + .pin_req = {P_SPI0_SCK, P_SPI0_MISO, P_SPI0_MOSI, 0}, }; static struct platform_device bfin_spi0_device = { diff --git a/arch/blackfin/mach-bf533/boards/generic_board.c b/arch/blackfin/mach-bf533/boards/generic_board.c index 310b777..e359a0d 100644 --- a/arch/blackfin/mach-bf533/boards/generic_board.c +++ b/arch/blackfin/mach-bf533/boards/generic_board.c @@ -58,10 +58,6 @@ static struct resource smc91x_resources[] = { .end = IRQ_PROG_INTB, .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL, }, { - /* - * denotes the flag pin and is used directly if - * CONFIG_IRQCHIP_DEMUX_GPIO is defined. - */ .start = IRQ_PF7, .end = IRQ_PF7, .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL, diff --git a/arch/blackfin/mach-bf533/boards/stamp.c b/arch/blackfin/mach-bf533/boards/stamp.c index 62ffa50..8fde8d8 100644 --- a/arch/blackfin/mach-bf533/boards/stamp.c +++ b/arch/blackfin/mach-bf533/boards/stamp.c @@ -35,13 +35,14 @@ #include <linux/spi/spi.h> #include <linux/spi/flash.h> #if defined(CONFIG_USB_ISP1362_HCD) || defined(CONFIG_USB_ISP1362_HCD_MODULE) -#include <linux/usb_isp1362.h> +#include <linux/usb/isp1362.h> #endif #include <linux/pata_platform.h> #include <linux/irq.h> #include <asm/dma.h> #include <asm/bfin5xx_spi.h> #include <asm/reboot.h> +#include <asm/portmux.h> /* * Name the Board for the /proc/cpuinfo @@ -286,6 +287,7 @@ static struct resource bfin_spi0_resource[] = { static struct bfin5xx_spi_master bfin_spi0_info = { .num_chipselect = 8, .enable_dma = 1, /* master has the ability to do dma transfer */ + .pin_req = {P_SPI0_SCK, P_SPI0_MISO, P_SPI0_MOSI, 0}, }; static struct platform_device bfin_spi0_device = { diff --git a/arch/blackfin/mach-bf537/Kconfig b/arch/blackfin/mach-bf537/Kconfig index e6648db..8255374 100644 --- a/arch/blackfin/mach-bf537/Kconfig +++ b/arch/blackfin/mach-bf537/Kconfig @@ -1,5 +1,7 @@ if (BF537 || BF534 || BF536) +source "arch/blackfin/mach-bf537/boards/Kconfig" + menu "BF537 Specific Configuration" comment "Interrupt Priority Assignment" diff --git a/arch/blackfin/mach-bf537/boards/Kconfig b/arch/blackfin/mach-bf537/boards/Kconfig new file mode 100644 index 0000000..96a1519 --- /dev/null +++ b/arch/blackfin/mach-bf537/boards/Kconfig @@ -0,0 +1,29 @@ +choice + prompt "System type" + default BFIN537_STAMP + help + Select your board! + +config BFIN537_STAMP + bool "BF537-STAMP" + help + BF537-STAMP board support. + +config BFIN537_BLUETECHNIX_CM + bool "Bluetechnix CM-BF537" + depends on (BF537) + help + CM-BF537 support for EVAL- and DEV-Board. + +config PNAV10 + bool "PNAV board" + depends on (BF537) + help + PNAV board support. + +config GENERIC_BF537_BOARD + bool "Generic" + help + Generic or Custom board support. + +endchoice diff --git a/arch/blackfin/mach-bf537/boards/Makefile b/arch/blackfin/mach-bf537/boards/Makefile index 23323ca..94a8517 100644 --- a/arch/blackfin/mach-bf537/boards/Makefile +++ b/arch/blackfin/mach-bf537/boards/Makefile @@ -2,8 +2,7 @@ # arch/blackfin/mach-bf537/boards/Makefile # -obj-y += eth_mac.o -obj-$(CONFIG_GENERIC_BOARD) += generic_board.o -obj-$(CONFIG_BFIN537_STAMP) += stamp.o led.o -obj-$(CONFIG_BFIN537_BLUETECHNIX_CM) += cm_bf537.o -obj-$(CONFIG_PNAV10) += pnav10.o +obj-$(CONFIG_GENERIC_BF537_BOARD) += generic_board.o +obj-$(CONFIG_BFIN537_STAMP) += stamp.o led.o +obj-$(CONFIG_BFIN537_BLUETECHNIX_CM) += cm_bf537.o +obj-$(CONFIG_PNAV10) += pnav10.o diff --git a/arch/blackfin/mach-bf537/boards/cm_bf537.c b/arch/blackfin/mach-bf537/boards/cm_bf537.c index 2915931..c0fb06d 100644 --- a/arch/blackfin/mach-bf537/boards/cm_bf537.c +++ b/arch/blackfin/mach-bf537/boards/cm_bf537.c @@ -34,11 +34,12 @@ #include <linux/mtd/partitions.h> #include <linux/spi/spi.h> #include <linux/spi/flash.h> -#include <linux/usb_isp1362.h> +#include <linux/usb/isp1362.h> #include <linux/pata_platform.h> #include <linux/irq.h> #include <asm/dma.h> #include <asm/bfin5xx_spi.h> +#include <asm/portmux.h> /* * Name the Board for the /proc/cpuinfo @@ -194,6 +195,7 @@ static struct resource bfin_spi0_resource[] = { static struct bfin5xx_spi_master bfin_spi0_info = { .num_chipselect = 8, .enable_dma = 1, /* master has the ability to do dma transfer */ + .pin_req = {P_SPI0_SCK, P_SPI0_MISO, P_SPI0_MOSI, 0}, }; static struct platform_device bfin_spi0_device = { @@ -425,3 +427,10 @@ static int __init cm_bf537_init(void) } arch_initcall(cm_bf537_init); + +void bfin_get_ether_addr(char *addr) +{ + random_ether_addr(addr); + printk(KERN_WARNING "%s:%s: Setting Ethernet MAC to a random one\n", __FILE__, __func__); +} +EXPORT_SYMBOL(bfin_get_ether_addr); diff --git a/arch/blackfin/mach-bf537/boards/eth_mac.c b/arch/blackfin/mach-bf537/boards/eth_mac.c deleted file mode 100644 index a725cc8..0000000 --- a/arch/blackfin/mach-bf537/boards/eth_mac.c +++ /dev/null @@ -1,50 +0,0 @@ -/* - * arch/blackfin/mach-bf537/board/eth_mac.c - * - * Copyright (C) 2007 Analog Devices, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -#include <linux/module.h> -#include <asm/blackfin.h> - -#if defined(CONFIG_GENERIC_BOARD) || defined(CONFIG_BFIN537_STAMP) - -/* - * Currently the MAC address is saved in Flash by U-Boot - */ -#define FLASH_MAC 0x203f0000 - -void get_bf537_ether_addr(char *addr) -{ - unsigned int flash_mac = (unsigned int) FLASH_MAC; - *(u32 *)(&(addr[0])) = bfin_read32(flash_mac); - flash_mac += 4; - *(u16 *)(&(addr[4])) = bfin_read16(flash_mac); -} - -#else - -/* - * Provide MAC address function for other specific board setting - */ -void get_bf537_ether_addr(char *addr) -{ - printk(KERN_WARNING "%s: No valid Ethernet MAC address found\n", __FILE__); -} - -#endif - -EXPORT_SYMBOL(get_bf537_ether_addr); diff --git a/arch/blackfin/mach-bf537/boards/generic_board.c b/arch/blackfin/mach-bf537/boards/generic_board.c index 255da7a..09f4bfb 100644 --- a/arch/blackfin/mach-bf537/boards/generic_board.c +++ b/arch/blackfin/mach-bf537/boards/generic_board.c @@ -35,7 +35,7 @@ #include <linux/spi/spi.h> #include <linux/spi/flash.h> #if defined(CONFIG_USB_ISP1362_HCD) || defined(CONFIG_USB_ISP1362_HCD_MODULE) -#include <linux/usb_isp1362.h> +#include <linux/usb/isp1362.h> #endif #include <linux/pata_platform.h> #include <linux/irq.h> @@ -44,6 +44,7 @@ #include <asm/dma.h> #include <asm/bfin5xx_spi.h> #include <asm/reboot.h> +#include <asm/portmux.h> #include <linux/spi/ad7877.h> /* @@ -502,7 +503,7 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = { .platform_data = &bfin_ad7877_ts_info, .irq = IRQ_PF6, .max_speed_hz = 12500000, /* max spi clock (SCK) speed in HZ */ - .bus_num = 1, + .bus_num = 0, .chip_select = 1, .controller_data = &spi_ad7877_chip_info, }, @@ -513,6 +514,7 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = { static struct bfin5xx_spi_master bfin_spi0_info = { .num_chipselect = 8, .enable_dma = 1, /* master has the ability to do dma transfer */ + .pin_req = {P_SPI0_SCK, P_SPI0_MISO, P_SPI0_MOSI, 0}, }; /* SPI (0) */ @@ -730,3 +732,10 @@ void native_machine_restart(char *cmd) if ((bfin_read_SYSCR() & 0x7) == 0x3) bfin_gpio_reset_spi0_ssel1(); } + +void bfin_get_ether_addr(char *addr) +{ + random_ether_addr(addr); + printk(KERN_WARNING "%s:%s: Setting Ethernet MAC to a random one\n", __FILE__, __func__); +} +EXPORT_SYMBOL(bfin_get_ether_addr); diff --git a/arch/blackfin/mach-bf537/boards/pnav10.c b/arch/blackfin/mach-bf537/boards/pnav10.c index 87b8089..fd5f4a6 100644 --- a/arch/blackfin/mach-bf537/boards/pnav10.c +++ b/arch/blackfin/mach-bf537/boards/pnav10.c @@ -35,11 +35,12 @@ #include <linux/spi/spi.h> #include <linux/spi/flash.h> #if defined(CONFIG_USB_ISP1362_HCD) || defined(CONFIG_USB_ISP1362_HCD_MODULE) -#include <linux/usb_isp1362.h> +#include <linux/usb/isp1362.h> #endif #include <linux/irq.h> #include <asm/dma.h> #include <asm/bfin5xx_spi.h> +#include <asm/portmux.h> #include <linux/usb/sl811.h> #include <linux/spi/ad7877.h> @@ -295,7 +296,7 @@ static struct bfin5xx_spi_chip spi_mmc_chip_info = { #if defined(CONFIG_TOUCHSCREEN_AD7877) || defined(CONFIG_TOUCHSCREEN_AD7877_MODULE) static struct bfin5xx_spi_chip spi_ad7877_chip_info = { - .cs_change_per_word = 1, + .cs_change_per_word = 0, .enable_dma = 0, .bits_per_word = 16, }; @@ -387,7 +388,7 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = { .platform_data = &bfin_ad7877_ts_info, .irq = IRQ_PF2, .max_speed_hz = 12500000, /* max spi clock (SCK) speed in HZ */ - .bus_num = 1, + .bus_num = 0, .chip_select = 5, .controller_data = &spi_ad7877_chip_info, }, @@ -413,6 +414,7 @@ static struct resource bfin_spi0_resource[] = { static struct bfin5xx_spi_master bfin_spi0_info = { .num_chipselect = 8, .enable_dma = 1, /* master has the ability to do dma transfer */ + .pin_req = {P_SPI0_SCK, P_SPI0_MISO, P_SPI0_MOSI, 0}, }; static struct platform_device bfin_spi0_device = { @@ -508,3 +510,10 @@ static int __init stamp_init(void) } arch_initcall(stamp_init); + +void bfin_get_ether_addr(char *addr) +{ + random_ether_addr(addr); + printk(KERN_WARNING "%s:%s: Setting Ethernet MAC to a random one\n", __FILE__, __func__); +} +EXPORT_SYMBOL(bfin_get_ether_addr); diff --git a/arch/blackfin/mach-bf537/boards/stamp.c b/arch/blackfin/mach-bf537/boards/stamp.c index 5f7b91f..07b0dc2 100644 --- a/arch/blackfin/mach-bf537/boards/stamp.c +++ b/arch/blackfin/mach-bf537/boards/stamp.c @@ -35,7 +35,7 @@ #include <linux/spi/spi.h> #include <linux/spi/flash.h> #if defined(CONFIG_USB_ISP1362_HCD) || defined(CONFIG_USB_ISP1362_HCD_MODULE) -#include <linux/usb_isp1362.h> +#include <linux/usb/isp1362.h> #endif #include <linux/pata_platform.h> #include <linux/irq.h> @@ -44,6 +44,7 @@ #include <asm/dma.h> #include <asm/bfin5xx_spi.h> #include <asm/reboot.h> +#include <asm/portmux.h> #include <linux/spi/ad7877.h> /* @@ -182,6 +183,28 @@ static struct platform_device dm9000_device = { }; #endif +#if defined(CONFIG_AX88180) || defined(CONFIG_AX88180_MODULE) +static struct resource ax88180_resources[] = { + [0] = { + .start = 0x20300000, + .end = 0x20300000 + 0x8000, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = IRQ_PF7, + .end = IRQ_PF7, + .flags = (IORESOURCE_IRQ | IORESOURCE_IRQ_LOWLEVEL), + }, +}; + +static struct platform_device ax88180_device = { + .name = "ax88180", + .id = -1, + .num_resources = ARRAY_SIZE(ax88180_resources), + .resource = ax88180_resources, +}; +#endif + #if defined(CONFIG_USB_SL811_HCD) || defined(CONFIG_USB_SL811_HCD_MODULE) static struct resource sl811_hcd_resources[] = { { @@ -502,7 +525,7 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = { .platform_data = &bfin_ad7877_ts_info, .irq = IRQ_PF6, .max_speed_hz = 12500000, /* max spi clock (SCK) speed in HZ */ - .bus_num = 1, + .bus_num = 0, .chip_select = 1, .controller_data = &spi_ad7877_chip_info, }, @@ -513,6 +536,7 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = { static struct bfin5xx_spi_master bfin_spi0_info = { .num_chipselect = 8, .enable_dma = 1, /* master has the ability to do dma transfer */ + .pin_req = {P_SPI0_SCK, P_SPI0_MISO, P_SPI0_MOSI, 0}, }; /* SPI (0) */ @@ -554,15 +578,20 @@ static struct platform_device bfin_fb_adv7393_device = { #if defined(CONFIG_SERIAL_BFIN) || defined(CONFIG_SERIAL_BFIN_MODULE) static struct resource bfin_uart_resources[] = { +#ifdef CONFIG_SERIAL_BFIN_UART0 { .start = 0xFFC00400, .end = 0xFFC004FF, .flags = IORESOURCE_MEM, - }, { + }, +#endif +#ifdef CONFIG_SERIAL_BFIN_UART1 + { .start = 0xFFC02000, .end = 0xFFC020FF, .flags = IORESOURCE_MEM, }, +#endif }; static struct platform_device bfin_uart_device = { @@ -669,6 +698,10 @@ static struct platform_device *stamp_devices[] __initdata = { &dm9000_device, #endif +#if defined(CONFIG_AX88180) || defined(CONFIG_AX88180_MODULE) + &ax88180_device, +#endif + #if defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE) &bfin_mac_device, #endif @@ -730,3 +763,14 @@ void native_machine_restart(char *cmd) if ((bfin_read_SYSCR() & 0x7) == 0x3) bfin_gpio_reset_spi0_ssel1(); } + +/* + * Currently the MAC address is saved in Flash by U-Boot + */ +#define FLASH_MAC 0x203f0000 +void bfin_get_ether_addr(char *addr) +{ + *(u32 *)(&(addr[0])) = bfin_read32(FLASH_MAC); + *(u16 *)(&(addr[4])) = bfin_read16(FLASH_MAC + 4); +} +EXPORT_SYMBOL(bfin_get_ether_addr); diff --git a/arch/blackfin/mach-bf548/Kconfig b/arch/blackfin/mach-bf548/Kconfig index 08d8dc8..d8bd3b4 100644 --- a/arch/blackfin/mach-bf548/Kconfig +++ b/arch/blackfin/mach-bf548/Kconfig @@ -1,5 +1,7 @@ if (BF54x) +source "arch/blackfin/mach-bf548/boards/Kconfig" + menu "BF548 Specific Configuration" config DEB_DMA_URGENT diff --git a/arch/blackfin/mach-bf548/boards/Kconfig b/arch/blackfin/mach-bf548/boards/Kconfig new file mode 100644 index 0000000..0571290 --- /dev/null +++ b/arch/blackfin/mach-bf548/boards/Kconfig @@ -0,0 +1,12 @@ +choice + prompt "System type" + default BFIN548_EZKIT + help + Select your board! + +config BFIN548_EZKIT + bool "BF548-EZKIT" + help + BFIN548-EZKIT board support. + +endchoice diff --git a/arch/blackfin/mach-bf548/boards/Makefile b/arch/blackfin/mach-bf548/boards/Makefile index 486e07c..a444cc7 100644 --- a/arch/blackfin/mach-bf548/boards/Makefile +++ b/arch/blackfin/mach-bf548/boards/Makefile @@ -2,4 +2,4 @@ # arch/blackfin/mach-bf548/boards/Makefile # -obj-$(CONFIG_BFIN548_EZKIT) += ezkit.o led.o +obj-$(CONFIG_BFIN548_EZKIT) += ezkit.o led.o diff --git a/arch/blackfin/mach-bf548/boards/ezkit.c b/arch/blackfin/mach-bf548/boards/ezkit.c index 6b6490e..d37d665 100644 --- a/arch/blackfin/mach-bf548/boards/ezkit.c +++ b/arch/blackfin/mach-bf548/boards/ezkit.c @@ -42,6 +42,7 @@ #include <asm/dma.h> #include <asm/gpio.h> #include <asm/nand.h> +#include <asm/portmux.h> #include <asm/mach/bf54x_keys.h> #include <linux/input.h> #include <linux/spi/ad7877.h> @@ -377,7 +378,7 @@ static struct bfin5xx_spi_chip spi_flash_chip_info = { #if defined(CONFIG_TOUCHSCREEN_AD7877) || defined(CONFIG_TOUCHSCREEN_AD7877_MODULE) static struct bfin5xx_spi_chip spi_ad7877_chip_info = { - .cs_change_per_word = 1, + .cs_change_per_word = 0, .enable_dma = 0, .bits_per_word = 16, }; @@ -453,9 +454,10 @@ static struct resource bfin_spi1_resource[] = { }; /* SPI controller data */ -static struct bfin5xx_spi_master bf54x_spi_master_info = { +static struct bfin5xx_spi_master bf54x_spi_master_info0 = { .num_chipselect = 8, .enable_dma = 1, /* master has the ability to do dma transfer */ + .pin_req = {P_SPI0_SCK, P_SPI0_MISO, P_SPI0_MOSI, 0}, }; static struct platform_device bf54x_spi_master0 = { @@ -464,17 +466,23 @@ static struct platform_device bf54x_spi_master0 = { .num_resources = ARRAY_SIZE(bfin_spi0_resource), .resource = bfin_spi0_resource, .dev = { - .platform_data = &bf54x_spi_master_info, /* Passed to driver */ + .platform_data = &bf54x_spi_master_info0, /* Passed to driver */ }, }; +static struct bfin5xx_spi_master bf54x_spi_master_info1 = { + .num_chipselect = 8, + .enable_dma = 1, /* master has the ability to do dma transfer */ + .pin_req = {P_SPI1_SCK, P_SPI1_MISO, P_SPI1_MOSI, 0}, +}; + static struct platform_device bf54x_spi_master1 = { .name = "bfin-spi", .id = 1, /* Bus number */ .num_resources = ARRAY_SIZE(bfin_spi1_resource), .resource = bfin_spi1_resource, .dev = { - .platform_data = &bf54x_spi_master_info, /* Passed to driver */ + .platform_data = &bf54x_spi_master_info1, /* Passed to driver */ }, }; #endif /* spi master and devices */ @@ -500,6 +508,7 @@ static struct platform_device i2c_bfin_twi0_device = { .resource = bfin_twi0_resource, }; +#if !defined(CONFIG_BF542) /* The BF542 only has 1 TWI */ static struct resource bfin_twi1_resource[] = { [0] = { .start = TWI1_REGBASE, @@ -520,6 +529,7 @@ static struct platform_device i2c_bfin_twi1_device = { .resource = bfin_twi1_resource, }; #endif +#endif static struct platform_device *ezkit_devices[] __initdata = { #if defined(CONFIG_RTC_DRV_BFIN) || defined(CONFIG_RTC_DRV_BFIN_MODULE) @@ -569,8 +579,10 @@ static struct platform_device *ezkit_devices[] __initdata = { #if defined(CONFIG_I2C_BLACKFIN_TWI) || defined(CONFIG_I2C_BLACKFIN_TWI_MODULE) &i2c_bfin_twi0_device, +#if !defined(CONFIG_BF542) &i2c_bfin_twi1_device, #endif +#endif }; static int __init stamp_init(void) diff --git a/arch/blackfin/mach-bf548/head.S b/arch/blackfin/mach-bf548/head.S index 3071c24..74b34c7 100644 --- a/arch/blackfin/mach-bf548/head.S +++ b/arch/blackfin/mach-bf548/head.S @@ -158,6 +158,27 @@ ENTRY(__stext) w[p2] = r0; ssync; + p2.h = hi(EBIU_MBSCTL); + p2.l = lo(EBIU_MBSCTL); + r0.h = hi(CONFIG_EBIU_MBSCTLVAL); + r0.l = lo(CONFIG_EBIU_MBSCTLVAL); + [p2] = r0; + ssync; + + p2.h = hi(EBIU_MODE); + p2.l = lo(EBIU_MODE); + r0.h = hi(CONFIG_EBIU_MODEVAL); + r0.l = lo(CONFIG_EBIU_MODEVAL); + [p2] = r0; + ssync; + + p2.h = hi(EBIU_FCTL); + p2.l = lo(EBIU_FCTL); + r0.h = hi(CONFIG_EBIU_FCTLVAL); + r0.l = lo(CONFIG_EBIU_FCTLVAL); + [p2] = r0; + ssync; + /* This section keeps the processor in supervisor mode * during kernel boot. Switches to user mode at end of boot. * See page 3-9 of Hardware Reference manual for documentation. diff --git a/arch/blackfin/mach-bf561/Kconfig b/arch/blackfin/mach-bf561/Kconfig index 0a17c4c..3f48954 100644 --- a/arch/blackfin/mach-bf561/Kconfig +++ b/arch/blackfin/mach-bf561/Kconfig @@ -1,4 +1,6 @@ -if BF561 +if (BF561) + +source "arch/blackfin/mach-bf561/boards/Kconfig" menu "BF561 Specific Configuration" diff --git a/arch/blackfin/mach-bf561/boards/Kconfig b/arch/blackfin/mach-bf561/boards/Kconfig new file mode 100644 index 0000000..e41a67b --- /dev/null +++ b/arch/blackfin/mach-bf561/boards/Kconfig @@ -0,0 +1,27 @@ +choice + prompt "System type" + default BFIN561_EZKIT + help + Select your board! + +config BFIN561_EZKIT + bool "BF561-EZKIT" + help + BF561-EZKIT-LITE board support. + +config BFIN561_TEPLA + bool "BF561-TEPLA" + help + BF561-TEPLA board support. + +config BFIN561_BLUETECHNIX_CM + bool "Bluetechnix CM-BF561" + help + CM-BF561 support for EVAL- and DEV-Board. + +config GENERIC_BF561_BOARD + bool "Generic" + help + Generic or Custom board support. + +endchoice diff --git a/arch/blackfin/mach-bf561/boards/Makefile b/arch/blackfin/mach-bf561/boards/Makefile index 495a1cf..04add01 100644 --- a/arch/blackfin/mach-bf561/boards/Makefile +++ b/arch/blackfin/mach-bf561/boards/Makefile @@ -2,7 +2,7 @@ # arch/blackfin/mach-bf561/boards/Makefile # -obj-$(CONFIG_GENERIC_BOARD) += generic_board.o +obj-$(CONFIG_GENERIC_BF561_BOARD) += generic_board.o obj-$(CONFIG_BFIN561_BLUETECHNIX_CM) += cm_bf561.o obj-$(CONFIG_BFIN561_EZKIT) += ezkit.o obj-$(CONFIG_BFIN561_TEPLA) += tepla.o diff --git a/arch/blackfin/mach-bf561/boards/cm_bf561.c b/arch/blackfin/mach-bf561/boards/cm_bf561.c index 97aeb43..c19cd29 100644 --- a/arch/blackfin/mach-bf561/boards/cm_bf561.c +++ b/arch/blackfin/mach-bf561/boards/cm_bf561.c @@ -33,11 +33,12 @@ #include <linux/mtd/partitions.h> #include <linux/spi/spi.h> #include <linux/spi/flash.h> -#include <linux/usb_isp1362.h> +#include <linux/usb/isp1362.h> #include <linux/pata_platform.h> #include <linux/irq.h> #include <asm/dma.h> #include <asm/bfin5xx_spi.h> +#include <asm/portmux.h> /* * Name the Board for the /proc/cpuinfo @@ -182,6 +183,7 @@ static struct resource bfin_spi0_resource[] = { static struct bfin5xx_spi_master bfin_spi0_info = { .num_chipselect = 8, .enable_dma = 1, /* master has the ability to do dma transfer */ + .pin_req = {P_SPI0_SCK, P_SPI0_MISO, P_SPI0_MOSI, 0}, }; static struct platform_device bfin_spi0_device = { diff --git a/arch/blackfin/mach-bf561/boards/ezkit.c b/arch/blackfin/mach-bf561/boards/ezkit.c index 059d516..4ff8f6e 100644 --- a/arch/blackfin/mach-bf561/boards/ezkit.c +++ b/arch/blackfin/mach-bf561/boards/ezkit.c @@ -35,6 +35,7 @@ #include <linux/pata_platform.h> #include <asm/dma.h> #include <asm/bfin5xx_spi.h> +#include <asm/portmux.h> /* * Name the Board for the /proc/cpuinfo @@ -115,6 +116,28 @@ static struct platform_device smc91x_device = { }; #endif +#if defined(CONFIG_AX88180) || defined(CONFIG_AX88180_MODULE) +static struct resource ax88180_resources[] = { + [0] = { + .start = 0x2c000000, + .end = 0x2c000000 + 0x8000, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = IRQ_PF10, + .end = IRQ_PF10, + .flags = (IORESOURCE_IRQ | IORESOURCE_IRQ_LOWLEVEL), + }, +}; + +static struct platform_device ax88180_device = { + .name = "ax88180", + .id = -1, + .num_resources = ARRAY_SIZE(ax88180_resources), + .resource = ax88180_resources, +}; +#endif + #if defined(CONFIG_SERIAL_BFIN) || defined(CONFIG_SERIAL_BFIN_MODULE) static struct resource bfin_uart_resources[] = { { @@ -160,6 +183,7 @@ static struct resource bfin_spi0_resource[] = { static struct bfin5xx_spi_master bfin_spi0_info = { .num_chipselect = 8, .enable_dma = 1, /* master has the ability to do dma transfer */ + .pin_req = {P_SPI0_SCK, P_SPI0_MISO, P_SPI0_MOSI, 0}, }; static struct platform_device bfin_spi0_device = { @@ -226,6 +250,11 @@ static struct platform_device *ezkit_devices[] __initdata = { #if defined(CONFIG_SMC91X) || defined(CONFIG_SMC91X_MODULE) &smc91x_device, #endif + +#if defined(CONFIG_AX88180) || defined(CONFIG_AX88180_MODULE) + &ax88180_device, +#endif + #if defined(CONFIG_SPI_BFIN) || defined(CONFIG_SPI_BFIN_MODULE) &bfin_spi0_device, #endif diff --git a/arch/blackfin/mach-bf561/boards/generic_board.c b/arch/blackfin/mach-bf561/boards/generic_board.c index 46816be..fc80c5d 100644 --- a/arch/blackfin/mach-bf561/boards/generic_board.c +++ b/arch/blackfin/mach-bf561/boards/generic_board.c @@ -48,10 +48,6 @@ static struct resource smc91x_resources[] = { .end = IRQ_PROG_INTB, .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL, }, { - /* - * denotes the flag pin and is used directly if - * CONFIG_IRQCHIP_DEMUX_GPIO is defined. - */ .start = IRQ_PF9, .end = IRQ_PF9, .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL, diff --git a/arch/blackfin/mach-bf561/boards/tepla.c b/arch/blackfin/mach-bf561/boards/tepla.c index 4a17c6d..ec6a220 100644 --- a/arch/blackfin/mach-bf561/boards/tepla.c +++ b/arch/blackfin/mach-bf561/boards/tepla.c @@ -31,10 +31,6 @@ static struct resource smc91x_resources[] = { .end = IRQ_PROG_INTB, .flags = IORESOURCE_IRQ|IORESOURCE_IRQ_HIGHLEVEL, }, { - /* - * denotes the flag pin and is used directly if - * CONFIG_IRQCHIP_DEMUX_GPIO is defined. - */ .start = IRQ_PF7, .end = IRQ_PF7, .flags = IORESOURCE_IRQ|IORESOURCE_IRQ_HIGHLEVEL, diff --git a/arch/blackfin/mach-common/cplbinfo.c b/arch/blackfin/mach-common/cplbinfo.c index 785ca98..a4f0b42 100644 --- a/arch/blackfin/mach-common/cplbinfo.c +++ b/arch/blackfin/mach-common/cplbinfo.c @@ -91,7 +91,7 @@ static char *cplb_print_entry(char *buf, int type) } else buf += sprintf(buf, "Data CPLB entry:\n"); - buf += sprintf(buf, "Address\t\tData\tSize\tValid\tLocked\tSwapin\n\tiCount\toCount\n"); + buf += sprintf(buf, "Address\t\tData\tSize\tValid\tLocked\tSwapin\tiCount\toCount\n"); while (*p_addr != 0xffffffff) { entry = cplb_find_entry(cplb_addr, cplb_data, *p_addr, *p_data); diff --git a/arch/blackfin/mach-common/cplbmgr.S b/arch/blackfin/mach-common/cplbmgr.S index 946703e..6f909cb 100644 --- a/arch/blackfin/mach-common/cplbmgr.S +++ b/arch/blackfin/mach-common/cplbmgr.S @@ -73,7 +73,7 @@ ENTRY(_cplb_mgr) /* ICPLB Miss Exception. We need to choose one of the * currently-installed CPLBs, and replace it with one * from the configuration table. - */ + */ P4.L = LO(ICPLB_FAULT_ADDR); P4.H = HI(ICPLB_FAULT_ADDR); @@ -222,7 +222,7 @@ ENTRY(_cplb_mgr) /* See if failed address > start address */ CC = R4 <= R0(IU); - IF !CC JUMP .Linext; + IF !CC JUMP .Linext; /* extract page size (17:16)*/ R3 = EXTRACT(R2, R1.L) (Z); @@ -271,16 +271,27 @@ ENTRY(_cplb_mgr) /* FAILED CASES*/ .Lno_page_in_table: - ( R7:4,P5:3 ) = [SP++]; R0 = CPLB_NO_ADDR_MATCH; - RTS; + JUMP .Lfail_ret; + .Lall_locked: - ( R7:4,P5:3 ) = [SP++]; R0 = CPLB_NO_UNLOCKED; - RTS; + JUMP .Lfail_ret; + .Lprot_violation: - ( R7:4,P5:3 ) = [SP++]; R0 = CPLB_PROT_VIOL; + +.Lfail_ret: + /* Make sure we turn protection/cache back on, even in the failing case */ + BITSET(R5,ENICPLB_P); + CLI R2; + SSYNC; /* SSYNC required before writing to IMEM_CONTROL. */ + .align 8; + [P4] = R5; + SSYNC; + STI R2; + + ( R7:4,P5:3 ) = [SP++]; RTS; .Ldcplb_write: diff --git a/arch/blackfin/mach-common/entry.S b/arch/blackfin/mach-common/entry.S index 1b13fa4..dc9d3ee 100644 --- a/arch/blackfin/mach-common/entry.S +++ b/arch/blackfin/mach-common/entry.S @@ -33,7 +33,7 @@ * after a timer-interrupt and after each system call. */ - +#include <linux/init.h> #include <linux/linkage.h> #include <linux/unistd.h> #include <asm/blackfin.h> @@ -71,25 +71,44 @@ ENDPROC(_safe_speculative_execution) * This one does not lower the level to IRQ5, and thus can be used to * patch up CPLB misses on the kernel stack. */ -ENTRY(_ex_dcplb) #if ANOMALY_05000261 +#define _ex_dviol _ex_workaround_261 +#define _ex_dmiss _ex_workaround_261 +#define _ex_dmult _ex_workaround_261 + +ENTRY(_ex_workaround_261) /* * Work around an anomaly: if we see a new DCPLB fault, return * without doing anything. Then, if we get the same fault again, * handle it. */ + P4 = R7; /* Store EXCAUSE */ p5.l = _last_cplb_fault_retx; p5.h = _last_cplb_fault_retx; r7 = [p5]; r6 = retx; [p5] = r6; cc = r6 == r7; - if !cc jump _return_from_exception; + if !cc jump _bfin_return_from_exception; /* fall through */ + R7 = P4; + R6 = 0x26; /* Data CPLB Miss */ + cc = R6 == R7; + if cc jump _ex_dcplb_miss (BP); + /* Handle 0x23 Data CPLB Protection Violation + * and Data CPLB Multiple Hits - Linux Trap Zero + */ + jump _ex_trap_c; +ENDPROC(_ex_workaround_261) + +#else +#define _ex_dviol _ex_trap_c +#define _ex_dmiss _ex_dcplb_miss +#define _ex_dmult _ex_trap_c #endif -ENDPROC(_ex_dcplb) -ENTRY(_ex_icplb) +ENTRY(_ex_dcplb_miss) +ENTRY(_ex_icplb_miss) (R7:6,P5:4) = [sp++]; ASTAT = [sp++]; SAVE_ALL_SYS @@ -98,7 +117,7 @@ ENTRY(_ex_icplb) RESTORE_ALL_SYS SP = EX_SCRATCH_REG; rtx; -ENDPROC(_ex_icplb) +ENDPROC(_ex_icplb_miss) ENTRY(_ex_syscall) DEBUG_START_HWTRACE(p5, r7) @@ -120,7 +139,7 @@ ENTRY(_ex_single_step) r7 = retx; r6 = reti; cc = r7 == r6; - if cc jump _return_from_exception + if cc jump _bfin_return_from_exception r7 = syscfg; bitclr (r7, 0); syscfg = R7; @@ -137,8 +156,9 @@ ENTRY(_ex_single_step) r7 = [p4]; cc = r6 == r7; if !cc jump _ex_trap_c; +ENDPROC(_ex_single_step) -ENTRY(_return_from_exception) +ENTRY(_bfin_return_from_exception) DEBUG_START_HWTRACE(p5, r7) #if ANOMALY_05000257 R7=LC0; @@ -150,7 +170,7 @@ ENTRY(_return_from_exception) ASTAT = [sp++]; sp = EX_SCRATCH_REG; rtx; -ENDPROC(_ex_soft_bp) +ENDPROC(_bfin_return_from_exception) ENTRY(_handle_bad_cplb) /* To get here, we just tried and failed to change a CPLB @@ -843,7 +863,7 @@ ENTRY(_ex_trace_buff_full) LC0 = [sp++]; P2 = [sp++]; P3 = [sp++]; - jump _return_from_exception; + jump _bfin_return_from_exception; ENDPROC(_ex_trace_buff_full) #if CONFIG_DEBUG_BFIN_HWTRACE_EXPAND_LEN == 4 @@ -861,7 +881,7 @@ ENTRY(_software_trace_buff) #endif /* CONFIG_DEBUG_BFIN_HWTRACE_EXPAND */ #if CONFIG_EARLY_PRINTK -.section .init.text +__INIT ENTRY(_early_trap) SAVE_ALL_SYS trace_buffer_stop(p0,r0); @@ -896,6 +916,7 @@ ENTRY(_early_trap) call _early_trap_c; SP += 12; ENDPROC(_early_trap) +__FINIT #endif /* CONFIG_EARLY_PRINTK */ /* @@ -908,6 +929,7 @@ ENDPROC(_early_trap) #else .data #endif + ENTRY(_ex_table) /* entry for each EXCAUSE[5:0] * This table must be in sync with the table in ./kernel/traps.c @@ -952,16 +974,16 @@ ENTRY(_ex_table) .long _ex_trap_c /* 0x20 - Reserved */ .long _ex_trap_c /* 0x21 - Undefined Instruction */ .long _ex_trap_c /* 0x22 - Illegal Instruction Combination */ - .long _ex_dcplb /* 0x23 - Data CPLB Protection Violation */ + .long _ex_dviol /* 0x23 - Data CPLB Protection Violation */ .long _ex_trap_c /* 0x24 - Data access misaligned */ .long _ex_trap_c /* 0x25 - Unrecoverable Event */ - .long _ex_dcplb /* 0x26 - Data CPLB Miss */ - .long _ex_trap_c /* 0x27 - Data CPLB Multiple Hits - Linux Trap Zero */ + .long _ex_dmiss /* 0x26 - Data CPLB Miss */ + .long _ex_dmult /* 0x27 - Data CPLB Multiple Hits - Linux Trap Zero */ .long _ex_trap_c /* 0x28 - Emulation Watchpoint */ .long _ex_trap_c /* 0x29 - Instruction fetch access error (535 only) */ .long _ex_trap_c /* 0x2A - Instruction fetch misaligned */ - .long _ex_icplb /* 0x2B - Instruction CPLB protection Violation */ - .long _ex_icplb /* 0x2C - Instruction CPLB miss */ + .long _ex_trap_c /* 0x2B - Instruction CPLB protection Violation */ + .long _ex_icplb_miss /* 0x2C - Instruction CPLB miss */ .long _ex_trap_c /* 0x2D - Instruction CPLB Multiple Hits */ .long _ex_trap_c /* 0x2E - Illegal use of Supervisor Resource */ .long _ex_trap_c /* 0x2E - Illegal use of Supervisor Resource */ diff --git a/arch/blackfin/mach-common/interrupt.S b/arch/blackfin/mach-common/interrupt.S index c6b32fe..4de3764 100644 --- a/arch/blackfin/mach-common/interrupt.S +++ b/arch/blackfin/mach-common/interrupt.S @@ -30,7 +30,6 @@ #include <asm/blackfin.h> #include <asm/mach/irq.h> -#include <linux/autoconf.h> #include <linux/linkage.h> #include <asm/entry.h> #include <asm/asm-offsets.h> diff --git a/arch/blackfin/mach-common/ints-priority-dc.c b/arch/blackfin/mach-common/ints-priority-dc.c index c2f05fa..4882f0e 100644 --- a/arch/blackfin/mach-common/ints-priority-dc.c +++ b/arch/blackfin/mach-common/ints-priority-dc.c @@ -181,7 +181,6 @@ static struct irq_chip bf561_internal_irqchip = { .unmask = bf561_internal_unmask_irq, }; -#ifdef CONFIG_IRQCHIP_DEMUX_GPIO static unsigned short gpio_enabled[gpio_bank(MAX_BLACKFIN_GPIOS)]; static unsigned short gpio_edge_triggered[gpio_bank(MAX_BLACKFIN_GPIOS)]; @@ -362,8 +361,6 @@ static void bf561_demux_gpio_irq(unsigned int inta_irq, } -#endif /* CONFIG_IRQCHIP_DEMUX_GPIO */ - void __init init_exception_vectors(void) { SSYNC(); @@ -413,26 +410,21 @@ int __init init_arch_irq(void) set_irq_chip(irq, &bf561_core_irqchip); else set_irq_chip(irq, &bf561_internal_irqchip); -#ifdef CONFIG_IRQCHIP_DEMUX_GPIO + if ((irq != IRQ_PROG0_INTA) && - (irq != IRQ_PROG1_INTA) && (irq != IRQ_PROG2_INTA)) { -#endif + (irq != IRQ_PROG1_INTA) && + (irq != IRQ_PROG2_INTA)) set_irq_handler(irq, handle_simple_irq); -#ifdef CONFIG_IRQCHIP_DEMUX_GPIO - } else { + else set_irq_chained_handler(irq, bf561_demux_gpio_irq); - } -#endif - } -#ifdef CONFIG_IRQCHIP_DEMUX_GPIO for (irq = IRQ_PF0; irq <= IRQ_PF47; irq++) { set_irq_chip(irq, &bf561_gpio_irqchip); /* if configured as edge, then will be changed to do_edge_IRQ */ set_irq_handler(irq, handle_level_irq); } -#endif + bfin_write_IMASK(0); CSYNC(); ilat = bfin_read_ILAT(); @@ -457,9 +449,8 @@ int __init init_arch_irq(void) } #ifdef CONFIG_DO_IRQ_L1 -void do_irq(int vec, struct pt_regs *fp)__attribute__((l1_text)); +__attribute__((l1_text)) #endif - void do_irq(int vec, struct pt_regs *fp) { if (vec == EVT_IVTMR_P) { diff --git a/arch/blackfin/mach-common/ints-priority-sc.c b/arch/blackfin/mach-common/ints-priority-sc.c index 2d2b635..147f073 100644 --- a/arch/blackfin/mach-common/ints-priority-sc.c +++ b/arch/blackfin/mach-common/ints-priority-sc.c @@ -308,7 +308,7 @@ static void bfin_demux_error_irq(unsigned int int_err_irq, } #endif /* BF537_GENERIC_ERROR_INT_DEMUX */ -#if defined(CONFIG_IRQCHIP_DEMUX_GPIO) && !defined(CONFIG_BF54x) +#if !defined(CONFIG_BF54x) static unsigned short gpio_enabled[gpio_bank(MAX_BLACKFIN_GPIOS)]; static unsigned short gpio_edge_triggered[gpio_bank(MAX_BLACKFIN_GPIOS)]; @@ -464,7 +464,7 @@ static void bfin_demux_gpio_irq(unsigned int intb_irq, } } -#else /* CONFIG_IRQCHIP_DEMUX_GPIO */ +#else /* CONFIG_BF54x */ #define NR_PINT_SYS_IRQS 4 #define NR_PINT_BITS 32 @@ -726,7 +726,7 @@ static void bfin_demux_gpio_irq(unsigned int intb_irq, } } -#endif /* CONFIG_IRQCHIP_DEMUX_GPIO */ +#endif void __init init_exception_vectors(void) { @@ -766,10 +766,10 @@ int __init init_arch_irq(void) bfin_write_SIC_IMASK1(SIC_UNMASK_ALL); bfin_write_SIC_IWR0(IWR_ENABLE_ALL); bfin_write_SIC_IWR1(IWR_ENABLE_ALL); -#ifdef CONFIG_BF54x +# ifdef CONFIG_BF54x bfin_write_SIC_IMASK2(SIC_UNMASK_ALL); bfin_write_SIC_IWR2(IWR_ENABLE_ALL); -#endif +# endif #else bfin_write_SIC_IMASK(SIC_UNMASK_ALL); bfin_write_SIC_IWR(IWR_ENABLE_ALL); @@ -778,13 +778,13 @@ int __init init_arch_irq(void) local_irq_disable(); -#if defined(CONFIG_IRQCHIP_DEMUX_GPIO) && defined(CONFIG_BF54x) -#ifdef CONFIG_PINTx_REASSIGN +#ifdef CONFIG_BF54x +# ifdef CONFIG_PINTx_REASSIGN pint[0]->assign = CONFIG_PINT0_ASSIGN; pint[1]->assign = CONFIG_PINT1_ASSIGN; pint[2]->assign = CONFIG_PINT2_ASSIGN; pint[3]->assign = CONFIG_PINT3_ASSIGN; -#endif +# endif /* Whenever PINTx_ASSIGN is altered init_pint_lut() must be executed! */ init_pint_lut(); #endif @@ -799,18 +799,17 @@ int __init init_arch_irq(void) #endif switch (irq) { -#ifdef CONFIG_IRQCHIP_DEMUX_GPIO #if defined(CONFIG_BF53x) case IRQ_PROG_INTA: set_irq_chained_handler(irq, bfin_demux_gpio_irq); break; -#if defined(BF537_FAMILY) && !(defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE)) +# if defined(BF537_FAMILY) && !(defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE)) case IRQ_MAC_RX: set_irq_chained_handler(irq, bfin_demux_gpio_irq); break; -#endif +# endif #elif defined(CONFIG_BF54x) case IRQ_PINT0: set_irq_chained_handler(irq, @@ -842,7 +841,6 @@ int __init init_arch_irq(void) bfin_demux_gpio_irq); break; #endif -#endif default: set_irq_handler(irq, handle_simple_irq); break; @@ -861,7 +859,6 @@ int __init init_arch_irq(void) } #endif -#ifdef CONFIG_IRQCHIP_DEMUX_GPIO #ifndef CONFIG_BF54x for (irq = IRQ_PF0; irq < NR_IRQS; irq++) { #else @@ -871,7 +868,7 @@ int __init init_arch_irq(void) /* if configured as edge, then will be changed to do_edge_IRQ */ set_irq_handler(irq, handle_level_irq); } -#endif + bfin_write_IMASK(0); CSYNC(); ilat = bfin_read_ILAT(); @@ -896,9 +893,8 @@ int __init init_arch_irq(void) } #ifdef CONFIG_DO_IRQ_L1 -void do_irq(int vec, struct pt_regs *fp) __attribute__((l1_text)); +__attribute__((l1_text)) #endif - void do_irq(int vec, struct pt_regs *fp) { if (vec == EVT_IVTMR_P) { diff --git a/arch/blackfin/mach-common/irqpanic.c b/arch/blackfin/mach-common/irqpanic.c index f05e3da..b22959b 100644 --- a/arch/blackfin/mach-common/irqpanic.c +++ b/arch/blackfin/mach-common/irqpanic.c @@ -153,27 +153,29 @@ asmlinkage void irq_panic(int reason, struct pt_regs *regs) case (SEQSTAT_HWERRCAUSE_SYSTEM_MMR): /* System MMR Error */ info.si_code = BUS_ADRALN; sig = SIGBUS; - printk(KERN_EMERG HWC_x2); + printk(KERN_EMERG HWC_x2(KERN_EMERG)); break; case (SEQSTAT_HWERRCAUSE_EXTERN_ADDR): /* External Memory Addressing Error */ info.si_code = BUS_ADRERR; sig = SIGBUS; - printk(KERN_EMERG HWC_x3); + printk(KERN_EMERG HWC_x3(KERN_EMERG)); break; case (SEQSTAT_HWERRCAUSE_PERF_FLOW): /* Performance Monitor Overflow */ - printk(KERN_EMERG HWC_x12); + printk(KERN_EMERG HWC_x12(KERN_EMERG)); break; case (SEQSTAT_HWERRCAUSE_RAISE_5): /* RAISE 5 instruction */ - printk(KERN_EMERG HWC_x18); + printk(KERN_EMERG HWC_x18(KERN_EMERG)); break; default: /* Reserved */ - printk(KERN_EMERG HWC_default); + printk(KERN_EMERG HWC_default(KERN_EMERG)); break; } } regs->ipend = bfin_read_IPEND(); - dump_bfin_regs(regs, (void *)regs->pc); + dump_bfin_process(regs); + dump_bfin_mem((void *)regs->pc); + show_regs(regs); if (0 == (info.si_signo = sig) || 0 == user_mode(regs)) /* in kernelspace */ panic("Unhandled IRQ or exceptions!\n"); else { /* in userspace */ diff --git a/arch/blackfin/mm/blackfin_sram.c b/arch/blackfin/mm/blackfin_sram.c index b99ea88..e41f0e8 100644 --- a/arch/blackfin/mm/blackfin_sram.c +++ b/arch/blackfin/mm/blackfin_sram.c @@ -27,7 +27,6 @@ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ -#include <linux/autoconf.h> #include <linux/module.h> #include <linux/kernel.h> #include <linux/types.h> diff --git a/arch/cris/Kconfig b/arch/cris/Kconfig index 21900a9..222da15 100644 --- a/arch/cris/Kconfig +++ b/arch/cris/Kconfig @@ -13,6 +13,10 @@ config ZONE_DMA bool default y +config NO_DMA + bool + default y + config RWSEM_GENERIC_SPINLOCK bool default y @@ -57,6 +61,10 @@ menu "General setup" source "fs/Kconfig.binfmt" +config GENERIC_HARDIRQS + bool + default y + config ETRAX_CMDLINE string "Kernel command line" default "root=/dev/mtdblock3" @@ -149,7 +157,8 @@ source "net/Kconfig" # bring in ETRAX built-in drivers menu "Drivers for built-in interfaces" -source arch/cris/arch-v10/drivers/Kconfig +# arch/cris/arch is a symlink to correct arch (arch-v10 or arch-v32) +source arch/cris/arch/drivers/Kconfig endmenu @@ -180,6 +189,10 @@ source "drivers/isdn/Kconfig" source "drivers/telephony/Kconfig" +source "drivers/i2c/Kconfig" + +source "drivers/rtc/Kconfig" + # # input before char - char/joystick depends on it. As does USB. # @@ -194,6 +207,10 @@ source "fs/Kconfig" source "sound/Kconfig" +source "drivers/pcmcia/Kconfig" + +source "drivers/pci/Kconfig" + source "drivers/usb/Kconfig" source "kernel/Kconfig.instrumentation" diff --git a/arch/cris/arch-v10/defconfig b/arch/cris/arch-v10/defconfig index 710c20b..572f119 100644 --- a/arch/cris/arch-v10/defconfig +++ b/arch/cris/arch-v10/defconfig @@ -99,7 +99,6 @@ CONFIG_MTD=y CONFIG_MTD_CFI=y # CONFIG_MTD_CFI_INTELEXT is not set CONFIG_MTD_CFI_AMDSTD=y -CONFIG_MTD_AMDSTD=y CONFIG_MTD_CHAR=y CONFIG_MTD_BLOCK=y CONFIG_ETRAX_I2C=y @@ -145,7 +144,6 @@ CONFIG_MTD_CFI=y # CONFIG_MTD_CFI_GEOMETRY is not set # CONFIG_MTD_CFI_INTELEXT is not set CONFIG_MTD_CFI_AMDSTD=y -CONFIG_MTD_AMDSTD=y # CONFIG_MTD_SHARP is not set # CONFIG_MTD_PHYSMAP is not set # CONFIG_MTD_NORA is not set diff --git a/arch/cris/arch-v10/drivers/Kconfig b/arch/cris/arch-v10/drivers/Kconfig index 03e2e68..e3c0f29 100644 --- a/arch/cris/arch-v10/drivers/Kconfig +++ b/arch/cris/arch-v10/drivers/Kconfig @@ -2,6 +2,7 @@ config ETRAX_ETHERNET bool "Ethernet support" depends on ETRAX_ARCH_V10 select NET_ETHERNET + select MII help This option enables the ETRAX 100LX built-in 10/100Mbit Ethernet controller. @@ -541,45 +542,6 @@ config ETRAX_RS485_DISABLE_RECEIVER loopback. Not all products are able to do this in software only. Axis 2400/2401 must disable receiver. -config ETRAX_IDE - bool "ATA/IDE support" - select IDE - select BLK_DEV_IDE - select BLK_DEV_IDEDISK - select BLK_DEV_IDECD - select BLK_DEV_IDEDMA - select IDE_GENERIC - help - Enable this to get support for ATA/IDE. - You can't use parallel ports or SCSI ports - at the same time. - - -config ETRAX_IDE_DELAY - int "Delay for drives to regain consciousness" - depends on ETRAX_IDE - default 15 - help - Number of seconds to wait for IDE drives to spin up after an IDE - reset. -choice - prompt "IDE reset pin" - depends on ETRAX_IDE - default ETRAX_IDE_PB7_RESET - -config ETRAX_IDE_PB7_RESET - bool "Port_PB_Bit_7" - help - IDE reset on pin 7 on port B - -config ETRAX_IDE_G27_RESET - bool "Port_G_Bit_27" - help - IDE reset on pin 27 on port G - -endchoice - - config ETRAX_USB_HOST bool "USB host" select USB @@ -605,8 +567,6 @@ config ETRAX_AXISFLASHMAP select MTD select MTD_CFI select MTD_CFI_AMDSTD - select MTD_OBSOLETE_CHIPS - select MTD_AMDSTD select MTD_CHAR select MTD_BLOCK select MTD_PARTITIONS diff --git a/arch/cris/arch-v10/drivers/axisflashmap.c b/arch/cris/arch-v10/drivers/axisflashmap.c index efd7b0f..ea3cf2e 100644 --- a/arch/cris/arch-v10/drivers/axisflashmap.c +++ b/arch/cris/arch-v10/drivers/axisflashmap.c @@ -312,12 +312,12 @@ static struct mtd_info *probe_cs(struct map_info *map_cs) "%s: Probing a 0x%08lx bytes large window at 0x%08lx.\n", map_cs->name, map_cs->size, map_cs->map_priv_1); -#ifdef CONFIG_MTD_AMDSTD - mtd_cs = do_map_probe("amd_flash", map_cs); -#endif #ifdef CONFIG_MTD_CFI + mtd_cs = do_map_probe("cfi_probe", map_cs); +#endif +#ifdef CONFIG_MTD_JEDECPROBE if (!mtd_cs) { - mtd_cs = do_map_probe("cfi_probe", map_cs); + mtd_cs = do_map_probe("jedec_probe", map_cs); } #endif diff --git a/arch/cris/arch-v10/drivers/gpio.c b/arch/cris/arch-v10/drivers/gpio.c index f389ed6..0d347a7 100644 --- a/arch/cris/arch-v10/drivers/gpio.c +++ b/arch/cris/arch-v10/drivers/gpio.c @@ -297,8 +297,10 @@ gpio_poll(struct file *file, data = *R_PORT_PB_DATA; else if (priv->minor == GPIO_MINOR_G) data = *R_PORT_G_DATA; - else + else { + spin_unlock(&gpio_lock); return 0; + } if ((data & priv->highalarm) || (~data & priv->lowalarm)) { @@ -381,18 +383,21 @@ static ssize_t gpio_write(struct file * file, const char * buf, size_t count, ssize_t retval = count; if (priv->minor !=GPIO_MINOR_A && priv->minor != GPIO_MINOR_B) { - return -EFAULT; + retval = -EFAULT; + goto out; } if (!access_ok(VERIFY_READ, buf, count)) { - return -EFAULT; + retval = -EFAULT; + goto out; } clk_mask = priv->clk_mask; data_mask = priv->data_mask; /* It must have been configured using the IO_CFG_WRITE_MODE */ /* Perhaps a better error code? */ if (clk_mask == 0 || data_mask == 0) { - return -EPERM; + retval = -EPERM; + goto out; } write_msb = priv->write_msb; D(printk("gpio_write: %lu to data 0x%02X clk 0x%02X msb: %i\n",count, data_mask, clk_mask, write_msb)); @@ -425,6 +430,7 @@ static ssize_t gpio_write(struct file * file, const char * buf, size_t count, } } } +out: spin_unlock(&gpio_lock); return retval; } @@ -506,6 +512,7 @@ gpio_release(struct inode *inode, struct file *filp) while (p) { if (p->highalarm | p->lowalarm) { gpio_some_alarms = 1; + spin_unlock(&gpio_lock); return 0; } p = p->next; diff --git a/arch/cris/arch-v10/kernel/entry.S b/arch/cris/arch-v10/kernel/entry.S index c5844cb..ec62c95 100644 --- a/arch/cris/arch-v10/kernel/entry.S +++ b/arch/cris/arch-v10/kernel/entry.S @@ -500,9 +500,8 @@ _work_notifysig: ;; deal with pending signals and notify-resume requests move.d $r9, $r10 ; do_notify_resume syscall/irq param - moveq 0, $r11 ; oldset param - 0 in this case - move.d $sp, $r12 ; the regs param - move.d $r1, $r13 ; the thread_info_flags parameter + move.d $sp, $r11 ; the regs param + move.d $r1, $r12 ; the thread_info_flags parameter jsr do_notify_resume ba _Rexit @@ -678,13 +677,19 @@ IRQ1_interrupt: push $r10 ; push orig_r10 clear.d [$sp=$sp-4] ; frametype == 0, normal frame + ;; If there is a glitch on the NMI pin shorter than ~100ns + ;; (i.e. non-active by the time we get here) then the nmi_pin bit + ;; in R_IRQ_MASK0_RD will already be cleared. The watchdog_nmi bit + ;; is cleared by us however (when feeding the watchdog), which is why + ;; we use that bit to determine what brought us here. + move.d [R_IRQ_MASK0_RD], $r1 ; External NMI or watchdog? - and.d 0x80000000, $r1 - beq wdog + and.d (1<<30), $r1 + bne wdog move.d $sp, $r10 jsr handle_nmi setf m ; Enable NMI again - retb ; Return from NMI + ba _Rexit ; Return the standard way nop wdog: #if defined(CONFIG_ETRAX_WATCHDOG) && !defined(CONFIG_SVINTO_SIM) @@ -775,22 +780,9 @@ multiple_interrupt: push $r10 ; push orig_r10 clear.d [$sp=$sp-4] ; frametype == 0, normal frame - moveq 2, $r2 ; first bit we care about is the timer0 irq - move.d [R_VECT_MASK_RD], $r0; read the irq bits that triggered the multiple irq - move.d $r0, [R_VECT_MASK_CLR] ; Block all active IRQs -1: - btst $r2, $r0 ; check for the irq given by bit r2 - bpl 2f - move.d $r2, $r10 ; First argument to do_IRQ - move.d $sp, $r11 ; second argument to do_IRQ - jsr do_IRQ -2: - addq 1, $r2 ; next vector bit - cmp.b 32, $r2 - bne 1b ; process all irq's up to and including number 31 - moveq 0, $r9 ; make ret_from_intr realise we came from an ir + move.d $sp, $r10 + jsr do_multiple_IRQ - move.d $r0, [R_VECT_MASK_SET] ; Unblock all the IRQs jump ret_from_intr do_sigtrap: @@ -837,6 +829,13 @@ _ugdb_handle_breakpoint: ba do_sigtrap ; SIGTRAP the offending process. pop $dccr ; Restore dccr in delay slot. + .global kernel_execve +kernel_execve: + move.d __NR_execve, $r9 + break 13 + ret + nop + .data hw_bp_trigs: @@ -1135,6 +1134,42 @@ sys_call_table: .long sys_add_key .long sys_request_key .long sys_keyctl + .long sys_ioprio_set + .long sys_ioprio_get /* 290 */ + .long sys_inotify_init + .long sys_inotify_add_watch + .long sys_inotify_rm_watch + .long sys_migrate_pages + .long sys_openat /* 295 */ + .long sys_mkdirat + .long sys_mknodat + .long sys_fchownat + .long sys_futimesat + .long sys_fstatat64 /* 300 */ + .long sys_unlinkat + .long sys_renameat + .long sys_linkat + .long sys_symlinkat + .long sys_readlinkat /* 305 */ + .long sys_fchmodat + .long sys_faccessat + .long sys_pselect6 + .long sys_ppoll + .long sys_unshare /* 310 */ + .long sys_set_robust_list + .long sys_get_robust_list + .long sys_splice + .long sys_sync_file_range + .long sys_tee /* 315 */ + .long sys_vmsplice + .long sys_move_pages + .long sys_getcpu + .long sys_epoll_pwait + .long sys_utimensat /* 320 */ + .long sys_signalfd + .long sys_timerfd + .long sys_eventfd + .long sys_fallocate /* * NOTE!! This doesn't have to be exact - we just have diff --git a/arch/cris/arch-v10/kernel/fasttimer.c b/arch/cris/arch-v10/kernel/fasttimer.c index d3ea052..c1a3a21 100644 --- a/arch/cris/arch-v10/kernel/fasttimer.c +++ b/arch/cris/arch-v10/kernel/fasttimer.c @@ -1,97 +1,9 @@ -/* $Id: fasttimer.c,v 1.9 2005/03/04 08:16:16 starvik Exp $ +/* * linux/arch/cris/kernel/fasttimer.c * * Fast timers for ETRAX100/ETRAX100LX - * This may be useful in other OS than Linux so use 2 space indentation... * - * $Log: fasttimer.c,v $ - * Revision 1.9 2005/03/04 08:16:16 starvik - * Merge of Linux 2.6.11. - * - * Revision 1.8 2005/01/05 06:09:29 starvik - * cli()/sti() will be obsolete in 2.6.11. - * - * Revision 1.7 2005/01/03 13:35:46 starvik - * Removed obsolete stuff. - * Mark fast timer IRQ as not shared. - * - * Revision 1.6 2004/05/14 10:18:39 starvik - * Export fast_timer_list - * - * Revision 1.5 2004/05/14 07:58:01 starvik - * Merge of changes from 2.4 - * - * Revision 1.4 2003/07/04 08:27:41 starvik - * Merge of Linux 2.5.74 - * - * Revision 1.3 2002/12/12 08:26:32 starvik - * Don't use C-comments inside CVS comments - * - * Revision 1.2 2002/12/11 15:42:02 starvik - * Extracted v10 (ETRAX 100LX) specific stuff from arch/cris/kernel/ - * - * Revision 1.1 2002/11/18 07:58:06 starvik - * Fast timers (from Linux 2.4) - * - * Revision 1.5 2002/10/15 06:21:39 starvik - * Added call to init_waitqueue_head - * - * Revision 1.4 2002/05/28 17:47:59 johana - * Added del_fast_timer() - * - * Revision 1.3 2002/05/28 16:16:07 johana - * Handle empty fast_timer_list - * - * Revision 1.2 2002/05/27 15:38:42 johana - * Made it compile without warnings on Linux 2.4. - * (includes, wait_queue, PROC_FS and snprintf) - * - * Revision 1.1 2002/05/27 15:32:25 johana - * arch/etrax100/kernel/fasttimer.c v1.8 from the elinux tree. - * - * Revision 1.8 2001/11/27 13:50:40 pkj - * Disable interrupts while stopping the timer and while modifying the - * list of active timers in timer1_handler() as it may be interrupted - * by other interrupts (e.g., the serial interrupt) which may add fast - * timers. - * - * Revision 1.7 2001/11/22 11:50:32 pkj - * * Only store information about the last 16 timers. - * * proc_fasttimer_read() now uses an allocated buffer, since it - * requires more space than just a page even for only writing the - * last 16 timers. The buffer is only allocated on request, so - * unless /proc/fasttimer is read, it is never allocated. - * * Renamed fast_timer_started to fast_timers_started to match - * fast_timers_added and fast_timers_expired. - * * Some clean-up. - * - * Revision 1.6 2000/12/13 14:02:08 johana - * Removed volatile for fast_timer_list - * - * Revision 1.5 2000/12/13 13:55:35 johana - * Added DEBUG_LOG, added som cli() and cleanup - * - * Revision 1.4 2000/12/05 13:48:50 johana - * Added range check when writing proc file, modified timer int handling - * - * Revision 1.3 2000/11/23 10:10:20 johana - * More debug/logging possibilities. - * Moved GET_JIFFIES_USEC() to timex.h and time.c - * - * Revision 1.2 2000/11/01 13:41:04 johana - * Clean up and bugfixes. - * Created new do_gettimeofday_fast() that gets a timeval struct - * with time based on jiffies and *R_TIMER0_DATA, uses a table - * for fast conversion of timer value to microseconds. - * (Much faster the standard do_gettimeofday() and we don't really - * want to use the true time - we want the "uptime" so timers don't screw up - * when we change the time. - * TODO: Add efficient support for continuous timers as well. - * - * Revision 1.1 2000/10/26 15:49:16 johana - * Added fasttimer, highresolution timers. - * - * Copyright (C) 2000,2001 2002 Axis Communications AB, Lund, Sweden + * Copyright (C) 2000-2007 Axis Communications AB, Lund, Sweden */ #include <linux/errno.h> @@ -125,7 +37,7 @@ #ifdef FAST_TIMER_SANITY_CHECKS #define SANITYCHECK(x) x -static int sanity_failed = 0; +static int sanity_failed; #else #define SANITYCHECK(x) #endif @@ -134,15 +46,13 @@ static int sanity_failed = 0; #define D2(x) #define DP(x) -#define __INLINE__ inline - -static int fast_timer_running = 0; -static int fast_timers_added = 0; -static int fast_timers_started = 0; -static int fast_timers_expired = 0; -static int fast_timers_deleted = 0; -static int fast_timer_is_init = 0; -static int fast_timer_ints = 0; +static unsigned int fast_timer_running; +static unsigned int fast_timers_added; +static unsigned int fast_timers_started; +static unsigned int fast_timers_expired; +static unsigned int fast_timers_deleted; +static unsigned int fast_timer_is_init; +static unsigned int fast_timer_ints; struct fast_timer *fast_timer_list = NULL; @@ -150,8 +60,8 @@ struct fast_timer *fast_timer_list = NULL; #define DEBUG_LOG_MAX 128 static const char * debug_log_string[DEBUG_LOG_MAX]; static unsigned long debug_log_value[DEBUG_LOG_MAX]; -static int debug_log_cnt = 0; -static int debug_log_cnt_wrapped = 0; +static unsigned int debug_log_cnt; +static unsigned int debug_log_cnt_wrapped; #define DEBUG_LOG(string, value) \ { \ @@ -206,45 +116,29 @@ int timer_freq_settings[NUM_TIMER_STATS]; int timer_delay_settings[NUM_TIMER_STATS]; /* Not true gettimeofday, only checks the jiffies (uptime) + useconds */ -void __INLINE__ do_gettimeofday_fast(struct timeval *tv) +inline void do_gettimeofday_fast(struct fasttime_t *tv) { - unsigned long sec = jiffies; - unsigned long usec = GET_JIFFIES_USEC(); - - usec += (sec % HZ) * (1000000 / HZ); - sec = sec / HZ; - - if (usec > 1000000) - { - usec -= 1000000; - sec++; - } - tv->tv_sec = sec; - tv->tv_usec = usec; + tv->tv_jiff = jiffies; + tv->tv_usec = GET_JIFFIES_USEC(); } -int __INLINE__ timeval_cmp(struct timeval *t0, struct timeval *t1) +inline int fasttime_cmp(struct fasttime_t *t0, struct fasttime_t *t1) { - if (t0->tv_sec < t1->tv_sec) - { - return -1; - } - else if (t0->tv_sec > t1->tv_sec) - { - return 1; - } - if (t0->tv_usec < t1->tv_usec) - { - return -1; - } - else if (t0->tv_usec > t1->tv_usec) - { - return 1; - } - return 0; + /* Compare jiffies. Takes care of wrapping */ + if (time_before(t0->tv_jiff, t1->tv_jiff)) + return -1; + else if (time_after(t0->tv_jiff, t1->tv_jiff)) + return 1; + + /* Compare us */ + if (t0->tv_usec < t1->tv_usec) + return -1; + else if (t0->tv_usec > t1->tv_usec) + return 1; + return 0; } -void __INLINE__ start_timer1(unsigned long delay_us) +inline void start_timer1(unsigned long delay_us) { int freq_index = 0; /* This is the lowest resolution */ unsigned long upper_limit = MAX_DELAY_US; @@ -285,7 +179,7 @@ void __INLINE__ start_timer1(unsigned long delay_us) timer_freq_settings[fast_timers_started % NUM_TIMER_STATS] = freq_index; timer_delay_settings[fast_timers_started % NUM_TIMER_STATS] = delay_us; - D1(printk("start_timer1 : %d us freq: %i div: %i\n", + D1(printk(KERN_DEBUG "start_timer1 : %d us freq: %i div: %i\n", delay_us, freq_index, div)); /* Clear timer1 irq */ *R_IRQ_MASK0_CLR = IO_STATE(R_IRQ_MASK0_CLR, timer1, clr); @@ -340,7 +234,7 @@ void start_one_shot_timer(struct fast_timer *t, printk(KERN_WARNING "timer name: %s data: 0x%08lX already in list!\n", name, data); sanity_failed++; - return; + goto done; } else { @@ -356,11 +250,11 @@ void start_one_shot_timer(struct fast_timer *t, t->name = name; t->tv_expires.tv_usec = t->tv_set.tv_usec + delay_us % 1000000; - t->tv_expires.tv_sec = t->tv_set.tv_sec + delay_us / 1000000; + t->tv_expires.tv_jiff = t->tv_set.tv_jiff + delay_us / 1000000 / HZ; if (t->tv_expires.tv_usec > 1000000) { t->tv_expires.tv_usec -= 1000000; - t->tv_expires.tv_sec++; + t->tv_expires.tv_jiff += HZ; } #ifdef FAST_TIMER_LOG timer_added_log[fast_timers_added % NUM_TIMER_STATS] = *t; @@ -368,7 +262,7 @@ void start_one_shot_timer(struct fast_timer *t, fast_timers_added++; /* Check if this should timeout before anything else */ - if (tmp == NULL || timeval_cmp(&t->tv_expires, &tmp->tv_expires) < 0) + if (tmp == NULL || fasttime_cmp(&t->tv_expires, &tmp->tv_expires) < 0) { /* Put first in list and modify the timer value */ t->prev = NULL; @@ -384,8 +278,8 @@ void start_one_shot_timer(struct fast_timer *t, start_timer1(delay_us); } else { /* Put in correct place in list */ - while (tmp->next && - timeval_cmp(&t->tv_expires, &tmp->next->tv_expires) > 0) + while (tmp->next && fasttime_cmp(&t->tv_expires, + &tmp->next->tv_expires) > 0) { tmp = tmp->next; } @@ -401,6 +295,7 @@ void start_one_shot_timer(struct fast_timer *t, D2(printk("start_one_shot_timer: %d us done\n", delay_us)); +done: local_irq_restore(flags); } /* start_one_shot_timer */ @@ -444,11 +339,18 @@ int del_fast_timer(struct fast_timer * t) /* Timer 1 interrupt handler */ static irqreturn_t -timer1_handler(int irq, void *dev_id, struct pt_regs *regs) +timer1_handler(int irq, void *dev_id) { struct fast_timer *t; unsigned long flags; + /* We keep interrupts disabled not only when we modify the + * fast timer list, but any time we hold a reference to a + * timer in the list, since del_fast_timer may be called + * from (another) interrupt context. Thus, the only time + * when interrupts are enabled is when calling the timer + * callback function. + */ local_irq_save(flags); /* Clear timer1 irq */ @@ -466,18 +368,19 @@ timer1_handler(int irq, void *dev_id, struct pt_regs *regs) fast_timer_running = 0; fast_timer_ints++; - local_irq_restore(flags); - t = fast_timer_list; while (t) { - struct timeval tv; + struct fasttime_t tv; + fast_timer_function_type *f; + unsigned long d; /* Has it really expired? */ do_gettimeofday_fast(&tv); - D1(printk("t: %is %06ius\n", tv.tv_sec, tv.tv_usec)); + D1(printk(KERN_DEBUG "t: %is %06ius\n", + tv.tv_jiff, tv.tv_usec)); - if (timeval_cmp(&t->tv_expires, &tv) <= 0) + if (fasttime_cmp(&t->tv_expires, &tv) <= 0) { /* Yes it has expired */ #ifdef FAST_TIMER_LOG @@ -486,7 +389,6 @@ timer1_handler(int irq, void *dev_id, struct pt_regs *regs) fast_timers_expired++; /* Remove this timer before call, since it may reuse the timer */ - local_irq_save(flags); if (t->prev) { t->prev->next = t->next; @@ -501,16 +403,23 @@ timer1_handler(int irq, void *dev_id, struct pt_regs *regs) } t->prev = NULL; t->next = NULL; - local_irq_restore(flags); - if (t->function != NULL) - { - t->function(t->data); - } - else - { + /* Save function callback data before enabling + * interrupts, since the timer may be removed and + * we don't know how it was allocated + * (e.g. ->function and ->data may become overwritten + * after deletion if the timer was stack-allocated). + */ + f = t->function; + d = t->data; + + if (f != NULL) { + /* Run callback with interrupts enabled. */ + local_irq_restore(flags); + f(d); + local_irq_save(flags); + } else DEBUG_LOG("!timer1 %i function==NULL!\n", fast_timer_ints); - } } else { @@ -518,16 +427,20 @@ timer1_handler(int irq, void *dev_id, struct pt_regs *regs) D1(printk(".\n")); } - local_irq_save(flags); if ((t = fast_timer_list) != NULL) { /* Start next timer.. */ - long us; - struct timeval tv; + long us = 0; + struct fasttime_t tv; do_gettimeofday_fast(&tv); - us = ((t->tv_expires.tv_sec - tv.tv_sec) * 1000000 + - t->tv_expires.tv_usec - tv.tv_usec); + + /* time_after_eq takes care of wrapping */ + if (time_after_eq(t->tv_expires.tv_jiff, tv.tv_jiff)) + us = ((t->tv_expires.tv_jiff - tv.tv_jiff) * + 1000000 / HZ + t->tv_expires.tv_usec - + tv.tv_usec); + if (us > 0) { if (!fast_timer_running) @@ -537,7 +450,6 @@ timer1_handler(int irq, void *dev_id, struct pt_regs *regs) #endif start_timer1(us); } - local_irq_restore(flags); break; } else @@ -548,9 +460,10 @@ timer1_handler(int irq, void *dev_id, struct pt_regs *regs) D1(printk("e! %d\n", us)); } } - local_irq_restore(flags); } + local_irq_restore(flags); + if (!t) { D1(printk("t1 stop!\n")); @@ -575,28 +488,17 @@ static void wake_up_func(unsigned long data) void schedule_usleep(unsigned long us) { struct fast_timer t; -#ifdef DECLARE_WAITQUEUE wait_queue_head_t sleep_wait; init_waitqueue_head(&sleep_wait); - { - DECLARE_WAITQUEUE(wait, current); -#else - struct wait_queue *sleep_wait = NULL; - struct wait_queue wait = { current, NULL }; -#endif D1(printk("schedule_usleep(%d)\n", us)); - add_wait_queue(&sleep_wait, &wait); - set_current_state(TASK_INTERRUPTIBLE); start_one_shot_timer(&t, wake_up_func, (unsigned long)&sleep_wait, us, "usleep"); - schedule(); - set_current_state(TASK_RUNNING); - remove_wait_queue(&sleep_wait, &wait); + /* Uninterruptible sleep on the fast timer. (The condition is somewhat + * redundant since the timer is what wakes us up.) */ + wait_event(sleep_wait, !fast_timer_pending(&t)); + D1(printk("done schedule_usleep(%d)\n", us)); -#ifdef DECLARE_WAITQUEUE - } -#endif } #ifdef CONFIG_PROC_FS @@ -616,7 +518,7 @@ static int proc_fasttimer_read(char *buf, char **start, off_t offset, int len unsigned long flags; int i = 0; int num_to_show; - struct timeval tv; + struct fasttime_t tv; struct fast_timer *t, *nextt; static char *bigbuf = NULL; static unsigned long used; @@ -624,7 +526,8 @@ static int proc_fasttimer_read(char *buf, char **start, off_t offset, int len if (!bigbuf && !(bigbuf = vmalloc(BIG_BUF_SIZE))) { used = 0; - bigbuf[0] = '\0'; + if (buf) + buf[0] = '\0'; return 0; } @@ -646,7 +549,7 @@ static int proc_fasttimer_read(char *buf, char **start, off_t offset, int len used += sprintf(bigbuf + used, "Fast timer running: %s\n", fast_timer_running ? "yes" : "no"); used += sprintf(bigbuf + used, "Current time: %lu.%06lu\n", - (unsigned long)tv.tv_sec, + (unsigned long)tv.tv_jiff, (unsigned long)tv.tv_usec); #ifdef FAST_TIMER_SANITY_CHECKS used += sprintf(bigbuf + used, "Sanity failed: %i\n", @@ -696,9 +599,9 @@ static int proc_fasttimer_read(char *buf, char **start, off_t offset, int len "d: %6li us data: 0x%08lX" "\n", t->name, - (unsigned long)t->tv_set.tv_sec, + (unsigned long)t->tv_set.tv_jiff, (unsigned long)t->tv_set.tv_usec, - (unsigned long)t->tv_expires.tv_sec, + (unsigned long)t->tv_expires.tv_jiff, (unsigned long)t->tv_expires.tv_usec, t->delay_us, t->data @@ -718,9 +621,9 @@ static int proc_fasttimer_read(char *buf, char **start, off_t offset, int len "d: %6li us data: 0x%08lX" "\n", t->name, - (unsigned long)t->tv_set.tv_sec, + (unsigned long)t->tv_set.tv_jiff, (unsigned long)t->tv_set.tv_usec, - (unsigned long)t->tv_expires.tv_sec, + (unsigned long)t->tv_expires.tv_jiff, (unsigned long)t->tv_expires.tv_usec, t->delay_us, t->data @@ -738,9 +641,9 @@ static int proc_fasttimer_read(char *buf, char **start, off_t offset, int len "d: %6li us data: 0x%08lX" "\n", t->name, - (unsigned long)t->tv_set.tv_sec, + (unsigned long)t->tv_set.tv_jiff, (unsigned long)t->tv_set.tv_usec, - (unsigned long)t->tv_expires.tv_sec, + (unsigned long)t->tv_expires.tv_jiff, (unsigned long)t->tv_expires.tv_usec, t->delay_us, t->data @@ -761,15 +664,15 @@ static int proc_fasttimer_read(char *buf, char **start, off_t offset, int len /* " func: 0x%08lX" */ "\n", t->name, - (unsigned long)t->tv_set.tv_sec, + (unsigned long)t->tv_set.tv_jiff, (unsigned long)t->tv_set.tv_usec, - (unsigned long)t->tv_expires.tv_sec, + (unsigned long)t->tv_expires.tv_jiff, (unsigned long)t->tv_expires.tv_usec, t->delay_us, t->data /* , t->function */ ); - local_irq_disable(); + local_irq_save(flags); if (t->next != nextt) { printk(KERN_WARNING "timer removed!\n"); @@ -798,7 +701,7 @@ static volatile int num_test_timeout = 0; static struct fast_timer tr[10]; static int exp_num[10]; -static struct timeval tv_exp[100]; +static struct fasttime_t tv_exp[100]; static void test_timeout(unsigned long data) { @@ -836,7 +739,7 @@ static void fast_timer_test(void) int prev_num; int j; - struct timeval tv, tv0, tv1, tv2; + struct fasttime_t tv, tv0, tv1, tv2; printk("fast_timer_test() start\n"); do_gettimeofday_fast(&tv); @@ -849,7 +752,8 @@ static void fast_timer_test(void) { do_gettimeofday_fast(&tv_exp[j]); } - printk("fast_timer_test() %is %06i\n", tv.tv_sec, tv.tv_usec); + printk(KERN_DEBUG "fast_timer_test() %is %06i\n", + tv.tv_jiff, tv.tv_usec); for (j = 0; j < 1000; j++) { @@ -858,12 +762,12 @@ static void fast_timer_test(void) } for (j = 0; j < 100; j++) { - printk("%i.%i %i.%i %i.%i %i.%i %i.%i\n", - tv_exp[j].tv_sec,tv_exp[j].tv_usec, - tv_exp[j+1].tv_sec,tv_exp[j+1].tv_usec, - tv_exp[j+2].tv_sec,tv_exp[j+2].tv_usec, - tv_exp[j+3].tv_sec,tv_exp[j+3].tv_usec, - tv_exp[j+4].tv_sec,tv_exp[j+4].tv_usec); + printk(KERN_DEBUG "%i.%i %i.%i %i.%i %i.%i %i.%i\n", + tv_exp[j].tv_jiff, tv_exp[j].tv_usec, + tv_exp[j+1].tv_jiff, tv_exp[j+1].tv_usec, + tv_exp[j+2].tv_jiff, tv_exp[j+2].tv_usec, + tv_exp[j+3].tv_jiff, tv_exp[j+3].tv_usec, + tv_exp[j+4].tv_jiff, tv_exp[j+4].tv_usec); j += 4; } do_gettimeofday_fast(&tv0); @@ -895,9 +799,12 @@ static void fast_timer_test(void) } } do_gettimeofday_fast(&tv2); - printk("Timers started %is %06i\n", tv0.tv_sec, tv0.tv_usec); - printk("Timers started at %is %06i\n", tv1.tv_sec, tv1.tv_usec); - printk("Timers done %is %06i\n", tv2.tv_sec, tv2.tv_usec); + printk(KERN_DEBUG "Timers started %is %06i\n", + tv0.tv_jiff, tv0.tv_usec); + printk(KERN_DEBUG "Timers started at %is %06i\n", + tv1.tv_jiff, tv1.tv_usec); + printk(KERN_DEBUG "Timers done %is %06i\n", + tv2.tv_jiff, tv2.tv_usec); DP(printk("buf0:\n"); printk(buf0); printk("buf1:\n"); @@ -919,9 +826,9 @@ static void fast_timer_test(void) printk("%-10s set: %6is %06ius exp: %6is %06ius " "data: 0x%08X func: 0x%08X\n", t->name, - t->tv_set.tv_sec, + t->tv_set.tv_jiff, t->tv_set.tv_usec, - t->tv_expires.tv_sec, + t->tv_expires.tv_jiff, t->tv_expires.tv_usec, t->data, t->function @@ -929,10 +836,12 @@ static void fast_timer_test(void) printk(" del: %6ius did exp: %6is %06ius as #%i error: %6li\n", t->delay_us, - tv_exp[j].tv_sec, + tv_exp[j].tv_jiff, tv_exp[j].tv_usec, exp_num[j], - (tv_exp[j].tv_sec - t->tv_expires.tv_sec)*1000000 + tv_exp[j].tv_usec - t->tv_expires.tv_usec); + (tv_exp[j].tv_jiff - t->tv_expires.tv_jiff) * + 1000000 + tv_exp[j].tv_usec - + t->tv_expires.tv_usec); } proc_fasttimer_read(buf5, NULL, 0, 0, 0); printk("buf5 after all done:\n"); @@ -942,7 +851,7 @@ static void fast_timer_test(void) #endif -void fast_timer_init(void) +int fast_timer_init(void) { /* For some reason, request_irq() hangs when called froom time_init() */ if (!fast_timer_is_init) @@ -975,4 +884,6 @@ void fast_timer_init(void) fast_timer_test(); #endif } + return 0; } +__initcall(fast_timer_init); diff --git a/arch/cris/arch-v10/kernel/io_interface_mux.c b/arch/cris/arch-v10/kernel/io_interface_mux.c index 29d48ad..3a9114e 100644 --- a/arch/cris/arch-v10/kernel/io_interface_mux.c +++ b/arch/cris/arch-v10/kernel/io_interface_mux.c @@ -304,7 +304,7 @@ static unsigned char clear_group_from_set(const unsigned char groups, struct if_ static struct if_group *get_group(const unsigned char groups) { int i; - for (i = 0; i < sizeof(if_groups)/sizeof(struct if_group); i++) { + for (i = 0; i < ARRAY_SIZE(if_groups); i++) { if (groups & if_groups[i].group) { return &if_groups[i]; } diff --git a/arch/cris/arch-v10/kernel/irq.c b/arch/cris/arch-v10/kernel/irq.c index 845c95f..e06ab00 100644 --- a/arch/cris/arch-v10/kernel/irq.c +++ b/arch/cris/arch-v10/kernel/irq.c @@ -12,10 +12,16 @@ */ #include <asm/irq.h> +#include <asm/current.h> #include <linux/irq.h> +#include <linux/interrupt.h> #include <linux/kernel.h> #include <linux/init.h> +/* From kgdb.c. */ +extern void kgdb_init(void); +extern void breakpoint(void); + #define mask_irq(irq_nr) (*R_VECT_MASK_CLR = 1 << (irq_nr)); #define unmask_irq(irq_nr) (*R_VECT_MASK_SET = 1 << (irq_nr)); @@ -75,8 +81,8 @@ BUILD_IRQ(12, 0x1000) BUILD_IRQ(13, 0x2000) void mmu_bus_fault(void); /* IRQ 14 is the bus fault interrupt */ void multiple_interrupt(void); /* IRQ 15 is the multiple IRQ interrupt */ -BUILD_IRQ(16, 0x10000) -BUILD_IRQ(17, 0x20000) +BUILD_IRQ(16, 0x10000 | 0x20000) /* ethernet tx interrupt needs to block rx */ +BUILD_IRQ(17, 0x20000 | 0x10000) /* ...and vice versa */ BUILD_IRQ(18, 0x40000) BUILD_IRQ(19, 0x80000) BUILD_IRQ(20, 0x100000) @@ -147,6 +153,55 @@ void system_call(void); /* from entry.S */ void do_sigtrap(void); /* from entry.S */ void gdb_handle_breakpoint(void); /* from entry.S */ +extern void do_IRQ(int irq, struct pt_regs * regs); + +/* Handle multiple IRQs */ +void do_multiple_IRQ(struct pt_regs* regs) +{ + int bit; + unsigned masked; + unsigned mask; + unsigned ethmask = 0; + + /* Get interrupts to mask and handle */ + mask = masked = *R_VECT_MASK_RD; + + /* Never mask timer IRQ */ + mask &= ~(IO_MASK(R_VECT_MASK_RD, timer0)); + + /* + * If either ethernet interrupt (rx or tx) is active then block + * the other one too. Unblock afterwards also. + */ + if (mask & + (IO_STATE(R_VECT_MASK_RD, dma0, active) | + IO_STATE(R_VECT_MASK_RD, dma1, active))) { + ethmask = (IO_MASK(R_VECT_MASK_RD, dma0) | + IO_MASK(R_VECT_MASK_RD, dma1)); + } + + /* Block them */ + *R_VECT_MASK_CLR = (mask | ethmask); + + /* An extra irq_enter here to prevent softIRQs to run after + * each do_IRQ. This will decrease the interrupt latency. + */ + irq_enter(); + + /* Handle all IRQs */ + for (bit = 2; bit < 32; bit++) { + if (masked & (1 << bit)) { + do_IRQ(bit, regs); + } + } + + /* This irq_exit() will trigger the soft IRQs. */ + irq_exit(); + + /* Unblock the IRQs again */ + *R_VECT_MASK_SET = (masked | ethmask); +} + /* init_IRQ() is called by start_kernel and is responsible for fixing IRQ masks and setting the irq vector table. */ diff --git a/arch/cris/arch-v10/kernel/setup.c b/arch/cris/arch-v10/kernel/setup.c index 682ef95..de27b50 100644 --- a/arch/cris/arch-v10/kernel/setup.c +++ b/arch/cris/arch-v10/kernel/setup.c @@ -13,6 +13,7 @@ #include <linux/seq_file.h> #include <linux/proc_fs.h> #include <linux/delay.h> +#include <linux/param.h> #ifdef CONFIG_PROC_FS #define HAS_FPU 0x0001 @@ -56,8 +57,8 @@ int show_cpuinfo(struct seq_file *m, void *v) revision = rdvr(); - if (revision >= sizeof cpu_info/sizeof *cpu_info) - info = &cpu_info[sizeof cpu_info/sizeof *cpu_info - 1]; + if (revision >= ARRAY_SIZE(cpu_info)) + info = &cpu_info[ARRAY_SIZE(cpu_info) - 1]; else info = &cpu_info[revision]; diff --git a/arch/cris/arch-v10/kernel/time.c b/arch/cris/arch-v10/kernel/time.c index 575a14b..5976f61 100644 --- a/arch/cris/arch-v10/kernel/time.c +++ b/arch/cris/arch-v10/kernel/time.c @@ -1,5 +1,4 @@ -/* $Id: time.c,v 1.5 2004/09/29 06:12:46 starvik Exp $ - * +/* * linux/arch/cris/arch-v10/kernel/time.c * * Copyright (C) 1991, 1992, 1995 Linus Torvalds @@ -20,6 +19,7 @@ #include <asm/io.h> #include <asm/delay.h> #include <asm/rtc.h> +#include <asm/irq_regs.h> /* define this if you need to use print_timestamp */ /* it will make jiffies at 96 hz instead of 100 hz though */ @@ -201,8 +201,9 @@ static long last_rtc_update = 0; extern void cris_do_profile(struct pt_regs *regs); static inline irqreturn_t -timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) +timer_interrupt(int irq, void *dev_id) { + struct pt_regs *regs = get_irq_regs(); /* acknowledge the timer irq */ #ifdef USE_CASCADE_TIMERS @@ -221,9 +222,11 @@ timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) #endif /* reset watchdog otherwise it resets us! */ - reset_watchdog(); + /* Update statistics. */ + update_process_times(user_mode(regs)); + /* call the real timer interrupt handler */ do_timer(1); diff --git a/arch/cris/arch-v10/lib/memset.c b/arch/cris/arch-v10/lib/memset.c index 82bb668..42c1101 100644 --- a/arch/cris/arch-v10/lib/memset.c +++ b/arch/cris/arch-v10/lib/memset.c @@ -66,7 +66,7 @@ void *memset(void *pdst, { register char *dst __asm__ ("r13") = pdst; - + /* This is NONPORTABLE, but since this whole routine is */ /* grossly nonportable that doesn't matter. */ @@ -110,52 +110,52 @@ void *memset(void *pdst, If you want to check that the allocation was right; then check the equalities in the first comment. It should say "r13=r13, r12=r12, r11=r11" */ - __asm__ volatile (" - ;; Check that the following is true (same register names on - ;; both sides of equal sign, as in r8=r8): - ;; %0=r13, %1=r12, %4=r11 - ;; - ;; Save the registers we'll clobber in the movem process - ;; on the stack. Don't mention them to gcc, it will only be - ;; upset. - subq 11*4,$sp - movem $r10,[$sp] - - move.d $r11,$r0 - move.d $r11,$r1 - move.d $r11,$r2 - move.d $r11,$r3 - move.d $r11,$r4 - move.d $r11,$r5 - move.d $r11,$r6 - move.d $r11,$r7 - move.d $r11,$r8 - move.d $r11,$r9 - move.d $r11,$r10 - - ;; Now we've got this: - ;; r13 - dst - ;; r12 - n - - ;; Update n for the first loop - subq 12*4,$r12 -0: - subq 12*4,$r12 - bge 0b - movem $r11,[$r13+] - - addq 12*4,$r12 ;; compensate for last loop underflowing n - - ;; Restore registers from stack - movem [$sp+],$r10" + __asm__ volatile ("\n\ + ;; Check that the following is true (same register names on \n\ + ;; both sides of equal sign, as in r8=r8): \n\ + ;; %0=r13, %1=r12, %4=r11 \n\ + ;; \n\ + ;; Save the registers we'll clobber in the movem process \n\ + ;; on the stack. Don't mention them to gcc, it will only be \n\ + ;; upset. \n\ + subq 11*4,$sp \n\ + movem $r10,[$sp] \n\ + \n\ + move.d $r11,$r0 \n\ + move.d $r11,$r1 \n\ + move.d $r11,$r2 \n\ + move.d $r11,$r3 \n\ + move.d $r11,$r4 \n\ + move.d $r11,$r5 \n\ + move.d $r11,$r6 \n\ + move.d $r11,$r7 \n\ + move.d $r11,$r8 \n\ + move.d $r11,$r9 \n\ + move.d $r11,$r10 \n\ + \n\ + ;; Now we've got this: \n\ + ;; r13 - dst \n\ + ;; r12 - n \n\ + \n\ + ;; Update n for the first loop \n\ + subq 12*4,$r12 \n\ +0: \n\ + subq 12*4,$r12 \n\ + bge 0b \n\ + movem $r11,[$r13+] \n\ + \n\ + addq 12*4,$r12 ;; compensate for last loop underflowing n \n\ + \n\ + ;; Restore registers from stack \n\ + movem [$sp+],$r10" /* Outputs */ : "=r" (dst), "=r" (n) /* Inputs */ : "0" (dst), "1" (n), "r" (lc)); - + } /* Either we directly starts copying, using dword copying - in a loop, or we copy as much as possible with 'movem' + in a loop, or we copy as much as possible with 'movem' and then the last block (<44 bytes) is copied here. This will work since 'movem' will have updated src,dst,n. */ diff --git a/arch/cris/arch-v10/lib/string.c b/arch/cris/arch-v10/lib/string.c index 15d6662..7161a2b 100644 --- a/arch/cris/arch-v10/lib/string.c +++ b/arch/cris/arch-v10/lib/string.c @@ -95,33 +95,33 @@ void *memcpy(void *pdst, If you want to check that the allocation was right; then check the equalities in the first comment. It should say "r13=r13, r11=r11, r12=r12" */ - __asm__ volatile (" - ;; Check that the following is true (same register names on - ;; both sides of equal sign, as in r8=r8): - ;; %0=r13, %1=r11, %2=r12 - ;; - ;; Save the registers we'll use in the movem process - ;; on the stack. - subq 11*4,$sp - movem $r10,[$sp] - - ;; Now we've got this: - ;; r11 - src - ;; r13 - dst - ;; r12 - n - - ;; Update n for the first loop - subq 44,$r12 -0: - movem [$r11+],$r10 - subq 44,$r12 - bge 0b - movem $r10,[$r13+] - - addq 44,$r12 ;; compensate for last loop underflowing n - - ;; Restore registers from stack - movem [$sp+],$r10" + __asm__ volatile ("\n\ + ;; Check that the following is true (same register names on \n\ + ;; both sides of equal sign, as in r8=r8): \n\ + ;; %0=r13, %1=r11, %2=r12 \n\ + ;; \n\ + ;; Save the registers we'll use in the movem process \n\ + ;; on the stack. \n\ + subq 11*4,$sp \n\ + movem $r10,[$sp] \n\ + \n\ + ;; Now we've got this: \n\ + ;; r11 - src \n\ + ;; r13 - dst \n\ + ;; r12 - n \n\ + \n\ + ;; Update n for the first loop \n\ + subq 44,$r12 \n\ +0: \n\ + movem [$r11+],$r10 \n\ + subq 44,$r12 \n\ + bge 0b \n\ + movem $r10,[$r13+] \n\ + \n\ + addq 44,$r12 ;; compensate for last loop underflowing n \n\ + \n\ + ;; Restore registers from stack \n\ + movem [$sp+],$r10" /* Outputs */ : "=r" (dst), "=r" (src), "=r" (n) /* Inputs */ : "0" (dst), "1" (src), "2" (n)); diff --git a/arch/cris/arch-v10/lib/usercopy.c b/arch/cris/arch-v10/lib/usercopy.c index a12c708..b8e6c04 100644 --- a/arch/cris/arch-v10/lib/usercopy.c +++ b/arch/cris/arch-v10/lib/usercopy.c @@ -92,58 +92,58 @@ __copy_user (void __user *pdst, const void *psrc, unsigned long pn) .ifnc %0%1%2%3,$r13$r11$r12$r10 \n\ .err \n\ .endif \n\ - - ;; Save the registers we'll use in the movem process - ;; on the stack. - subq 11*4,$sp - movem $r10,[$sp] - - ;; Now we've got this: - ;; r11 - src - ;; r13 - dst - ;; r12 - n - - ;; Update n for the first loop - subq 44,$r12 - -; Since the noted PC of a faulting instruction in a delay-slot of a taken -; branch, is that of the branch target, we actually point at the from-movem -; for this case. There is no ambiguity here; if there was a fault in that -; instruction (meaning a kernel oops), the faulted PC would be the address -; after *that* movem. - -0: - movem [$r11+],$r10 - subq 44,$r12 - bge 0b - movem $r10,[$r13+] -1: - addq 44,$r12 ;; compensate for last loop underflowing n - - ;; Restore registers from stack - movem [$sp+],$r10 -2: - .section .fixup,\"ax\" - -; To provide a correct count in r10 of bytes that failed to be copied, -; we jump back into the loop if the loop-branch was taken. There is no -; performance penalty for sany use; the program will segfault soon enough. - -3: - move.d [$sp],$r10 - addq 44,$r10 - move.d $r10,[$sp] - jump 0b -4: - movem [$sp+],$r10 - addq 44,$r10 - addq 44,$r12 - jump 2b - - .previous - .section __ex_table,\"a\" - .dword 0b,3b - .dword 1b,4b + \n\ + ;; Save the registers we'll use in the movem process \n\ + ;; on the stack. \n\ + subq 11*4,$sp \n\ + movem $r10,[$sp] \n\ + \n\ + ;; Now we've got this: \n\ + ;; r11 - src \n\ + ;; r13 - dst \n\ + ;; r12 - n \n\ + \n\ + ;; Update n for the first loop \n\ + subq 44,$r12 \n\ + \n\ +; Since the noted PC of a faulting instruction in a delay-slot of a taken \n\ +; branch, is that of the branch target, we actually point at the from-movem \n\ +; for this case. There is no ambiguity here; if there was a fault in that \n\ +; instruction (meaning a kernel oops), the faulted PC would be the address \n\ +; after *that* movem. \n\ + \n\ +0: \n\ + movem [$r11+],$r10 \n\ + subq 44,$r12 \n\ + bge 0b \n\ + movem $r10,[$r13+] \n\ +1: \n\ + addq 44,$r12 ;; compensate for last loop underflowing n \n\ + \n\ + ;; Restore registers from stack \n\ + movem [$sp+],$r10 \n\ +2: \n\ + .section .fixup,\"ax\" \n\ + \n\ +; To provide a correct count in r10 of bytes that failed to be copied, \n\ +; we jump back into the loop if the loop-branch was taken. There is no \n\ +; performance penalty for sany use; the program will segfault soon enough.\n\ + \n\ +3: \n\ + move.d [$sp],$r10 \n\ + addq 44,$r10 \n\ + move.d $r10,[$sp] \n\ + jump 0b \n\ +4: \n\ + movem [$sp+],$r10 \n\ + addq 44,$r10 \n\ + addq 44,$r12 \n\ + jump 2b \n\ + \n\ + .previous \n\ + .section __ex_table,\"a\" \n\ + .dword 0b,3b \n\ + .dword 1b,4b \n\ .previous" /* Outputs */ : "=r" (dst), "=r" (src), "=r" (n), "=r" (retn) @@ -253,59 +253,59 @@ __copy_user_zeroing (void __user *pdst, const void *psrc, unsigned long pn) If you want to check that the allocation was right; then check the equalities in the first comment. It should say "r13=r13, r11=r11, r12=r12" */ - __asm__ volatile (" + __asm__ volatile ("\n\ .ifnc %0%1%2%3,$r13$r11$r12$r10 \n\ .err \n\ .endif \n\ - - ;; Save the registers we'll use in the movem process - ;; on the stack. - subq 11*4,$sp - movem $r10,[$sp] - - ;; Now we've got this: - ;; r11 - src - ;; r13 - dst - ;; r12 - n - - ;; Update n for the first loop - subq 44,$r12 -0: - movem [$r11+],$r10 -1: - subq 44,$r12 - bge 0b - movem $r10,[$r13+] - - addq 44,$r12 ;; compensate for last loop underflowing n - - ;; Restore registers from stack - movem [$sp+],$r10 -4: - .section .fixup,\"ax\" - -;; Do not jump back into the loop if we fail. For some uses, we get a -;; page fault somewhere on the line. Without checking for page limits, -;; we don't know where, but we need to copy accurately and keep an -;; accurate count; not just clear the whole line. To do that, we fall -;; down in the code below, proceeding with smaller amounts. It should -;; be kept in mind that we have to cater to code like what at one time -;; was in fs/super.c: -;; i = size - copy_from_user((void *)page, data, size); -;; which would cause repeated faults while clearing the remainder of -;; the SIZE bytes at PAGE after the first fault. -;; A caveat here is that we must not fall through from a failing page -;; to a valid page. - -3: - movem [$sp+],$r10 - addq 44,$r12 ;; Get back count before faulting point. - subq 44,$r11 ;; Get back pointer to faulting movem-line. - jump 4b ;; Fall through, pretending the fault didn't happen. - - .previous - .section __ex_table,\"a\" - .dword 1b,3b + \n\ + ;; Save the registers we'll use in the movem process \n\ + ;; on the stack. \n\ + subq 11*4,$sp \n\ + movem $r10,[$sp] \n\ + \n\ + ;; Now we've got this: \n\ + ;; r11 - src \n\ + ;; r13 - dst \n\ + ;; r12 - n \n\ + \n\ + ;; Update n for the first loop \n\ + subq 44,$r12 \n\ +0: \n\ + movem [$r11+],$r10 \n\ +1: \n\ + subq 44,$r12 \n\ + bge 0b \n\ + movem $r10,[$r13+] \n\ + \n\ + addq 44,$r12 ;; compensate for last loop underflowing n \n\ + \n\ + ;; Restore registers from stack \n\ + movem [$sp+],$r10 \n\ +4: \n\ + .section .fixup,\"ax\" \n\ + \n\ +;; Do not jump back into the loop if we fail. For some uses, we get a \n\ +;; page fault somewhere on the line. Without checking for page limits, \n\ +;; we don't know where, but we need to copy accurately and keep an \n\ +;; accurate count; not just clear the whole line. To do that, we fall \n\ +;; down in the code below, proceeding with smaller amounts. It should \n\ +;; be kept in mind that we have to cater to code like what at one time \n\ +;; was in fs/super.c: \n\ +;; i = size - copy_from_user((void *)page, data, size); \n\ +;; which would cause repeated faults while clearing the remainder of \n\ +;; the SIZE bytes at PAGE after the first fault. \n\ +;; A caveat here is that we must not fall through from a failing page \n\ +;; to a valid page. \n\ + \n\ +3: \n\ + movem [$sp+],$r10 \n\ + addq 44,$r12 ;; Get back count before faulting point. \n\ + subq 44,$r11 ;; Get back pointer to faulting movem-line. \n\ + jump 4b ;; Fall through, pretending the fault didn't happen.\n\ + \n\ + .previous \n\ + .section __ex_table,\"a\" \n\ + .dword 1b,3b \n\ .previous" /* Outputs */ : "=r" (dst), "=r" (src), "=r" (n), "=r" (retn) @@ -425,64 +425,64 @@ __do_clear_user (void __user *pto, unsigned long pn) If you want to check that the allocation was right; then check the equalities in the first comment. It should say something like "r13=r13, r11=r11, r12=r12". */ - __asm__ volatile (" + __asm__ volatile ("\n\ .ifnc %0%1%2,$r13$r12$r10 \n\ .err \n\ .endif \n\ - - ;; Save the registers we'll clobber in the movem process - ;; on the stack. Don't mention them to gcc, it will only be - ;; upset. - subq 11*4,$sp - movem $r10,[$sp] - - clear.d $r0 - clear.d $r1 - clear.d $r2 - clear.d $r3 - clear.d $r4 - clear.d $r5 - clear.d $r6 - clear.d $r7 - clear.d $r8 - clear.d $r9 - clear.d $r10 - clear.d $r11 - - ;; Now we've got this: - ;; r13 - dst - ;; r12 - n - - ;; Update n for the first loop - subq 12*4,$r12 -0: - subq 12*4,$r12 - bge 0b - movem $r11,[$r13+] -1: - addq 12*4,$r12 ;; compensate for last loop underflowing n - - ;; Restore registers from stack - movem [$sp+],$r10 -2: - .section .fixup,\"ax\" -3: - move.d [$sp],$r10 - addq 12*4,$r10 - move.d $r10,[$sp] - clear.d $r10 - jump 0b - -4: - movem [$sp+],$r10 - addq 12*4,$r10 - addq 12*4,$r12 - jump 2b - - .previous - .section __ex_table,\"a\" - .dword 0b,3b - .dword 1b,4b + \n\ + ;; Save the registers we'll clobber in the movem process \n\ + ;; on the stack. Don't mention them to gcc, it will only be \n\ + ;; upset. \n\ + subq 11*4,$sp \n\ + movem $r10,[$sp] \n\ + \n\ + clear.d $r0 \n\ + clear.d $r1 \n\ + clear.d $r2 \n\ + clear.d $r3 \n\ + clear.d $r4 \n\ + clear.d $r5 \n\ + clear.d $r6 \n\ + clear.d $r7 \n\ + clear.d $r8 \n\ + clear.d $r9 \n\ + clear.d $r10 \n\ + clear.d $r11 \n\ + \n\ + ;; Now we've got this: \n\ + ;; r13 - dst \n\ + ;; r12 - n \n\ + \n\ + ;; Update n for the first loop \n\ + subq 12*4,$r12 \n\ +0: \n\ + subq 12*4,$r12 \n\ + bge 0b \n\ + movem $r11,[$r13+] \n\ +1: \n\ + addq 12*4,$r12 ;; compensate for last loop underflowing n\n\ + \n\ + ;; Restore registers from stack \n\ + movem [$sp+],$r10 \n\ +2: \n\ + .section .fixup,\"ax\" \n\ +3: \n\ + move.d [$sp],$r10 \n\ + addq 12*4,$r10 \n\ + move.d $r10,[$sp] \n\ + clear.d $r10 \n\ + jump 0b \n\ + \n\ +4: \n\ + movem [$sp+],$r10 \n\ + addq 12*4,$r10 \n\ + addq 12*4,$r12 \n\ + jump 2b \n\ + \n\ + .previous \n\ + .section __ex_table,\"a\" \n\ + .dword 0b,3b \n\ + .dword 1b,4b \n\ .previous" /* Outputs */ : "=r" (dst), "=r" (n), "=r" (retn) diff --git a/arch/cris/arch-v32/drivers/Kconfig b/arch/cris/arch-v32/drivers/Kconfig index cc6ba54..9bccb5e 100644 --- a/arch/cris/arch-v32/drivers/Kconfig +++ b/arch/cris/arch-v32/drivers/Kconfig @@ -362,8 +362,6 @@ config ETRAX_AXISFLASHMAP select MTD select MTD_CFI select MTD_CFI_AMDSTD - select MTD_OBSOLETE_CHIPS - select MTD_AMDSTD select MTD_CHAR select MTD_BLOCK select MTD_PARTITIONS @@ -584,18 +582,6 @@ config ETRAX_PE_CHANGEABLE_BITS that a user can change the value on using ioctl's. Bit set = changeable. -config ETRAX_IDE - bool "ATA/IDE support" - depends on ETRAX_ARCH_V32 - select IDE - select BLK_DEV_IDE - select BLK_DEV_IDEDISK - select BLK_DEV_IDECD - select BLK_DEV_IDEDMA - select IDE_GENERIC - help - Enables the ETRAX IDE driver. - config ETRAX_CARDBUS bool "Cardbus support" depends on ETRAX_ARCH_V32 diff --git a/arch/cris/arch-v32/drivers/axisflashmap.c b/arch/cris/arch-v32/drivers/axisflashmap.c index 3ec12ea..c5ff95e 100644 --- a/arch/cris/arch-v32/drivers/axisflashmap.c +++ b/arch/cris/arch-v32/drivers/axisflashmap.c @@ -190,13 +190,12 @@ static struct mtd_info *probe_cs(struct map_info *map_cs) "%s: Probing a 0x%08lx bytes large window at 0x%08lx.\n", map_cs->name, map_cs->size, map_cs->map_priv_1); -#ifdef CONFIG_MTD_AMDSTD - mtd_cs = do_map_probe("amd_flash", map_cs); -#endif #ifdef CONFIG_MTD_CFI - if (!mtd_cs) { mtd_cs = do_map_probe("cfi_probe", map_cs); - } +#endif +#ifdef CONFIG_MTD_JEDECPROBE + if (!mtd_cs) + mtd_cs = do_map_probe("jedec_probe", map_cs); #endif return mtd_cs; diff --git a/arch/cris/arch-v32/drivers/sync_serial.c b/arch/cris/arch-v32/drivers/sync_serial.c index df89298..d581b0a 100644 --- a/arch/cris/arch-v32/drivers/sync_serial.c +++ b/arch/cris/arch-v32/drivers/sync_serial.c @@ -185,7 +185,7 @@ static struct sync_port ports[]= } }; -#define NUMBER_OF_PORTS (sizeof(ports)/sizeof(sync_port)) +#define NUMBER_OF_PORTS ARRAY_SIZE(ports) static const struct file_operations sync_serial_fops = { .owner = THIS_MODULE, diff --git a/arch/cris/arch-v32/kernel/cache.c b/arch/cris/arch-v32/kernel/cache.c new file mode 100644 index 0000000..80da7b8 --- /dev/null +++ b/arch/cris/arch-v32/kernel/cache.c @@ -0,0 +1,33 @@ +#include <linux/module.h> +#include <asm/io.h> +#include <asm/arch/cache.h> +#include <asm/arch/hwregs/dma.h> + +/* This file is used to workaround a cache bug, Guinness TR 106. */ + +inline void flush_dma_descr(struct dma_descr_data *descr, int flush_buf) +{ + /* Flush descriptor to make sure we get correct in_eop and after. */ + asm volatile ("ftagd [%0]" :: "r" (descr)); + /* Flush buffer pointed out by descriptor. */ + if (flush_buf) + cris_flush_cache_range(phys_to_virt((unsigned)descr->buf), + (unsigned)(descr->after - descr->buf)); +} +EXPORT_SYMBOL(flush_dma_descr); + +void flush_dma_list(struct dma_descr_data *descr) +{ + while (1) { + flush_dma_descr(descr, 1); + if (descr->eol) + break; + descr = phys_to_virt((unsigned)descr->next); + } +} +EXPORT_SYMBOL(flush_dma_list); + +/* From cacheflush.S */ +EXPORT_SYMBOL(cris_flush_cache); +/* From cacheflush.S */ +EXPORT_SYMBOL(cris_flush_cache_range); diff --git a/arch/cris/arch-v32/kernel/cacheflush.S b/arch/cris/arch-v32/kernel/cacheflush.S new file mode 100644 index 0000000..956e8fb --- /dev/null +++ b/arch/cris/arch-v32/kernel/cacheflush.S @@ -0,0 +1,94 @@ + .global cris_flush_cache_range +cris_flush_cache_range: + move.d 1024, $r12 + cmp.d $r11, $r12 + bhi cris_flush_1KB + nop + add.d $r10, $r11 + ftagd [$r10] +cris_flush_last: + addq 32, $r10 + cmp.d $r11, $r10 + blt cris_flush_last + ftagd [$r10] + ret + nop +cris_flush_1KB: + ftagd [$r10] + addq 32, $r10 + ftagd [$r10] + addq 32, $r10 + ftagd [$r10] + addq 32, $r10 + ftagd [$r10] + addq 32, $r10 + ftagd [$r10] + addq 32, $r10 + ftagd [$r10] + addq 32, $r10 + ftagd [$r10] + addq 32, $r10 + ftagd [$r10] + addq 32, $r10 + ftagd [$r10] + addq 32, $r10 + ftagd [$r10] + addq 32, $r10 + ftagd [$r10] + addq 32, $r10 + ftagd [$r10] + addq 32, $r10 + ftagd [$r10] + addq 32, $r10 + ftagd [$r10] + addq 32, $r10 + ftagd [$r10] + addq 32, $r10 + ftagd [$r10] + addq 32, $r10 + ftagd [$r10] + addq 32, $r10 + ftagd [$r10] + addq 32, $r10 + ftagd [$r10] + addq 32, $r10 + ftagd [$r10] + addq 32, $r10 + ftagd [$r10] + addq 32, $r10 + ftagd [$r10] + addq 32, $r10 + ftagd [$r10] + addq 32, $r10 + ftagd [$r10] + addq 32, $r10 + ftagd [$r10] + addq 32, $r10 + ftagd [$r10] + addq 32, $r10 + ftagd [$r10] + addq 32, $r10 + ftagd [$r10] + addq 32, $r10 + ftagd [$r10] + addq 32, $r10 + ftagd [$r10] + addq 32, $r10 + ftagd [$r10] + addq 32, $r10 + ftagd [$r10] + addq 32, $r10 + ba cris_flush_cache_range + sub.d $r12, $r11 + + .global cris_flush_cache +cris_flush_cache: + moveq 0, $r10 +cris_flush_line: + move.d 16*1024, $r11 + addq 16, $r10 + cmp.d $r10, $r11 + blt cris_flush_line + fidxd [$r10] + ret + nop diff --git a/arch/cris/arch-v32/kernel/io.c b/arch/cris/arch-v32/kernel/io.c index dfbfcb8..a22a9e0 100644 --- a/arch/cris/arch-v32/kernel/io.c +++ b/arch/cris/arch-v32/kernel/io.c @@ -49,7 +49,7 @@ struct crisv32_ioport crisv32_ioports[] = } }; -#define NBR_OF_PORTS sizeof(crisv32_ioports)/sizeof(struct crisv32_ioport) +#define NBR_OF_PORTS ARRAY_SIZE(crisv32_ioports) struct crisv32_iopin crisv32_led1_green; struct crisv32_iopin crisv32_led1_red; diff --git a/arch/cris/arch-v32/kernel/setup.c b/arch/cris/arch-v32/kernel/setup.c index 4662f36..72e9e83 100644 --- a/arch/cris/arch-v32/kernel/setup.c +++ b/arch/cris/arch-v32/kernel/setup.c @@ -54,12 +54,10 @@ show_cpuinfo(struct seq_file *m, void *v) { int i; int cpu = (int)v - 1; - int entries; unsigned long revision; struct cpu_info *info; - entries = sizeof cpinfo / sizeof(struct cpu_info); - info = &cpinfo[entries - 1]; + info = &cpinfo[ARRAY_SIZE(cpinfo) - 1]; #ifdef CONFIG_SMP if (!cpu_online(cpu)) @@ -68,7 +66,7 @@ show_cpuinfo(struct seq_file *m, void *v) revision = rdvr(); - for (i = 0; i < entries; i++) { + for (i = 0; i < ARRAY_SIZE(cpinfo); i++) { if (cpinfo[i].rev == revision) { info = &cpinfo[i]; break; diff --git a/arch/cris/defconfig b/arch/cris/defconfig index 142a108..9c33ae6 100644 --- a/arch/cris/defconfig +++ b/arch/cris/defconfig @@ -226,8 +226,6 @@ CONFIG_MTD_CFI_UTIL=y CONFIG_MTD_RAM=y # CONFIG_MTD_ROM is not set # CONFIG_MTD_ABSENT is not set -CONFIG_MTD_OBSOLETE_CHIPS=y -CONFIG_MTD_AMDSTD=y # CONFIG_MTD_SHARP is not set # CONFIG_MTD_JEDEC is not set @@ -276,6 +274,7 @@ CONFIG_MTDRAM_ABS_POS=0x0 # CONFIG_BLK_DEV_FD is not set # CONFIG_BLK_DEV_COW_COMMON is not set # CONFIG_BLK_DEV_LOOP is not set +# CONFIG_BLK_DEV_CRYPTOLOOP is not set # CONFIG_BLK_DEV_NBD is not set # CONFIG_BLK_DEV_UB is not set CONFIG_BLK_DEV_RAM=y @@ -302,16 +301,14 @@ CONFIG_IOSCHED_CFQ=y # # ATA/ATAPI/MFM/RLL support # -CONFIG_IDE=y -CONFIG_BLK_DEV_IDE=y +# CONFIG_IDE is not set +# CONFIG_PARIDE is not set # # Please see Documentation/ide.txt for help/info on IDE drives # # CONFIG_BLK_DEV_IDE_SATA is not set -CONFIG_BLK_DEV_IDEDISK=y # CONFIG_IDEDISK_MULTI_MODE is not set -CONFIG_BLK_DEV_IDECD=y # CONFIG_BLK_DEV_IDETAPE is not set # CONFIG_BLK_DEV_IDEFLOPPY is not set # CONFIG_IDE_TASK_IOCTL is not set @@ -321,7 +318,6 @@ CONFIG_BLK_DEV_IDECD=y # # CONFIG_IDE_GENERIC is not set # CONFIG_IDE_ARM is not set -CONFIG_BLK_DEV_IDEDMA=y # CONFIG_IDEDMA_AUTO is not set # CONFIG_BLK_DEV_HD is not set @@ -329,6 +325,7 @@ CONFIG_BLK_DEV_IDEDMA=y # SCSI device support # # CONFIG_SCSI is not set +# CONFIG_ISCSI_TCP is not set # # IEEE 1394 (FireWire) support @@ -414,26 +411,11 @@ CONFIG_NETFILTER=y # CONFIG_NET_POLL_CONTROLLER is not set # CONFIG_HAMRADIO is not set # CONFIG_IRDA is not set -CONFIG_BT=y -CONFIG_BT_L2CAP=y -# CONFIG_BT_SCO is not set -CONFIG_BT_RFCOMM=y -# CONFIG_BT_RFCOMM_TTY is not set -CONFIG_BT_BNEP=y -# CONFIG_BT_BNEP_MC_FILTER is not set -# CONFIG_BT_BNEP_PROTO_FILTER is not set -# CONFIG_BT_HIDP is not set - -# -# Bluetooth device drivers -# -CONFIG_BT_HCIUSB=y -# CONFIG_BT_HCIUSB_SCO is not set -# CONFIG_BT_HCIUART is not set -# CONFIG_BT_HCIBCM203X is not set -# CONFIG_BT_HCIBPA10X is not set -# CONFIG_BT_HCIBFUSB is not set -# CONFIG_BT_HCIVHCI is not set +# CONFIG_AF_RXRPC is not set +# CONFIG_AF_RXRPC_DEBUG is not set +# CONFIG_BT is not set +# CONFIG_I2C is not set + CONFIG_NETDEVICES=y # CONFIG_DUMMY is not set # CONFIG_BONDING is not set @@ -485,31 +467,17 @@ CONFIG_NET_ETHERNET=y # # Input device support # -CONFIG_INPUT=y - -# -# Userland interfaces -# -CONFIG_INPUT_MOUSEDEV=y -CONFIG_INPUT_MOUSEDEV_PSAUX=y -CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 -CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 -# CONFIG_INPUT_JOYDEV is not set -# CONFIG_INPUT_TSDEV is not set -# CONFIG_INPUT_EVDEV is not set -# CONFIG_INPUT_EVBUG is not set +# CONFIG_INPUT is not set # # Input I/O drivers # -# CONFIG_GAMEPORT is not set -CONFIG_SOUND_GAMEPORT=y CONFIG_SERIO=y # CONFIG_SERIO_I8042 is not set # CONFIG_SERIO_SERPORT is not set -# CONFIG_SERIO_CT82C710 is not set -CONFIG_SERIO_LIBPS2=y +# CONFIG_SERIO_LIBPS2 is not set # CONFIG_SERIO_RAW is not set +# CONFIG_GAMEPORT is not set # # Input Device Drivers @@ -525,6 +493,7 @@ CONFIG_MOUSE_PS2=y # CONFIG_MOUSE_SERIAL is not set # CONFIG_MOUSE_VSXXXAA is not set # CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TABLET is not set # CONFIG_INPUT_TOUCHSCREEN is not set # CONFIG_INPUT_MISC is not set @@ -542,6 +511,8 @@ CONFIG_MOUSE_PS2=y # # Non-8250 serial port support # +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y CONFIG_UNIX98_PTYS=y CONFIG_LEGACY_PTYS=y CONFIG_LEGACY_PTY_COUNT=256 @@ -559,6 +530,8 @@ CONFIG_LEGACY_PTY_COUNT=256 # CONFIG_GEN_RTC is not set # CONFIG_DTLK is not set # CONFIG_R3964 is not set +# CONFIG_RTC_LIB is not set +# CONFIG_RTC_CLASS is not set # # Ftape, the floppy tape device driver @@ -660,7 +633,9 @@ CONFIG_NFS_V3=y # CONFIG_NFSD is not set CONFIG_LOCKD=y CONFIG_LOCKD_V4=y +CONFIG_NFS_COMMON=y CONFIG_SUNRPC=y +# CONFIG_SUNRPC_BIND34 is not set # CONFIG_RPCSEC_GSS_KRB5 is not set # CONFIG_RPCSEC_GSS_SPKM3 is not set # CONFIG_SMB_FS is not set @@ -686,9 +661,21 @@ CONFIG_MSDOS_PARTITION=y # CONFIG_SOUND is not set # +# Generic devices +# +# CONFIG_SND_MPU401_UART is not set +# CONFIG_SND_DUMMY is not set +# CONFIG_SND_VIRMIDI is not set +# CONFIG_SND_MTPAV is not set +# CONFIG_SND_SERIAL_U16550 is not set +# CONFIG_SND_MPU401 is not set + +# # PCCARD (PCMCIA/CardBus) support # # CONFIG_PCCARD is not set +# CONFIG_PARPORT_PC_PCMCIA is not set +# CONFIG_NET_PCMCIA is not set # # PC-card bridges @@ -734,6 +721,7 @@ CONFIG_USB_DEVICEFS=y # USB Input Devices # # CONFIG_USB_HID is not set +# HID_SUPPORT is not set # # USB HID Boot Protocol drivers @@ -829,7 +817,7 @@ CONFIG_USB_RTL8150=y # # Hardware crypto devices -# +# CONFIG_CRYPTO_HW is not set # # Library routines diff --git a/arch/cris/kernel/crisksyms.c b/arch/cris/kernel/crisksyms.c index 105bb5e..62f0e75 100644 --- a/arch/cris/kernel/crisksyms.c +++ b/arch/cris/kernel/crisksyms.c @@ -27,6 +27,7 @@ extern void __Mod(void); extern void __ashldi3(void); extern void __ashrdi3(void); extern void __lshrdi3(void); +extern void __negdi2(void); extern void iounmap(volatile void * __iomem); /* Platform dependent support */ @@ -34,19 +35,6 @@ EXPORT_SYMBOL(kernel_thread); EXPORT_SYMBOL(get_cmos_time); EXPORT_SYMBOL(loops_per_usec); -/* String functions */ -EXPORT_SYMBOL(memcmp); -EXPORT_SYMBOL(memmove); -EXPORT_SYMBOL(strstr); -EXPORT_SYMBOL(strcpy); -EXPORT_SYMBOL(strchr); -EXPORT_SYMBOL(strcmp); -EXPORT_SYMBOL(strlen); -EXPORT_SYMBOL(strcat); -EXPORT_SYMBOL(strncat); -EXPORT_SYMBOL(strncmp); -EXPORT_SYMBOL(strncpy); - /* Math functions */ EXPORT_SYMBOL(__Udiv); EXPORT_SYMBOL(__Umod); @@ -55,6 +43,7 @@ EXPORT_SYMBOL(__Mod); EXPORT_SYMBOL(__ashldi3); EXPORT_SYMBOL(__ashrdi3); EXPORT_SYMBOL(__lshrdi3); +EXPORT_SYMBOL(__negdi2); /* Memory functions */ EXPORT_SYMBOL(__ioremap); @@ -84,4 +73,4 @@ EXPORT_SYMBOL(start_one_shot_timer); EXPORT_SYMBOL(del_fast_timer); EXPORT_SYMBOL(schedule_usleep); #endif - +EXPORT_SYMBOL(csum_partial); diff --git a/arch/cris/kernel/irq.c b/arch/cris/kernel/irq.c index 5c27ff8..2dfac8c 100644 --- a/arch/cris/kernel/irq.c +++ b/arch/cris/kernel/irq.c @@ -2,7 +2,7 @@ * * linux/arch/cris/kernel/irq.c * - * Copyright (c) 2000,2001 Axis Communications AB + * Copyright (c) 2000,2007 Axis Communications AB * * Authors: Bjorn Wesen (bjornw@axis.com) * @@ -92,14 +92,16 @@ skip: asmlinkage void do_IRQ(int irq, struct pt_regs * regs) { unsigned long sp; + struct pt_regs *old_regs = set_irq_regs(regs); irq_enter(); sp = rdsp(); if (unlikely((sp & (PAGE_SIZE - 1)) < (PAGE_SIZE/8))) { printk("do_IRQ: stack overflow: %lX\n", sp); show_stack(NULL, (unsigned long *)sp); } - __do_IRQ(irq, regs); + __do_IRQ(irq); irq_exit(); + set_irq_regs(old_regs); } void weird_irq(void) diff --git a/arch/cris/kernel/process.c b/arch/cris/kernel/process.c index 123451c..9ca558f 100644 --- a/arch/cris/kernel/process.c +++ b/arch/cris/kernel/process.c @@ -195,6 +195,11 @@ EXPORT_SYMBOL(enable_hlt); */ void (*pm_idle)(void); +extern void default_idle(void); + +void (*pm_power_off)(void); +EXPORT_SYMBOL(pm_power_off); + /* * The idle thread. There's no useful work to be * done, so just try to conserve power and have a diff --git a/arch/cris/kernel/ptrace.c b/arch/cris/kernel/ptrace.c index 1085d03..3ccd20e 100644 --- a/arch/cris/kernel/ptrace.c +++ b/arch/cris/kernel/ptrace.c @@ -81,13 +81,13 @@ /* notification of userspace execution resumption * - triggered by current->work.notify_resume */ -extern int do_signal(int canrestart, sigset_t *oldset, struct pt_regs *regs); +extern int do_signal(int canrestart, struct pt_regs *regs); -void do_notify_resume(int canrestart, sigset_t *oldset, struct pt_regs *regs, +void do_notify_resume(int canrestart, struct pt_regs *regs, __u32 thread_info_flags ) { /* deal with pending signal delivery */ if (thread_info_flags & _TIF_SIGPENDING) - do_signal(canrestart,oldset,regs); + do_signal(canrestart,regs); } diff --git a/arch/cris/kernel/sys_cris.c b/arch/cris/kernel/sys_cris.c index 514359b..8b99841 100644 --- a/arch/cris/kernel/sys_cris.c +++ b/arch/cris/kernel/sys_cris.c @@ -13,6 +13,7 @@ #include <linux/sched.h> #include <linux/syscalls.h> #include <linux/mm.h> +#include <linux/fs.h> #include <linux/smp.h> #include <linux/smp_lock.h> #include <linux/sem.h> diff --git a/arch/cris/kernel/time.c b/arch/cris/kernel/time.c index acfd045..7a2cc7e 100644 --- a/arch/cris/kernel/time.c +++ b/arch/cris/kernel/time.c @@ -171,10 +171,6 @@ get_cmos_time(void) mon = CMOS_READ(RTC_MONTH); year = CMOS_READ(RTC_YEAR); - printk(KERN_DEBUG - "rtc: sec 0x%x min 0x%x hour 0x%x day 0x%x mon 0x%x year 0x%x\n", - sec, min, hour, day, mon, year); - BCD_TO_BIN(sec); BCD_TO_BIN(min); BCD_TO_BIN(hour); @@ -207,12 +203,12 @@ void cris_do_profile(struct pt_regs* regs) { -#if CONFIG_SYSTEM_PROFILER +#ifdef CONFIG_SYSTEM_PROFILER cris_profile_sample(regs); #endif -#if CONFIG_PROFILING - profile_tick(CPU_PROFILING, regs); +#ifdef CONFIG_PROFILING + profile_tick(CPU_PROFILING); #endif } diff --git a/arch/frv/kernel/break.S b/arch/frv/kernel/break.S index dac4a5f..bd0bdf9 100644 --- a/arch/frv/kernel/break.S +++ b/arch/frv/kernel/break.S @@ -63,7 +63,7 @@ __break_trace_through_exceptions: # entry point for Break Exceptions/Interrupts # ############################################################################### - .text + .section .text.break .balign 4 .globl __entry_break __entry_break: diff --git a/arch/frv/kernel/entry.S b/arch/frv/kernel/entry.S index 1e74f3c..f926c70 100644 --- a/arch/frv/kernel/entry.S +++ b/arch/frv/kernel/entry.S @@ -38,7 +38,7 @@ #define nr_syscalls ((syscall_table_size)/4) - .text + .section .text.entry .balign 4 .macro LEDS val diff --git a/arch/frv/kernel/vmlinux.lds.S b/arch/frv/kernel/vmlinux.lds.S index 3b71e0c..a17a81d 100644 --- a/arch/frv/kernel/vmlinux.lds.S +++ b/arch/frv/kernel/vmlinux.lds.S @@ -76,6 +76,12 @@ SECTIONS *(.data.init_task) } + . = ALIGN(4096); + .data.page_aligned : { *(.data.idt) } + + . = ALIGN(L1_CACHE_BYTES); + .data.cacheline_aligned : { *(.data.cacheline_aligned) } + .trap : { /* trap table management - read entry-table.S before modifying */ . = ALIGN(8192); @@ -86,28 +92,25 @@ SECTIONS *(.trap.break) } - . = ALIGN(4096); - .data.page_aligned : { *(.data.idt) } - - . = ALIGN(L1_CACHE_BYTES); - .data.cacheline_aligned : { *(.data.cacheline_aligned) } - /* Text and read-only data */ . = ALIGN(4); _text = .; _stext = .; .text : { - *( - .text.start .text.* + *(.text.start) + *(.text.entry) + *(.text.break) + *(.text.tlbmiss) + TEXT_TEXT + SCHED_TEXT + LOCK_TEXT #ifdef CONFIG_DEBUG_INFO + *( .init.text .exit.text .exitcall.exit -#endif ) - TEXT_TEXT - SCHED_TEXT - LOCK_TEXT +#endif *(.fixup) *(.gnu.warning) *(.exitcall.exit) diff --git a/arch/frv/mm/init.c b/arch/frv/mm/init.c index 4103c2c..b841ecf 100644 --- a/arch/frv/mm/init.c +++ b/arch/frv/mm/init.c @@ -197,7 +197,7 @@ void __init mem_init(void) /* * free the memory that was only required for initialisation */ -void __init free_initmem(void) +void free_initmem(void) { #if defined(CONFIG_RAMKERNEL) && !defined(CONFIG_PROTECT_KERNEL) unsigned long start, end, addr; diff --git a/arch/frv/mm/tlb-miss.S b/arch/frv/mm/tlb-miss.S index 04da674..0764348 100644 --- a/arch/frv/mm/tlb-miss.S +++ b/arch/frv/mm/tlb-miss.S @@ -16,7 +16,7 @@ #include <asm/highmem.h> #include <asm/spr-regs.h> - .section .text + .section .text.tlbmiss .balign 4 .globl __entry_insn_mmu_miss diff --git a/arch/ia64/hp/sim/boot/fw-emu.c b/arch/ia64/hp/sim/boot/fw-emu.c index 1189d03..bf6d9d8 100644 --- a/arch/ia64/hp/sim/boot/fw-emu.c +++ b/arch/ia64/hp/sim/boot/fw-emu.c @@ -285,7 +285,7 @@ sys_fw_init (const char *args, int arglen) } cmd_line[arglen] = '\0'; - memset(efi_systab, 0, sizeof(efi_systab)); + memset(efi_systab, 0, sizeof(*efi_systab)); efi_systab->hdr.signature = EFI_SYSTEM_TABLE_SIGNATURE; efi_systab->hdr.revision = ((1 << 16) | 00); efi_systab->hdr.headersize = sizeof(efi_systab->hdr); diff --git a/arch/ia64/ia32/ia32priv.h b/arch/ia64/ia32/ia32priv.h index 466bbcb..c5c872b 100644 --- a/arch/ia64/ia32/ia32priv.h +++ b/arch/ia64/ia32/ia32priv.h @@ -290,7 +290,6 @@ struct old_linux32_dirent { #define _ASM_IA64_ELF_H /* Don't include elf.h */ #include <linux/sched.h> -#include <asm/processor.h> /* * This is used to ensure we don't load something for the wrong architecture. diff --git a/arch/ia64/kernel/.gitignore b/arch/ia64/kernel/.gitignore new file mode 100644 index 0000000..9830775 --- /dev/null +++ b/arch/ia64/kernel/.gitignore @@ -0,0 +1 @@ +gate.lds diff --git a/arch/ia64/kernel/acpi.c b/arch/ia64/kernel/acpi.c index 3d45d24..897e208 100644 --- a/arch/ia64/kernel/acpi.c +++ b/arch/ia64/kernel/acpi.c @@ -678,9 +678,11 @@ int __init acpi_boot_init(void) /* I/O APIC */ if (acpi_table_parse_madt - (ACPI_MADT_TYPE_IO_SAPIC, acpi_parse_iosapic, NR_IOSAPICS) < 1) - printk(KERN_ERR PREFIX - "Error parsing MADT - no IOSAPIC entries\n"); + (ACPI_MADT_TYPE_IO_SAPIC, acpi_parse_iosapic, NR_IOSAPICS) < 1) { + if (!ia64_platform_is("sn2")) + printk(KERN_ERR PREFIX + "Error parsing MADT - no IOSAPIC entries\n"); + } /* System-Level Interrupt Routing */ diff --git a/arch/ia64/kernel/efi.c b/arch/ia64/kernel/efi.c index 6216eba..8e8f8b6 100644 --- a/arch/ia64/kernel/efi.c +++ b/arch/ia64/kernel/efi.c @@ -218,9 +218,10 @@ efi_gettimeofday (struct timespec *ts) { efi_time_t tm; - memset(ts, 0, sizeof(ts)); - if ((*efi.get_time)(&tm, NULL) != EFI_SUCCESS) + if ((*efi.get_time)(&tm, NULL) != EFI_SUCCESS) { + memset(ts, 0, sizeof(*ts)); return; + } ts->tv_sec = mktime(tm.year, tm.month, tm.day, tm.hour, tm.minute, tm.second); ts->tv_nsec = tm.nanosecond; @@ -1112,7 +1113,7 @@ efi_initialize_iomem_resources(struct resource *code_resource, if (md->num_pages == 0) /* should not happen */ continue; - flags = IORESOURCE_MEM; + flags = IORESOURCE_MEM | IORESOURCE_BUSY; switch (md->type) { case EFI_MEMORY_MAPPED_IO: @@ -1134,12 +1135,11 @@ efi_initialize_iomem_resources(struct resource *code_resource, case EFI_ACPI_MEMORY_NVS: name = "ACPI Non-volatile Storage"; - flags |= IORESOURCE_BUSY; break; case EFI_UNUSABLE_MEMORY: name = "reserved"; - flags |= IORESOURCE_BUSY | IORESOURCE_DISABLED; + flags |= IORESOURCE_DISABLED; break; case EFI_RESERVED_TYPE: @@ -1148,7 +1148,6 @@ efi_initialize_iomem_resources(struct resource *code_resource, case EFI_ACPI_RECLAIM_MEMORY: default: name = "reserved"; - flags |= IORESOURCE_BUSY; break; } diff --git a/arch/ia64/kernel/iosapic.c b/arch/ia64/kernel/iosapic.c index cfe4654..274a593 100644 --- a/arch/ia64/kernel/iosapic.c +++ b/arch/ia64/kernel/iosapic.c @@ -748,6 +748,15 @@ skip_numa_setup: #endif } +static inline unsigned char choose_dmode(void) +{ +#ifdef CONFIG_SMP + if (smp_int_redirect & SMP_IRQ_REDIRECTION) + return IOSAPIC_LOWEST_PRIORITY; +#endif + return IOSAPIC_FIXED; +} + /* * ACPI can describe IOSAPIC interrupts via static tables and namespace * methods. This provides an interface to register those interrupts and @@ -762,6 +771,7 @@ iosapic_register_intr (unsigned int gsi, unsigned long flags; struct iosapic_rte_info *rte; u32 low32; + unsigned char dmode; /* * If this GSI has already been registered (i.e., it's a @@ -791,8 +801,8 @@ iosapic_register_intr (unsigned int gsi, spin_lock(&irq_desc[irq].lock); dest = get_target_cpu(gsi, irq); - err = register_intr(gsi, irq, IOSAPIC_LOWEST_PRIORITY, - polarity, trigger); + dmode = choose_dmode(); + err = register_intr(gsi, irq, dmode, polarity, trigger); if (err < 0) { spin_unlock(&irq_desc[irq].lock); irq = err; @@ -961,10 +971,12 @@ iosapic_override_isa_irq (unsigned int isa_irq, unsigned int gsi, { int vector, irq; unsigned int dest = cpu_physical_id(smp_processor_id()); + unsigned char dmode; irq = vector = isa_irq_to_vector(isa_irq); BUG_ON(bind_irq_vector(irq, vector, CPU_MASK_ALL)); - register_intr(gsi, irq, IOSAPIC_LOWEST_PRIORITY, polarity, trigger); + dmode = choose_dmode(); + register_intr(gsi, irq, dmode, polarity, trigger); DBG("ISA: IRQ %u -> GSI %u (%s,%s) -> CPU %d (0x%04x) vector %d\n", isa_irq, gsi, trigger == IOSAPIC_EDGE ? "edge" : "level", diff --git a/arch/ia64/kernel/irq.c b/arch/ia64/kernel/irq.c index 44be1c95..6dee579 100644 --- a/arch/ia64/kernel/irq.c +++ b/arch/ia64/kernel/irq.c @@ -61,9 +61,11 @@ int show_interrupts(struct seq_file *p, void *v) unsigned long flags; if (i == 0) { - seq_printf(p, " "); + char cpuname[16]; + seq_printf(p, " "); for_each_online_cpu(j) { - seq_printf(p, "CPU%d ",j); + snprintf(cpuname, 10, "CPU%d", j); + seq_printf(p, "%10s ", cpuname); } seq_putc(p, '\n'); } diff --git a/arch/ia64/kernel/mca.c b/arch/ia64/kernel/mca.c index cc87025..10b48cd 100644 --- a/arch/ia64/kernel/mca.c +++ b/arch/ia64/kernel/mca.c @@ -571,7 +571,7 @@ out: * Outputs * None */ -static void __init +void ia64_mca_register_cpev (int cpev) { /* Register the CPE interrupt vector with SAL */ diff --git a/arch/ia64/kernel/palinfo.c b/arch/ia64/kernel/palinfo.c index 6ef6ffb..396004e 100644 --- a/arch/ia64/kernel/palinfo.c +++ b/arch/ia64/kernel/palinfo.c @@ -470,7 +470,7 @@ register_info(char *page) return p - page; } -static const char *proc_features[]={ +static char *proc_features_0[]={ /* Feature set 0 */ NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL, NULL,NULL,NULL,NULL,NULL,NULL,NULL, NULL,NULL, NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL, @@ -502,25 +502,92 @@ static const char *proc_features[]={ "Enable BERR promotion" }; +static char *proc_features_16[]={ /* Feature set 16 */ + "Disable ETM", + "Enable ETM", + "Enable MCA on half-way timer", + "Enable snoop WC", + NULL, + "Enable Fast Deferral", + "Disable MCA on memory aliasing", + "Enable RSB", + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "DP system processor", + "Low Voltage", + "HT supported", + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL +}; + +static char **proc_features[]={ + proc_features_0, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, + proc_features_16, + NULL, NULL, NULL, NULL, +}; + +static char * +feature_set_info(char *page, u64 avail, u64 status, u64 control, u64 set) +{ + char *p = page; + char **vf, **v; + int i; + + vf = v = proc_features[set]; + for(i=0; i < 64; i++, avail >>=1, status >>=1, control >>=1) { + + if (!(control)) /* No remaining bits set */ + break; + if (!(avail & 0x1)) /* Print only bits that are available */ + continue; + if (vf) + v = vf + i; + if ( v && *v ) { + p += sprintf(p, "%-40s : %s %s\n", *v, + avail & 0x1 ? (status & 0x1 ? + "On " : "Off"): "", + avail & 0x1 ? (control & 0x1 ? + "Ctrl" : "NoCtrl"): ""); + } else { + p += sprintf(p, "Feature set %2ld bit %2d\t\t\t" + " : %s %s\n", + set, i, + avail & 0x1 ? (status & 0x1 ? + "On " : "Off"): "", + avail & 0x1 ? (control & 0x1 ? + "Ctrl" : "NoCtrl"): ""); + } + } + return p; +} static int processor_info(char *page) { char *p = page; - const char **v = proc_features; - u64 avail=1, status=1, control=1; - int i; + u64 avail=1, status=1, control=1, feature_set=0; s64 ret; - if ((ret=ia64_pal_proc_get_features(&avail, &status, &control)) != 0) return 0; + do { + ret = ia64_pal_proc_get_features(&avail, &status, &control, + feature_set); + if (ret < 0) { + return p - page; + } + if (ret == 1) { + feature_set++; + continue; + } + + p = feature_set_info(p, avail, status, control, feature_set); + + feature_set++; + } while(1); - for(i=0; i < 64; i++, v++,avail >>=1, status >>=1, control >>=1) { - if ( ! *v ) continue; - p += sprintf(p, "%-40s : %s%s %s\n", *v, - avail & 0x1 ? "" : "NotImpl", - avail & 0x1 ? (status & 0x1 ? "On" : "Off"): "", - avail & 0x1 ? (control & 0x1 ? "Ctrl" : "NoCtrl"): ""); - } return p - page; } diff --git a/arch/ia64/kernel/patch.c b/arch/ia64/kernel/patch.c index e796e29..2cb9425 100644 --- a/arch/ia64/kernel/patch.c +++ b/arch/ia64/kernel/patch.c @@ -129,9 +129,6 @@ ia64_patch_mckinley_e9 (unsigned long start, unsigned long end) first_time = 0; if (need_workaround) printk(KERN_INFO "Leaving McKinley Errata 9 workaround enabled\n"); - else - printk(KERN_INFO "McKinley Errata 9 workaround not needed; " - "disabling it\n"); } if (need_workaround) return; diff --git a/arch/ia64/kernel/perfmon.c b/arch/ia64/kernel/perfmon.c index 59169bf7..73e7c2e 100644 --- a/arch/ia64/kernel/perfmon.c +++ b/arch/ia64/kernel/perfmon.c @@ -558,7 +558,7 @@ static ctl_table pfm_sysctl_dir[] = { { .ctl_name = CTL_UNNUMBERED, .procname = "perfmon", - .mode = 0755, + .mode = 0555, .child = pfm_ctl_table, }, {} @@ -567,7 +567,7 @@ static ctl_table pfm_sysctl_root[] = { { .ctl_name = CTL_KERN, .procname = "kernel", - .mode = 0755, + .mode = 0555, .child = pfm_sysctl_dir, }, {} diff --git a/arch/ia64/mm/contig.c b/arch/ia64/mm/contig.c index d3c538b..7e9c275 100644 --- a/arch/ia64/mm/contig.c +++ b/arch/ia64/mm/contig.c @@ -146,6 +146,46 @@ find_bootmap_location (unsigned long start, unsigned long end, void *arg) return 0; } +#ifdef CONFIG_SMP +static void *cpu_data; +/** + * per_cpu_init - setup per-cpu variables + * + * Allocate and setup per-cpu data areas. + */ +void * __cpuinit +per_cpu_init (void) +{ + int cpu; + static int first_time=1; + + /* + * get_free_pages() cannot be used before cpu_init() done. BSP + * allocates "NR_CPUS" pages for all CPUs to avoid that AP calls + * get_zeroed_page(). + */ + if (first_time) { + first_time=0; + for (cpu = 0; cpu < NR_CPUS; cpu++) { + memcpy(cpu_data, __phys_per_cpu_start, __per_cpu_end - __per_cpu_start); + __per_cpu_offset[cpu] = (char *) cpu_data - __per_cpu_start; + cpu_data += PERCPU_PAGE_SIZE; + per_cpu(local_per_cpu_offset, cpu) = __per_cpu_offset[cpu]; + } + } + return __per_cpu_start + __per_cpu_offset[smp_processor_id()]; +} + +static inline void +alloc_per_cpu_data(void) +{ + cpu_data = __alloc_bootmem(PERCPU_PAGE_SIZE * NR_CPUS, + PERCPU_PAGE_SIZE, __pa(MAX_DMA_ADDRESS)); +} +#else +#define alloc_per_cpu_data() do { } while (0) +#endif /* CONFIG_SMP */ + /** * find_memory - setup memory map * @@ -182,41 +222,9 @@ find_memory (void) find_initrd(); + alloc_per_cpu_data(); } -#ifdef CONFIG_SMP -/** - * per_cpu_init - setup per-cpu variables - * - * Allocate and setup per-cpu data areas. - */ -void * __cpuinit -per_cpu_init (void) -{ - void *cpu_data; - int cpu; - static int first_time=1; - - /* - * get_free_pages() cannot be used before cpu_init() done. BSP - * allocates "NR_CPUS" pages for all CPUs to avoid that AP calls - * get_zeroed_page(). - */ - if (first_time) { - first_time=0; - cpu_data = __alloc_bootmem(PERCPU_PAGE_SIZE * NR_CPUS, - PERCPU_PAGE_SIZE, __pa(MAX_DMA_ADDRESS)); - for (cpu = 0; cpu < NR_CPUS; cpu++) { - memcpy(cpu_data, __phys_per_cpu_start, __per_cpu_end - __per_cpu_start); - __per_cpu_offset[cpu] = (char *) cpu_data - __per_cpu_start; - cpu_data += PERCPU_PAGE_SIZE; - per_cpu(local_per_cpu_offset, cpu) = __per_cpu_offset[cpu]; - } - } - return __per_cpu_start + __per_cpu_offset[smp_processor_id()]; -} -#endif /* CONFIG_SMP */ - static int count_pages (u64 start, u64 end, void *arg) { diff --git a/arch/ia64/sn/kernel/irq.c b/arch/ia64/sn/kernel/irq.c index 0f9b126..53351c3 100644 --- a/arch/ia64/sn/kernel/irq.c +++ b/arch/ia64/sn/kernel/irq.c @@ -5,7 +5,7 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (c) 2000-2006 Silicon Graphics, Inc. All Rights Reserved. + * Copyright (c) 2000-2007 Silicon Graphics, Inc. All Rights Reserved. */ #include <linux/irq.h> @@ -85,12 +85,18 @@ static void sn_shutdown_irq(unsigned int irq) { } +extern void ia64_mca_register_cpev(int); + static void sn_disable_irq(unsigned int irq) { + if (irq == local_vector_to_irq(IA64_CPE_VECTOR)) + ia64_mca_register_cpev(0); } static void sn_enable_irq(unsigned int irq) { + if (irq == local_vector_to_irq(IA64_CPE_VECTOR)) + ia64_mca_register_cpev(irq); } static void sn_ack_irq(unsigned int irq) diff --git a/arch/ia64/sn/kernel/xpc_main.c b/arch/ia64/sn/kernel/xpc_main.c index e336e16..81785b7 100644 --- a/arch/ia64/sn/kernel/xpc_main.c +++ b/arch/ia64/sn/kernel/xpc_main.c @@ -3,7 +3,7 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (c) 2004-2006 Silicon Graphics, Inc. All Rights Reserved. + * Copyright (c) 2004-2007 Silicon Graphics, Inc. All Rights Reserved. */ @@ -257,7 +257,9 @@ xpc_hb_checker(void *ignore) set_cpus_allowed(current, cpumask_of_cpu(XPC_HB_CHECK_CPU)); + /* set our heartbeating to other partitions into motion */ xpc_hb_check_timeout = jiffies + (xpc_hb_check_interval * HZ); + xpc_hb_beater(0); while (!(volatile int) xpc_exiting) { @@ -1338,16 +1340,8 @@ xpc_init(void) dev_warn(xpc_part, "can't register die notifier\n"); } - - /* - * Set the beating to other partitions into motion. This is - * the last requirement for other partitions' discovery to - * initiate communications with us. - */ init_timer(&xpc_hb_timer); xpc_hb_timer.function = xpc_hb_beater; - xpc_hb_beater(0); - /* * The real work-horse behind xpc. This processes incoming diff --git a/arch/m32r/kernel/signal.c b/arch/m32r/kernel/signal.c index a753d79..1812454 100644 --- a/arch/m32r/kernel/signal.c +++ b/arch/m32r/kernel/signal.c @@ -36,7 +36,7 @@ sys_rt_sigsuspend(sigset_t __user *unewset, size_t sigsetsize, unsigned long r2, unsigned long r3, unsigned long r4, unsigned long r5, unsigned long r6, struct pt_regs *regs) { - sigset_t saveset, newset; + sigset_t newset; /* XXX: Don't preclude handling different sized sigset_t's. */ if (sigsetsize != sizeof(sigset_t)) @@ -44,21 +44,18 @@ sys_rt_sigsuspend(sigset_t __user *unewset, size_t sigsetsize, if (copy_from_user(&newset, unewset, sizeof(newset))) return -EFAULT; - sigdelsetmask(&newset, ~_BLOCKABLE); + sigdelsetmask(&newset, sigmask(SIGKILL)|sigmask(SIGSTOP)); spin_lock_irq(¤t->sighand->siglock); - saveset = current->blocked; + current->saved_sigmask = current->blocked; current->blocked = newset; recalc_sigpending(); spin_unlock_irq(¤t->sighand->siglock); - regs->r0 = -EINTR; - while (1) { - current->state = TASK_INTERRUPTIBLE; - schedule(); - if (do_signal(regs, &saveset)) - return regs->r0; - } + current->state = TASK_INTERRUPTIBLE; + schedule(); + set_thread_flag(TIF_RESTORE_SIGMASK); + return -ERESTARTNOHAND; } asmlinkage int diff --git a/arch/m32r/kernel/syscall_table.S b/arch/m32r/kernel/syscall_table.S index 751ac2a..95aa798 100644 --- a/arch/m32r/kernel/syscall_table.S +++ b/arch/m32r/kernel/syscall_table.S @@ -284,3 +284,43 @@ ENTRY(sys_call_table) .long sys_mq_getsetattr .long sys_ni_syscall /* reserved for kexec */ .long sys_waitid + .long sys_ni_syscall /* 285 */ /* available */ + .long sys_add_key + .long sys_request_key + .long sys_keyctl + .long sys_ioprio_set + .long sys_ioprio_get /* 290 */ + .long sys_inotify_init + .long sys_inotify_add_watch + .long sys_inotify_rm_watch + .long sys_migrate_pages + .long sys_openat /* 295 */ + .long sys_mkdirat + .long sys_mknodat + .long sys_fchownat + .long sys_futimesat + .long sys_fstatat64 /* 300 */ + .long sys_unlinkat + .long sys_renameat + .long sys_linkat + .long sys_symlinkat + .long sys_readlinkat /* 305 */ + .long sys_fchmodat + .long sys_faccessat + .long sys_pselect6 + .long sys_ppoll + .long sys_unshare /* 310 */ + .long sys_set_robust_list + .long sys_get_robust_list + .long sys_splice + .long sys_sync_file_range + .long sys_tee /* 315 */ + .long sys_vmsplice + .long sys_move_pages + .long sys_getcpu + .long sys_epoll_pwait + .long sys_utimensat /* 320 */ + .long sys_signalfd + .long sys_timerfd + .long sys_eventfd + .long sys_fallocate diff --git a/arch/m68k/atari/atakeyb.c b/arch/m68k/atari/atakeyb.c index 880add1..8a2a53b 100644 --- a/arch/m68k/atari/atakeyb.c +++ b/arch/m68k/atari/atakeyb.c @@ -565,7 +565,7 @@ void atari_kbd_leds(unsigned int leds) static int atari_keyb_done = 0; -int __init atari_keyb_init(void) +int atari_keyb_init(void) { if (atari_keyb_done) return 0; @@ -631,6 +631,7 @@ int __init atari_keyb_init(void) atari_keyb_done = 1; return 0; } +EXPORT_SYMBOL_GPL(atari_keyb_init); int atari_kbd_translate(unsigned char keycode, unsigned char *keycodep, char raw_mode) { diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index 2c7d6c2..455bd1f 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -22,6 +22,7 @@ config MACH_ALCHEMY config BASLER_EXCITE bool "Basler eXcite smart camera" select CEVT_R4K + select CSRC_R4K select DMA_COHERENT select HW_HAS_PCI select IRQ_CPU @@ -49,6 +50,7 @@ config BASLER_EXCITE_PROTOTYPE config BCM47XX bool "BCM47XX based boards" select CEVT_R4K + select CSRC_R4K select DMA_NONCOHERENT select HW_HAS_PCI select IRQ_CPU @@ -66,6 +68,7 @@ config BCM47XX config MIPS_COBALT bool "Cobalt Server" select CEVT_R4K + select CSRC_R4K select CEVT_GT641XX select DMA_NONCOHERENT select HW_HAS_PCI @@ -85,6 +88,7 @@ config MACH_DECSTATION bool "DECstations" select BOOT_ELF32 select CEVT_R4K + select CSRC_R4K select DMA_NONCOHERENT select NO_IOPORT select IRQ_CPU @@ -117,6 +121,7 @@ config MACH_JAZZ select ARC32 select ARCH_MAY_HAVE_PC_FDC select CEVT_R4K + select CSRC_R4K select GENERIC_ISA_DMA select IRQ_CPU select I8253 @@ -137,6 +142,7 @@ config MACH_JAZZ config LASAT bool "LASAT Networks platforms" select CEVT_R4K + select CSRC_R4K select DMA_NONCOHERENT select SYS_HAS_EARLY_PRINTK select HW_HAS_PCI @@ -154,6 +160,7 @@ config LEMOTE_FULONG bool "Lemote Fulong mini-PC" select ARCH_SPARSEMEM_ENABLE select CEVT_R4K + select CSRC_R4K select SYS_HAS_CPU_LOONGSON2 select DMA_NONCOHERENT select BOOT_ELF32 @@ -179,6 +186,7 @@ config MIPS_ATLAS bool "MIPS Atlas board" select BOOT_ELF32 select CEVT_R4K + select CSRC_R4K select DMA_NONCOHERENT select SYS_HAS_EARLY_PRINTK select IRQ_CPU @@ -210,6 +218,7 @@ config MIPS_MALTA select ARCH_MAY_HAVE_PC_FDC select BOOT_ELF32 select CEVT_R4K + select CSRC_R4K select DMA_NONCOHERENT select GENERIC_ISA_DMA select IRQ_CPU @@ -241,6 +250,7 @@ config MIPS_MALTA config MIPS_SEAD bool "MIPS SEAD board" select CEVT_R4K + select CSRC_R4K select IRQ_CPU select DMA_NONCOHERENT select SYS_HAS_EARLY_PRINTK @@ -260,6 +270,7 @@ config MIPS_SEAD config MIPS_SIM bool 'MIPS simulator (MIPSsim)' select CEVT_R4K + select CSRC_R4K select DMA_NONCOHERENT select SYS_HAS_EARLY_PRINTK select IRQ_CPU @@ -278,6 +289,7 @@ config MIPS_SIM config MARKEINS bool "NEC EMMA2RH Mark-eins" select CEVT_R4K + select CSRC_R4K select DMA_NONCOHERENT select HW_HAS_PCI select IRQ_CPU @@ -293,6 +305,7 @@ config MARKEINS config MACH_VR41XX bool "NEC VR4100 series based machines" select CEVT_R4K + select CSRC_R4K select SYS_HAS_CPU_VR41XX select GENERIC_HARDIRQS_NO__DO_IRQ @@ -330,6 +343,7 @@ config PMC_MSP config PMC_YOSEMITE bool "PMC-Sierra Yosemite eval board" select CEVT_R4K + select CSRC_R4K select DMA_COHERENT select HW_HAS_PCI select IRQ_CPU @@ -351,6 +365,7 @@ config PMC_YOSEMITE config QEMU bool "Qemu" select CEVT_R4K + select CSRC_R4K select DMA_COHERENT select GENERIC_ISA_DMA select HAVE_STD_PC_SERIAL_PORT @@ -361,10 +376,10 @@ config QEMU select PCSPEAKER select SWAP_IO_SPACE select SYS_HAS_CPU_MIPS32_R1 + select SYS_HAS_EARLY_PRINTK select SYS_SUPPORTS_32BIT_KERNEL select SYS_SUPPORTS_BIG_ENDIAN select SYS_SUPPORTS_LITTLE_ENDIAN - select ARCH_SPARSEMEM_ENABLE select GENERIC_HARDIRQS_NO__DO_IRQ select NR_CPUS_DEFAULT_1 select SYS_SUPPORTS_SMP @@ -382,9 +397,11 @@ config SGI_IP22 select ARC32 select BOOT_ELF32 select CEVT_R4K + select CSRC_R4K select DMA_NONCOHERENT select HW_HAS_EISA select I8253 + select I8259 select IP22_CPU_SCACHE select IRQ_CPU select GENERIC_ISA_DMA_SUPPORT_BROKEN @@ -427,6 +444,7 @@ config SGI_IP32 select ARC32 select BOOT_ELF32 select CEVT_R4K + select CSRC_R4K select DMA_NONCOHERENT select HW_HAS_PCI select IRQ_CPU @@ -498,6 +516,7 @@ config SIBYTE_SWARM select SYS_SUPPORTS_HIGHMEM select SYS_SUPPORTS_KGDB select SYS_SUPPORTS_LITTLE_ENDIAN + select ZONE_DMA32 if 64BIT config SIBYTE_LITTLESUR bool "Sibyte BCM91250C2-LittleSur" @@ -548,6 +567,7 @@ config SIBYTE_BIGSUR select SYS_SUPPORTS_BIG_ENDIAN select SYS_SUPPORTS_HIGHMEM select SYS_SUPPORTS_LITTLE_ENDIAN + select ZONE_DMA32 if 64BIT config SNI_RM bool "SNI RM200/300/400" @@ -556,6 +576,7 @@ config SNI_RM select ARCH_MAY_HAVE_PC_FDC select BOOT_ELF32 select CEVT_R4K + select CSRC_R4K select DMA_NONCOHERENT select GENERIC_ISA_DMA select HW_HAS_EISA @@ -599,6 +620,7 @@ config TOSHIBA_JMR3927 config TOSHIBA_RBTX4927 bool "Toshiba RBTX49[23]7 board" select CEVT_R4K + select CSRC_R4K select CEVT_TXX9 select DMA_NONCOHERENT select HAS_TXX9_SERIAL @@ -621,6 +643,7 @@ config TOSHIBA_RBTX4927 config TOSHIBA_RBTX4938 bool "Toshiba RBTX4938 board" select CEVT_R4K + select CSRC_R4K select CEVT_TXX9 select DMA_NONCOHERENT select HAS_TXX9_SERIAL @@ -642,6 +665,7 @@ config TOSHIBA_RBTX4938 config WR_PPMC bool "Wind River PPMC board" select CEVT_R4K + select CSRC_R4K select IRQ_CPU select BOOT_ELF32 select DMA_NONCOHERENT @@ -752,6 +776,9 @@ config CEVT_TXX9 config CSRC_BCM1480 bool +config CSRC_R4K + bool + config CSRC_SB1250 bool @@ -1409,7 +1436,6 @@ config MIPS_MT_SMP depends on SYS_SUPPORTS_MULTITHREADING select CPU_MIPSR2_IRQ_VI select CPU_MIPSR2_IRQ_EI - select CPU_MIPSR2_SRS select MIPS_MT select NR_CPUS_DEFAULT_2 select SMP @@ -1426,7 +1452,6 @@ config MIPS_MT_SMTC select GENERIC_CLOCKEVENTS_BROADCAST select CPU_MIPSR2_IRQ_VI select CPU_MIPSR2_IRQ_EI - select CPU_MIPSR2_SRS select MIPS_MT select NR_CPUS_DEFAULT_8 select SMP @@ -1453,7 +1478,6 @@ config MIPS_VPE_LOADER depends on SYS_SUPPORTS_MULTITHREADING select CPU_MIPSR2_IRQ_VI select CPU_MIPSR2_IRQ_EI - select CPU_MIPSR2_SRS select MIPS_MT help Includes a loader for loading an elf relocatable object @@ -1582,12 +1606,6 @@ config CPU_MIPSR2_IRQ_VI config CPU_MIPSR2_IRQ_EI bool -# -# Shadow registers are an R2 feature -# -config CPU_MIPSR2_SRS - bool - config CPU_HAS_SYNC bool depends on !CPU_R3000 @@ -1649,6 +1667,9 @@ config ARCH_DISCONTIGMEM_ENABLE or have huge holes in the physical address space for other reasons. See <file:Documentation/vm/numa> for more. +config ARCH_POPULATES_NODE_MAP + def_bool y + config ARCH_SPARSEMEM_ENABLE bool select SPARSEMEM_STATIC @@ -1954,6 +1975,9 @@ config I8253 config PCSPEAKER bool +config ZONE_DMA32 + bool + source "drivers/pcmcia/Kconfig" source "drivers/pci/hotplug/Kconfig" diff --git a/arch/mips/Makefile b/arch/mips/Makefile index 23c1775..a1f8d8b 100644 --- a/arch/mips/Makefile +++ b/arch/mips/Makefile @@ -44,7 +44,7 @@ endif ifneq ($(SUBARCH),$(ARCH)) ifeq ($(CROSS_COMPILE),) - CROSS_COMPILE := $(call cc-cross-prefix, $(tool-archpref)-linux- $(tool-archpref)-gnu-linux- $(tool-archpref)-unknown-gnu-linux-) + CROSS_COMPILE := $(call cc-cross-prefix, $(tool-archpref)-linux- $(tool-archpref)-linux-gnu- $(tool-archpref)-unknown-linux-gnu-) endif endif diff --git a/arch/mips/au1000/Kconfig b/arch/mips/au1000/Kconfig index b36cec58..05d1354 100644 --- a/arch/mips/au1000/Kconfig +++ b/arch/mips/au1000/Kconfig @@ -138,6 +138,7 @@ config SOC_AU1X00 bool select 64BIT_PHYS_ADDR select CEVT_R4K + select CSRC_R4K select IRQ_CPU select SYS_HAS_CPU_MIPS32_R1 select SYS_SUPPORTS_32BIT_KERNEL diff --git a/arch/mips/kernel/Makefile b/arch/mips/kernel/Makefile index b551535..ffa0836 100644 --- a/arch/mips/kernel/Makefile +++ b/arch/mips/kernel/Makefile @@ -14,6 +14,7 @@ obj-$(CONFIG_CEVT_GT641XX) += cevt-gt641xx.o obj-$(CONFIG_CEVT_SB1250) += cevt-sb1250.o obj-$(CONFIG_CEVT_TXX9) += cevt-txx9.o obj-$(CONFIG_CSRC_BCM1480) += csrc-bcm1480.o +obj-$(CONFIG_CSRC_R4K) += csrc-r4k.o obj-$(CONFIG_CSRC_SB1250) += csrc-sb1250.o binfmt_irix-objs := irixelf.o irixinv.o irixioctl.o irixsig.o \ @@ -43,6 +44,7 @@ obj-$(CONFIG_CPU_TX49XX) += r4k_fpu.o r4k_switch.o obj-$(CONFIG_CPU_VR41XX) += r4k_fpu.o r4k_switch.o obj-$(CONFIG_SMP) += smp.o +obj-$(CONFIG_SMP_UP) += smp-up.o obj-$(CONFIG_MIPS_MT) += mips-mt.o obj-$(CONFIG_MIPS_MT_FPAFF) += mips-mt-fpaff.o diff --git a/arch/mips/kernel/cevt-bcm1480.c b/arch/mips/kernel/cevt-bcm1480.c index 21e6d63..0a57f86 100644 --- a/arch/mips/kernel/cevt-bcm1480.c +++ b/arch/mips/kernel/cevt-bcm1480.c @@ -75,6 +75,7 @@ static int sibyte_next_event(unsigned long delta, struct clock_event_device *cd) cfg = IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_CFG)); init = IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_INIT)); + __raw_writeq(0, cfg); __raw_writeq(delta - 1, init); __raw_writeq(M_SCD_TIMER_ENABLE, cfg); @@ -122,7 +123,7 @@ void __cpuinit sb1480_clockevent_init(void) CLOCK_EVT_FEAT_ONESHOT; clockevent_set_clock(cd, V_SCD_TIMER_FREQ); cd->max_delta_ns = clockevent_delta2ns(0x7fffff, cd); - cd->min_delta_ns = clockevent_delta2ns(1, cd); + cd->min_delta_ns = clockevent_delta2ns(2, cd); cd->rating = 200; cd->irq = irq; cd->cpumask = cpumask_of_cpu(cpu); @@ -143,7 +144,10 @@ void __cpuinit sb1480_clockevent_init(void) action->handler = sibyte_counter_handler; action->flags = IRQF_DISABLED | IRQF_PERCPU; + action->mask = cpumask_of_cpu(cpu); action->name = name; action->dev_id = cd; + + irq_set_affinity(irq, cpumask_of_cpu(cpu)); setup_irq(irq, action); } diff --git a/arch/mips/kernel/cevt-r4k.c b/arch/mips/kernel/cevt-r4k.c index bab935a..24a2d90 100644 --- a/arch/mips/kernel/cevt-r4k.c +++ b/arch/mips/kernel/cevt-r4k.c @@ -219,7 +219,7 @@ static int c0_compare_int_usable(void) return 1; } -void __cpuinit mips_clockevent_init(void) +int __cpuinit mips_clockevent_init(void) { uint64_t mips_freq = mips_hpt_frequency; unsigned int cpu = smp_processor_id(); @@ -227,7 +227,7 @@ void __cpuinit mips_clockevent_init(void) unsigned int irq; if (!cpu_has_counter || !mips_hpt_frequency) - return; + return -ENXIO; #ifdef CONFIG_MIPS_MT_SMTC setup_smtc_dummy_clockevent_device(); @@ -237,11 +237,11 @@ void __cpuinit mips_clockevent_init(void) * device. */ if (cpu) - return; + return 0; #endif if (!c0_compare_int_usable()) - return; + return -ENXIO; /* * With vectored interrupts things are getting platform specific. @@ -276,8 +276,8 @@ void __cpuinit mips_clockevent_init(void) clockevents_register_device(cd); - if (!cp0_timer_irq_installed) - return; + if (cp0_timer_irq_installed) + return 0; cp0_timer_irq_installed = 1; @@ -287,4 +287,6 @@ void __cpuinit mips_clockevent_init(void) #else setup_irq(irq, &c0_compare_irqaction); #endif + + return 0; } diff --git a/arch/mips/kernel/cevt-sb1250.c b/arch/mips/kernel/cevt-sb1250.c index e2029d0..63ac3ad 100644 --- a/arch/mips/kernel/cevt-sb1250.c +++ b/arch/mips/kernel/cevt-sb1250.c @@ -73,6 +73,7 @@ static int sibyte_next_event(unsigned long delta, struct clock_event_device *cd) cfg = IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_CFG)); init = IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_INIT)); + __raw_writeq(0, cfg); __raw_writeq(delta - 1, init); __raw_writeq(M_SCD_TIMER_ENABLE, cfg); @@ -121,7 +122,7 @@ void __cpuinit sb1250_clockevent_init(void) CLOCK_EVT_FEAT_ONESHOT; clockevent_set_clock(cd, V_SCD_TIMER_FREQ); cd->max_delta_ns = clockevent_delta2ns(0x7fffff, cd); - cd->min_delta_ns = clockevent_delta2ns(1, cd); + cd->min_delta_ns = clockevent_delta2ns(2, cd); cd->rating = 200; cd->irq = irq; cd->cpumask = cpumask_of_cpu(cpu); @@ -142,7 +143,10 @@ void __cpuinit sb1250_clockevent_init(void) action->handler = sibyte_counter_handler; action->flags = IRQF_DISABLED | IRQF_PERCPU; + action->mask = cpumask_of_cpu(cpu); action->name = name; action->dev_id = cd; + + irq_set_affinity(irq, cpumask_of_cpu(cpu)); setup_irq(irq, action); } diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c index c8c47a2..5c27943 100644 --- a/arch/mips/kernel/cpu-probe.c +++ b/arch/mips/kernel/cpu-probe.c @@ -943,6 +943,11 @@ __init void cpu_probe(void) } __cpu_name[cpu] = cpu_to_name(c); + + if (cpu_has_mips_r2) + c->srsets = ((read_c0_srsctl() >> 26) & 0x0f) + 1; + else + c->srsets = 1; } __init void cpu_report(void) diff --git a/arch/mips/kernel/csrc-r4k.c b/arch/mips/kernel/csrc-r4k.c new file mode 100644 index 0000000..0e2b5cd --- /dev/null +++ b/arch/mips/kernel/csrc-r4k.c @@ -0,0 +1,33 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 2007 by Ralf Baechle + */ +#include <linux/clocksource.h> +#include <linux/init.h> + +#include <asm/time.h> + +static cycle_t c0_hpt_read(void) +{ + return read_c0_count(); +} + +static struct clocksource clocksource_mips = { + .name = "MIPS", + .read = c0_hpt_read, + .mask = CLOCKSOURCE_MASK(32), + .flags = CLOCK_SOURCE_IS_CONTINUOUS, +}; + +void __init init_mips_clocksource(void) +{ + /* Calclate a somewhat reasonable rating value */ + clocksource_mips.rating = 200 + mips_hpt_frequency / 10000000; + + clocksource_set_clock(&clocksource_mips, mips_hpt_frequency); + + clocksource_register(&clocksource_mips); +} diff --git a/arch/mips/kernel/csrc-sb1250.c b/arch/mips/kernel/csrc-sb1250.c index ebb16e6..92212bb 100644 --- a/arch/mips/kernel/csrc-sb1250.c +++ b/arch/mips/kernel/csrc-sb1250.c @@ -43,7 +43,7 @@ static cycle_t sb1250_hpt_read(void) } struct clocksource bcm1250_clocksource = { - .name = "MIPS", + .name = "bcm1250-counter-3", .rating = 200, .read = sb1250_hpt_read, .mask = CLOCKSOURCE_MASK(23), diff --git a/arch/mips/kernel/genex.S b/arch/mips/kernel/genex.S index c0f19d6..e76a76b 100644 --- a/arch/mips/kernel/genex.S +++ b/arch/mips/kernel/genex.S @@ -146,7 +146,7 @@ NESTED(handle_int, PT_SIZE, sp) and k0, ST0_IEP bnez k0, 1f - mfc0 k0, EP0_EPC + mfc0 k0, CP0_EPC .set noreorder j k0 rfe diff --git a/arch/mips/kernel/irixsig.c b/arch/mips/kernel/irixsig.c index 33506ff..5b10ac1 100644 --- a/arch/mips/kernel/irixsig.c +++ b/arch/mips/kernel/irixsig.c @@ -430,6 +430,7 @@ asmlinkage int irix_sigprocmask(int how, irix_sigset_t __user *new, break; default: + spin_unlock_irq(¤t->sighand->siglock); return -EINVAL; } recalc_sigpending(); diff --git a/arch/mips/kernel/irq-rm7000.c b/arch/mips/kernel/irq-rm7000.c index 2507328..971adf6 100644 --- a/arch/mips/kernel/irq-rm7000.c +++ b/arch/mips/kernel/irq-rm7000.c @@ -44,5 +44,5 @@ void __init rm7k_cpu_irq_init(void) for (i = base; i < base + 4; i++) set_irq_chip_and_handler(i, &rm7k_irq_controller, - handle_level_irq); + handle_percpu_irq); } diff --git a/arch/mips/kernel/irq-rm9000.c b/arch/mips/kernel/irq-rm9000.c index ae83d2d..7b04583 100644 --- a/arch/mips/kernel/irq-rm9000.c +++ b/arch/mips/kernel/irq-rm9000.c @@ -104,5 +104,5 @@ void __init rm9k_cpu_irq_init(void) rm9000_perfcount_irq = base + 1; set_irq_chip_and_handler(rm9000_perfcount_irq, &rm9k_perfcounter_irq, - handle_level_irq); + handle_percpu_irq); } diff --git a/arch/mips/kernel/irq_cpu.c b/arch/mips/kernel/irq_cpu.c index 7b66e03..0ee2567 100644 --- a/arch/mips/kernel/irq_cpu.c +++ b/arch/mips/kernel/irq_cpu.c @@ -116,5 +116,5 @@ void __init mips_cpu_irq_init(void) for (i = irq_base + 2; i < irq_base + 8; i++) set_irq_chip_and_handler(i, &mips_cpu_irq_controller, - handle_level_irq); + handle_percpu_irq); } diff --git a/arch/mips/kernel/proc.c b/arch/mips/kernel/proc.c index efd2d13..6e6e947 100644 --- a/arch/mips/kernel/proc.c +++ b/arch/mips/kernel/proc.c @@ -60,6 +60,8 @@ static int show_cpuinfo(struct seq_file *m, void *v) cpu_has_dsp ? " dsp" : "", cpu_has_mipsmt ? " mt" : "" ); + seq_printf(m, "shadow register sets\t: %d\n", + cpu_data[n].srsets); sprintf(fmt, "VCE%%c exceptions\t\t: %s\n", cpu_has_vce ? "%u" : "not available"); diff --git a/arch/mips/kernel/scall64-n32.S b/arch/mips/kernel/scall64-n32.S index 118be24..01993ec 100644 --- a/arch/mips/kernel/scall64-n32.S +++ b/arch/mips/kernel/scall64-n32.S @@ -293,7 +293,7 @@ EXPORT(sysn32_call_table) PTR sys_ni_syscall /* 6170, was get_kernel_syms */ PTR sys_ni_syscall /* was query_module */ PTR sys_quotactl - PTR sys_nfsservctl + PTR compat_sys_nfsservctl PTR sys_ni_syscall /* res. for getpmsg */ PTR sys_ni_syscall /* 6175 for putpmsg */ PTR sys_ni_syscall /* res. for afs_syscall */ diff --git a/arch/mips/kernel/setup.c b/arch/mips/kernel/setup.c index a06a27d..7f6ddcb 100644 --- a/arch/mips/kernel/setup.c +++ b/arch/mips/kernel/setup.c @@ -269,7 +269,7 @@ static void __init bootmem_init(void) static void __init bootmem_init(void) { - unsigned long reserved_end; + unsigned long init_begin, reserved_end; unsigned long mapstart = ~0UL; unsigned long bootmap_size; int i; @@ -342,6 +342,35 @@ static void __init bootmem_init(void) */ bootmap_size = init_bootmem_node(NODE_DATA(0), mapstart, min_low_pfn, max_low_pfn); + + + init_begin = PFN_UP(__pa_symbol(&__init_begin)); + for (i = 0; i < boot_mem_map.nr_map; i++) { + unsigned long start, end; + + start = PFN_UP(boot_mem_map.map[i].addr); + end = PFN_DOWN(boot_mem_map.map[i].addr + + boot_mem_map.map[i].size); + + if (start <= init_begin) + start = init_begin; + if (start >= end) + continue; + +#ifndef CONFIG_HIGHMEM + if (end > max_low_pfn) + end = max_low_pfn; + + /* + * ... finally, is the area going away? + */ + if (end <= start) + continue; +#endif + + add_active_range(0, start, end); + } + /* * Register fully available low RAM pages with the bootmem allocator. */ diff --git a/arch/mips/kernel/smp-up.c b/arch/mips/kernel/smp-up.c new file mode 100644 index 0000000..ead6c30 --- /dev/null +++ b/arch/mips/kernel/smp-up.c @@ -0,0 +1,67 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 2006, 07 by Ralf Baechle (ralf@linux-mips.org) + * + * Symmetric Uniprocessor (TM) Support + */ +#include <linux/kernel.h> +#include <linux/sched.h> + +/* + * Send inter-processor interrupt + */ +void up_send_ipi_single(int cpu, unsigned int action) +{ + panic(KERN_ERR "%s called", __func__); +} + +static inline void up_send_ipi_mask(cpumask_t mask, unsigned int action) +{ + panic(KERN_ERR "%s called", __func__); +} + +/* + * After we've done initial boot, this function is called to allow the + * board code to clean up state, if needed + */ +void __cpuinit up_init_secondary(void) +{ +} + +void __cpuinit up_smp_finish(void) +{ +} + +/* Hook for after all CPUs are online */ +void up_cpus_done(void) +{ +} + +/* + * Firmware CPU startup hook + */ +void __cpuinit up_boot_secondary(int cpu, struct task_struct *idle) +{ +} + +void __init up_smp_setup(void) +{ +} + +void __init up_prepare_cpus(unsigned int max_cpus) +{ +} + +struct plat_smp_ops up_smp_ops = { + .send_ipi_single = up_send_ipi_single, + .send_ipi_mask = up_send_ipi_mask, + .init_secondary = up_init_secondary, + .smp_finish = up_smp_finish, + .cpus_done = up_cpus_done, + .boot_secondary = up_boot_secondary, + .smp_setup = up_smp_setup, + .prepare_cpus = up_prepare_cpus, +}; diff --git a/arch/mips/kernel/time.c b/arch/mips/kernel/time.c index 3284b9b..5207542 100644 --- a/arch/mips/kernel/time.c +++ b/arch/mips/kernel/time.c @@ -50,14 +50,6 @@ int update_persistent_clock(struct timespec now) return rtc_mips_set_mmss(now.tv_sec); } -/* - * High precision timer functions for a R4k-compatible timer. - */ -static cycle_t c0_hpt_read(void) -{ - return read_c0_count(); -} - int (*mips_timer_state)(void); int null_perf_irq(void) @@ -84,55 +76,6 @@ EXPORT_SYMBOL(perf_irq); unsigned int mips_hpt_frequency; -static struct clocksource clocksource_mips = { - .name = "MIPS", - .read = c0_hpt_read, - .mask = CLOCKSOURCE_MASK(32), - .flags = CLOCK_SOURCE_IS_CONTINUOUS, -}; - -static unsigned int __init calibrate_hpt(void) -{ - cycle_t frequency, hpt_start, hpt_end, hpt_count, hz; - - const int loops = HZ / 10; - int log_2_loops = 0; - int i; - - /* - * We want to calibrate for 0.1s, but to avoid a 64-bit - * division we round the number of loops up to the nearest - * power of 2. - */ - while (loops > 1 << log_2_loops) - log_2_loops++; - i = 1 << log_2_loops; - - /* - * Wait for a rising edge of the timer interrupt. - */ - while (mips_timer_state()); - while (!mips_timer_state()); - - /* - * Now see how many high precision timer ticks happen - * during the calculated number of periods between timer - * interrupts. - */ - hpt_start = clocksource_mips.read(); - do { - while (mips_timer_state()); - while (!mips_timer_state()); - } while (--i); - hpt_end = clocksource_mips.read(); - - hpt_count = (hpt_end - hpt_start) & clocksource_mips.mask; - hz = HZ; - frequency = hpt_count * hz; - - return frequency >> log_2_loops; -} - void __init clocksource_set_clock(struct clocksource *cs, unsigned int clock) { u64 temp; @@ -166,16 +109,6 @@ void __cpuinit clockevent_set_clock(struct clock_event_device *cd, cd->mult = (u32) temp; } -static void __init init_mips_clocksource(void) -{ - /* Calclate a somewhat reasonable rating value */ - clocksource_mips.rating = 200 + mips_hpt_frequency / 10000000; - - clocksource_set_clock(&clocksource_mips, mips_hpt_frequency); - - clocksource_register(&clocksource_mips); -} - void __init __weak plat_time_init(void) { } @@ -194,21 +127,42 @@ void __init plat_timer_setup(void) BUG(); } +static __init int cpu_has_mfc0_count_bug(void) +{ + switch (current_cpu_type()) { + case CPU_R4000PC: + case CPU_R4000SC: + case CPU_R4000MC: + /* + * V3.0 is documented as suffering from the mfc0 from count bug. + * Afaik this is the last version of the R4000. Later versions + * were marketed as R4400. + */ + return 1; + + case CPU_R4400PC: + case CPU_R4400SC: + case CPU_R4400MC: + /* + * The published errata for the R4400 upto 3.0 say the CPU + * has the mfc0 from count bug. + */ + if ((current_cpu_data.processor_id & 0xff) <= 0x30) + return 1; + + /* + * I don't have erratas for newer R4400 so be paranoid. + */ + return 1; + } + + return 0; +} + void __init time_init(void) { plat_time_init(); - if (cpu_has_counter && (mips_hpt_frequency || mips_timer_state)) { - /* We know counter frequency. Or we can get it. */ - if (!mips_hpt_frequency) - mips_hpt_frequency = calibrate_hpt(); - - /* Report the high precision timer rate for a reference. */ - printk("Using %u.%03u MHz high precision timer.\n", - ((mips_hpt_frequency + 500) / 1000) / 1000, - ((mips_hpt_frequency + 500) / 1000) % 1000); + if (mips_clockevent_init() || !cpu_has_mfc0_count_bug()) init_mips_clocksource(); - } - - mips_clockevent_init(); } diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c index fa50078..23e73d0 100644 --- a/arch/mips/kernel/traps.c +++ b/arch/mips/kernel/traps.c @@ -1100,59 +1100,6 @@ void *set_except_vector(int n, void *addr) return (void *)old_handler; } -#ifdef CONFIG_CPU_MIPSR2_SRS -/* - * MIPSR2 shadow register set allocation - * FIXME: SMP... - */ - -static struct shadow_registers { - /* - * Number of shadow register sets supported - */ - unsigned long sr_supported; - /* - * Bitmap of allocated shadow registers - */ - unsigned long sr_allocated; -} shadow_registers; - -static void mips_srs_init(void) -{ - shadow_registers.sr_supported = ((read_c0_srsctl() >> 26) & 0x0f) + 1; - printk(KERN_INFO "%ld MIPSR2 register sets available\n", - shadow_registers.sr_supported); - shadow_registers.sr_allocated = 1; /* Set 0 used by kernel */ -} - -int mips_srs_max(void) -{ - return shadow_registers.sr_supported; -} - -int mips_srs_alloc(void) -{ - struct shadow_registers *sr = &shadow_registers; - int set; - -again: - set = find_first_zero_bit(&sr->sr_allocated, sr->sr_supported); - if (set >= sr->sr_supported) - return -1; - - if (test_and_set_bit(set, &sr->sr_allocated)) - goto again; - - return set; -} - -void mips_srs_free(int set) -{ - struct shadow_registers *sr = &shadow_registers; - - clear_bit(set, &sr->sr_allocated); -} - static asmlinkage void do_default_vi(void) { show_regs(get_irq_regs()); @@ -1163,6 +1110,7 @@ static void *set_vi_srs_handler(int n, vi_handler_t addr, int srs) { unsigned long handler; unsigned long old_handler = vi_handlers[n]; + int srssets = current_cpu_data.srsets; u32 *w; unsigned char *b; @@ -1178,7 +1126,7 @@ static void *set_vi_srs_handler(int n, vi_handler_t addr, int srs) b = (unsigned char *)(ebase + 0x200 + n*VECTORSPACING); - if (srs >= mips_srs_max()) + if (srs >= srssets) panic("Shadow register set %d not supported", srs); if (cpu_has_veic) { @@ -1186,7 +1134,7 @@ static void *set_vi_srs_handler(int n, vi_handler_t addr, int srs) board_bind_eic_interrupt(n, srs); } else if (cpu_has_vint) { /* SRSMap is only defined if shadow sets are implemented */ - if (mips_srs_max() > 1) + if (srssets > 1) change_c0_srsmap(0xf << n*4, srs << n*4); } @@ -1253,14 +1201,6 @@ void *set_vi_handler(int n, vi_handler_t addr) return set_vi_srs_handler(n, addr, 0); } -#else - -static inline void mips_srs_init(void) -{ -} - -#endif /* CONFIG_CPU_MIPSR2_SRS */ - /* * This is used by native signal handling */ @@ -1503,8 +1443,6 @@ void __init trap_init(void) else ebase = CAC_BASE; - mips_srs_init(); - per_cpu_trap_init(); /* diff --git a/arch/mips/kernel/vpe.c b/arch/mips/kernel/vpe.c index 436a64f..c06eb81 100644 --- a/arch/mips/kernel/vpe.c +++ b/arch/mips/kernel/vpe.c @@ -470,7 +470,7 @@ static int apply_r_mips_lo16(struct module *me, uint32_t *location, */ if (v != l->value) { printk(KERN_DEBUG "VPE loader: " - "apply_r_mips_lo16/hi16: " + "apply_r_mips_lo16/hi16: \t" "inconsistent value information\n"); return -ENOEXEC; } @@ -629,7 +629,7 @@ static void simplify_symbols(Elf_Shdr * sechdrs, break; case SHN_MIPS_SCOMMON: - printk(KERN_DEBUG "simplify_symbols: ignoring SHN_MIPS_SCOMMON" + printk(KERN_DEBUG "simplify_symbols: ignoring SHN_MIPS_SCOMMON " "symbol <%s> st_shndx %d\n", strtab + sym[i].st_name, sym[i].st_shndx); // .sbss section @@ -1003,6 +1003,7 @@ static void cleanup_tc(struct tc *tc) write_tc_c0_tcstatus(tmp); write_tc_c0_tchalt(TCHALT_H); + mips_ihb(); /* bind it to anything other than VPE1 */ // write_tc_c0_tcbind(read_tc_c0_tcbind() & ~TCBIND_CURVPE); // | TCBIND_CURVPE @@ -1235,9 +1236,12 @@ int vpe_free(vpe_handle vpe) settc(t->index); write_vpe_c0_vpeconf0(read_vpe_c0_vpeconf0() & ~VPECONF0_VPA); - /* mark the TC unallocated and halt'ed */ - write_tc_c0_tcstatus(read_tc_c0_tcstatus() & ~TCSTATUS_A); + /* halt the TC */ write_tc_c0_tchalt(TCHALT_H); + mips_ihb(); + + /* mark the TC unallocated */ + write_tc_c0_tcstatus(read_tc_c0_tcstatus() & ~TCSTATUS_A); v->state = VPE_STATE_UNUSED; @@ -1533,14 +1537,16 @@ static int __init vpe_module_init(void) t->pvpe = get_vpe(0); /* set the parent vpe */ } + /* halt the TC */ + write_tc_c0_tchalt(TCHALT_H); + mips_ihb(); + tmp = read_tc_c0_tcstatus(); /* mark not activated and not dynamically allocatable */ tmp &= ~(TCSTATUS_A | TCSTATUS_DA); tmp |= TCSTATUS_IXMT; /* interrupt exempt */ write_tc_c0_tcstatus(tmp); - - write_tc_c0_tchalt(TCHALT_H); } } diff --git a/arch/mips/lasat/interrupt.c b/arch/mips/lasat/interrupt.c index ba9692b..cfeab66 100644 --- a/arch/mips/lasat/interrupt.c +++ b/arch/mips/lasat/interrupt.c @@ -19,17 +19,14 @@ * Lasat boards. */ #include <linux/init.h> -#include <linux/irq.h> -#include <linux/sched.h> -#include <linux/slab.h> #include <linux/interrupt.h> -#include <linux/kernel_stat.h> +#include <linux/irq.h> #include <asm/bootinfo.h> #include <asm/irq_cpu.h> #include <asm/lasat/lasatint.h> -#include <asm/time.h> -#include <asm/gdb-stub.h> + +#include <irq.h> static volatile int *lasat_int_status; static volatile int *lasat_int_mask; @@ -97,12 +94,18 @@ asmlinkage void plat_irq_dispatch(void) /* if int_status == 0, then the interrupt has already been cleared */ if (int_status) { - irq = LASATINT_BASE + ls1bit32(int_status); + irq = LASAT_IRQ_BASE + ls1bit32(int_status); do_IRQ(irq); } } +static struct irqaction cascade = { + .handler = no_action, + .mask = CPU_MASK_NONE, + .name = "cascade", +}; + void __init arch_init_irq(void) { int i; @@ -127,6 +130,9 @@ void __init arch_init_irq(void) } mips_cpu_irq_init(); - for (i = LASATINT_BASE; i <= LASATINT_END; i++) + + for (i = LASAT_IRQ_BASE; i <= LASAT_IRQ_END; i++) set_irq_chip_and_handler(i, &lasat_irq_type, handle_level_irq); + + setup_irq(LASAT_CASCADE_IRQ, &cascade); } diff --git a/arch/mips/math-emu/ieee754.c b/arch/mips/math-emu/ieee754.c index 946aee3..cb1b682 100644 --- a/arch/mips/math-emu/ieee754.c +++ b/arch/mips/math-emu/ieee754.c @@ -108,6 +108,7 @@ int ieee754si_xcpt(int r, const char *op, ...) ax.rv.si = r; va_start(ax.ap, op); ieee754_xcpt(&ax); + va_end(ax.ap); return ax.rv.si; } @@ -122,5 +123,6 @@ s64 ieee754di_xcpt(s64 r, const char *op, ...) ax.rv.di = r; va_start(ax.ap, op); ieee754_xcpt(&ax); + va_end(ax.ap); return ax.rv.di; } diff --git a/arch/mips/math-emu/ieee754dp.c b/arch/mips/math-emu/ieee754dp.c index 3e214aa..6d2d89f 100644 --- a/arch/mips/math-emu/ieee754dp.c +++ b/arch/mips/math-emu/ieee754dp.c @@ -57,6 +57,7 @@ ieee754dp ieee754dp_xcpt(ieee754dp r, const char *op, ...) ax.rv.dp = r; va_start(ax.ap, op); ieee754_xcpt(&ax); + va_end(ax.ap); return ax.rv.dp; } @@ -83,6 +84,7 @@ ieee754dp ieee754dp_nanxcpt(ieee754dp r, const char *op, ...) ax.rv.dp = r; va_start(ax.ap, op); ieee754_xcpt(&ax); + va_end(ax.ap); return ax.rv.dp; } diff --git a/arch/mips/math-emu/ieee754sp.c b/arch/mips/math-emu/ieee754sp.c index adda851..4635340 100644 --- a/arch/mips/math-emu/ieee754sp.c +++ b/arch/mips/math-emu/ieee754sp.c @@ -58,6 +58,7 @@ ieee754sp ieee754sp_xcpt(ieee754sp r, const char *op, ...) ax.rv.sp = r; va_start(ax.ap, op); ieee754_xcpt(&ax); + va_end(ax.ap); return ax.rv.sp; } @@ -84,6 +85,7 @@ ieee754sp ieee754sp_nanxcpt(ieee754sp r, const char *op, ...) ax.rv.sp = r; va_start(ax.ap, op); ieee754_xcpt(&ax); + va_end(ax.ap); return ax.rv.sp; } diff --git a/arch/mips/mipssim/sim_time.c b/arch/mips/mipssim/sim_time.c index bfaafa3..e39bbe9 100644 --- a/arch/mips/mipssim/sim_time.c +++ b/arch/mips/mipssim/sim_time.c @@ -101,9 +101,7 @@ unsigned __init get_c0_compare_int(void) void __init plat_time_init(void) { - unsigned int est_freq, flags; - - local_irq_save(flags); + unsigned int est_freq; /* Set Data mode - binary. */ CMOS_WRITE(CMOS_READ(RTC_CONTROL) | RTC_DM_BINARY, RTC_CONTROL); @@ -114,6 +112,4 @@ void __init plat_time_init(void) (est_freq % 1000000) * 100 / 1000000); cpu_khz = est_freq / 1000; - - local_irq_restore(flags); } diff --git a/arch/mips/mm/c-r4k.c b/arch/mips/mm/c-r4k.c index 6806d58..9355f1c 100644 --- a/arch/mips/mm/c-r4k.c +++ b/arch/mips/mm/c-r4k.c @@ -7,6 +7,7 @@ * Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 Ralf Baechle (ralf@gnu.org) * Copyright (C) 1999, 2000 Silicon Graphics, Inc. */ +#include <linux/hardirq.h> #include <linux/init.h> #include <linux/highmem.h> #include <linux/kernel.h> @@ -507,7 +508,11 @@ static inline void local_r4k_flush_data_cache_page(void * addr) static void r4k_flush_data_cache_page(unsigned long addr) { - r4k_on_each_cpu(local_r4k_flush_data_cache_page, (void *) addr, 1, 1); + if (in_atomic()) + local_r4k_flush_data_cache_page((void *)addr); + else + r4k_on_each_cpu(local_r4k_flush_data_cache_page, (void *) addr, + 1, 1); } struct flush_icache_range_args { diff --git a/arch/mips/mm/cerr-sb1.c b/arch/mips/mm/cerr-sb1.c index e7f539e3..1bd1f18 100644 --- a/arch/mips/mm/cerr-sb1.c +++ b/arch/mips/mm/cerr-sb1.c @@ -154,7 +154,7 @@ static void check_bus_watcher(void) if (status & ~(1UL << 31)) { l2_err = csr_in32(IOADDR(A_BUS_L2_ERRORS)); #ifdef DUMP_L2_ECC_TAG_ON_ERROR - l2_tag = in64(IO_SPACE_BASE | A_L2_ECC_TAG); + l2_tag = in64(IOADDR(A_L2_ECC_TAG)); #endif memio_err = csr_in32(IOADDR(A_BUS_MEM_IO_ERRORS)); printk("Bus watcher error counters: %08x %08x\n", l2_err, memio_err); @@ -183,9 +183,9 @@ asmlinkage void sb1_cache_error(void) #ifdef CONFIG_SIBYTE_BW_TRACE /* Freeze the trace buffer now */ #if defined(CONFIG_SIBYTE_BCM1x55) || defined(CONFIG_SIBYTE_BCM1x80) - csr_out32(M_BCM1480_SCD_TRACE_CFG_FREEZE, IO_SPACE_BASE | A_SCD_TRACE_CFG); + csr_out32(M_BCM1480_SCD_TRACE_CFG_FREEZE, IOADDR(A_SCD_TRACE_CFG)); #else - csr_out32(M_SCD_TRACE_CFG_FREEZE, IO_SPACE_BASE | A_SCD_TRACE_CFG); + csr_out32(M_SCD_TRACE_CFG_FREEZE, IOADDR(A_SCD_TRACE_CFG)); #endif printk("Trace buffer frozen\n"); #endif diff --git a/arch/mips/mm/dma-default.c b/arch/mips/mm/dma-default.c index 33519ce..ae76795 100644 --- a/arch/mips/mm/dma-default.c +++ b/arch/mips/mm/dma-default.c @@ -40,16 +40,38 @@ static inline int cpu_is_noncoherent_r10000(struct device *dev) current_cpu_type() == CPU_R12000); } +static gfp_t massage_gfp_flags(const struct device *dev, gfp_t gfp) +{ + /* ignore region specifiers */ + gfp &= ~(__GFP_DMA | __GFP_DMA32 | __GFP_HIGHMEM); + +#ifdef CONFIG_ZONE_DMA32 + if (dev == NULL) + gfp |= __GFP_DMA; + else if (dev->coherent_dma_mask < DMA_BIT_MASK(24)) + gfp |= __GFP_DMA; + else +#endif +#ifdef CONFIG_ZONE_DMA32 + if (dev->coherent_dma_mask < DMA_BIT_MASK(32)) + gfp |= __GFP_DMA32; + else +#endif + ; + + /* Don't invoke OOM killer */ + gfp |= __GFP_NORETRY; + + return gfp; +} + void *dma_alloc_noncoherent(struct device *dev, size_t size, dma_addr_t * dma_handle, gfp_t gfp) { void *ret; - /* ignore region specifiers */ - gfp &= ~(__GFP_DMA | __GFP_HIGHMEM); + gfp = massage_gfp_flags(dev, gfp); - if (dev == NULL || (dev->coherent_dma_mask < 0xffffffff)) - gfp |= GFP_DMA; ret = (void *) __get_free_pages(gfp, get_order(size)); if (ret != NULL) { @@ -67,11 +89,8 @@ void *dma_alloc_coherent(struct device *dev, size_t size, { void *ret; - /* ignore region specifiers */ - gfp &= ~(__GFP_DMA | __GFP_HIGHMEM); + gfp = massage_gfp_flags(dev, gfp); - if (dev == NULL || (dev->coherent_dma_mask < 0xffffffff)) - gfp |= GFP_DMA; ret = (void *) __get_free_pages(gfp, get_order(size)); if (ret) { @@ -343,7 +362,7 @@ int dma_supported(struct device *dev, u64 mask) * so we can't guarantee allocations that must be * within a tighter range than GFP_DMA.. */ - if (mask < 0x00ffffff) + if (mask < DMA_BIT_MASK(24)) return 0; return 1; diff --git a/arch/mips/mm/init.c b/arch/mips/mm/init.c index 110ee76..480dec0 100644 --- a/arch/mips/mm/init.c +++ b/arch/mips/mm/init.c @@ -347,11 +347,8 @@ static int __init page_is_ram(unsigned long pagenr) void __init paging_init(void) { - unsigned long zones_size[MAX_NR_ZONES] = { 0, }; -#ifndef CONFIG_FLATMEM - unsigned long zholes_size[MAX_NR_ZONES] = { 0, }; - unsigned long i, j, pfn; -#endif + unsigned long max_zone_pfns[MAX_NR_ZONES]; + unsigned long lastpfn; pagetable_init(); @@ -361,35 +358,27 @@ void __init paging_init(void) kmap_coherent_init(); #ifdef CONFIG_ZONE_DMA - if (min_low_pfn < MAX_DMA_PFN && MAX_DMA_PFN <= max_low_pfn) { - zones_size[ZONE_DMA] = MAX_DMA_PFN - min_low_pfn; - zones_size[ZONE_NORMAL] = max_low_pfn - MAX_DMA_PFN; - } else if (max_low_pfn < MAX_DMA_PFN) - zones_size[ZONE_DMA] = max_low_pfn - min_low_pfn; - else + max_zone_pfns[ZONE_DMA] = MAX_DMA_PFN; #endif - zones_size[ZONE_NORMAL] = max_low_pfn - min_low_pfn; - +#ifdef CONFIG_ZONE_DMA32 + max_zone_pfns[ZONE_DMA32] = MAX_DMA32_PFN; +#endif + max_zone_pfns[ZONE_NORMAL] = max_low_pfn; + lastpfn = max_low_pfn; #ifdef CONFIG_HIGHMEM - zones_size[ZONE_HIGHMEM] = highend_pfn - highstart_pfn; + max_zone_pfns[ZONE_HIGHMEM] = highend_pfn; + lastpfn = highend_pfn; - if (cpu_has_dc_aliases && zones_size[ZONE_HIGHMEM]) { + if (cpu_has_dc_aliases && max_low_pfn != highend_pfn) { printk(KERN_WARNING "This processor doesn't support highmem." - " %ldk highmem ignored\n", zones_size[ZONE_HIGHMEM]); - zones_size[ZONE_HIGHMEM] = 0; + " %ldk highmem ignored\n", + (highend_pfn - max_low_pfn) << (PAGE_SHIFT - 10)); + max_zone_pfns[ZONE_HIGHMEM] = max_low_pfn; + lastpfn = max_low_pfn; } #endif -#ifdef CONFIG_FLATMEM - free_area_init(zones_size); -#else - pfn = min_low_pfn; - for (i = 0; i < MAX_NR_ZONES; i++) - for (j = 0; j < zones_size[i]; j++, pfn++) - if (!page_is_ram(pfn)) - zholes_size[i]++; - free_area_init_node(0, NODE_DATA(0), zones_size, 0, zholes_size); -#endif + free_area_init_nodes(max_zone_pfns); } static struct kcore_list kcore_mem, kcore_vmalloc; @@ -426,7 +415,7 @@ void __init mem_init(void) #ifdef CONFIG_HIGHMEM for (tmp = highstart_pfn; tmp < highend_pfn; tmp++) { - struct page *page = mem_map + tmp; + struct page *page = pfn_to_page(tmp); if (!page_is_ram(tmp)) { SetPageReserved(page); diff --git a/arch/mips/pci/fixup-sni.c b/arch/mips/pci/fixup-sni.c index a45bedd..5c8a79b 100644 --- a/arch/mips/pci/fixup-sni.c +++ b/arch/mips/pci/fixup-sni.c @@ -113,6 +113,16 @@ static char irq_tab_pcit[13][5] __initdata = { { 0, INTA, INTB, INTC, INTD }, /* Slot 5 */ }; +static char irq_tab_pcit_cplus[13][5] __initdata = { + /* INTA INTB INTC INTD */ + { 0, 0, 0, 0, 0 }, /* HOST bridge */ + { 0, INTB, INTC, INTD, INTA }, /* PCI Slot 9 */ + { 0, 0, 0, 0, 0 }, /* PCI-EISA */ + { 0, 0, 0, 0, 0 }, /* Unused */ + { 0, INTA, INTB, INTC, INTD }, /* PCI-PCI bridge */ + { 0, INTB, INTC, INTD, INTA }, /* fixup */ +}; + static inline int is_rm300_revd(void) { unsigned char csmsr = *(volatile unsigned char *)PCIMT_CSMSR; @@ -123,8 +133,19 @@ static inline int is_rm300_revd(void) int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) { switch (sni_brd_type) { - case SNI_BRD_PCI_TOWER: case SNI_BRD_PCI_TOWER_CPLUS: + if (slot == 4) { + /* + * SNI messed up interrupt wiring for onboard + * PCI bus 1; we need to fix this up here + */ + while (dev && dev->bus->number != 1) + dev = dev->bus->self; + if (dev && dev->devfn >= PCI_DEVFN(4, 0)) + slot = 5; + } + return irq_tab_pcit_cplus[slot][pin]; + case SNI_BRD_PCI_TOWER: return irq_tab_pcit[slot][pin]; case SNI_BRD_PCI_MTOWER: diff --git a/arch/mips/pci/pci-lasat.c b/arch/mips/pci/pci-lasat.c index 174f314..e70ae32 100644 --- a/arch/mips/pci/pci-lasat.c +++ b/arch/mips/pci/pci-lasat.c @@ -5,12 +5,14 @@ * * Copyright (C) 2000, 2001, 04 Keith M Wesolowski */ -#include <linux/kernel.h> #include <linux/init.h> +#include <linux/kernel.h> #include <linux/pci.h> #include <linux/types.h> + #include <asm/bootinfo.h> -#include <asm/lasat/lasatint.h> + +#include <irq.h> extern struct pci_ops nile4_pci_ops; extern struct pci_ops gt64xxx_pci0_ops; @@ -55,15 +57,15 @@ static int __init lasat_pci_setup(void) arch_initcall(lasat_pci_setup); -#define LASATINT_ETH1 (LASATINT_BASE + 0) -#define LASATINT_ETH0 (LASATINT_BASE + 1) -#define LASATINT_HDC (LASATINT_BASE + 2) -#define LASATINT_COMP (LASATINT_BASE + 3) -#define LASATINT_HDLC (LASATINT_BASE + 4) -#define LASATINT_PCIA (LASATINT_BASE + 5) -#define LASATINT_PCIB (LASATINT_BASE + 6) -#define LASATINT_PCIC (LASATINT_BASE + 7) -#define LASATINT_PCID (LASATINT_BASE + 8) +#define LASAT_IRQ_ETH1 (LASAT_IRQ_BASE + 0) +#define LASAT_IRQ_ETH0 (LASAT_IRQ_BASE + 1) +#define LASAT_IRQ_HDC (LASAT_IRQ_BASE + 2) +#define LASAT_IRQ_COMP (LASAT_IRQ_BASE + 3) +#define LASAT_IRQ_HDLC (LASAT_IRQ_BASE + 4) +#define LASAT_IRQ_PCIA (LASAT_IRQ_BASE + 5) +#define LASAT_IRQ_PCIB (LASAT_IRQ_BASE + 6) +#define LASAT_IRQ_PCIC (LASAT_IRQ_BASE + 7) +#define LASAT_IRQ_PCID (LASAT_IRQ_BASE + 8) int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) { @@ -71,13 +73,13 @@ int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) case 1: case 2: case 3: - return LASATINT_PCIA + (((slot-1) + (pin-1)) % 4); + return LASAT_IRQ_PCIA + (((slot-1) + (pin-1)) % 4); case 4: - return LASATINT_ETH1; /* Ethernet 1 (LAN 2) */ + return LASAT_IRQ_ETH1; /* Ethernet 1 (LAN 2) */ case 5: - return LASATINT_ETH0; /* Ethernet 0 (LAN 1) */ + return LASAT_IRQ_ETH0; /* Ethernet 0 (LAN 1) */ case 6: - return LASATINT_HDC; /* IDE controller */ + return LASAT_IRQ_HDC; /* IDE controller */ default: return 0xff; /* Illegal */ } diff --git a/arch/mips/pci/pci-vr41xx.c b/arch/mips/pci/pci-vr41xx.c index 240df9e..33c4f68 100644 --- a/arch/mips/pci/pci-vr41xx.c +++ b/arch/mips/pci/pci-vr41xx.c @@ -154,6 +154,7 @@ static int __init vr41xx_pciu_init(void) pciu_write(PCICLKSELREG, QUARTER_VTCLOCK); else { printk(KERN_ERR "PCI Clock is over 33MHz.\n"); + iounmap(pciu_base); return -EINVAL; } diff --git a/arch/mips/pmc-sierra/Kconfig b/arch/mips/pmc-sierra/Kconfig index 6b293ce..90261b8 100644 --- a/arch/mips/pmc-sierra/Kconfig +++ b/arch/mips/pmc-sierra/Kconfig @@ -5,12 +5,14 @@ choice config PMC_MSP4200_EVAL bool "PMC-Sierra MSP4200 Eval Board" select CEVT_R4K + select CSRC_R4K select IRQ_MSP_SLP select HW_HAS_PCI config PMC_MSP4200_GW bool "PMC-Sierra MSP4200 VoIP Gateway" select CEVT_R4K + select CSRC_R4K select IRQ_MSP_SLP select HW_HAS_PCI diff --git a/arch/mips/qemu/Makefile b/arch/mips/qemu/Makefile index cec24c1..2ba4ef3 100644 --- a/arch/mips/qemu/Makefile +++ b/arch/mips/qemu/Makefile @@ -4,6 +4,7 @@ obj-y = q-firmware.o q-irq.o q-mem.o q-setup.o q-reset.o -obj-$(CONFIG_SMP) += q-smp.o +obj-$(CONFIG_EARLY_PRINTK) += q-console.o +obj-$(CONFIG_SMP) += q-smp.o EXTRA_CFLAGS += -Werror diff --git a/arch/mips/qemu/q-console.c b/arch/mips/qemu/q-console.c new file mode 100644 index 0000000..81101ae --- /dev/null +++ b/arch/mips/qemu/q-console.c @@ -0,0 +1,26 @@ +#include <linux/console.h> +#include <linux/init.h> +#include <linux/serial_reg.h> +#include <asm/io.h> + +#define PORT(offset) (0x3f8 + (offset)) + +static inline unsigned int serial_in(int offset) +{ + return inb(PORT(offset)); +} + +static inline void serial_out(int offset, int value) +{ + outb(value, PORT(offset)); +} + +int prom_putchar(char c) +{ + while ((serial_in(UART_LSR) & UART_LSR_THRE) == 0) + ; + + serial_out(UART_TX, c); + + return 1; +} diff --git a/arch/mips/qemu/q-firmware.c b/arch/mips/qemu/q-firmware.c index c2239b4..3ed43f4 100644 --- a/arch/mips/qemu/q-firmware.c +++ b/arch/mips/qemu/q-firmware.c @@ -2,6 +2,9 @@ #include <linux/string.h> #include <asm/addrspace.h> #include <asm/bootinfo.h> +#include <asm/io.h> + +#define QEMU_PORT_BASE 0xb4000000 void __init prom_init(void) { @@ -15,4 +18,7 @@ void __init prom_init(void) } else { add_memory_region(0x0<<20, 0x10<<20, BOOT_MEM_RAM); } + + + set_io_port_base(QEMU_PORT_BASE); } diff --git a/arch/mips/qemu/q-setup.c b/arch/mips/qemu/q-setup.c index 23d34c1..969cedc 100644 --- a/arch/mips/qemu/q-setup.c +++ b/arch/mips/qemu/q-setup.c @@ -6,8 +6,6 @@ extern void qemu_reboot_setup(void); -#define QEMU_PORT_BASE 0xb4000000 - const char *get_system_type(void) { return "Qemu"; @@ -20,6 +18,5 @@ void __init plat_time_init(void) void __init plat_mem_setup(void) { - set_io_port_base(QEMU_PORT_BASE); qemu_reboot_setup(); } diff --git a/arch/mips/sgi-ip22/ip22-eisa.c b/arch/mips/sgi-ip22/ip22-eisa.c index 26854fb..1617241 100644 --- a/arch/mips/sgi-ip22/ip22-eisa.c +++ b/arch/mips/sgi-ip22/ip22-eisa.c @@ -36,6 +36,7 @@ #include <asm/sgi/ioc.h> #include <asm/sgi/mc.h> #include <asm/sgi/ip22.h> +#include <asm/i8259.h> /* I2 has four EISA slots. */ #define IP22_EISA_MAX_SLOTS 4 @@ -93,126 +94,11 @@ static irqreturn_t ip22_eisa_intr(int irq, void *dev_id) return IRQ_NONE; } -static void enable_eisa1_irq(unsigned int irq) -{ - u8 mask; - - mask = inb(EISA_INT1_MASK); - mask &= ~((u8) (1 << irq)); - outb(mask, EISA_INT1_MASK); -} - -static unsigned int startup_eisa1_irq(unsigned int irq) -{ - u8 edge; - - /* Only use edge interrupts for EISA */ - - edge = inb(EISA_INT1_EDGE_LEVEL); - edge &= ~((u8) (1 << irq)); - outb(edge, EISA_INT1_EDGE_LEVEL); - - enable_eisa1_irq(irq); - return 0; -} - -static void disable_eisa1_irq(unsigned int irq) -{ - u8 mask; - - mask = inb(EISA_INT1_MASK); - mask |= ((u8) (1 << irq)); - outb(mask, EISA_INT1_MASK); -} - -static void mask_and_ack_eisa1_irq(unsigned int irq) -{ - disable_eisa1_irq(irq); - - outb(0x20, EISA_INT1_CTRL); -} - -static void end_eisa1_irq(unsigned int irq) -{ - if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) - enable_eisa1_irq(irq); -} - -static struct irq_chip ip22_eisa1_irq_type = { - .name = "IP22 EISA", - .startup = startup_eisa1_irq, - .ack = mask_and_ack_eisa1_irq, - .mask = disable_eisa1_irq, - .mask_ack = mask_and_ack_eisa1_irq, - .unmask = enable_eisa1_irq, - .end = end_eisa1_irq, -}; - -static void enable_eisa2_irq(unsigned int irq) -{ - u8 mask; - - mask = inb(EISA_INT2_MASK); - mask &= ~((u8) (1 << (irq - 8))); - outb(mask, EISA_INT2_MASK); -} - -static unsigned int startup_eisa2_irq(unsigned int irq) -{ - u8 edge; - - /* Only use edge interrupts for EISA */ - - edge = inb(EISA_INT2_EDGE_LEVEL); - edge &= ~((u8) (1 << (irq - 8))); - outb(edge, EISA_INT2_EDGE_LEVEL); - - enable_eisa2_irq(irq); - return 0; -} - -static void disable_eisa2_irq(unsigned int irq) -{ - u8 mask; - - mask = inb(EISA_INT2_MASK); - mask |= ((u8) (1 << (irq - 8))); - outb(mask, EISA_INT2_MASK); -} - -static void mask_and_ack_eisa2_irq(unsigned int irq) -{ - disable_eisa2_irq(irq); - - outb(0x20, EISA_INT2_CTRL); -} - -static void end_eisa2_irq(unsigned int irq) -{ - if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) - enable_eisa2_irq(irq); -} - -static struct irq_chip ip22_eisa2_irq_type = { - .name = "IP22 EISA", - .startup = startup_eisa2_irq, - .ack = mask_and_ack_eisa2_irq, - .mask = disable_eisa2_irq, - .mask_ack = mask_and_ack_eisa2_irq, - .unmask = enable_eisa2_irq, - .end = end_eisa2_irq, -}; - static struct irqaction eisa_action = { .handler = ip22_eisa_intr, .name = "EISA", }; -static struct irqaction cascade_action = { - .handler = no_action, - .name = "EISA cascade", -}; - int __init ip22_eisa_init(void) { int i, c; @@ -248,29 +134,13 @@ int __init ip22_eisa_init(void) outb(1, EISA_EXT_NMI_RESET_CTRL); udelay(50); /* Wait long enough for the dust to settle */ outb(0, EISA_EXT_NMI_RESET_CTRL); - outb(0x11, EISA_INT1_CTRL); - outb(0x11, EISA_INT2_CTRL); - outb(0, EISA_INT1_MASK); - outb(8, EISA_INT2_MASK); - outb(4, EISA_INT1_MASK); - outb(2, EISA_INT2_MASK); - outb(1, EISA_INT1_MASK); - outb(1, EISA_INT2_MASK); - outb(0xfb, EISA_INT1_MASK); - outb(0xff, EISA_INT2_MASK); outb(0, EISA_DMA2_WRITE_SINGLE); - for (i = SGINT_EISA; i < (SGINT_EISA + EISA_MAX_IRQ); i++) { - if (i < (SGINT_EISA + 8)) - set_irq_chip(i, &ip22_eisa1_irq_type); - else - set_irq_chip(i, &ip22_eisa2_irq_type); - } + init_i8259_irqs(); /* Cannot use request_irq because of kmalloc not being ready at such * an early stage. Yes, I've been bitten... */ setup_irq(SGI_EISA_IRQ, &eisa_action); - setup_irq(SGINT_EISA + 2, &cascade_action); EISA_bus = 1; return 0; diff --git a/arch/mips/sgi-ip22/ip22-nvram.c b/arch/mips/sgi-ip22/ip22-nvram.c index e19d60d..0177566 100644 --- a/arch/mips/sgi-ip22/ip22-nvram.c +++ b/arch/mips/sgi-ip22/ip22-nvram.c @@ -32,19 +32,19 @@ for (x=0; x<100000; x++) __asm__ __volatile__(""); }) #define eeprom_cs_on(ptr) ({ \ - *ptr &= ~EEPROM_DATO; \ - *ptr &= ~EEPROM_ECLK; \ - *ptr &= ~EEPROM_EPROT; \ - delay(); \ - *ptr |= EEPROM_CSEL; \ - *ptr |= EEPROM_ECLK; }) + __raw_writel(__raw_readl(ptr) & ~EEPROM_DATO, ptr); \ + __raw_writel(__raw_readl(ptr) & ~EEPROM_ECLK, ptr); \ + __raw_writel(__raw_readl(ptr) & ~EEPROM_EPROT, ptr); \ + delay(); \ + __raw_writel(__raw_readl(ptr) | EEPROM_CSEL, ptr); \ + __raw_writel(__raw_readl(ptr) | EEPROM_ECLK, ptr); }) #define eeprom_cs_off(ptr) ({ \ - *ptr &= ~EEPROM_ECLK; \ - *ptr &= ~EEPROM_CSEL; \ - *ptr |= EEPROM_EPROT; \ - *ptr |= EEPROM_ECLK; }) + __raw_writel(__raw_readl(ptr) & ~EEPROM_ECLK, ptr); \ + __raw_writel(__raw_readl(ptr) & ~EEPROM_CSEL, ptr); \ + __raw_writel(__raw_readl(ptr) | EEPROM_EPROT, ptr); \ + __raw_writel(__raw_readl(ptr) | EEPROM_ECLK, ptr); }) #define BITS_IN_COMMAND 11 /* @@ -60,15 +60,17 @@ static inline void eeprom_cmd(unsigned int *ctrl, unsigned cmd, unsigned reg) ser_cmd = cmd | (reg << (16 - BITS_IN_COMMAND)); for (i = 0; i < BITS_IN_COMMAND; i++) { if (ser_cmd & (1<<15)) /* if high order bit set */ - writel(readl(ctrl) | EEPROM_DATO, ctrl); + __raw_writel(__raw_readl(ctrl) | EEPROM_DATO, ctrl); else - writel(readl(ctrl) & ~EEPROM_DATO, ctrl); - writel(readl(ctrl) & ~EEPROM_ECLK, ctrl); - writel(readl(ctrl) | EEPROM_ECLK, ctrl); + __raw_writel(__raw_readl(ctrl) & ~EEPROM_DATO, ctrl); + __raw_writel(__raw_readl(ctrl) & ~EEPROM_ECLK, ctrl); + delay(); + __raw_writel(__raw_readl(ctrl) | EEPROM_ECLK, ctrl); + delay(); ser_cmd <<= 1; } /* see data sheet timing diagram */ - writel(readl(ctrl) & ~EEPROM_DATO, ctrl); + __raw_writel(__raw_readl(ctrl) & ~EEPROM_DATO, ctrl); } unsigned short ip22_eeprom_read(unsigned int *ctrl, int reg) @@ -76,18 +78,18 @@ unsigned short ip22_eeprom_read(unsigned int *ctrl, int reg) unsigned short res = 0; int i; - writel(readl(ctrl) & ~EEPROM_EPROT, ctrl); + __raw_writel(__raw_readl(ctrl) & ~EEPROM_EPROT, ctrl); eeprom_cs_on(ctrl); eeprom_cmd(ctrl, EEPROM_READ, reg); /* clock the data ouf of serial mem */ for (i = 0; i < 16; i++) { - writel(readl(ctrl) & ~EEPROM_ECLK, ctrl); + __raw_writel(__raw_readl(ctrl) & ~EEPROM_ECLK, ctrl); delay(); - writel(readl(ctrl) | EEPROM_ECLK, ctrl); + __raw_writel(__raw_readl(ctrl) | EEPROM_ECLK, ctrl); delay(); res <<= 1; - if (readl(ctrl) & EEPROM_DATI) + if (__raw_readl(ctrl) & EEPROM_DATI) res |= 1; } diff --git a/arch/mips/sgi-ip22/ip22-setup.c b/arch/mips/sgi-ip22/ip22-setup.c index 174f09e..5f389ee 100644 --- a/arch/mips/sgi-ip22/ip22-setup.c +++ b/arch/mips/sgi-ip22/ip22-setup.c @@ -31,25 +31,6 @@ unsigned long sgi_gfxaddr; EXPORT_SYMBOL_GPL(sgi_gfxaddr); -/* - * Stop-A is originally a Sun thing that isn't standard on IP22 so to avoid - * accidents it's disabled by default on IP22. - * - * FIXME: provide a mechanism to change the value of stop_a_enabled. - */ -int stop_a_enabled; - -void ip22_do_break(void) -{ - if (!stop_a_enabled) - return; - - printk("\n"); - ArcEnterInteractiveMode(); -} - -EXPORT_SYMBOL(ip22_do_break); - extern void ip22_be_init(void) __init; void __init plat_mem_setup(void) diff --git a/arch/mips/sgi-ip32/ip32-irq.c b/arch/mips/sgi-ip32/ip32-irq.c index aab17dd..cab7cc2 100644 --- a/arch/mips/sgi-ip32/ip32-irq.c +++ b/arch/mips/sgi-ip32/ip32-irq.c @@ -209,18 +209,18 @@ static unsigned long macepci_mask; static void enable_macepci_irq(unsigned int irq) { - macepci_mask |= MACEPCI_CONTROL_INT(irq - 9); + macepci_mask |= MACEPCI_CONTROL_INT(irq - MACEPCI_SCSI0_IRQ); mace->pci.control = macepci_mask; - crime_mask |= 1 << (irq - 1); + crime_mask |= 1 << (irq - CRIME_IRQ_BASE); crime->imask = crime_mask; } static void disable_macepci_irq(unsigned int irq) { - crime_mask &= ~(1 << (irq - 1)); + crime_mask &= ~(1 << (irq - CRIME_IRQ_BASE)); crime->imask = crime_mask; flush_crime_bus(); - macepci_mask &= ~MACEPCI_CONTROL_INT(irq - 9); + macepci_mask &= ~MACEPCI_CONTROL_INT(irq - MACEPCI_SCSI0_IRQ); mace->pci.control = macepci_mask; flush_mace_bus(); } @@ -299,7 +299,7 @@ static void enable_maceisa_irq(unsigned int irq) pr_debug("crime_int %08x enabled\n", crime_int); crime_mask |= crime_int; crime->imask = crime_mask; - maceisa_mask |= 1 << (irq - 33); + maceisa_mask |= 1 << (irq - MACEISA_AUDIO_SW_IRQ); mace->perif.ctrl.imask = maceisa_mask; } @@ -307,7 +307,7 @@ static void disable_maceisa_irq(unsigned int irq) { unsigned int crime_int = 0; - maceisa_mask &= ~(1 << (irq - 33)); + maceisa_mask &= ~(1 << (irq - MACEISA_AUDIO_SW_IRQ)); if (!(maceisa_mask & MACEISA_AUDIO_INT)) crime_int |= MACE_AUDIO_INT; if (!(maceisa_mask & MACEISA_MISC_INT)) @@ -331,7 +331,7 @@ static void mask_and_ack_maceisa_irq(unsigned int irq) case MACEISA_SERIAL2_TDMAPR_IRQ: /* edge triggered */ mace_int = mace->perif.ctrl.istat; - mace_int &= ~(1 << (irq - 33)); + mace_int &= ~(1 << (irq - MACEISA_AUDIO_SW_IRQ)); mace->perif.ctrl.istat = mace_int; break; } @@ -359,13 +359,17 @@ static struct irq_chip ip32_maceisa_interrupt = { static void enable_mace_irq(unsigned int irq) { - crime_mask |= 1 << (irq - 1); + unsigned int bit = irq - CRIME_IRQ_BASE; + + crime_mask |= (1 << bit); crime->imask = crime_mask; } static void disable_mace_irq(unsigned int irq) { - crime_mask &= ~(1 << (irq - 1)); + unsigned int bit = irq - CRIME_IRQ_BASE; + + crime_mask &= ~(1 << bit); crime->imask = crime_mask; flush_crime_bus(); } @@ -489,7 +493,7 @@ void __init arch_init_irq(void) mace->perif.ctrl.imask = 0; mips_cpu_irq_init(); - for (irq = MIPS_CPU_IRQ_BASE + 8; irq <= IP32_IRQ_MAX; irq++) { + for (irq = CRIME_IRQ_BASE; irq <= IP32_IRQ_MAX; irq++) { switch (irq) { case MACE_VID_IN1_IRQ ... MACE_PCI_BRIDGE_IRQ: set_irq_chip(irq, &ip32_mace_interrupt); diff --git a/arch/mips/sibyte/bcm1480/irq.c b/arch/mips/sibyte/bcm1480/irq.c index e28d626..db372a0 100644 --- a/arch/mips/sibyte/bcm1480/irq.c +++ b/arch/mips/sibyte/bcm1480/irq.c @@ -370,11 +370,11 @@ void __init arch_init_irq(void) #endif /* Setup uart 1 settings, mapper */ /* QQQ FIXME */ - __raw_writeq(M_DUART_IMR_BRK, IO_SPACE_BASE + A_DUART_IMRREG(kgdb_port)); + __raw_writeq(M_DUART_IMR_BRK, IOADDR(A_DUART_IMRREG(kgdb_port))); __raw_writeq(IMR_IP6_VAL, - IO_SPACE_BASE + A_BCM1480_IMR_REGISTER(0, R_BCM1480_IMR_INTERRUPT_MAP_BASE_H) + - (kgdb_irq<<3)); + IOADDR(A_BCM1480_IMR_REGISTER(0, R_BCM1480_IMR_INTERRUPT_MAP_BASE_H) + + (kgdb_irq << 3))); bcm1480_unmask_irq(0, kgdb_irq); #ifdef CONFIG_GDB_CONSOLE @@ -412,18 +412,6 @@ static void bcm1480_kgdb_interrupt(void) extern void bcm1480_mailbox_interrupt(void); -static inline void dispatch_ip4(void) -{ - int cpu = smp_processor_id(); - int irq = K_BCM1480_INT_TIMER_0 + cpu; - - /* Reset the timer */ - __raw_writeq(M_SCD_TIMER_ENABLE|M_SCD_TIMER_MODE_CONTINUOUS, - IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_CFG))); - - do_IRQ(irq); -} - static inline void dispatch_ip2(void) { unsigned long long mask_h, mask_l; @@ -451,6 +439,7 @@ static inline void dispatch_ip2(void) asmlinkage void plat_irq_dispatch(void) { + unsigned int cpu = smp_processor_id(); unsigned int pending; #ifdef CONFIG_SIBYTE_BCM1480_PROF @@ -467,7 +456,7 @@ asmlinkage void plat_irq_dispatch(void) #endif if (pending & CAUSEF_IP4) - dispatch_ip4(); + do_IRQ(K_BCM1480_INT_TIMER_0 + cpu); #ifdef CONFIG_SMP else if (pending & CAUSEF_IP3) bcm1480_mailbox_interrupt(); diff --git a/arch/mips/sni/pcimt.c b/arch/mips/sni/pcimt.c index 4df070f..834650f 100644 --- a/arch/mips/sni/pcimt.c +++ b/arch/mips/sni/pcimt.c @@ -244,7 +244,7 @@ static void pcimt_hwint1(void) if (pend & IT_EISA) { int irq; /* - * Note: ASIC PCI's builtin interrupt achknowledge feature is + * Note: ASIC PCI's builtin interrupt acknowledge feature is * broken. Using it may result in loss of some or all i8259 * interrupts, so don't use PCIMT_INT_ACKNOWLEDGE ... */ diff --git a/arch/mips/vr41xx/Kconfig b/arch/mips/vr41xx/Kconfig index eeb089f..559acc0 100644 --- a/arch/mips/vr41xx/Kconfig +++ b/arch/mips/vr41xx/Kconfig @@ -6,6 +6,7 @@ choice config CASIO_E55 bool "CASIO CASSIOPEIA E-10/15/55/65" select CEVT_R4K + select CSRC_R4K select DMA_NONCOHERENT select IRQ_CPU select ISA @@ -15,6 +16,7 @@ config CASIO_E55 config IBM_WORKPAD bool "IBM WorkPad z50" select CEVT_R4K + select CSRC_R4K select DMA_NONCOHERENT select IRQ_CPU select ISA @@ -24,6 +26,7 @@ config IBM_WORKPAD config NEC_CMBVR4133 bool "NEC CMB-VR4133" select CEVT_R4K + select CSRC_R4K select DMA_NONCOHERENT select IRQ_CPU select HW_HAS_PCI @@ -33,6 +36,7 @@ config NEC_CMBVR4133 config TANBAC_TB022X bool "TANBAC VR4131 multichip module and TANBAC VR4131DIMM" select CEVT_R4K + select CSRC_R4K select DMA_NONCOHERENT select IRQ_CPU select HW_HAS_PCI @@ -48,6 +52,7 @@ config TANBAC_TB022X config VICTOR_MPC30X bool "Victor MP-C303/304" select CEVT_R4K + select CSRC_R4K select DMA_NONCOHERENT select IRQ_CPU select HW_HAS_PCI @@ -58,6 +63,7 @@ config VICTOR_MPC30X config ZAO_CAPCELLA bool "ZAO Networks Capcella" select CEVT_R4K + select CSRC_R4K select DMA_NONCOHERENT select IRQ_CPU select HW_HAS_PCI diff --git a/arch/mips/vr41xx/common/icu.c b/arch/mips/vr41xx/common/icu.c index 1899601..3f23d9f 100644 --- a/arch/mips/vr41xx/common/icu.c +++ b/arch/mips/vr41xx/common/icu.c @@ -525,6 +525,7 @@ static inline int set_sysint1_assign(unsigned int irq, unsigned char assign) intassign1 |= (uint16_t)assign << 9; break; default: + spin_unlock_irq(&desc->lock); return -EINVAL; } @@ -592,6 +593,7 @@ static inline int set_sysint2_assign(unsigned int irq, unsigned char assign) intassign3 |= (uint16_t)assign << 12; break; default: + spin_unlock_irq(&desc->lock); return -EINVAL; } diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index 18f397ca..232c298 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig @@ -187,6 +187,11 @@ config FORCE_MAX_ZONEORDER default "9" if PPC_64K_PAGES default "13" +config HUGETLB_PAGE_SIZE_VARIABLE + bool + depends on HUGETLB_PAGE + default y + config MATH_EMULATION bool "Math emulation" depends on 4xx || 8xx || E200 || PPC_MPC832x || E500 diff --git a/arch/powerpc/Makefile b/arch/powerpc/Makefile index 4e16534..bd87626 100644 --- a/arch/powerpc/Makefile +++ b/arch/powerpc/Makefile @@ -107,6 +107,9 @@ endif # No AltiVec instruction when building kernel KBUILD_CFLAGS += $(call cc-option,-mno-altivec) +# No SPE instruction when building kernel +KBUILD_CFLAGS += $(call cc-option,-mno-spe) + # Enable unit-at-a-time mode when possible. It shrinks the # kernel considerably. KBUILD_CFLAGS += $(call cc-option,-funit-at-a-time) diff --git a/arch/powerpc/boot/dts/mpc832x_mds.dts b/arch/powerpc/boot/dts/mpc832x_mds.dts index fcd333c..c64f303 100644 --- a/arch/powerpc/boot/dts/mpc832x_mds.dts +++ b/arch/powerpc/boot/dts/mpc832x_mds.dts @@ -57,12 +57,19 @@ }; i2c@3000 { + #address-cells = <1>; + #size-cells = <0>; device_type = "i2c"; compatible = "fsl-i2c"; reg = <3000 100>; interrupts = <e 8>; interrupt-parent = < &ipic >; dfsrr; + + rtc@68 { + compatible = "dallas,ds1374"; + reg = <68>; + }; }; serial@4500 { @@ -104,7 +111,7 @@ reg = <700 100>; device_type = "ipic"; }; - + par_io@1400 { reg = <1400 100>; device_type = "par_io"; @@ -117,7 +124,6 @@ 3 5 1 0 2 0 /* MDC */ 0 d 2 0 1 0 /* RX_CLK (CLK9) */ 3 18 2 0 1 0 /* TX_CLK (CLK10) */ - 1 1 1 0 1 0 /* TxD1 */ 1 0 1 0 1 0 /* TxD0 */ 1 1 1 0 1 0 /* TxD1 */ 1 2 1 0 1 0 /* TxD2 */ @@ -165,11 +171,11 @@ reg = <e0100000 480>; brg-frequency = <0>; bus-frequency = <BCD3D80>; - + muram@10000 { device_type = "muram"; ranges = <0 00010000 00004000>; - + data-only@0 { reg = <0 4000>; }; @@ -228,7 +234,7 @@ compatible = "ucc_geth"; model = "UCC"; device-id = <4>; - reg = <3000 200>; + reg = <3200 200>; interrupts = <23>; interrupt-parent = < &qeic >; /* diff --git a/arch/powerpc/boot/dts/mpc834x_mds.dts b/arch/powerpc/boot/dts/mpc834x_mds.dts index e5a84ef..49363f8 100644 --- a/arch/powerpc/boot/dts/mpc834x_mds.dts +++ b/arch/powerpc/boot/dts/mpc834x_mds.dts @@ -57,15 +57,24 @@ }; i2c@3000 { + #address-cells = <1>; + #size-cells = <0>; device_type = "i2c"; compatible = "fsl-i2c"; reg = <3000 100>; interrupts = <e 8>; interrupt-parent = < &ipic >; dfsrr; + + rtc@68 { + compatible = "dallas,ds1374"; + reg = <68>; + }; }; i2c@3100 { + #address-cells = <1>; + #size-cells = <0>; device_type = "i2c"; compatible = "fsl-i2c"; reg = <3100 100>; diff --git a/arch/powerpc/boot/dts/mpc836x_mds.dts b/arch/powerpc/boot/dts/mpc836x_mds.dts index fbd1573..0b2d2b5 100644 --- a/arch/powerpc/boot/dts/mpc836x_mds.dts +++ b/arch/powerpc/boot/dts/mpc836x_mds.dts @@ -62,15 +62,24 @@ }; i2c@3000 { + #address-cells = <1>; + #size-cells = <0>; device_type = "i2c"; compatible = "fsl-i2c"; reg = <3000 100>; interrupts = <e 8>; interrupt-parent = < &ipic >; dfsrr; + + rtc@68 { + compatible = "dallas,ds1374"; + reg = <68>; + }; }; i2c@3100 { + #address-cells = <1>; + #size-cells = <0>; device_type = "i2c"; compatible = "fsl-i2c"; reg = <3100 100>; diff --git a/arch/powerpc/boot/dts/mpc8544ds.dts b/arch/powerpc/boot/dts/mpc8544ds.dts index 3f9d15c..6c608de 100644 --- a/arch/powerpc/boot/dts/mpc8544ds.dts +++ b/arch/powerpc/boot/dts/mpc8544ds.dts @@ -272,24 +272,24 @@ clock-frequency = <1fca055>; interrupt-parent = <&mpic>; interrupts = <1b 2>; - interrupt-map-mask = <fb00 0 0 0>; + interrupt-map-mask = <ff00 0 0 1>; interrupt-map = < // IDSEL 0x1c USB - e000 0 0 0 &i8259 c 2 - e100 0 0 0 &i8259 9 2 - e200 0 0 0 &i8259 a 2 - e300 0 0 0 &i8259 b 2 + e000 0 0 1 &i8259 c 2 + e100 0 0 1 &i8259 9 2 + e200 0 0 1 &i8259 a 2 + e300 0 0 1 &i8259 b 2 // IDSEL 0x1d Audio - e800 0 0 0 &i8259 6 2 + e800 0 0 1 &i8259 6 2 // IDSEL 0x1e Legacy - f000 0 0 0 &i8259 7 2 - f100 0 0 0 &i8259 7 2 + f000 0 0 1 &i8259 7 2 + f100 0 0 1 &i8259 7 2 // IDSEL 0x1f IDE/SATA - f800 0 0 0 &i8259 e 2 - f900 0 0 0 &i8259 5 2 + f800 0 0 1 &i8259 e 2 + f900 0 0 1 &i8259 5 2 >; pcie@0 { diff --git a/arch/powerpc/boot/dts/mpc8572ds.dts b/arch/powerpc/boot/dts/mpc8572ds.dts index d638dee..0eb44fb 100644 --- a/arch/powerpc/boot/dts/mpc8572ds.dts +++ b/arch/powerpc/boot/dts/mpc8572ds.dts @@ -219,36 +219,120 @@ clock-frequency = <1fca055>; interrupt-parent = <&mpic>; interrupts = <18 2>; - interrupt-map-mask = <fb00 0 0 0>; + interrupt-map-mask = <ff00 0 0 7>; interrupt-map = < - /* IDSEL 0x11 - PCI slot 1 */ + /* IDSEL 0x11 func 0 - PCI slot 1 */ 8800 0 0 1 &mpic 2 1 8800 0 0 2 &mpic 3 1 8800 0 0 3 &mpic 4 1 8800 0 0 4 &mpic 1 1 - /* IDSEL 0x12 - PCI slot 2 */ + /* IDSEL 0x11 func 1 - PCI slot 1 */ + 8900 0 0 1 &mpic 2 1 + 8900 0 0 2 &mpic 3 1 + 8900 0 0 3 &mpic 4 1 + 8900 0 0 4 &mpic 1 1 + + /* IDSEL 0x11 func 2 - PCI slot 1 */ + 8a00 0 0 1 &mpic 2 1 + 8a00 0 0 2 &mpic 3 1 + 8a00 0 0 3 &mpic 4 1 + 8a00 0 0 4 &mpic 1 1 + + /* IDSEL 0x11 func 3 - PCI slot 1 */ + 8b00 0 0 1 &mpic 2 1 + 8b00 0 0 2 &mpic 3 1 + 8b00 0 0 3 &mpic 4 1 + 8b00 0 0 4 &mpic 1 1 + + /* IDSEL 0x11 func 4 - PCI slot 1 */ + 8c00 0 0 1 &mpic 2 1 + 8c00 0 0 2 &mpic 3 1 + 8c00 0 0 3 &mpic 4 1 + 8c00 0 0 4 &mpic 1 1 + + /* IDSEL 0x11 func 5 - PCI slot 1 */ + 8d00 0 0 1 &mpic 2 1 + 8d00 0 0 2 &mpic 3 1 + 8d00 0 0 3 &mpic 4 1 + 8d00 0 0 4 &mpic 1 1 + + /* IDSEL 0x11 func 6 - PCI slot 1 */ + 8e00 0 0 1 &mpic 2 1 + 8e00 0 0 2 &mpic 3 1 + 8e00 0 0 3 &mpic 4 1 + 8e00 0 0 4 &mpic 1 1 + + /* IDSEL 0x11 func 7 - PCI slot 1 */ + 8f00 0 0 1 &mpic 2 1 + 8f00 0 0 2 &mpic 3 1 + 8f00 0 0 3 &mpic 4 1 + 8f00 0 0 4 &mpic 1 1 + + /* IDSEL 0x12 func 0 - PCI slot 2 */ 9000 0 0 1 &mpic 3 1 9000 0 0 2 &mpic 4 1 9000 0 0 3 &mpic 1 1 9000 0 0 4 &mpic 2 1 + /* IDSEL 0x12 func 1 - PCI slot 2 */ + 9100 0 0 1 &mpic 3 1 + 9100 0 0 2 &mpic 4 1 + 9100 0 0 3 &mpic 1 1 + 9100 0 0 4 &mpic 2 1 + + /* IDSEL 0x12 func 2 - PCI slot 2 */ + 9200 0 0 1 &mpic 3 1 + 9200 0 0 2 &mpic 4 1 + 9200 0 0 3 &mpic 1 1 + 9200 0 0 4 &mpic 2 1 + + /* IDSEL 0x12 func 3 - PCI slot 2 */ + 9300 0 0 1 &mpic 3 1 + 9300 0 0 2 &mpic 4 1 + 9300 0 0 3 &mpic 1 1 + 9300 0 0 4 &mpic 2 1 + + /* IDSEL 0x12 func 4 - PCI slot 2 */ + 9400 0 0 1 &mpic 3 1 + 9400 0 0 2 &mpic 4 1 + 9400 0 0 3 &mpic 1 1 + 9400 0 0 4 &mpic 2 1 + + /* IDSEL 0x12 func 5 - PCI slot 2 */ + 9500 0 0 1 &mpic 3 1 + 9500 0 0 2 &mpic 4 1 + 9500 0 0 3 &mpic 1 1 + 9500 0 0 4 &mpic 2 1 + + /* IDSEL 0x12 func 6 - PCI slot 2 */ + 9600 0 0 1 &mpic 3 1 + 9600 0 0 2 &mpic 4 1 + 9600 0 0 3 &mpic 1 1 + 9600 0 0 4 &mpic 2 1 + + /* IDSEL 0x12 func 7 - PCI slot 2 */ + 9700 0 0 1 &mpic 3 1 + 9700 0 0 2 &mpic 4 1 + 9700 0 0 3 &mpic 1 1 + 9700 0 0 4 &mpic 2 1 + // IDSEL 0x1c USB - e000 0 0 0 &i8259 c 2 - e100 0 0 0 &i8259 9 2 - e200 0 0 0 &i8259 a 2 - e300 0 0 0 &i8259 b 2 + e000 0 0 1 &i8259 c 2 + e100 0 0 1 &i8259 9 2 + e200 0 0 1 &i8259 a 2 + e300 0 0 1 &i8259 b 2 // IDSEL 0x1d Audio - e800 0 0 0 &i8259 6 2 + e800 0 0 1 &i8259 6 2 // IDSEL 0x1e Legacy - f000 0 0 0 &i8259 7 2 - f100 0 0 0 &i8259 7 2 + f000 0 0 1 &i8259 7 2 + f100 0 0 1 &i8259 7 2 // IDSEL 0x1f IDE/SATA - f800 0 0 0 &i8259 e 2 - f900 0 0 0 &i8259 5 2 + f800 0 0 1 &i8259 e 2 + f900 0 0 1 &i8259 5 2 >; diff --git a/arch/powerpc/boot/dts/mpc8641_hpcn.dts b/arch/powerpc/boot/dts/mpc8641_hpcn.dts index 3677659..abb26dc 100644 --- a/arch/powerpc/boot/dts/mpc8641_hpcn.dts +++ b/arch/powerpc/boot/dts/mpc8641_hpcn.dts @@ -235,36 +235,120 @@ clock-frequency = <1fca055>; interrupt-parent = <&mpic>; interrupts = <18 2>; - interrupt-map-mask = <fb00 0 0 0>; + interrupt-map-mask = <ff00 0 0 7>; interrupt-map = < - /* IDSEL 0x11 */ - 8800 0 0 1 &i8259 9 2 - 8800 0 0 2 &i8259 a 2 - 8800 0 0 3 &i8259 b 2 - 8800 0 0 4 &i8259 c 2 - - /* IDSEL 0x12 */ - 9000 0 0 1 &i8259 a 2 - 9000 0 0 2 &i8259 b 2 - 9000 0 0 3 &i8259 c 2 - 9000 0 0 4 &i8259 9 2 + /* IDSEL 0x11 func 0 - PCI slot 1 */ + 8800 0 0 1 &mpic 2 1 + 8800 0 0 2 &mpic 3 1 + 8800 0 0 3 &mpic 4 1 + 8800 0 0 4 &mpic 1 1 + + /* IDSEL 0x11 func 1 - PCI slot 1 */ + 8900 0 0 1 &mpic 2 1 + 8900 0 0 2 &mpic 3 1 + 8900 0 0 3 &mpic 4 1 + 8900 0 0 4 &mpic 1 1 + + /* IDSEL 0x11 func 2 - PCI slot 1 */ + 8a00 0 0 1 &mpic 2 1 + 8a00 0 0 2 &mpic 3 1 + 8a00 0 0 3 &mpic 4 1 + 8a00 0 0 4 &mpic 1 1 + + /* IDSEL 0x11 func 3 - PCI slot 1 */ + 8b00 0 0 1 &mpic 2 1 + 8b00 0 0 2 &mpic 3 1 + 8b00 0 0 3 &mpic 4 1 + 8b00 0 0 4 &mpic 1 1 + + /* IDSEL 0x11 func 4 - PCI slot 1 */ + 8c00 0 0 1 &mpic 2 1 + 8c00 0 0 2 &mpic 3 1 + 8c00 0 0 3 &mpic 4 1 + 8c00 0 0 4 &mpic 1 1 + + /* IDSEL 0x11 func 5 - PCI slot 1 */ + 8d00 0 0 1 &mpic 2 1 + 8d00 0 0 2 &mpic 3 1 + 8d00 0 0 3 &mpic 4 1 + 8d00 0 0 4 &mpic 1 1 + + /* IDSEL 0x11 func 6 - PCI slot 1 */ + 8e00 0 0 1 &mpic 2 1 + 8e00 0 0 2 &mpic 3 1 + 8e00 0 0 3 &mpic 4 1 + 8e00 0 0 4 &mpic 1 1 + + /* IDSEL 0x11 func 7 - PCI slot 1 */ + 8f00 0 0 1 &mpic 2 1 + 8f00 0 0 2 &mpic 3 1 + 8f00 0 0 3 &mpic 4 1 + 8f00 0 0 4 &mpic 1 1 + + /* IDSEL 0x12 func 0 - PCI slot 2 */ + 9000 0 0 1 &mpic 3 1 + 9000 0 0 2 &mpic 4 1 + 9000 0 0 3 &mpic 1 1 + 9000 0 0 4 &mpic 2 1 + + /* IDSEL 0x12 func 1 - PCI slot 2 */ + 9100 0 0 1 &mpic 3 1 + 9100 0 0 2 &mpic 4 1 + 9100 0 0 3 &mpic 1 1 + 9100 0 0 4 &mpic 2 1 + + /* IDSEL 0x12 func 2 - PCI slot 2 */ + 9200 0 0 1 &mpic 3 1 + 9200 0 0 2 &mpic 4 1 + 9200 0 0 3 &mpic 1 1 + 9200 0 0 4 &mpic 2 1 + + /* IDSEL 0x12 func 3 - PCI slot 2 */ + 9300 0 0 1 &mpic 3 1 + 9300 0 0 2 &mpic 4 1 + 9300 0 0 3 &mpic 1 1 + 9300 0 0 4 &mpic 2 1 + + /* IDSEL 0x12 func 4 - PCI slot 2 */ + 9400 0 0 1 &mpic 3 1 + 9400 0 0 2 &mpic 4 1 + 9400 0 0 3 &mpic 1 1 + 9400 0 0 4 &mpic 2 1 + + /* IDSEL 0x12 func 5 - PCI slot 2 */ + 9500 0 0 1 &mpic 3 1 + 9500 0 0 2 &mpic 4 1 + 9500 0 0 3 &mpic 1 1 + 9500 0 0 4 &mpic 2 1 + + /* IDSEL 0x12 func 6 - PCI slot 2 */ + 9600 0 0 1 &mpic 3 1 + 9600 0 0 2 &mpic 4 1 + 9600 0 0 3 &mpic 1 1 + 9600 0 0 4 &mpic 2 1 + + /* IDSEL 0x12 func 7 - PCI slot 2 */ + 9700 0 0 1 &mpic 3 1 + 9700 0 0 2 &mpic 4 1 + 9700 0 0 3 &mpic 1 1 + 9700 0 0 4 &mpic 2 1 // IDSEL 0x1c USB - e000 0 0 0 &i8259 c 2 - e100 0 0 0 &i8259 9 2 - e200 0 0 0 &i8259 a 2 - e300 0 0 0 &i8259 b 2 + e000 0 0 1 &i8259 c 2 + e100 0 0 1 &i8259 9 2 + e200 0 0 1 &i8259 a 2 + e300 0 0 1 &i8259 b 2 // IDSEL 0x1d Audio - e800 0 0 0 &i8259 6 2 + e800 0 0 1 &i8259 6 2 // IDSEL 0x1e Legacy - f000 0 0 0 &i8259 7 2 - f100 0 0 0 &i8259 7 2 + f000 0 0 1 &i8259 7 2 + f100 0 0 1 &i8259 7 2 // IDSEL 0x1f IDE/SATA - f800 0 0 0 &i8259 e 2 - f900 0 0 0 &i8259 5 2 + f800 0 0 1 &i8259 e 2 + f900 0 0 1 &i8259 5 2 >; pcie@0 { diff --git a/arch/powerpc/boot/dts/walnut.dts b/arch/powerpc/boot/dts/walnut.dts index fa681f5..754fa39 100644 --- a/arch/powerpc/boot/dts/walnut.dts +++ b/arch/powerpc/boot/dts/walnut.dts @@ -122,7 +122,9 @@ device_type = "network"; compatible = "ibm,emac-405gp", "ibm,emac"; interrupt-parent = <&UIC0>; - interrupts = <9 4 f 4>; + interrupts = < + f 4 /* Ethernet */ + 9 4 /* Ethernet Wake Up */>; local-mac-address = [000000000000]; /* Filled in by zImage */ reg = <ef600800 70>; mal-device = <&MAL>; diff --git a/arch/powerpc/boot/wrapper b/arch/powerpc/boot/wrapper index 39b27e5..31147a0 100755 --- a/arch/powerpc/boot/wrapper +++ b/arch/powerpc/boot/wrapper @@ -21,6 +21,14 @@ # (default ./arch/powerpc/boot) # -W dir specify working directory for temporary files (default .) +# Stop execution if any command fails +set -e + +# Allow for verbose output +if [ "$V" = 1 ]; then + set -x +fi + # defaults kernel= ofile=zImage @@ -111,7 +119,7 @@ if [ -n "$dts" ]; then if [ -z "$dtb" ]; then dtb="$platform.dtb" fi - dtc -O dtb -o "$dtb" -b 0 -V 16 "$dts" || exit 1 + dtc -O dtb -o "$dtb" -b 0 -V 16 "$dts" fi if [ -z "$kernel" ]; then @@ -149,7 +157,6 @@ cuboot*) ps3) platformo="$object/ps3-head.o $object/ps3-hvcall.o $object/ps3.o" lds=$object/zImage.ps3.lds - binary=y gzip= ext=bin objflags="-O binary --set-section-flags=.bss=contents,alloc,load,data" @@ -233,7 +240,7 @@ entry=`${CROSS}objdump -f "$ofile" | grep '^start address ' | cut -d' ' -f3` if [ -n "$binary" ]; then mv "$ofile" "$ofile".elf - ${CROSS}objcopy -O binary "$ofile".elf "$ofile".bin + ${CROSS}objcopy -O binary "$ofile".elf "$ofile" fi # post-processing needed for some platforms @@ -246,9 +253,9 @@ coff) $object/hack-coff "$ofile" ;; cuboot*) - gzip -f -9 "$ofile".bin + gzip -f -9 "$ofile" mkimage -A ppc -O linux -T kernel -C gzip -a "$base" -e "$entry" \ - $uboot_version -d "$ofile".bin.gz "$ofile" + $uboot_version -d "$ofile".gz "$ofile" ;; treeboot*) mv "$ofile" "$ofile.elf" @@ -269,11 +276,11 @@ ps3) # then copied to offset 0x100. At runtime the bootwrapper program # copies the 0x100 bytes at __system_reset_kernel to addr 0x100. - system_reset_overlay=0x`${CROSS}nm "$ofile".elf \ + system_reset_overlay=0x`${CROSS}nm "$ofile" \ | grep ' __system_reset_overlay$' \ | cut -d' ' -f1` system_reset_overlay=`printf "%d" $system_reset_overlay` - system_reset_kernel=0x`${CROSS}nm "$ofile".elf \ + system_reset_kernel=0x`${CROSS}nm "$ofile" \ | grep ' __system_reset_kernel$' \ | cut -d' ' -f1` system_reset_kernel=`printf "%d" $system_reset_kernel` @@ -282,23 +289,15 @@ ps3) rm -f "$object/otheros.bld" - msg=$(dd if="$ofile.bin" of="$ofile.bin" conv=notrunc \ - skip=$overlay_dest seek=$system_reset_kernel \ - count=$overlay_size bs=1 2>&1) + ${CROSS}objcopy -O binary "$ofile" "$ofile.bin" - if [ $? -ne "0" ]; then - echo $msg - exit 1 - fi - - msg=$(dd if="$ofile.bin" of="$ofile.bin" conv=notrunc \ - skip=$system_reset_overlay seek=$overlay_dest \ - count=$overlay_size bs=1 2>&1) + dd if="$ofile.bin" of="$ofile.bin" conv=notrunc \ + skip=$overlay_dest seek=$system_reset_kernel \ + count=$overlay_size bs=1 - if [ $? -ne "0" ]; then - echo $msg - exit 2 - fi + dd if="$ofile.bin" of="$ofile.bin" conv=notrunc \ + skip=$system_reset_overlay seek=$overlay_dest \ + count=$overlay_size bs=1 gzip --force -9 --stdout "$ofile.bin" > "$object/otheros.bld" ;; diff --git a/arch/powerpc/configs/mpc832x_mds_defconfig b/arch/powerpc/configs/mpc832x_mds_defconfig index dd68d18..e069018 100644 --- a/arch/powerpc/configs/mpc832x_mds_defconfig +++ b/arch/powerpc/configs/mpc832x_mds_defconfig @@ -774,7 +774,53 @@ CONFIG_USB_ARCH_HAS_EHCI=y # CONFIG_NEW_LEDS is not set # CONFIG_INFINIBAND is not set # CONFIG_EDAC is not set -# CONFIG_RTC_CLASS is not set +CONFIG_RTC_LIB=y +CONFIG_RTC_CLASS=y +CONFIG_RTC_HCTOSYS=y +CONFIG_RTC_HCTOSYS_DEVICE="rtc0" +# CONFIG_RTC_DEBUG is not set + +# +# RTC interfaces +# +CONFIG_RTC_INTF_SYSFS=y +CONFIG_RTC_INTF_PROC=y +CONFIG_RTC_INTF_DEV=y +# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set +# CONFIG_RTC_DRV_TEST is not set + +# +# I2C RTC drivers +# +# CONFIG_RTC_DRV_DS1307 is not set +CONFIG_RTC_DRV_DS1374=y +# CONFIG_RTC_DRV_DS1672 is not set +# CONFIG_RTC_DRV_MAX6900 is not set +# CONFIG_RTC_DRV_RS5C372 is not set +# CONFIG_RTC_DRV_ISL1208 is not set +# CONFIG_RTC_DRV_X1205 is not set +# CONFIG_RTC_DRV_PCF8563 is not set +# CONFIG_RTC_DRV_PCF8583 is not set +# CONFIG_RTC_DRV_M41T80 is not set + +# +# SPI RTC drivers +# + +# +# Platform RTC drivers +# +# CONFIG_RTC_DRV_CMOS is not set +# CONFIG_RTC_DRV_DS1553 is not set +# CONFIG_RTC_DRV_STK17TA8 is not set +# CONFIG_RTC_DRV_DS1742 is not set +# CONFIG_RTC_DRV_M48T86 is not set +# CONFIG_RTC_DRV_M48T59 is not set +# CONFIG_RTC_DRV_V3020 is not set + +# +# on-CPU RTC drivers +# # # DMA Engine support diff --git a/arch/powerpc/configs/mpc832x_rdb_defconfig b/arch/powerpc/configs/mpc832x_rdb_defconfig index 4f39102..7a5b13f 100644 --- a/arch/powerpc/configs/mpc832x_rdb_defconfig +++ b/arch/powerpc/configs/mpc832x_rdb_defconfig @@ -685,8 +685,21 @@ CONFIG_I2C_MPC=y # # SPI support # -# CONFIG_SPI is not set -# CONFIG_SPI_MASTER is not set +CONFIG_SPI=y +CONFIG_SPI_MASTER=y + +# +# SPI Master Controller Drivers +# +CONFIG_SPI_BITBANG=y +CONFIG_SPI_MPC83xx=y + +# +# SPI Protocol Masters +# +# CONFIG_SPI_AT25 is not set +# CONFIG_SPI_SPIDEV is not set +# CONFIG_SPI_TLE62X0 is not set # CONFIG_W1 is not set # CONFIG_POWER_SUPPLY is not set CONFIG_HWMON=y @@ -710,6 +723,7 @@ CONFIG_HWMON=y # CONFIG_SENSORS_GL520SM is not set # CONFIG_SENSORS_IT87 is not set # CONFIG_SENSORS_LM63 is not set +# CONFIG_SENSORS_LM70 is not set # CONFIG_SENSORS_LM75 is not set # CONFIG_SENSORS_LM77 is not set # CONFIG_SENSORS_LM78 is not set @@ -896,7 +910,24 @@ CONFIG_USB_MON=y # USB Gadget Support # # CONFIG_USB_GADGET is not set -# CONFIG_MMC is not set +CONFIG_MMC=y +# CONFIG_MMC_DEBUG is not set +# CONFIG_MMC_UNSAFE_RESUME is not set + +# +# MMC/SD Card Drivers +# +CONFIG_MMC_BLOCK=y +CONFIG_MMC_BLOCK_BOUNCE=y +# CONFIG_SDIO_UART is not set + +# +# MMC/SD Host Controller Drivers +# +# CONFIG_MMC_SDHCI is not set +# CONFIG_MMC_WBSD is not set +# CONFIG_MMC_TIFM_SD is not set +CONFIG_MMC_SPI=y # CONFIG_NEW_LEDS is not set # CONFIG_INFINIBAND is not set # CONFIG_EDAC is not set @@ -1101,9 +1132,9 @@ CONFIG_UCC=y CONFIG_BITREVERSE=y # CONFIG_CRC_CCITT is not set # CONFIG_CRC16 is not set -# CONFIG_CRC_ITU_T is not set +CONFIG_CRC_ITU_T=y CONFIG_CRC32=y -# CONFIG_CRC7 is not set +CONFIG_CRC7=y # CONFIG_LIBCRC32C is not set CONFIG_PLIST=y CONFIG_HAS_IOMEM=y diff --git a/arch/powerpc/configs/mpc834x_itx_defconfig b/arch/powerpc/configs/mpc834x_itx_defconfig index eb28dd8..ba512d1 100644 --- a/arch/powerpc/configs/mpc834x_itx_defconfig +++ b/arch/powerpc/configs/mpc834x_itx_defconfig @@ -867,7 +867,7 @@ CONFIG_USB_EHCI_ROOT_HUB_TT=y CONFIG_USB_EHCI_FSL=y # CONFIG_USB_ISP116X_HCD is not set # CONFIG_USB_OHCI_HCD is not set -# CONFIG_USB_UHCI_HCD is not set +CONFIG_USB_UHCI_HCD=y # CONFIG_USB_SL811_HCD is not set # CONFIG_USB_R8A66597_HCD is not set diff --git a/arch/powerpc/configs/mpc834x_itxgp_defconfig b/arch/powerpc/configs/mpc834x_itxgp_defconfig index 22b9546..9faa948 100644 --- a/arch/powerpc/configs/mpc834x_itxgp_defconfig +++ b/arch/powerpc/configs/mpc834x_itxgp_defconfig @@ -760,15 +760,101 @@ CONFIG_USB_SUPPORT=y CONFIG_USB_ARCH_HAS_HCD=y CONFIG_USB_ARCH_HAS_OHCI=y CONFIG_USB_ARCH_HAS_EHCI=y -# CONFIG_USB is not set +CONFIG_USB=y +# CONFIG_USB_DEBUG is not set + +# +# Miscellaneous USB options +# +# CONFIG_USB_DEVICEFS is not set +CONFIG_USB_DEVICE_CLASS=y +# CONFIG_USB_DYNAMIC_MINORS is not set +# CONFIG_USB_OTG is not set + +# +# USB Host Controller Drivers +# +CONFIG_USB_EHCI_HCD=y +# CONFIG_USB_EHCI_SPLIT_ISO is not set CONFIG_USB_EHCI_ROOT_HUB_TT=y +# CONFIG_USB_EHCI_TT_NEWSCHED is not set CONFIG_USB_EHCI_FSL=y +# CONFIG_USB_ISP116X_HCD is not set +# CONFIG_USB_OHCI_HCD is not set +CONFIG_USB_UHCI_HCD=y +# CONFIG_USB_SL811_HCD is not set +# CONFIG_USB_R8A66597_HCD is not set + +# +# USB Device Class drivers +# +# CONFIG_USB_ACM is not set +# CONFIG_USB_PRINTER is not set # # NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' # # +# may also be needed; see USB_STORAGE Help for more information +# +CONFIG_USB_STORAGE=y +# CONFIG_USB_STORAGE_DEBUG is not set +# CONFIG_USB_STORAGE_DATAFAB is not set +# CONFIG_USB_STORAGE_FREECOM is not set +# CONFIG_USB_STORAGE_DPCM is not set +# CONFIG_USB_STORAGE_USBAT is not set +# CONFIG_USB_STORAGE_SDDR09 is not set +# CONFIG_USB_STORAGE_SDDR55 is not set +# CONFIG_USB_STORAGE_JUMPSHOT is not set +# CONFIG_USB_STORAGE_ALAUDA is not set +# CONFIG_USB_STORAGE_KARMA is not set +# CONFIG_USB_LIBUSUAL is not set + +# +# USB Imaging devices +# +# CONFIG_USB_MDC800 is not set +# CONFIG_USB_MICROTEK is not set +CONFIG_USB_MON=y + +# +# USB port drivers +# + +# +# USB Serial Converter support +# +# CONFIG_USB_SERIAL is not set + +# +# USB Miscellaneous drivers +# +# CONFIG_USB_EMI62 is not set +# CONFIG_USB_EMI26 is not set +# CONFIG_USB_ADUTUX is not set +# CONFIG_USB_AUERSWALD is not set +# CONFIG_USB_RIO500 is not set +# CONFIG_USB_LEGOTOWER is not set +# CONFIG_USB_LCD is not set +# CONFIG_USB_BERRY_CHARGE is not set +# CONFIG_USB_LED is not set +# CONFIG_USB_CYPRESS_CY7C63 is not set +# CONFIG_USB_CYTHERM is not set +# CONFIG_USB_PHIDGET is not set +# CONFIG_USB_IDMOUSE is not set +# CONFIG_USB_FTDI_ELAN is not set +# CONFIG_USB_APPLEDISPLAY is not set +# CONFIG_USB_SISUSBVGA is not set +# CONFIG_USB_LD is not set +# CONFIG_USB_TRANCEVIBRATOR is not set +# CONFIG_USB_IOWARRIOR is not set + +# +# USB DSL modem support +# + +# # USB Gadget Support # # CONFIG_USB_GADGET is not set diff --git a/arch/powerpc/configs/mpc834x_mds_defconfig b/arch/powerpc/configs/mpc834x_mds_defconfig index e59a88e..356f736 100644 --- a/arch/powerpc/configs/mpc834x_mds_defconfig +++ b/arch/powerpc/configs/mpc834x_mds_defconfig @@ -721,7 +721,53 @@ CONFIG_USB_EHCI_FSL=y # CONFIG_NEW_LEDS is not set # CONFIG_INFINIBAND is not set # CONFIG_EDAC is not set -# CONFIG_RTC_CLASS is not set +CONFIG_RTC_LIB=y +CONFIG_RTC_CLASS=y +CONFIG_RTC_HCTOSYS=y +CONFIG_RTC_HCTOSYS_DEVICE="rtc0" +# CONFIG_RTC_DEBUG is not set + +# +# RTC interfaces +# +CONFIG_RTC_INTF_SYSFS=y +CONFIG_RTC_INTF_PROC=y +CONFIG_RTC_INTF_DEV=y +# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set +# CONFIG_RTC_DRV_TEST is not set + +# +# I2C RTC drivers +# +# CONFIG_RTC_DRV_DS1307 is not set +CONFIG_RTC_DRV_DS1374=y +# CONFIG_RTC_DRV_DS1672 is not set +# CONFIG_RTC_DRV_MAX6900 is not set +# CONFIG_RTC_DRV_RS5C372 is not set +# CONFIG_RTC_DRV_ISL1208 is not set +# CONFIG_RTC_DRV_X1205 is not set +# CONFIG_RTC_DRV_PCF8563 is not set +# CONFIG_RTC_DRV_PCF8583 is not set +# CONFIG_RTC_DRV_M41T80 is not set + +# +# SPI RTC drivers +# + +# +# Platform RTC drivers +# +# CONFIG_RTC_DRV_CMOS is not set +# CONFIG_RTC_DRV_DS1553 is not set +# CONFIG_RTC_DRV_STK17TA8 is not set +# CONFIG_RTC_DRV_DS1742 is not set +# CONFIG_RTC_DRV_M48T86 is not set +# CONFIG_RTC_DRV_M48T59 is not set +# CONFIG_RTC_DRV_V3020 is not set + +# +# on-CPU RTC drivers +# # # DMA Engine support diff --git a/arch/powerpc/configs/mpc836x_mds_defconfig b/arch/powerpc/configs/mpc836x_mds_defconfig index 7565752..1b4d375 100644 --- a/arch/powerpc/configs/mpc836x_mds_defconfig +++ b/arch/powerpc/configs/mpc836x_mds_defconfig @@ -773,7 +773,53 @@ CONFIG_USB_ARCH_HAS_EHCI=y # CONFIG_NEW_LEDS is not set # CONFIG_INFINIBAND is not set # CONFIG_EDAC is not set -# CONFIG_RTC_CLASS is not set +CONFIG_RTC_LIB=y +CONFIG_RTC_CLASS=y +CONFIG_RTC_HCTOSYS=y +CONFIG_RTC_HCTOSYS_DEVICE="rtc0" +# CONFIG_RTC_DEBUG is not set + +# +# RTC interfaces +# +CONFIG_RTC_INTF_SYSFS=y +CONFIG_RTC_INTF_PROC=y +CONFIG_RTC_INTF_DEV=y +# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set +# CONFIG_RTC_DRV_TEST is not set + +# +# I2C RTC drivers +# +# CONFIG_RTC_DRV_DS1307 is not set +CONFIG_RTC_DRV_DS1374=y +# CONFIG_RTC_DRV_DS1672 is not set +# CONFIG_RTC_DRV_MAX6900 is not set +# CONFIG_RTC_DRV_RS5C372 is not set +# CONFIG_RTC_DRV_ISL1208 is not set +# CONFIG_RTC_DRV_X1205 is not set +# CONFIG_RTC_DRV_PCF8563 is not set +# CONFIG_RTC_DRV_PCF8583 is not set +# CONFIG_RTC_DRV_M41T80 is not set + +# +# SPI RTC drivers +# + +# +# Platform RTC drivers +# +# CONFIG_RTC_DRV_CMOS is not set +# CONFIG_RTC_DRV_DS1553 is not set +# CONFIG_RTC_DRV_STK17TA8 is not set +# CONFIG_RTC_DRV_DS1742 is not set +# CONFIG_RTC_DRV_M48T86 is not set +# CONFIG_RTC_DRV_M48T59 is not set +# CONFIG_RTC_DRV_V3020 is not set + +# +# on-CPU RTC drivers +# # # DMA Engine support diff --git a/arch/powerpc/configs/mpc8568mds_defconfig b/arch/powerpc/configs/mpc8568mds_defconfig index 883d8af..d665e7a 100644 --- a/arch/powerpc/configs/mpc8568mds_defconfig +++ b/arch/powerpc/configs/mpc8568mds_defconfig @@ -768,7 +768,53 @@ CONFIG_USB_ARCH_HAS_EHCI=y # CONFIG_NEW_LEDS is not set # CONFIG_INFINIBAND is not set # CONFIG_EDAC is not set -# CONFIG_RTC_CLASS is not set +CONFIG_RTC_LIB=y +CONFIG_RTC_CLASS=y +CONFIG_RTC_HCTOSYS=y +CONFIG_RTC_HCTOSYS_DEVICE="rtc0" +# CONFIG_RTC_DEBUG is not set + +# +# RTC interfaces +# +CONFIG_RTC_INTF_SYSFS=y +CONFIG_RTC_INTF_PROC=y +CONFIG_RTC_INTF_DEV=y +# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set +# CONFIG_RTC_DRV_TEST is not set + +# +# I2C RTC drivers +# +# CONFIG_RTC_DRV_DS1307 is not set +CONFIG_RTC_DRV_DS1374=y +# CONFIG_RTC_DRV_DS1672 is not set +# CONFIG_RTC_DRV_MAX6900 is not set +# CONFIG_RTC_DRV_RS5C372 is not set +# CONFIG_RTC_DRV_ISL1208 is not set +# CONFIG_RTC_DRV_X1205 is not set +# CONFIG_RTC_DRV_PCF8563 is not set +# CONFIG_RTC_DRV_PCF8583 is not set +# CONFIG_RTC_DRV_M41T80 is not set + +# +# SPI RTC drivers +# + +# +# Platform RTC drivers +# +# CONFIG_RTC_DRV_CMOS is not set +# CONFIG_RTC_DRV_DS1553 is not set +# CONFIG_RTC_DRV_STK17TA8 is not set +# CONFIG_RTC_DRV_DS1742 is not set +# CONFIG_RTC_DRV_M48T86 is not set +# CONFIG_RTC_DRV_M48T59 is not set +# CONFIG_RTC_DRV_V3020 is not set + +# +# on-CPU RTC drivers +# # # DMA Engine support diff --git a/arch/powerpc/configs/pasemi_defconfig b/arch/powerpc/configs/pasemi_defconfig index 1ccf3ed..78c968a 100644 --- a/arch/powerpc/configs/pasemi_defconfig +++ b/arch/powerpc/configs/pasemi_defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.23-rc4 -# Thu Aug 30 16:40:47 2007 +# Linux kernel version: 2.6.24-rc2 +# Tue Nov 6 23:23:50 2007 # CONFIG_PPC64=y @@ -10,6 +10,7 @@ CONFIG_PPC64=y # CONFIG_POWER4_ONLY=y CONFIG_POWER4=y +# CONFIG_TUNE_CELL is not set CONFIG_PPC_FPU=y CONFIG_ALTIVEC=y CONFIG_PPC_STD_MMU=y @@ -18,8 +19,13 @@ CONFIG_PPC_MM_SLICES=y CONFIG_SMP=y CONFIG_NR_CPUS=2 CONFIG_64BIT=y +CONFIG_WORD_SIZE=64 CONFIG_PPC_MERGE=y CONFIG_MMU=y +CONFIG_GENERIC_CMOS_UPDATE=y +CONFIG_GENERIC_TIME=y +CONFIG_GENERIC_TIME_VSYSCALL=y +CONFIG_GENERIC_CLOCKEVENTS=y CONFIG_GENERIC_HARDIRQS=y CONFIG_IRQ_PER_CPU=y CONFIG_RWSEM_XCHGADD_ALGORITHM=y @@ -65,7 +71,10 @@ CONFIG_SYSVIPC_SYSCTL=y # CONFIG_AUDIT is not set # CONFIG_IKCONFIG is not set CONFIG_LOG_BUF_SHIFT=17 -# CONFIG_CPUSETS is not set +# CONFIG_CGROUPS is not set +CONFIG_FAIR_GROUP_SCHED=y +CONFIG_FAIR_USER_SCHED=y +# CONFIG_FAIR_CGROUP_SCHED is not set CONFIG_SYSFS_DEPRECATED=y # CONFIG_RELAY is not set CONFIG_BLK_DEV_INITRD=y @@ -86,7 +95,6 @@ CONFIG_FUTEX=y CONFIG_ANON_INODES=y CONFIG_EPOLL=y CONFIG_SIGNALFD=y -CONFIG_TIMERFD=y CONFIG_EVENTFD=y CONFIG_SHMEM=y CONFIG_VM_EVENT_COUNTERS=y @@ -107,14 +115,15 @@ CONFIG_STOP_MACHINE=y CONFIG_BLOCK=y # CONFIG_BLK_DEV_IO_TRACE is not set # CONFIG_BLK_DEV_BSG is not set +CONFIG_BLOCK_COMPAT=y # # IO Schedulers # CONFIG_IOSCHED_NOOP=y CONFIG_IOSCHED_AS=y -# CONFIG_IOSCHED_DEADLINE is not set -# CONFIG_IOSCHED_CFQ is not set +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y CONFIG_DEFAULT_AS=y # CONFIG_DEFAULT_DEADLINE is not set # CONFIG_DEFAULT_CFQ is not set @@ -125,7 +134,6 @@ CONFIG_DEFAULT_IOSCHED="anticipatory" # Platform support # CONFIG_PPC_MULTIPLATFORM=y -# CONFIG_EMBEDDED6xx is not set # CONFIG_PPC_82xx is not set # CONFIG_PPC_83xx is not set # CONFIG_PPC_86xx is not set @@ -141,6 +149,7 @@ CONFIG_PPC_PASEMI=y # PA Semi PWRficient options # CONFIG_PPC_PASEMI_IOMMU=y +# CONFIG_PPC_PASEMI_IOMMU_DMA_FORCE is not set CONFIG_PPC_PASEMI_MDIO=y CONFIG_ELECTRA_IDE=y # CONFIG_PPC_CELLEB is not set @@ -156,29 +165,52 @@ CONFIG_MPIC=y # CONFIG_U3_DART is not set # CONFIG_PPC_RTAS is not set # CONFIG_MMIO_NVRAM is not set +CONFIG_MPIC_BROKEN_REGREAD=y # CONFIG_PPC_MPC106 is not set # CONFIG_PPC_970_NAP is not set # CONFIG_PPC_INDIRECT_IO is not set # CONFIG_GENERIC_IOMAP is not set -# CONFIG_CPU_FREQ is not set +CONFIG_CPU_FREQ=y +CONFIG_CPU_FREQ_TABLE=y +CONFIG_CPU_FREQ_DEBUG=y +CONFIG_CPU_FREQ_STAT=y +# CONFIG_CPU_FREQ_STAT_DETAILS is not set +CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y +# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set +# CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND is not set +# CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE is not set +CONFIG_CPU_FREQ_GOV_PERFORMANCE=y +CONFIG_CPU_FREQ_GOV_POWERSAVE=y +CONFIG_CPU_FREQ_GOV_USERSPACE=y +CONFIG_CPU_FREQ_GOV_ONDEMAND=y +# CONFIG_CPU_FREQ_GOV_CONSERVATIVE is not set + +# +# CPU Frequency drivers +# +CONFIG_PPC_PASEMI_CPUFREQ=y # CONFIG_CPM2 is not set # CONFIG_FSL_ULI1575 is not set # # Kernel options # -CONFIG_HZ_100=y +CONFIG_TICK_ONESHOT=y +CONFIG_NO_HZ=y +CONFIG_HIGH_RES_TIMERS=y +CONFIG_GENERIC_CLOCKEVENTS_BUILD=y +# CONFIG_HZ_100 is not set # CONFIG_HZ_250 is not set # CONFIG_HZ_300 is not set -# CONFIG_HZ_1000 is not set -CONFIG_HZ=100 +CONFIG_HZ_1000=y +CONFIG_HZ=1000 CONFIG_PREEMPT_NONE=y # CONFIG_PREEMPT_VOLUNTARY is not set # CONFIG_PREEMPT is not set -CONFIG_PREEMPT_BKL=y +# CONFIG_PREEMPT_BKL is not set CONFIG_BINFMT_ELF=y # CONFIG_BINFMT_MISC is not set -CONFIG_FORCE_MAX_ZONEORDER=13 +CONFIG_FORCE_MAX_ZONEORDER=9 CONFIG_IOMMU_VMERGE=y CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y # CONFIG_KEXEC is not set @@ -196,12 +228,13 @@ CONFIG_FLATMEM_MANUAL=y CONFIG_FLATMEM=y CONFIG_FLAT_NODE_MEM_MAP=y # CONFIG_SPARSEMEM_STATIC is not set +CONFIG_SPARSEMEM_VMEMMAP_ENABLE=y CONFIG_SPLIT_PTLOCK_CPUS=4 CONFIG_RESOURCES_64BIT=y CONFIG_ZONE_DMA_FLAG=1 CONFIG_BOUNCE=y -# CONFIG_PPC_HAS_HASH_64K is not set -# CONFIG_PPC_64K_PAGES is not set +CONFIG_PPC_HAS_HASH_64K=y +CONFIG_PPC_64K_PAGES=y # CONFIG_SCHED_SMT is not set CONFIG_PROC_DEVICETREE=y # CONFIG_CMDLINE_BOOL is not set @@ -222,11 +255,8 @@ CONFIG_PCI_SYSCALL=y # CONFIG_PCIEPORTBUS is not set CONFIG_ARCH_SUPPORTS_MSI=y # CONFIG_PCI_MSI is not set +CONFIG_PCI_LEGACY=y # CONFIG_PCI_DEBUG is not set - -# -# PCCARD (PCMCIA/CardBus) support -# CONFIG_PCCARD=y CONFIG_PCMCIA_DEBUG=y CONFIG_PCMCIA=y @@ -240,6 +270,7 @@ CONFIG_CARDBUS=y # CONFIG_YENTA is not set # CONFIG_PD6729 is not set # CONFIG_I82092 is not set +# CONFIG_ELECTRA_CF is not set # CONFIG_HOTPLUG_PCI is not set CONFIG_KERNEL_START=0xc000000000000000 @@ -255,7 +286,7 @@ CONFIG_PACKET=y # CONFIG_PACKET_MMAP is not set CONFIG_UNIX=y CONFIG_XFRM=y -# CONFIG_XFRM_USER is not set +CONFIG_XFRM_USER=y # CONFIG_XFRM_SUB_POLICY is not set # CONFIG_XFRM_MIGRATE is not set CONFIG_NET_KEY=y @@ -281,6 +312,7 @@ CONFIG_INET_TUNNEL=y CONFIG_INET_XFRM_MODE_TRANSPORT=y CONFIG_INET_XFRM_MODE_TUNNEL=y CONFIG_INET_XFRM_MODE_BEET=y +CONFIG_INET_LRO=y CONFIG_INET_DIAG=y CONFIG_INET_TCP_DIAG=y # CONFIG_TCP_CONG_ADVANCED is not set @@ -306,10 +338,6 @@ CONFIG_DEFAULT_TCP_CONG="cubic" # CONFIG_LAPB is not set # CONFIG_ECONET is not set # CONFIG_WAN_ROUTER is not set - -# -# QoS and/or fair queueing -# # CONFIG_NET_SCHED is not set # @@ -338,6 +366,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic" # # Generic Driver Options # +CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" CONFIG_STANDALONE=y CONFIG_PREVENT_FIRMWARE_BUILD=y CONFIG_FW_LOADER=y @@ -361,6 +390,7 @@ CONFIG_MTD_BLOCK=y # CONFIG_INFTL is not set # CONFIG_RFD_FTL is not set # CONFIG_SSFDC is not set +# CONFIG_MTD_OOPS is not set # # RAM/ROM/Flash chip drivers @@ -385,6 +415,7 @@ CONFIG_MTD_CFI_I2=y # Mapping drivers for chip access # # CONFIG_MTD_COMPLEX_MAPPINGS is not set +# CONFIG_MTD_INTEL_VR_NOR is not set # CONFIG_MTD_PLATRAM is not set # @@ -402,7 +433,15 @@ CONFIG_MTD_PHRAM=y # CONFIG_MTD_DOC2000 is not set # CONFIG_MTD_DOC2001 is not set # CONFIG_MTD_DOC2001PLUS is not set -# CONFIG_MTD_NAND is not set +CONFIG_MTD_NAND=y +# CONFIG_MTD_NAND_VERIFY_WRITE is not set +# CONFIG_MTD_NAND_ECC_SMC is not set +# CONFIG_MTD_NAND_MUSEUM_IDS is not set +CONFIG_MTD_NAND_IDS=y +# CONFIG_MTD_NAND_DISKONCHIP is not set +# CONFIG_MTD_NAND_CAFE is not set +# CONFIG_MTD_NAND_PLATFORM is not set +# CONFIG_MTD_ALAUDA is not set # CONFIG_MTD_ONENAND is not set # @@ -455,10 +494,42 @@ CONFIG_IDE_PROC_FS=y # IDE chipset support/bugfixes # # CONFIG_IDE_GENERIC is not set -# CONFIG_BLK_DEV_IDEPCI is not set +# CONFIG_BLK_DEV_PLATFORM is not set + +# +# PCI IDE chipsets support +# # CONFIG_IDEPCI_PCIBUS_ORDER is not set +# CONFIG_BLK_DEV_GENERIC is not set +# CONFIG_BLK_DEV_OPTI621 is not set +# CONFIG_BLK_DEV_AEC62XX is not set +# CONFIG_BLK_DEV_ALI15X3 is not set +# CONFIG_BLK_DEV_AMD74XX is not set +# CONFIG_BLK_DEV_CMD64X is not set +# CONFIG_BLK_DEV_TRIFLEX is not set +# CONFIG_BLK_DEV_CY82C693 is not set +# CONFIG_BLK_DEV_CS5520 is not set +# CONFIG_BLK_DEV_CS5530 is not set +# CONFIG_BLK_DEV_HPT34X is not set +# CONFIG_BLK_DEV_HPT366 is not set +# CONFIG_BLK_DEV_JMICRON is not set +# CONFIG_BLK_DEV_SC1200 is not set +# CONFIG_BLK_DEV_PIIX is not set +# CONFIG_BLK_DEV_IT8213 is not set +# CONFIG_BLK_DEV_IT821X is not set +# CONFIG_BLK_DEV_NS87415 is not set +# CONFIG_BLK_DEV_PDC202XX_OLD is not set +# CONFIG_BLK_DEV_PDC202XX_NEW is not set +# CONFIG_BLK_DEV_SVWKS is not set +# CONFIG_BLK_DEV_SIIMAGE is not set +# CONFIG_BLK_DEV_SL82C105 is not set +# CONFIG_BLK_DEV_SLC90E66 is not set +# CONFIG_BLK_DEV_TRM290 is not set +# CONFIG_BLK_DEV_VIA82CXXX is not set +# CONFIG_BLK_DEV_TC86C001 is not set # CONFIG_IDE_ARM is not set # CONFIG_BLK_DEV_IDEDMA is not set +CONFIG_IDE_ARCH_OBSOLETE_INIT=y # CONFIG_BLK_DEV_HD is not set # @@ -498,10 +569,11 @@ CONFIG_SCSI_WAIT_SCAN=m # CONFIG_SCSI_FC_ATTRS is not set # CONFIG_SCSI_ISCSI_ATTRS is not set # CONFIG_SCSI_SAS_LIBSAS is not set +# CONFIG_SCSI_SRP_ATTRS is not set CONFIG_SCSI_LOWLEVEL=y # CONFIG_ISCSI_TCP is not set -CONFIG_BLK_DEV_3W_XXXX_RAID=y -CONFIG_SCSI_3W_9XXX=y +# CONFIG_BLK_DEV_3W_XXXX_RAID is not set +# CONFIG_SCSI_3W_9XXX is not set # CONFIG_SCSI_ACARD is not set # CONFIG_SCSI_AACRAID is not set # CONFIG_SCSI_AIC7XXX is not set @@ -574,9 +646,10 @@ CONFIG_ATA_GENERIC=y # CONFIG_PATA_OLDPIIX is not set # CONFIG_PATA_NETCELL is not set # CONFIG_PATA_NS87410 is not set +# CONFIG_PATA_NS87415 is not set # CONFIG_PATA_OPTI is not set # CONFIG_PATA_OPTIDMA is not set -# CONFIG_PATA_PCMCIA is not set +CONFIG_PATA_PCMCIA=y # CONFIG_PATA_PDC_OLD is not set # CONFIG_PATA_RADISYS is not set # CONFIG_PATA_RZ1000 is not set @@ -589,41 +662,13 @@ CONFIG_ATA_GENERIC=y # CONFIG_PATA_WINBOND is not set CONFIG_PATA_PLATFORM=y # CONFIG_MD is not set - -# -# Fusion MPT device support -# # CONFIG_FUSION is not set -# CONFIG_FUSION_SPI is not set -# CONFIG_FUSION_FC is not set -# CONFIG_FUSION_SAS is not set # # IEEE 1394 (FireWire) support # # CONFIG_FIREWIRE is not set -CONFIG_IEEE1394=y - -# -# Subsystem Options -# -# CONFIG_IEEE1394_VERBOSEDEBUG is not set - -# -# Controllers -# -CONFIG_IEEE1394_PCILYNX=y -CONFIG_IEEE1394_OHCI1394=y - -# -# Protocols -# -# CONFIG_IEEE1394_VIDEO1394 is not set -CONFIG_IEEE1394_SBP2=y -# CONFIG_IEEE1394_ETH1394_ROM_ENTRY is not set -# CONFIG_IEEE1394_ETH1394 is not set -# CONFIG_IEEE1394_DV1394 is not set -CONFIG_IEEE1394_RAWIO=y +# CONFIG_IEEE1394 is not set # CONFIG_I2O is not set # CONFIG_MACINTOSH_DRIVERS is not set CONFIG_NETDEVICES=y @@ -633,6 +678,8 @@ CONFIG_DUMMY=y # CONFIG_MACVLAN is not set # CONFIG_EQUALIZER is not set # CONFIG_TUN is not set +# CONFIG_VETH is not set +# CONFIG_IP1000 is not set # CONFIG_ARCNET is not set CONFIG_PHYLIB=y @@ -649,6 +696,7 @@ CONFIG_MARVELL_PHY=y # CONFIG_BROADCOM_PHY is not set # CONFIG_ICPLUS_PHY is not set # CONFIG_FIXED_PHY is not set +# CONFIG_MDIO_BITBANG is not set CONFIG_NET_ETHERNET=y CONFIG_MII=y # CONFIG_HAPPYMEAL is not set @@ -657,13 +705,16 @@ CONFIG_MII=y # CONFIG_NET_VENDOR_3COM is not set # CONFIG_NET_TULIP is not set # CONFIG_HP100 is not set +# CONFIG_IBM_NEW_EMAC_ZMII is not set +# CONFIG_IBM_NEW_EMAC_RGMII is not set +# CONFIG_IBM_NEW_EMAC_TAH is not set +# CONFIG_IBM_NEW_EMAC_EMAC4 is not set CONFIG_NET_PCI=y # CONFIG_PCNET32 is not set # CONFIG_AMD8111_ETH is not set # CONFIG_ADAPTEC_STARFIRE is not set # CONFIG_B44 is not set # CONFIG_FORCEDETH is not set -# CONFIG_DGRS is not set # CONFIG_EEPRO100 is not set # CONFIG_E100 is not set # CONFIG_FEALNX is not set @@ -682,6 +733,7 @@ CONFIG_NETDEV_1000=y CONFIG_E1000=y CONFIG_E1000_NAPI=y # CONFIG_E1000_DISABLE_PACKET_SPLIT is not set +# CONFIG_E1000E is not set # CONFIG_NS83820 is not set # CONFIG_HAMACHI is not set # CONFIG_YELLOWFIN is not set @@ -689,6 +741,7 @@ CONFIG_E1000_NAPI=y # CONFIG_SIS190 is not set # CONFIG_SKGE is not set # CONFIG_SKY2 is not set +# CONFIG_SK98LIN is not set # CONFIG_VIA_VELOCITY is not set CONFIG_TIGON3=y # CONFIG_BNX2 is not set @@ -697,12 +750,15 @@ CONFIG_TIGON3=y CONFIG_NETDEV_10000=y # CONFIG_CHELSIO_T1 is not set # CONFIG_CHELSIO_T3 is not set +# CONFIG_IXGBE is not set # CONFIG_IXGB is not set # CONFIG_S2IO is not set # CONFIG_MYRI10GE is not set # CONFIG_NETXEN_NIC is not set +# CONFIG_NIU is not set CONFIG_PASEMI_MAC=y # CONFIG_MLX4_CORE is not set +# CONFIG_TEHUTI is not set # CONFIG_TR is not set # @@ -749,7 +805,6 @@ CONFIG_INPUT_MOUSEDEV_PSAUX=y CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 CONFIG_INPUT_JOYDEV=y -# CONFIG_INPUT_TSDEV is not set CONFIG_INPUT_EVDEV=y # CONFIG_INPUT_EVBUG is not set @@ -810,15 +865,12 @@ CONFIG_UNIX98_PTYS=y CONFIG_LEGACY_PTYS=y CONFIG_LEGACY_PTY_COUNT=4 # CONFIG_IPMI_HANDLER is not set -# CONFIG_WATCHDOG is not set CONFIG_HW_RANDOM=y CONFIG_HW_RANDOM_PASEMI=y CONFIG_GEN_RTC=y CONFIG_GEN_RTC_X=y # CONFIG_R3964 is not set # CONFIG_APPLICOM is not set -# CONFIG_AGP is not set -# CONFIG_DRM is not set # # PCMCIA character devices @@ -896,8 +948,6 @@ CONFIG_SENSORS_EEPROM=y # CONFIG_POWER_SUPPLY is not set CONFIG_HWMON=y CONFIG_HWMON_VID=y -# CONFIG_SENSORS_ABITUGURU is not set -# CONFIG_SENSORS_ABITUGURU3 is not set # CONFIG_SENSORS_AD7418 is not set # CONFIG_SENSORS_ADM1021 is not set # CONFIG_SENSORS_ADM1025 is not set @@ -905,12 +955,12 @@ CONFIG_HWMON_VID=y # CONFIG_SENSORS_ADM1029 is not set # CONFIG_SENSORS_ADM1031 is not set # CONFIG_SENSORS_ADM9240 is not set -# CONFIG_SENSORS_ASB100 is not set +# CONFIG_SENSORS_ADT7470 is not set # CONFIG_SENSORS_ATXP1 is not set # CONFIG_SENSORS_DS1621 is not set # CONFIG_SENSORS_F71805F is not set -# CONFIG_SENSORS_FSCHER is not set -# CONFIG_SENSORS_FSCPOS is not set +# CONFIG_SENSORS_F71882FG is not set +# CONFIG_SENSORS_F75375S is not set # CONFIG_SENSORS_GL518SM is not set # CONFIG_SENSORS_GL520SM is not set # CONFIG_SENSORS_IT87 is not set @@ -946,6 +996,13 @@ CONFIG_SENSORS_LM90=y # CONFIG_SENSORS_W83627HF is not set # CONFIG_SENSORS_W83627EHF is not set # CONFIG_HWMON_DEBUG_CHIP is not set +# CONFIG_WATCHDOG is not set + +# +# Sonics Silicon Backplane +# +CONFIG_SSB_POSSIBLE=y +# CONFIG_SSB is not set # # Multifunction device drivers @@ -963,14 +1020,14 @@ CONFIG_DAB=y # # Graphics support # -CONFIG_BACKLIGHT_LCD_SUPPORT=y -CONFIG_LCD_CLASS_DEVICE=m -CONFIG_BACKLIGHT_CLASS_DEVICE=y - -# -# Display device support -# -# CONFIG_DISPLAY_SUPPORT is not set +# CONFIG_AGP is not set +CONFIG_DRM=y +# CONFIG_DRM_TDFX is not set +# CONFIG_DRM_R128 is not set +CONFIG_DRM_RADEON=y +# CONFIG_DRM_MGA is not set +# CONFIG_DRM_VIA is not set +# CONFIG_DRM_SAVAGE is not set CONFIG_VGASTATE=y # CONFIG_VIDEO_OUTPUT_CONTROL is not set CONFIG_FB=y @@ -979,6 +1036,7 @@ CONFIG_FB_DDC=y CONFIG_FB_CFB_FILLRECT=y CONFIG_FB_CFB_COPYAREA=y CONFIG_FB_CFB_IMAGEBLIT=y +# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set # CONFIG_FB_SYS_FILLRECT is not set # CONFIG_FB_SYS_COPYAREA is not set # CONFIG_FB_SYS_IMAGEBLIT is not set @@ -1026,6 +1084,15 @@ CONFIG_FB_RADEON_BACKLIGHT=y # CONFIG_FB_PM3 is not set # CONFIG_FB_IBM_GXT4500 is not set # CONFIG_FB_VIRTUAL is not set +CONFIG_BACKLIGHT_LCD_SUPPORT=y +# CONFIG_LCD_CLASS_DEVICE is not set +CONFIG_BACKLIGHT_CLASS_DEVICE=y +# CONFIG_BACKLIGHT_CORGI is not set + +# +# Display device support +# +# CONFIG_DISPLAY_SUPPORT is not set # # Console display driver support @@ -1178,6 +1245,7 @@ CONFIG_SND_USB_USX2Y=y CONFIG_HID_SUPPORT=y CONFIG_HID=y # CONFIG_HID_DEBUG is not set +# CONFIG_HIDRAW is not set # # USB Input Devices @@ -1328,6 +1396,7 @@ CONFIG_RTC_INTF_DEV=y # I2C RTC drivers # CONFIG_RTC_DRV_DS1307=y +# CONFIG_RTC_DRV_DS1374 is not set # CONFIG_RTC_DRV_DS1672 is not set # CONFIG_RTC_DRV_MAX6900 is not set # CONFIG_RTC_DRV_RS5C372 is not set @@ -1357,19 +1426,6 @@ CONFIG_RTC_DRV_DS1307=y # # -# DMA Engine support -# -# CONFIG_DMA_ENGINE is not set - -# -# DMA Clients -# - -# -# DMA Devices -# - -# # Userspace I/O # # CONFIG_UIO is not set @@ -1388,7 +1444,6 @@ CONFIG_EXT3_FS_XATTR=y # CONFIG_EXT3_FS_SECURITY is not set # CONFIG_EXT4DEV_FS is not set CONFIG_JBD=y -# CONFIG_JBD_DEBUG is not set CONFIG_FS_MBCACHE=y # CONFIG_REISERFS_FS is not set # CONFIG_JFS_FS is not set @@ -1436,7 +1491,6 @@ CONFIG_TMPFS=y # CONFIG_TMPFS_POSIX_ACL is not set CONFIG_HUGETLBFS=y CONFIG_HUGETLB_PAGE=y -CONFIG_RAMFS=y CONFIG_CONFIGFS_FS=y # @@ -1449,30 +1503,43 @@ CONFIG_CONFIGFS_FS=y # CONFIG_BEFS_FS is not set # CONFIG_BFS_FS is not set # CONFIG_EFS_FS is not set -# CONFIG_JFFS2_FS is not set +CONFIG_JFFS2_FS=y +CONFIG_JFFS2_FS_DEBUG=0 +CONFIG_JFFS2_FS_WRITEBUFFER=y +# CONFIG_JFFS2_FS_WBUF_VERIFY is not set +# CONFIG_JFFS2_SUMMARY is not set +# CONFIG_JFFS2_FS_XATTR is not set +# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set +CONFIG_JFFS2_ZLIB=y +# CONFIG_JFFS2_LZO is not set +CONFIG_JFFS2_RTIME=y +# CONFIG_JFFS2_RUBIN is not set # CONFIG_CRAMFS is not set # CONFIG_VXFS_FS is not set # CONFIG_HPFS_FS is not set # CONFIG_QNX4FS_FS is not set # CONFIG_SYSV_FS is not set # CONFIG_UFS_FS is not set - -# -# Network File Systems -# +CONFIG_NETWORK_FILESYSTEMS=y CONFIG_NFS_FS=y CONFIG_NFS_V3=y # CONFIG_NFS_V3_ACL is not set # CONFIG_NFS_V4 is not set # CONFIG_NFS_DIRECTIO is not set -# CONFIG_NFSD is not set +CONFIG_NFSD=y +CONFIG_NFSD_V3=y +# CONFIG_NFSD_V3_ACL is not set +CONFIG_NFSD_V4=y +CONFIG_NFSD_TCP=y CONFIG_ROOT_NFS=y CONFIG_LOCKD=y CONFIG_LOCKD_V4=y +CONFIG_EXPORTFS=y CONFIG_NFS_COMMON=y CONFIG_SUNRPC=y +CONFIG_SUNRPC_GSS=y # CONFIG_SUNRPC_BIND34 is not set -# CONFIG_RPCSEC_GSS_KRB5 is not set +CONFIG_RPCSEC_GSS_KRB5=y # CONFIG_RPCSEC_GSS_SPKM3 is not set # CONFIG_SMB_FS is not set # CONFIG_CIFS is not set @@ -1501,10 +1568,6 @@ CONFIG_MSDOS_PARTITION=y # CONFIG_KARMA_PARTITION is not set # CONFIG_EFI_PARTITION is not set # CONFIG_SYSV68_PARTITION is not set - -# -# Native Language Support -# CONFIG_NLS=y CONFIG_NLS_DEFAULT="iso8859-1" CONFIG_NLS_CODEPAGE_437=y @@ -1545,10 +1608,6 @@ CONFIG_NLS_ISO8859_1=y # CONFIG_NLS_KOI8_R is not set # CONFIG_NLS_KOI8_U is not set # CONFIG_NLS_UTF8 is not set - -# -# Distributed Lock Manager -# # CONFIG_DLM is not set # CONFIG_UCC_SLOW is not set @@ -1561,23 +1620,24 @@ CONFIG_CRC_CCITT=y # CONFIG_CRC_ITU_T is not set CONFIG_CRC32=y # CONFIG_CRC7 is not set -# CONFIG_LIBCRC32C is not set +CONFIG_LIBCRC32C=m +CONFIG_ZLIB_INFLATE=y +CONFIG_ZLIB_DEFLATE=y CONFIG_PLIST=y CONFIG_HAS_IOMEM=y CONFIG_HAS_IOPORT=y CONFIG_HAS_DMA=y - -# -# Instrumentation Support -# +CONFIG_INSTRUMENTATION=y CONFIG_PROFILING=y CONFIG_OPROFILE=y # CONFIG_KPROBES is not set +# CONFIG_MARKERS is not set # # Kernel hacking # # CONFIG_PRINTK_TIME is not set +CONFIG_ENABLE_WARN_DEPRECATED=y CONFIG_ENABLE_MUST_CHECK=y CONFIG_MAGIC_SYSRQ=y # CONFIG_UNUSED_SYMBOLS is not set @@ -1586,7 +1646,7 @@ CONFIG_MAGIC_SYSRQ=y CONFIG_DEBUG_KERNEL=y # CONFIG_DEBUG_SHIRQ is not set CONFIG_DETECT_SOFTLOCKUP=y -CONFIG_SCHED_DEBUG=y +# CONFIG_SCHED_DEBUG is not set # CONFIG_SCHEDSTATS is not set # CONFIG_TIMER_STATS is not set # CONFIG_SLUB_DEBUG_ON is not set @@ -1601,9 +1661,12 @@ CONFIG_DEBUG_BUGVERBOSE=y # CONFIG_DEBUG_INFO is not set # CONFIG_DEBUG_VM is not set # CONFIG_DEBUG_LIST is not set +# CONFIG_DEBUG_SG is not set # CONFIG_FORCED_INLINING is not set +# CONFIG_BOOT_PRINTK_DELAY is not set # CONFIG_RCU_TORTURE_TEST is not set # CONFIG_FAULT_INJECTION is not set +# CONFIG_SAMPLES is not set # CONFIG_DEBUG_STACKOVERFLOW is not set # CONFIG_DEBUG_STACK_USAGE is not set # CONFIG_DEBUG_PAGEALLOC is not set @@ -1620,6 +1683,7 @@ CONFIG_XMON_DISASSEMBLY=y # # CONFIG_KEYS is not set # CONFIG_SECURITY is not set +# CONFIG_SECURITY_FILE_CAPABILITIES is not set CONFIG_CRYPTO=y CONFIG_CRYPTO_ALGAPI=y CONFIG_CRYPTO_BLKCIPHER=y @@ -1628,34 +1692,38 @@ CONFIG_CRYPTO_MANAGER=y CONFIG_CRYPTO_HMAC=y # CONFIG_CRYPTO_XCBC is not set # CONFIG_CRYPTO_NULL is not set -# CONFIG_CRYPTO_MD4 is not set +CONFIG_CRYPTO_MD4=y CONFIG_CRYPTO_MD5=y CONFIG_CRYPTO_SHA1=y -# CONFIG_CRYPTO_SHA256 is not set -# CONFIG_CRYPTO_SHA512 is not set +CONFIG_CRYPTO_SHA256=y +CONFIG_CRYPTO_SHA512=y # CONFIG_CRYPTO_WP512 is not set # CONFIG_CRYPTO_TGR192 is not set # CONFIG_CRYPTO_GF128MUL is not set -CONFIG_CRYPTO_ECB=m +# CONFIG_CRYPTO_ECB is not set CONFIG_CRYPTO_CBC=y -CONFIG_CRYPTO_PCBC=m +# CONFIG_CRYPTO_PCBC is not set # CONFIG_CRYPTO_LRW is not set +# CONFIG_CRYPTO_XTS is not set # CONFIG_CRYPTO_CRYPTD is not set CONFIG_CRYPTO_DES=y # CONFIG_CRYPTO_FCRYPT is not set -# CONFIG_CRYPTO_BLOWFISH is not set +CONFIG_CRYPTO_BLOWFISH=y # CONFIG_CRYPTO_TWOFISH is not set # CONFIG_CRYPTO_SERPENT is not set -# CONFIG_CRYPTO_AES is not set +CONFIG_CRYPTO_AES=y # CONFIG_CRYPTO_CAST5 is not set # CONFIG_CRYPTO_CAST6 is not set # CONFIG_CRYPTO_TEA is not set # CONFIG_CRYPTO_ARC4 is not set # CONFIG_CRYPTO_KHAZAD is not set # CONFIG_CRYPTO_ANUBIS is not set +# CONFIG_CRYPTO_SEED is not set # CONFIG_CRYPTO_DEFLATE is not set # CONFIG_CRYPTO_MICHAEL_MIC is not set # CONFIG_CRYPTO_CRC32C is not set # CONFIG_CRYPTO_CAMELLIA is not set # CONFIG_CRYPTO_TEST is not set -# CONFIG_CRYPTO_HW is not set +# CONFIG_CRYPTO_AUTHENC is not set +CONFIG_CRYPTO_HW=y +# CONFIG_PPC_CLOCK is not set diff --git a/arch/powerpc/configs/ppc64_defconfig b/arch/powerpc/configs/ppc64_defconfig index 05582af..3e90c83 100644 --- a/arch/powerpc/configs/ppc64_defconfig +++ b/arch/powerpc/configs/ppc64_defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.23-rc4 -# Thu Aug 30 16:47:09 2007 +# Linux kernel version: 2.6.24-rc2 +# Tue Nov 6 23:43:56 2007 # CONFIG_PPC64=y @@ -11,6 +11,7 @@ CONFIG_PPC64=y # CONFIG_POWER4_ONLY is not set CONFIG_POWER3=y CONFIG_POWER4=y +# CONFIG_TUNE_CELL is not set CONFIG_PPC_FPU=y CONFIG_ALTIVEC=y CONFIG_PPC_STD_MMU=y @@ -19,8 +20,13 @@ CONFIG_VIRT_CPU_ACCOUNTING=y CONFIG_SMP=y CONFIG_NR_CPUS=32 CONFIG_64BIT=y +CONFIG_WORD_SIZE=64 CONFIG_PPC_MERGE=y CONFIG_MMU=y +CONFIG_GENERIC_CMOS_UPDATE=y +CONFIG_GENERIC_TIME=y +CONFIG_GENERIC_TIME_VSYSCALL=y +CONFIG_GENERIC_CLOCKEVENTS=y CONFIG_GENERIC_HARDIRQS=y CONFIG_IRQ_PER_CPU=y CONFIG_RWSEM_XCHGADD_ALGORITHM=y @@ -72,8 +78,15 @@ CONFIG_IKCONFIG=y CONFIG_IKCONFIG_PROC=y CONFIG_LOG_BUF_SHIFT=17 CONFIG_CGROUPS=y +# CONFIG_CGROUP_DEBUG is not set +# CONFIG_CGROUP_NS is not set +# CONFIG_CGROUP_CPUACCT is not set CONFIG_CPUSETS=y +CONFIG_FAIR_GROUP_SCHED=y +CONFIG_FAIR_USER_SCHED=y +# CONFIG_FAIR_CGROUP_SCHED is not set CONFIG_SYSFS_DEPRECATED=y +CONFIG_PROC_PID_CPUSET=y CONFIG_RELAY=y CONFIG_BLK_DEV_INITRD=y CONFIG_INITRAMFS_SOURCE="" @@ -93,7 +106,6 @@ CONFIG_FUTEX=y CONFIG_ANON_INODES=y CONFIG_EPOLL=y CONFIG_SIGNALFD=y -CONFIG_TIMERFD=y CONFIG_EVENTFD=y CONFIG_SHMEM=y CONFIG_VM_EVENT_COUNTERS=y @@ -114,6 +126,7 @@ CONFIG_STOP_MACHINE=y CONFIG_BLOCK=y CONFIG_BLK_DEV_IO_TRACE=y CONFIG_BLK_DEV_BSG=y +CONFIG_BLOCK_COMPAT=y # # IO Schedulers @@ -132,7 +145,6 @@ CONFIG_DEFAULT_IOSCHED="anticipatory" # Platform support # CONFIG_PPC_MULTIPLATFORM=y -# CONFIG_EMBEDDED6xx is not set # CONFIG_PPC_82xx is not set # CONFIG_PPC_83xx is not set # CONFIG_PPC_86xx is not set @@ -155,7 +167,15 @@ CONFIG_VIOPATH=y CONFIG_PPC_PMAC=y CONFIG_PPC_PMAC64=y CONFIG_PPC_MAPLE=y -# CONFIG_PPC_PASEMI is not set +CONFIG_PPC_PASEMI=y + +# +# PA Semi PWRficient options +# +CONFIG_PPC_PASEMI_IOMMU=y +# CONFIG_PPC_PASEMI_IOMMU_DMA_FORCE is not set +CONFIG_PPC_PASEMI_MDIO=y +CONFIG_ELECTRA_IDE=y CONFIG_PPC_CELLEB=y # CONFIG_PPC_PS3 is not set CONFIG_PPC_CELL=y @@ -188,6 +208,7 @@ CONFIG_RTAS_FLASH=m CONFIG_PPC_PMI=m CONFIG_MMIO_NVRAM=y CONFIG_MPIC_U3_HT_IRQS=y +CONFIG_MPIC_BROKEN_REGREAD=y CONFIG_IBMVIO=y # CONFIG_IBMEBUS is not set # CONFIG_PPC_MPC106 is not set @@ -201,6 +222,8 @@ CONFIG_CPU_FREQ_STAT=y # CONFIG_CPU_FREQ_STAT_DETAILS is not set CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y # CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set +# CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND is not set +# CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE is not set CONFIG_CPU_FREQ_GOV_PERFORMANCE=y CONFIG_CPU_FREQ_GOV_POWERSAVE=y CONFIG_CPU_FREQ_GOV_USERSPACE=y @@ -211,6 +234,7 @@ CONFIG_CPU_FREQ_GOV_USERSPACE=y # CPU Frequency drivers # CONFIG_CPU_FREQ_PMAC64=y +CONFIG_PPC_PASEMI_CPUFREQ=y # CONFIG_CPM2 is not set CONFIG_AXON_RAM=m # CONFIG_FSL_ULI1575 is not set @@ -254,6 +278,8 @@ CONFIG_SPARSEMEM=y CONFIG_HAVE_MEMORY_PRESENT=y # CONFIG_SPARSEMEM_STATIC is not set CONFIG_SPARSEMEM_EXTREME=y +CONFIG_SPARSEMEM_VMEMMAP_ENABLE=y +CONFIG_SPARSEMEM_VMEMMAP=y CONFIG_MEMORY_HOTPLUG=y CONFIG_MEMORY_HOTPLUG_SPARSE=y CONFIG_SPLIT_PTLOCK_CPUS=4 @@ -268,6 +294,7 @@ CONFIG_PROC_DEVICETREE=y # CONFIG_CMDLINE_BOOL is not set # CONFIG_PM is not set CONFIG_SUSPEND_SMP_POSSIBLE=y +CONFIG_HIBERNATION_SMP_POSSIBLE=y CONFIG_SECCOMP=y # CONFIG_WANT_DEVICE_TREE is not set CONFIG_ISA_DMA_API=y @@ -284,12 +311,22 @@ CONFIG_PCI_SYSCALL=y # CONFIG_PCIEPORTBUS is not set CONFIG_ARCH_SUPPORTS_MSI=y CONFIG_PCI_MSI=y +CONFIG_PCI_LEGACY=y # CONFIG_PCI_DEBUG is not set +CONFIG_PCCARD=y +# CONFIG_PCMCIA_DEBUG is not set +CONFIG_PCMCIA=y +CONFIG_PCMCIA_LOAD_CIS=y +CONFIG_PCMCIA_IOCTL=y +CONFIG_CARDBUS=y # -# PCCARD (PCMCIA/CardBus) support +# PC-card bridges # -# CONFIG_PCCARD is not set +# CONFIG_YENTA is not set +# CONFIG_PD6729 is not set +# CONFIG_I82092 is not set +CONFIG_ELECTRA_CF=y CONFIG_HOTPLUG_PCI=m # CONFIG_HOTPLUG_PCI_FAKE is not set # CONFIG_HOTPLUG_PCI_CPCI is not set @@ -319,7 +356,10 @@ CONFIG_INET=y CONFIG_IP_MULTICAST=y # CONFIG_IP_ADVANCED_ROUTER is not set CONFIG_IP_FIB_HASH=y -# CONFIG_IP_PNP is not set +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +CONFIG_IP_PNP_BOOTP=y +# CONFIG_IP_PNP_RARP is not set CONFIG_NET_IPIP=y # CONFIG_NET_IPGRE is not set # CONFIG_IP_MROUTE is not set @@ -333,6 +373,7 @@ CONFIG_INET_TUNNEL=y CONFIG_INET_XFRM_MODE_TRANSPORT=y CONFIG_INET_XFRM_MODE_TUNNEL=y CONFIG_INET_XFRM_MODE_BEET=y +# CONFIG_INET_LRO is not set CONFIG_INET_DIAG=y CONFIG_INET_TCP_DIAG=y # CONFIG_TCP_CONG_ADVANCED is not set @@ -404,6 +445,7 @@ CONFIG_NETFILTER_XT_MATCH_STATE=m CONFIG_NETFILTER_XT_MATCH_STATISTIC=m CONFIG_NETFILTER_XT_MATCH_STRING=m CONFIG_NETFILTER_XT_MATCH_TCPMSS=m +# CONFIG_NETFILTER_XT_MATCH_TIME is not set CONFIG_NETFILTER_XT_MATCH_U32=m CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m @@ -465,10 +507,6 @@ CONFIG_LLC=y # CONFIG_LAPB is not set # CONFIG_ECONET is not set # CONFIG_WAN_ROUTER is not set - -# -# QoS and/or fair queueing -# # CONFIG_NET_SCHED is not set CONFIG_NET_CLS_ROUTE=y @@ -498,6 +536,7 @@ CONFIG_NET_CLS_ROUTE=y # # Generic Driver Options # +CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" CONFIG_STANDALONE=y CONFIG_PREVENT_FIRMWARE_BUILD=y CONFIG_FW_LOADER=y @@ -539,6 +578,8 @@ CONFIG_BLK_DEV_IDE=y # CONFIG_BLK_DEV_IDE_SATA is not set CONFIG_BLK_DEV_IDEDISK=y # CONFIG_IDEDISK_MULTI_MODE is not set +# CONFIG_BLK_DEV_IDECS is not set +# CONFIG_BLK_DEV_DELKIN is not set CONFIG_BLK_DEV_IDECD=y # CONFIG_BLK_DEV_IDETAPE is not set # CONFIG_BLK_DEV_IDEFLOPPY is not set @@ -550,6 +591,11 @@ CONFIG_IDE_PROC_FS=y # IDE chipset support/bugfixes # CONFIG_IDE_GENERIC=y +# CONFIG_BLK_DEV_PLATFORM is not set + +# +# PCI IDE chipsets support +# CONFIG_BLK_DEV_IDEPCI=y CONFIG_IDEPCI_SHARE_IRQ=y CONFIG_IDEPCI_PCIBUS_ORDER=y @@ -557,8 +603,6 @@ CONFIG_IDEPCI_PCIBUS_ORDER=y CONFIG_BLK_DEV_GENERIC=y # CONFIG_BLK_DEV_OPTI621 is not set CONFIG_BLK_DEV_IDEDMA_PCI=y -# CONFIG_BLK_DEV_IDEDMA_FORCED is not set -# CONFIG_IDEDMA_ONLYDISK is not set # CONFIG_BLK_DEV_AEC62XX is not set # CONFIG_BLK_DEV_ALI15X3 is not set CONFIG_BLK_DEV_AMD74XX=y @@ -590,7 +634,7 @@ CONFIG_BLK_DEV_IDE_PMAC_ATA100FIRST=y CONFIG_BLK_DEV_IDEDMA_PMAC=y # CONFIG_IDE_ARM is not set CONFIG_BLK_DEV_IDEDMA=y -# CONFIG_IDEDMA_IVB is not set +CONFIG_IDE_ARCH_OBSOLETE_INIT=y # CONFIG_BLK_DEV_HD is not set # @@ -631,6 +675,7 @@ CONFIG_SCSI_FC_ATTRS=y CONFIG_SCSI_ISCSI_ATTRS=m # CONFIG_SCSI_SAS_ATTRS is not set # CONFIG_SCSI_SAS_LIBSAS is not set +CONFIG_SCSI_SRP_ATTRS=y CONFIG_SCSI_LOWLEVEL=y # CONFIG_ISCSI_TCP is not set # CONFIG_BLK_DEV_3W_XXXX_RAID is not set @@ -671,19 +716,20 @@ CONFIG_SCSI_LPFC=m # CONFIG_SCSI_DC390T is not set CONFIG_SCSI_DEBUG=m # CONFIG_SCSI_SRP is not set +# CONFIG_SCSI_LOWLEVEL_PCMCIA is not set CONFIG_ATA=y CONFIG_ATA_NONSTANDARD=y # CONFIG_SATA_AHCI is not set CONFIG_SATA_SVW=y # CONFIG_ATA_PIIX is not set -# CONFIG_SATA_MV is not set +CONFIG_SATA_MV=y # CONFIG_SATA_NV is not set # CONFIG_PDC_ADMA is not set # CONFIG_SATA_QSTOR is not set # CONFIG_SATA_PROMISE is not set # CONFIG_SATA_SX4 is not set # CONFIG_SATA_SIL is not set -# CONFIG_SATA_SIL24 is not set +CONFIG_SATA_SIL24=y # CONFIG_SATA_SIS is not set # CONFIG_SATA_ULI is not set # CONFIG_SATA_VIA is not set @@ -713,8 +759,10 @@ CONFIG_SATA_SVW=y # CONFIG_PATA_OLDPIIX is not set # CONFIG_PATA_NETCELL is not set # CONFIG_PATA_NS87410 is not set +# CONFIG_PATA_NS87415 is not set # CONFIG_PATA_OPTI is not set # CONFIG_PATA_OPTIDMA is not set +CONFIG_PATA_PCMCIA=y # CONFIG_PATA_PDC_OLD is not set # CONFIG_PATA_RADISYS is not set # CONFIG_PATA_RZ1000 is not set @@ -725,6 +773,7 @@ CONFIG_SATA_SVW=y # CONFIG_PATA_SIS is not set # CONFIG_PATA_VIA is not set CONFIG_PATA_WINBOND=y +CONFIG_PATA_PLATFORM=y CONFIG_PATA_SCC=y CONFIG_MD=y CONFIG_BLK_DEV_MD=y @@ -745,15 +794,10 @@ CONFIG_DM_ZERO=m CONFIG_DM_MULTIPATH=m CONFIG_DM_MULTIPATH_EMC=m # CONFIG_DM_MULTIPATH_RDAC is not set +# CONFIG_DM_MULTIPATH_HP is not set # CONFIG_DM_DELAY is not set - -# -# Fusion MPT device support -# +# CONFIG_DM_UEVENT is not set # CONFIG_FUSION is not set -# CONFIG_FUSION_SPI is not set -# CONFIG_FUSION_FC is not set -# CONFIG_FUSION_SAS is not set # # IEEE 1394 (FireWire) support @@ -800,13 +844,15 @@ CONFIG_BONDING=m # CONFIG_MACVLAN is not set # CONFIG_EQUALIZER is not set CONFIG_TUN=m +# CONFIG_VETH is not set +# CONFIG_IP1000 is not set # CONFIG_ARCNET is not set -CONFIG_PHYLIB=m +CONFIG_PHYLIB=y # # MII PHY device drivers # -CONFIG_MARVELL_PHY=m +CONFIG_MARVELL_PHY=y # CONFIG_DAVICOM_PHY is not set # CONFIG_QSEMI_PHY is not set # CONFIG_LXT_PHY is not set @@ -818,6 +864,9 @@ CONFIG_BROADCOM_PHY=m CONFIG_FIXED_PHY=m CONFIG_FIXED_MII_10_FDX=y CONFIG_FIXED_MII_100_FDX=y +# CONFIG_FIXED_MII_1000_FDX is not set +CONFIG_FIXED_MII_AMNT=1 +# CONFIG_MDIO_BITBANG is not set CONFIG_NET_ETHERNET=y CONFIG_MII=y # CONFIG_HAPPYMEAL is not set @@ -829,6 +878,11 @@ CONFIG_VORTEX=y # CONFIG_NET_TULIP is not set # CONFIG_HP100 is not set CONFIG_IBMVETH=m +# CONFIG_IBM_NEW_EMAC is not set +CONFIG_IBM_NEW_EMAC_ZMII=y +CONFIG_IBM_NEW_EMAC_RGMII=y +CONFIG_IBM_NEW_EMAC_TAH=y +CONFIG_IBM_NEW_EMAC_EMAC4=y CONFIG_NET_PCI=y CONFIG_PCNET32=y # CONFIG_PCNET32_NAPI is not set @@ -836,7 +890,6 @@ CONFIG_PCNET32=y # CONFIG_ADAPTEC_STARFIRE is not set # CONFIG_B44 is not set # CONFIG_FORCEDETH is not set -# CONFIG_DGRS is not set # CONFIG_EEPRO100 is not set CONFIG_E100=y # CONFIG_FEALNX is not set @@ -856,6 +909,7 @@ CONFIG_ACENIC_OMIT_TIGON_I=y CONFIG_E1000=y # CONFIG_E1000_NAPI is not set # CONFIG_E1000_DISABLE_PACKET_SPLIT is not set +# CONFIG_E1000E is not set # CONFIG_NS83820 is not set # CONFIG_HAMACHI is not set # CONFIG_YELLOWFIN is not set @@ -863,6 +917,7 @@ CONFIG_E1000=y # CONFIG_SIS190 is not set # CONFIG_SKGE is not set # CONFIG_SKY2 is not set +# CONFIG_SK98LIN is not set # CONFIG_VIA_VELOCITY is not set CONFIG_TIGON3=y # CONFIG_BNX2 is not set @@ -872,13 +927,16 @@ CONFIG_SPIDER_NET=m CONFIG_NETDEV_10000=y # CONFIG_CHELSIO_T1 is not set # CONFIG_CHELSIO_T3 is not set +# CONFIG_IXGBE is not set CONFIG_IXGB=m # CONFIG_IXGB_NAPI is not set # CONFIG_S2IO is not set # CONFIG_MYRI10GE is not set # CONFIG_NETXEN_NIC is not set -CONFIG_PASEMI_MAC=m +# CONFIG_NIU is not set +CONFIG_PASEMI_MAC=y # CONFIG_MLX4_CORE is not set +# CONFIG_TEHUTI is not set CONFIG_TR=y CONFIG_IBMOL=y # CONFIG_3C359 is not set @@ -899,6 +957,7 @@ CONFIG_IBMOL=y # CONFIG_USB_RTL8150 is not set # CONFIG_USB_USBNET_MII is not set # CONFIG_USB_USBNET is not set +# CONFIG_NET_PCMCIA is not set # CONFIG_WAN is not set CONFIG_ISERIES_VETH=m # CONFIG_FDDI is not set @@ -918,6 +977,7 @@ CONFIG_SLHC=m # CONFIG_NET_FC is not set # CONFIG_SHAPER is not set CONFIG_NETCONSOLE=y +# CONFIG_NETCONSOLE_DYNAMIC is not set CONFIG_NETPOLL=y CONFIG_NETPOLL_TRAP=y CONFIG_NET_POLL_CONTROLLER=y @@ -939,7 +999,6 @@ CONFIG_INPUT_MOUSEDEV=y CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 # CONFIG_INPUT_JOYDEV is not set -# CONFIG_INPUT_TSDEV is not set CONFIG_INPUT_EVDEV=m # CONFIG_INPUT_EVBUG is not set @@ -1002,6 +1061,7 @@ CONFIG_HW_CONSOLE=y CONFIG_SERIAL_8250=y CONFIG_SERIAL_8250_CONSOLE=y CONFIG_SERIAL_8250_PCI=y +# CONFIG_SERIAL_8250_CS is not set CONFIG_SERIAL_8250_NR_UARTS=4 CONFIG_SERIAL_8250_RUNTIME_UARTS=4 # CONFIG_SERIAL_8250_EXTENDED is not set @@ -1029,14 +1089,18 @@ CONFIG_HVC_RTAS=y CONFIG_HVC_BEAT=y CONFIG_HVCS=m # CONFIG_IPMI_HANDLER is not set -# CONFIG_WATCHDOG is not set # CONFIG_HW_RANDOM is not set CONFIG_GEN_RTC=y # CONFIG_GEN_RTC_X is not set # CONFIG_R3964 is not set # CONFIG_APPLICOM is not set -# CONFIG_AGP is not set -# CONFIG_DRM is not set + +# +# PCMCIA character devices +# +# CONFIG_SYNCLINK_CS is not set +# CONFIG_CARDMAN_4000 is not set +# CONFIG_CARDMAN_4040 is not set CONFIG_RAW_DRIVER=y CONFIG_MAX_RAW_DEVS=256 # CONFIG_HANGCHECK_TIMER is not set @@ -1068,6 +1132,7 @@ CONFIG_I2C_POWERMAC=y # CONFIG_I2C_NFORCE2 is not set # CONFIG_I2C_OCORES is not set # CONFIG_I2C_PARPORT_LIGHT is not set +CONFIG_I2C_PASEMI=y # CONFIG_I2C_PROSAVAGE is not set # CONFIG_I2C_SAVAGE4 is not set # CONFIG_I2C_SIMTEC is not set @@ -1106,6 +1171,13 @@ CONFIG_I2C_POWERMAC=y # CONFIG_W1 is not set # CONFIG_POWER_SUPPLY is not set # CONFIG_HWMON is not set +# CONFIG_WATCHDOG is not set + +# +# Sonics Silicon Backplane +# +CONFIG_SSB_POSSIBLE=y +# CONFIG_SSB is not set # # Multifunction device drivers @@ -1122,18 +1194,8 @@ CONFIG_I2C_POWERMAC=y # # Graphics support # -CONFIG_BACKLIGHT_LCD_SUPPORT=y -CONFIG_LCD_CLASS_DEVICE=y -CONFIG_BACKLIGHT_CLASS_DEVICE=y - -# -# Display device support -# -CONFIG_DISPLAY_SUPPORT=y - -# -# Display hardware drivers -# +# CONFIG_AGP is not set +# CONFIG_DRM is not set # CONFIG_VGASTATE is not set CONFIG_VIDEO_OUTPUT_CONTROL=m CONFIG_FB=y @@ -1142,6 +1204,7 @@ CONFIG_FB_DDC=y CONFIG_FB_CFB_FILLRECT=y CONFIG_FB_CFB_COPYAREA=y CONFIG_FB_CFB_IMAGEBLIT=y +# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set # CONFIG_FB_SYS_FILLRECT is not set # CONFIG_FB_SYS_COPYAREA is not set # CONFIG_FB_SYS_IMAGEBLIT is not set @@ -1192,6 +1255,19 @@ CONFIG_FB_RADEON_BACKLIGHT=y # CONFIG_FB_PM3 is not set CONFIG_FB_IBM_GXT4500=y # CONFIG_FB_VIRTUAL is not set +CONFIG_BACKLIGHT_LCD_SUPPORT=y +CONFIG_LCD_CLASS_DEVICE=y +CONFIG_BACKLIGHT_CLASS_DEVICE=y +# CONFIG_BACKLIGHT_CORGI is not set + +# +# Display device support +# +CONFIG_DISPLAY_SUPPORT=y + +# +# Display hardware drivers +# # # Console display driver support @@ -1333,6 +1409,12 @@ CONFIG_SND_AOA_SOUNDBUS_I2S=m # CONFIG_SND_USB_CAIAQ is not set # +# PCMCIA devices +# +# CONFIG_SND_VXPOCKET is not set +# CONFIG_SND_PDAUDIOCF is not set + +# # System on Chip audio support # # CONFIG_SND_SOC is not set @@ -1348,6 +1430,7 @@ CONFIG_SND_AOA_SOUNDBUS_I2S=m CONFIG_HID_SUPPORT=y CONFIG_HID=y # CONFIG_HID_DEBUG is not set +# CONFIG_HIDRAW is not set # # USB Input Devices @@ -1489,19 +1572,53 @@ CONFIG_EDAC=y # # CONFIG_EDAC_DEBUG is not set CONFIG_EDAC_MM_EDAC=y -# CONFIG_RTC_CLASS is not set +CONFIG_EDAC_PASEMI=y +CONFIG_RTC_LIB=y +CONFIG_RTC_CLASS=y +CONFIG_RTC_HCTOSYS=y +CONFIG_RTC_HCTOSYS_DEVICE="rtc0" +# CONFIG_RTC_DEBUG is not set + +# +# RTC interfaces +# +CONFIG_RTC_INTF_SYSFS=y +CONFIG_RTC_INTF_PROC=y +CONFIG_RTC_INTF_DEV=y +# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set +# CONFIG_RTC_DRV_TEST is not set + +# +# I2C RTC drivers +# +CONFIG_RTC_DRV_DS1307=y +# CONFIG_RTC_DRV_DS1374 is not set +# CONFIG_RTC_DRV_DS1672 is not set +# CONFIG_RTC_DRV_MAX6900 is not set +# CONFIG_RTC_DRV_RS5C372 is not set +# CONFIG_RTC_DRV_ISL1208 is not set +# CONFIG_RTC_DRV_X1205 is not set +# CONFIG_RTC_DRV_PCF8563 is not set +# CONFIG_RTC_DRV_PCF8583 is not set +# CONFIG_RTC_DRV_M41T80 is not set # -# DMA Engine support +# SPI RTC drivers # -# CONFIG_DMA_ENGINE is not set # -# DMA Clients +# Platform RTC drivers # +# CONFIG_RTC_DRV_CMOS is not set +# CONFIG_RTC_DRV_DS1553 is not set +# CONFIG_RTC_DRV_STK17TA8 is not set +# CONFIG_RTC_DRV_DS1742 is not set +# CONFIG_RTC_DRV_M48T86 is not set +# CONFIG_RTC_DRV_M48T59 is not set +# CONFIG_RTC_DRV_V3020 is not set # -# DMA Devices +# on-CPU RTC drivers # # @@ -1585,7 +1702,6 @@ CONFIG_TMPFS=y # CONFIG_TMPFS_POSIX_ACL is not set CONFIG_HUGETLBFS=y CONFIG_HUGETLB_PAGE=y -CONFIG_RAMFS=y # CONFIG_CONFIGFS_FS is not set # @@ -1604,10 +1720,7 @@ CONFIG_CRAMFS=y # CONFIG_QNX4FS_FS is not set # CONFIG_SYSV_FS is not set # CONFIG_UFS_FS is not set - -# -# Network File Systems -# +CONFIG_NETWORK_FILESYSTEMS=y CONFIG_NFS_FS=y CONFIG_NFS_V3=y CONFIG_NFS_V3_ACL=y @@ -1619,6 +1732,7 @@ CONFIG_NFSD_V3=y CONFIG_NFSD_V3_ACL=y CONFIG_NFSD_V4=y CONFIG_NFSD_TCP=y +CONFIG_ROOT_NFS=y CONFIG_LOCKD=y CONFIG_LOCKD_V4=y CONFIG_EXPORTFS=m @@ -1626,6 +1740,7 @@ CONFIG_NFS_ACL_SUPPORT=y CONFIG_NFS_COMMON=y CONFIG_SUNRPC=y CONFIG_SUNRPC_GSS=y +CONFIG_SUNRPC_XPRT_RDMA=m # CONFIG_SUNRPC_BIND34 is not set CONFIG_RPCSEC_GSS_KRB5=y CONFIG_RPCSEC_GSS_SPKM3=m @@ -1662,10 +1777,6 @@ CONFIG_MSDOS_PARTITION=y # CONFIG_KARMA_PARTITION is not set # CONFIG_EFI_PARTITION is not set # CONFIG_SYSV68_PARTITION is not set - -# -# Native Language Support -# CONFIG_NLS=y CONFIG_NLS_DEFAULT="iso8859-1" CONFIG_NLS_CODEPAGE_437=y @@ -1706,10 +1817,6 @@ CONFIG_NLS_ISO8859_15=m CONFIG_NLS_KOI8_R=m CONFIG_NLS_KOI8_U=m CONFIG_NLS_UTF8=m - -# -# Distributed Lock Manager -# # CONFIG_DLM is not set # CONFIG_UCC_SLOW is not set @@ -1733,18 +1840,17 @@ CONFIG_PLIST=y CONFIG_HAS_IOMEM=y CONFIG_HAS_IOPORT=y CONFIG_HAS_DMA=y - -# -# Instrumentation Support -# +CONFIG_INSTRUMENTATION=y CONFIG_PROFILING=y CONFIG_OPROFILE=y # CONFIG_KPROBES is not set +# CONFIG_MARKERS is not set # # Kernel hacking # # CONFIG_PRINTK_TIME is not set +CONFIG_ENABLE_WARN_DEPRECATED=y CONFIG_ENABLE_MUST_CHECK=y CONFIG_MAGIC_SYSRQ=y # CONFIG_UNUSED_SYMBOLS is not set @@ -1768,9 +1874,12 @@ CONFIG_DEBUG_BUGVERBOSE=y # CONFIG_DEBUG_INFO is not set # CONFIG_DEBUG_VM is not set # CONFIG_DEBUG_LIST is not set +# CONFIG_DEBUG_SG is not set CONFIG_FORCED_INLINING=y +# CONFIG_BOOT_PRINTK_DELAY is not set # CONFIG_RCU_TORTURE_TEST is not set # CONFIG_FAULT_INJECTION is not set +# CONFIG_SAMPLES is not set CONFIG_DEBUG_STACKOVERFLOW=y CONFIG_DEBUG_STACK_USAGE=y # CONFIG_DEBUG_PAGEALLOC is not set @@ -1780,6 +1889,7 @@ CONFIG_XMON=y # CONFIG_XMON_DEFAULT is not set CONFIG_XMON_DISASSEMBLY=y CONFIG_IRQSTACKS=y +# CONFIG_VIRQ_DEBUG is not set CONFIG_BOOTX_TEXT=y # CONFIG_PPC_EARLY_DEBUG is not set @@ -1788,6 +1898,7 @@ CONFIG_BOOTX_TEXT=y # # CONFIG_KEYS is not set # CONFIG_SECURITY is not set +# CONFIG_SECURITY_FILE_CAPABILITIES is not set CONFIG_XOR_BLOCKS=y CONFIG_ASYNC_CORE=y CONFIG_ASYNC_MEMCPY=y @@ -1812,6 +1923,7 @@ CONFIG_CRYPTO_ECB=m CONFIG_CRYPTO_CBC=y CONFIG_CRYPTO_PCBC=m # CONFIG_CRYPTO_LRW is not set +# CONFIG_CRYPTO_XTS is not set # CONFIG_CRYPTO_CRYPTD is not set CONFIG_CRYPTO_DES=y # CONFIG_CRYPTO_FCRYPT is not set @@ -1826,9 +1938,12 @@ CONFIG_CRYPTO_TEA=m CONFIG_CRYPTO_ARC4=m CONFIG_CRYPTO_KHAZAD=m CONFIG_CRYPTO_ANUBIS=m +# CONFIG_CRYPTO_SEED is not set CONFIG_CRYPTO_DEFLATE=m CONFIG_CRYPTO_MICHAEL_MIC=m CONFIG_CRYPTO_CRC32C=m # CONFIG_CRYPTO_CAMELLIA is not set CONFIG_CRYPTO_TEST=m +# CONFIG_CRYPTO_AUTHENC is not set # CONFIG_CRYPTO_HW is not set +# CONFIG_PPC_CLOCK is not set diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c index 2c8e756..d67bcd8 100644 --- a/arch/powerpc/kernel/asm-offsets.c +++ b/arch/powerpc/kernel/asm-offsets.c @@ -284,6 +284,10 @@ int main(void) DEFINE(CFG_SYSCALL_MAP32, offsetof(struct vdso_data, syscall_map_32)); DEFINE(WTOM_CLOCK_SEC, offsetof(struct vdso_data, wtom_clock_sec)); DEFINE(WTOM_CLOCK_NSEC, offsetof(struct vdso_data, wtom_clock_nsec)); + DEFINE(CFG_ICACHE_BLOCKSZ, offsetof(struct vdso_data, icache_block_size)); + DEFINE(CFG_DCACHE_BLOCKSZ, offsetof(struct vdso_data, dcache_block_size)); + DEFINE(CFG_ICACHE_LOGBLOCKSZ, offsetof(struct vdso_data, icache_log_block_size)); + DEFINE(CFG_DCACHE_LOGBLOCKSZ, offsetof(struct vdso_data, dcache_log_block_size)); #ifdef CONFIG_PPC64 DEFINE(CFG_SYSCALL_MAP64, offsetof(struct vdso_data, syscall_map_64)); DEFINE(TVAL64_TV_SEC, offsetof(struct timeval, tv_sec)); diff --git a/arch/powerpc/kernel/btext.c b/arch/powerpc/kernel/btext.c index 3ef51fb..9c74fdf 100644 --- a/arch/powerpc/kernel/btext.c +++ b/arch/powerpc/kernel/btext.c @@ -186,7 +186,9 @@ int btext_initialize(struct device_node *np) pitch = *prop; if (pitch == 1) pitch = 0x1000; - prop = of_get_property(np, "address", NULL); + prop = of_get_property(np, "linux,bootx-addr", NULL); + if (prop == NULL) + prop = of_get_property(np, "address", NULL); if (prop) address = *prop; diff --git a/arch/powerpc/kernel/cputable.c b/arch/powerpc/kernel/cputable.c index d3fb7d0..9ed351f 100644 --- a/arch/powerpc/kernel/cputable.c +++ b/arch/powerpc/kernel/cputable.c @@ -1104,6 +1104,16 @@ static struct cpu_spec __initdata cpu_specs[] = { { .pvr_mask = 0xf0000fff, .pvr_value = 0x40000850, + .cpu_name = "440GR Rev. A", + .cpu_features = CPU_FTRS_44X, + .cpu_user_features = COMMON_USER_BOOKE, + .icache_bsize = 32, + .dcache_bsize = 32, + .platform = "ppc440", + }, + { /* Use logical PVR for 440EP (logical pvr = pvr | 0x8) */ + .pvr_mask = 0xf0000fff, + .pvr_value = 0x40000858, .cpu_name = "440EP Rev. A", .cpu_features = CPU_FTRS_44X, .cpu_user_features = COMMON_USER_BOOKE | PPC_FEATURE_HAS_FPU, @@ -1115,28 +1125,27 @@ static struct cpu_spec __initdata cpu_specs[] = { { .pvr_mask = 0xf0000fff, .pvr_value = 0x400008d3, - .cpu_name = "440EP Rev. B", + .cpu_name = "440GR Rev. B", .cpu_features = CPU_FTRS_44X, .cpu_user_features = COMMON_USER_BOOKE | PPC_FEATURE_HAS_FPU, .icache_bsize = 32, .dcache_bsize = 32, - .cpu_setup = __setup_cpu_440ep, .platform = "ppc440", }, - { /* 440EPX */ - .pvr_mask = 0xf0000ffb, - .pvr_value = 0x200008D0, - .cpu_name = "440EPX", + { /* Use logical PVR for 440EP (logical pvr = pvr | 0x8) */ + .pvr_mask = 0xf0000fff, + .pvr_value = 0x400008db, + .cpu_name = "440EP Rev. B", .cpu_features = CPU_FTRS_44X, .cpu_user_features = COMMON_USER_BOOKE | PPC_FEATURE_HAS_FPU, .icache_bsize = 32, .dcache_bsize = 32, - .cpu_setup = __setup_cpu_440epx, + .cpu_setup = __setup_cpu_440ep, .platform = "ppc440", }, { /* 440GRX */ .pvr_mask = 0xf0000ffb, - .pvr_value = 0x200008D8, + .pvr_value = 0x200008D0, .cpu_name = "440GRX", .cpu_features = CPU_FTRS_44X, .cpu_user_features = COMMON_USER_BOOKE, @@ -1145,6 +1154,17 @@ static struct cpu_spec __initdata cpu_specs[] = { .cpu_setup = __setup_cpu_440grx, .platform = "ppc440", }, + { /* Use logical PVR for 440EPx (logical pvr = pvr | 0x8) */ + .pvr_mask = 0xf0000ffb, + .pvr_value = 0x200008D8, + .cpu_name = "440EPX", + .cpu_features = CPU_FTRS_44X, + .cpu_user_features = COMMON_USER_BOOKE | PPC_FEATURE_HAS_FPU, + .icache_bsize = 32, + .dcache_bsize = 32, + .cpu_setup = __setup_cpu_440epx, + .platform = "ppc440", + }, { /* 440GP Rev. B */ .pvr_mask = 0xf0000fff, .pvr_value = 0x40000440, diff --git a/arch/powerpc/kernel/entry_32.S b/arch/powerpc/kernel/entry_32.S index 21d889e..69a91bd 100644 --- a/arch/powerpc/kernel/entry_32.S +++ b/arch/powerpc/kernel/entry_32.S @@ -244,6 +244,16 @@ syscall_exit_cont: andis. r10,r0,DBCR0_IC@h bnel- load_dbcr0 #endif +#ifdef CONFIG_44x + lis r4,icache_44x_need_flush@ha + lwz r5,icache_44x_need_flush@l(r4) + cmplwi cr0,r5,0 + bne- 2f +1: +#endif /* CONFIG_44x */ +BEGIN_FTR_SECTION + lwarx r7,0,r1 +END_FTR_SECTION_IFSET(CPU_FTR_NEED_PAIRED_STWCX) stwcx. r0,0,r1 /* to clear the reservation */ lwz r4,_LINK(r1) lwz r5,_CCR(r1) @@ -258,6 +268,12 @@ syscall_exit_cont: mtspr SPRN_SRR1,r8 SYNC RFI +#ifdef CONFIG_44x +2: li r7,0 + iccci r0,r0 + stw r7,icache_44x_need_flush@l(r4) + b 1b +#endif /* CONFIG_44x */ 66: li r3,-ENOSYS b ret_from_syscall @@ -683,6 +699,16 @@ resume_kernel: /* interrupts are hard-disabled at this point */ restore: +#ifdef CONFIG_44x + lis r4,icache_44x_need_flush@ha + lwz r5,icache_44x_need_flush@l(r4) + cmplwi cr0,r5,0 + beq+ 1f + li r6,0 + iccci r0,r0 + stw r6,icache_44x_need_flush@l(r4) +1: +#endif /* CONFIG_44x */ lwz r0,GPR0(r1) lwz r2,GPR2(r1) REST_4GPRS(3, r1) @@ -694,6 +720,9 @@ restore: mtctr r11 PPC405_ERR77(0,r1) +BEGIN_FTR_SECTION + lwarx r11,0,r1 +END_FTR_SECTION_IFSET(CPU_FTR_NEED_PAIRED_STWCX) stwcx. r0,0,r1 /* to clear the reservation */ #if !(defined(CONFIG_4xx) || defined(CONFIG_BOOKE)) diff --git a/arch/powerpc/kernel/head_64.S b/arch/powerpc/kernel/head_64.S index 97c5857..c349868 100644 --- a/arch/powerpc/kernel/head_64.S +++ b/arch/powerpc/kernel/head_64.S @@ -904,7 +904,7 @@ handle_page_fault: */ 12: bl .save_nvgprs addi r3,r1,STACK_FRAME_OVERHEAD - lwz r4,_DAR(r1) + ld r4,_DAR(r1) bl .low_hash_fault b .ret_from_except diff --git a/arch/powerpc/kernel/idle.c b/arch/powerpc/kernel/idle.c index abd2957..c3cf0e8 100644 --- a/arch/powerpc/kernel/idle.c +++ b/arch/powerpc/kernel/idle.c @@ -122,7 +122,7 @@ static ctl_table powersave_nap_sysctl_root[] = { { .ctl_name = CTL_KERN, .procname = "kernel", - .mode = 0755, + .mode = 0555, .child = powersave_nap_ctl_table, }, {} diff --git a/arch/powerpc/kernel/misc_32.S b/arch/powerpc/kernel/misc_32.S index 8533de5..8b642ab 100644 --- a/arch/powerpc/kernel/misc_32.S +++ b/arch/powerpc/kernel/misc_32.S @@ -288,7 +288,16 @@ _GLOBAL(_tlbia) */ _GLOBAL(_tlbie) #if defined(CONFIG_40x) + /* We run the search with interrupts disabled because we have to change + * the PID and I don't want to preempt when that happens. + */ + mfmsr r5 + mfspr r6,SPRN_PID + wrteei 0 + mtspr SPRN_PID,r4 tlbsx. r3, 0, r3 + mtspr SPRN_PID,r6 + wrtee r5 bne 10f sync /* There are only 64 TLB entries, so r3 < 64, which means bit 25 is clear. @@ -297,23 +306,23 @@ _GLOBAL(_tlbie) tlbwe r3, r3, TLB_TAG isync 10: + #elif defined(CONFIG_44x) - mfspr r4,SPRN_MMUCR - mfspr r5,SPRN_PID /* Get PID */ - rlwimi r4,r5,0,24,31 /* Set TID */ + mfspr r5,SPRN_MMUCR + rlwimi r5,r4,0,24,31 /* Set TID */ /* We have to run the search with interrupts disabled, even critical * and debug interrupts (in fact the only critical exceptions we have * are debug and machine check). Otherwise an interrupt which causes * a TLB miss can clobber the MMUCR between the mtspr and the tlbsx. */ - mfmsr r5 + mfmsr r4 lis r6,(MSR_EE|MSR_CE|MSR_ME|MSR_DE)@ha addi r6,r6,(MSR_EE|MSR_CE|MSR_ME|MSR_DE)@l - andc r6,r5,r6 + andc r6,r4,r6 mtmsr r6 - mtspr SPRN_MMUCR,r4 + mtspr SPRN_MMUCR,r5 tlbsx. r3, 0, r3 - mtmsr r5 + mtmsr r4 bne 10f sync /* There are only 64 TLB entries, so r3 < 64, @@ -534,12 +543,21 @@ END_FTR_SECTION_IFSET(CPU_FTR_COHERENT_ICACHE) addi r3,r3,L1_CACHE_BYTES bdnz 0b sync +#ifndef CONFIG_44x + /* We don't flush the icache on 44x. Those have a virtual icache + * and we don't have access to the virtual address here (it's + * not the page vaddr but where it's mapped in user space). The + * flushing of the icache on these is handled elsewhere, when + * a change in the address space occurs, before returning to + * user space + */ mtctr r4 1: icbi 0,r6 addi r6,r6,L1_CACHE_BYTES bdnz 1b sync isync +#endif /* CONFIG_44x */ blr /* diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c index b9d8837..41e13f4 100644 --- a/arch/powerpc/kernel/process.c +++ b/arch/powerpc/kernel/process.c @@ -350,7 +350,7 @@ struct task_struct *__switch_to(struct task_struct *prev, local_irq_save(flags); account_system_vtime(current); - account_process_vtime(current); + account_process_tick(current, 0); calculate_steal_time(); last = _switch(old_thread, new_thread); diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c index 9f329a8..acc0d24 100644 --- a/arch/powerpc/kernel/prom.c +++ b/arch/powerpc/kernel/prom.c @@ -697,6 +697,18 @@ static int __init early_init_dt_scan_cpus(unsigned long node, prop = of_get_flat_dt_prop(node, "cpu-version", NULL); if (prop && (*prop & 0xff000000) == 0x0f000000) identify_cpu(0, *prop); +#if defined(CONFIG_44x) && defined(CONFIG_PPC_FPU) + /* + * Since 440GR(x)/440EP(x) processors have the same pvr, + * we check the node path and set bit 28 in the cur_cpu_spec + * pvr for EP(x) processor version. This bit is always 0 in + * the "real" pvr. Then we call identify_cpu again with + * the new logical pvr to enable FPU support. + */ + if (strstr(uname, "440EP")) { + identify_cpu(0, cur_cpu_spec->pvr_value | 0x8); + } +#endif } check_cpu_feature_properties(node); diff --git a/arch/powerpc/kernel/prom_init.c b/arch/powerpc/kernel/prom_init.c index 1db10f7..1add6ef 100644 --- a/arch/powerpc/kernel/prom_init.c +++ b/arch/powerpc/kernel/prom_init.c @@ -1244,7 +1244,7 @@ static void __init prom_initialize_tce_table(void) local_alloc_bottom = base; /* It seems OF doesn't null-terminate the path :-( */ - memset(path, 0, sizeof(path)); + memset(path, 0, PROM_SCRATCH_SIZE); /* Call OF to setup the TCE hardware */ if (call_prom("package-to-path", 3, 1, node, path, PROM_SCRATCH_SIZE-1) == PROM_ERROR) { diff --git a/arch/powerpc/kernel/rtas.c b/arch/powerpc/kernel/rtas.c index 2147807..053cac1 100644 --- a/arch/powerpc/kernel/rtas.c +++ b/arch/powerpc/kernel/rtas.c @@ -19,6 +19,9 @@ #include <linux/init.h> #include <linux/capability.h> #include <linux/delay.h> +#include <linux/smp.h> +#include <linux/completion.h> +#include <linux/cpumask.h> #include <asm/prom.h> #include <asm/rtas.h> @@ -34,6 +37,8 @@ #include <asm/lmb.h> #include <asm/udbg.h> #include <asm/syscalls.h> +#include <asm/smp.h> +#include <asm/atomic.h> struct rtas_t rtas = { .lock = SPIN_LOCK_UNLOCKED @@ -41,8 +46,10 @@ struct rtas_t rtas = { EXPORT_SYMBOL(rtas); struct rtas_suspend_me_data { - long waiting; - struct rtas_args *args; + atomic_t working; /* number of cpus accessing this struct */ + int token; /* ibm,suspend-me */ + int error; + struct completion *complete; /* wait on this until working == 0 */ }; DEFINE_SPINLOCK(rtas_data_buf_lock); @@ -631,18 +638,18 @@ void rtas_halt(void) /* Must be in the RMO region, so we place it here */ static char rtas_os_term_buf[2048]; -void rtas_os_term(char *str) +void rtas_panic_msg(char *str) { - int status; + snprintf(rtas_os_term_buf, 2048, "OS panic: %s", str); +} - if (panic_timeout) - return; +void rtas_os_term(void) +{ + int status; if (RTAS_UNKNOWN_SERVICE == rtas_token("ibm,os-term")) return; - snprintf(rtas_os_term_buf, 2048, "OS panic: %s", str); - do { status = rtas_call(rtas_token("ibm,os-term"), 1, 1, NULL, __pa(rtas_os_term_buf)); @@ -657,50 +664,62 @@ static int ibm_suspend_me_token = RTAS_UNKNOWN_SERVICE; #ifdef CONFIG_PPC_PSERIES static void rtas_percpu_suspend_me(void *info) { - int i; long rc; - long flags; + unsigned long msr_save; + int cpu; struct rtas_suspend_me_data *data = (struct rtas_suspend_me_data *)info; - /* - * We use "waiting" to indicate our state. As long - * as it is >0, we are still trying to all join up. - * If it goes to 0, we have successfully joined up and - * one thread got H_CONTINUE. If any error happens, - * we set it to <0. - */ - local_irq_save(flags); - do { - rc = plpar_hcall_norets(H_JOIN); - smp_rmb(); - } while (rc == H_SUCCESS && data->waiting > 0); - if (rc == H_SUCCESS) - goto out; + atomic_inc(&data->working); + + /* really need to ensure MSR.EE is off for H_JOIN */ + msr_save = mfmsr(); + mtmsr(msr_save & ~(MSR_EE)); + + rc = plpar_hcall_norets(H_JOIN); - if (rc == H_CONTINUE) { - data->waiting = 0; - data->args->args[data->args->nargs] = - rtas_call(ibm_suspend_me_token, 0, 1, NULL); - for_each_possible_cpu(i) - plpar_hcall_norets(H_PROD,i); + mtmsr(msr_save); + + if (rc == H_SUCCESS) { + /* This cpu was prodded and the suspend is complete. */ + goto out; + } else if (rc == H_CONTINUE) { + /* All other cpus are in H_JOIN, this cpu does + * the suspend. + */ + printk(KERN_DEBUG "calling ibm,suspend-me on cpu %i\n", + smp_processor_id()); + data->error = rtas_call(data->token, 0, 1, NULL); + + if (data->error) + printk(KERN_DEBUG "ibm,suspend-me returned %d\n", + data->error); } else { - data->waiting = -EBUSY; - printk(KERN_ERR "Error on H_JOIN hypervisor call\n"); + printk(KERN_ERR "H_JOIN on cpu %i failed with rc = %ld\n", + smp_processor_id(), rc); + data->error = rc; } - + /* This cpu did the suspend or got an error; in either case, + * we need to prod all other other cpus out of join state. + * Extra prods are harmless. + */ + for_each_online_cpu(cpu) + plpar_hcall_norets(H_PROD, get_hard_smp_processor_id(cpu)); out: - local_irq_restore(flags); - return; + if (atomic_dec_return(&data->working) == 0) + complete(data->complete); } static int rtas_ibm_suspend_me(struct rtas_args *args) { - int i; long state; long rc; unsigned long retbuf[PLPAR_HCALL_BUFSIZE]; struct rtas_suspend_me_data data; + DECLARE_COMPLETION_ONSTACK(done); + + if (!rtas_service_present("ibm,suspend-me")) + return -ENOSYS; /* Make sure the state is valid */ rc = plpar_hcall(H_VASI_STATE, retbuf, @@ -721,25 +740,23 @@ static int rtas_ibm_suspend_me(struct rtas_args *args) return 0; } - data.waiting = 1; - data.args = args; + atomic_set(&data.working, 0); + data.token = rtas_token("ibm,suspend-me"); + data.error = 0; + data.complete = &done; /* Call function on all CPUs. One of us will make the * rtas call */ if (on_each_cpu(rtas_percpu_suspend_me, &data, 1, 0)) - data.waiting = -EINVAL; + data.error = -EINVAL; - if (data.waiting != 0) - printk(KERN_ERR "Error doing global join\n"); + wait_for_completion(&done); - /* Prod each CPU. This won't hurt, and will wake - * anyone we successfully put to sleep with H_JOIN. - */ - for_each_possible_cpu(i) - plpar_hcall_norets(H_PROD, i); + if (data.error != 0) + printk(KERN_ERR "Error doing global join\n"); - return data.waiting; + return data.error; } #else /* CONFIG_PPC_PSERIES */ static int rtas_ibm_suspend_me(struct rtas_args *args) diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c index ede77db..3b1529c 100644 --- a/arch/powerpc/kernel/setup_64.c +++ b/arch/powerpc/kernel/setup_64.c @@ -291,23 +291,16 @@ static void __init initialize_cache_info(void) if ( num_cpus == 1 ) { const u32 *sizep, *lsizep; u32 size, lsize; - const char *dc, *ic; - - /* Then read cache informations */ - if (machine_is(powermac)) { - dc = "d-cache-block-size"; - ic = "i-cache-block-size"; - } else { - dc = "d-cache-line-size"; - ic = "i-cache-line-size"; - } size = 0; lsize = cur_cpu_spec->dcache_bsize; sizep = of_get_property(np, "d-cache-size", NULL); if (sizep != NULL) size = *sizep; - lsizep = of_get_property(np, dc, NULL); + lsizep = of_get_property(np, "d-cache-block-size", NULL); + /* fallback if block size missing */ + if (lsizep == NULL) + lsizep = of_get_property(np, "d-cache-line-size", NULL); if (lsizep != NULL) lsize = *lsizep; if (sizep == 0 || lsizep == 0) @@ -324,7 +317,9 @@ static void __init initialize_cache_info(void) sizep = of_get_property(np, "i-cache-size", NULL); if (sizep != NULL) size = *sizep; - lsizep = of_get_property(np, ic, NULL); + lsizep = of_get_property(np, "i-cache-block-size", NULL); + if (lsizep == NULL) + lsizep = of_get_property(np, "i-cache-line-size", NULL); if (lsizep != NULL) lsize = *lsizep; if (sizep == 0 || lsizep == 0) diff --git a/arch/powerpc/kernel/swsusp_32.S b/arch/powerpc/kernel/swsusp_32.S index 69e8f86..77fc766 100644 --- a/arch/powerpc/kernel/swsusp_32.S +++ b/arch/powerpc/kernel/swsusp_32.S @@ -133,10 +133,12 @@ _GLOBAL(swsusp_arch_suspend) /* Resume code */ _GLOBAL(swsusp_arch_resume) +#ifdef CONFIG_ALTIVEC /* Stop pending alitvec streams and memory accesses */ BEGIN_FTR_SECTION DSSALL END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC) +#endif sync /* Disable MSR:DR to make sure we don't take a TLB or diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c index 9eb3284..a925a8e 100644 --- a/arch/powerpc/kernel/time.c +++ b/arch/powerpc/kernel/time.c @@ -241,8 +241,9 @@ void account_system_vtime(struct task_struct *tsk) /* deltascaled includes both user and system time. * Hence scale it based on the purr ratio to estimate * the system time */ - deltascaled = deltascaled * get_paca()->system_time / - (get_paca()->system_time + get_paca()->user_time); + if (get_paca()->user_time) + deltascaled = deltascaled * get_paca()->system_time / + (get_paca()->system_time + get_paca()->user_time); delta += get_paca()->system_time; get_paca()->system_time = 0; } @@ -259,7 +260,7 @@ void account_system_vtime(struct task_struct *tsk) * user and system time records. * Must be called with interrupts disabled. */ -void account_process_vtime(struct task_struct *tsk) +void account_process_tick(struct task_struct *tsk, int user_tick) { cputime_t utime, utimescaled; @@ -274,18 +275,6 @@ void account_process_vtime(struct task_struct *tsk) account_user_time_scaled(tsk, utimescaled); } -static void account_process_time(struct pt_regs *regs) -{ - int cpu = smp_processor_id(); - - account_process_vtime(current); - run_local_timers(); - if (rcu_pending(cpu)) - rcu_check_callbacks(cpu, user_mode(regs)); - scheduler_tick(); - run_posix_cpu_timers(current); -} - /* * Stuff for accounting stolen time. */ @@ -375,7 +364,6 @@ static void snapshot_purr(void) #else /* ! CONFIG_VIRT_CPU_ACCOUNTING */ #define calc_cputime_factors() -#define account_process_time(regs) update_process_times(user_mode(regs)) #define calculate_steal_time() do { } while (0) #endif @@ -586,7 +574,7 @@ void timer_interrupt(struct pt_regs * regs) /* not time for this event yet */ now = per_cpu(decrementer_next_tb, cpu) - now; if (now <= DECREMENTER_MAX) - set_dec((unsigned int)now - 1); + set_dec((int)now); return; } old_regs = set_irq_regs(regs); @@ -599,20 +587,8 @@ void timer_interrupt(struct pt_regs * regs) get_lppaca()->int_dword.fields.decr_int = 0; #endif - /* - * We cannot disable the decrementer, so in the period - * between this cpu's being marked offline in cpu_online_map - * and calling stop-self, it is taking timer interrupts. - * Avoid calling into the scheduler rebalancing code if this - * is the case. - */ - if (!cpu_is_offline(cpu)) - account_process_time(regs); - if (evt->event_handler) evt->event_handler(evt); - else - evt->set_next_event(DECREMENTER_MAX, evt); #ifdef CONFIG_PPC_ISERIES if (firmware_has_feature(FW_FEATURE_ISERIES) && hvlpevent_is_pending()) @@ -836,9 +812,6 @@ static int decrementer_set_next_event(unsigned long evt, struct clock_event_device *dev) { __get_cpu_var(decrementer_next_tb) = get_tb_or_rtc() + evt; - /* The decrementer interrupts on the 0 -> -1 transition */ - if (evt) - --evt; set_dec(evt); return 0; } @@ -857,7 +830,7 @@ static void register_decrementer_clockevent(int cpu) *dec = decrementer_clockevent; dec->cpumask = cpumask_of_cpu(cpu); - printk(KERN_INFO "clockevent: %s mult[%lx] shift[%d] cpu[%d]\n", + printk(KERN_DEBUG "clockevent: %s mult[%lx] shift[%d] cpu[%d]\n", dec->name, dec->mult, dec->shift, cpu); clockevents_register_device(dec); @@ -871,7 +844,8 @@ void init_decrementer_clockevent(void) decrementer_clockevent.shift); decrementer_clockevent.max_delta_ns = clockevent_delta2ns(DECREMENTER_MAX, &decrementer_clockevent); - decrementer_clockevent.min_delta_ns = 1000; + decrementer_clockevent.min_delta_ns = + clockevent_delta2ns(2, &decrementer_clockevent); register_decrementer_clockevent(cpu); } diff --git a/arch/powerpc/kernel/vdso.c b/arch/powerpc/kernel/vdso.c index 2322ba5..3702df7 100644 --- a/arch/powerpc/kernel/vdso.c +++ b/arch/powerpc/kernel/vdso.c @@ -699,11 +699,22 @@ static int __init vdso_init(void) vdso_data->icache_size = ppc64_caches.isize; vdso_data->icache_line_size = ppc64_caches.iline_size; + /* XXXOJN: Blocks should be added to ppc64_caches and used instead */ + vdso_data->dcache_block_size = ppc64_caches.dline_size; + vdso_data->icache_block_size = ppc64_caches.iline_size; + vdso_data->dcache_log_block_size = ppc64_caches.log_dline_size; + vdso_data->icache_log_block_size = ppc64_caches.log_iline_size; + /* * Calculate the size of the 64 bits vDSO */ vdso64_pages = (&vdso64_end - &vdso64_start) >> PAGE_SHIFT; DBG("vdso64_kbase: %p, 0x%x pages\n", vdso64_kbase, vdso64_pages); +#else + vdso_data->dcache_block_size = L1_CACHE_BYTES; + vdso_data->dcache_log_block_size = L1_CACHE_SHIFT; + vdso_data->icache_block_size = L1_CACHE_BYTES; + vdso_data->icache_log_block_size = L1_CACHE_SHIFT; #endif /* CONFIG_PPC64 */ diff --git a/arch/powerpc/kernel/vdso32/cacheflush.S b/arch/powerpc/kernel/vdso32/cacheflush.S index 9cb3199..1ba6feb 100644 --- a/arch/powerpc/kernel/vdso32/cacheflush.S +++ b/arch/powerpc/kernel/vdso32/cacheflush.S @@ -23,29 +23,46 @@ * * Flushes the data cache & invalidate the instruction cache for the * provided range [start, end[ - * - * Note: all CPUs supported by this kernel have a 128 bytes cache - * line size so we don't have to peek that info from the datapage */ V_FUNCTION_BEGIN(__kernel_sync_dicache) .cfi_startproc - li r5,127 - andc r6,r3,r5 /* round low to line bdy */ + mflr r12 + .cfi_register lr,r12 + mr r11,r3 + bl __get_datapage@local + mtlr r12 + mr r10,r3 + + lwz r7,CFG_DCACHE_BLOCKSZ(r10) + addi r5,r7,-1 + andc r6,r11,r5 /* round low to line bdy */ subf r8,r6,r4 /* compute length */ add r8,r8,r5 /* ensure we get enough */ - srwi. r8,r8,7 /* compute line count */ + lwz r9,CFG_DCACHE_LOGBLOCKSZ(r10) + srw. r8,r8,r9 /* compute line count */ crclr cr0*4+so beqlr /* nothing to do? */ mtctr r8 - mr r3,r6 -1: dcbst 0,r3 - addi r3,r3,128 +1: dcbst 0,r6 + add r6,r6,r7 bdnz 1b sync + +/* Now invalidate the instruction cache */ + + lwz r7,CFG_ICACHE_BLOCKSZ(r10) + addi r5,r7,-1 + andc r6,r11,r5 /* round low to line bdy */ + subf r8,r6,r4 /* compute length */ + add r8,r8,r5 + lwz r9,CFG_ICACHE_LOGBLOCKSZ(r10) + srw. r8,r8,r9 /* compute line count */ + crclr cr0*4+so + beqlr /* nothing to do? */ mtctr r8 -1: icbi 0,r6 - addi r6,r6,128 - bdnz 1b +2: icbi 0,r6 + add r6,r6,r7 + bdnz 2b isync li r3,0 blr diff --git a/arch/powerpc/kernel/vdso64/cacheflush.S b/arch/powerpc/kernel/vdso64/cacheflush.S index 66a36d3..69c5af2 100644 --- a/arch/powerpc/kernel/vdso64/cacheflush.S +++ b/arch/powerpc/kernel/vdso64/cacheflush.S @@ -23,29 +23,46 @@ * * Flushes the data cache & invalidate the instruction cache for the * provided range [start, end[ - * - * Note: all CPUs supported by this kernel have a 128 bytes cache - * line size so we don't have to peek that info from the datapage */ V_FUNCTION_BEGIN(__kernel_sync_dicache) .cfi_startproc - li r5,127 - andc r6,r3,r5 /* round low to line bdy */ + mflr r12 + .cfi_register lr,r12 + mr r11,r3 + bl V_LOCAL_FUNC(__get_datapage) + mtlr r12 + mr r10,r3 + + lwz r7,CFG_DCACHE_BLOCKSZ(r10) + addi r5,r7,-1 + andc r6,r11,r5 /* round low to line bdy */ subf r8,r6,r4 /* compute length */ add r8,r8,r5 /* ensure we get enough */ - srwi. r8,r8,7 /* compute line count */ + lwz r9,CFG_DCACHE_LOGBLOCKSZ(r10) + srw. r8,r8,r9 /* compute line count */ crclr cr0*4+so beqlr /* nothing to do? */ mtctr r8 - mr r3,r6 -1: dcbst 0,r3 - addi r3,r3,128 +1: dcbst 0,r6 + add r6,r6,r7 bdnz 1b sync + +/* Now invalidate the instruction cache */ + + lwz r7,CFG_ICACHE_BLOCKSZ(r10) + addi r5,r7,-1 + andc r6,r11,r5 /* round low to line bdy */ + subf r8,r6,r4 /* compute length */ + add r8,r8,r5 + lwz r9,CFG_ICACHE_LOGBLOCKSZ(r10) + srw. r8,r8,r9 /* compute line count */ + crclr cr0*4+so + beqlr /* nothing to do? */ mtctr r8 -1: icbi 0,r6 - addi r6,r6,128 - bdnz 1b +2: icbi 0,r6 + add r6,r6,r7 + bdnz 2b isync li r3,0 blr diff --git a/arch/powerpc/kernel/vmlinux.lds.S b/arch/powerpc/kernel/vmlinux.lds.S index 823a8cb..f66fa5d 100644 --- a/arch/powerpc/kernel/vmlinux.lds.S +++ b/arch/powerpc/kernel/vmlinux.lds.S @@ -37,11 +37,10 @@ SECTIONS ALIGN_FUNCTION(); *(.text.head) _text = .; - TEXT_TEXT + *(.text .fixup .text.init.refok .exit.text.refok) SCHED_TEXT LOCK_TEXT KPROBES_TEXT - *(.fixup) #ifdef CONFIG_PPC32 *(.got1) diff --git a/arch/powerpc/mm/40x_mmu.c b/arch/powerpc/mm/40x_mmu.c index e067df8..3899ea9 100644 --- a/arch/powerpc/mm/40x_mmu.c +++ b/arch/powerpc/mm/40x_mmu.c @@ -98,13 +98,12 @@ unsigned long __init mmu_mapin_ram(void) v = KERNELBASE; p = PPC_MEMSTART; - s = 0; + s = total_lowmem; - if (__map_without_ltlbs) { - return s; - } + if (__map_without_ltlbs) + return 0; - while (s <= (total_lowmem - LARGE_PAGE_SIZE_16M)) { + while (s >= LARGE_PAGE_SIZE_16M) { pmd_t *pmdp; unsigned long val = p | _PMD_SIZE_16M | _PAGE_HWEXEC | _PAGE_HWWRITE; @@ -116,10 +115,10 @@ unsigned long __init mmu_mapin_ram(void) v += LARGE_PAGE_SIZE_16M; p += LARGE_PAGE_SIZE_16M; - s += LARGE_PAGE_SIZE_16M; + s -= LARGE_PAGE_SIZE_16M; } - while (s <= (total_lowmem - LARGE_PAGE_SIZE_4M)) { + while (s >= LARGE_PAGE_SIZE_4M) { pmd_t *pmdp; unsigned long val = p | _PMD_SIZE_4M | _PAGE_HWEXEC | _PAGE_HWWRITE; @@ -128,8 +127,8 @@ unsigned long __init mmu_mapin_ram(void) v += LARGE_PAGE_SIZE_4M; p += LARGE_PAGE_SIZE_4M; - s += LARGE_PAGE_SIZE_4M; + s -= LARGE_PAGE_SIZE_4M; } - return s; + return total_lowmem - s; } diff --git a/arch/powerpc/mm/44x_mmu.c b/arch/powerpc/mm/44x_mmu.c index c3df504..04dc087 100644 --- a/arch/powerpc/mm/44x_mmu.c +++ b/arch/powerpc/mm/44x_mmu.c @@ -35,6 +35,7 @@ */ unsigned int tlb_44x_index; /* = 0 */ unsigned int tlb_44x_hwater = PPC44x_TLB_SIZE - 1 - PPC44x_EARLY_TLBS; +int icache_44x_need_flush; /* * "Pins" a 256MB TLB entry in AS0 for kernel lowmem diff --git a/arch/powerpc/mm/fault.c b/arch/powerpc/mm/fault.c index a18fda3..8135da0 100644 --- a/arch/powerpc/mm/fault.c +++ b/arch/powerpc/mm/fault.c @@ -309,7 +309,7 @@ good_area: set_bit(PG_arch_1, &page->flags); } pte_update(ptep, 0, _PAGE_HWEXEC); - _tlbie(address); + _tlbie(address, mm->context.id); pte_unmap_unlock(ptep, ptl); up_read(&mm->mmap_sem); return 0; diff --git a/arch/powerpc/mm/hash_low_64.S b/arch/powerpc/mm/hash_low_64.S index ad253b9..e935edd 100644 --- a/arch/powerpc/mm/hash_low_64.S +++ b/arch/powerpc/mm/hash_low_64.S @@ -331,7 +331,7 @@ htab_pte_insert_failure: *****************************************************************************/ /* _hash_page_4K(unsigned long ea, unsigned long access, unsigned long vsid, - * pte_t *ptep, unsigned long trap, int local) + * pte_t *ptep, unsigned long trap, int local, int ssize) */ /* @@ -557,7 +557,8 @@ htab_inval_old_hpte: mr r4,r31 /* PTE.pte */ li r5,0 /* PTE.hidx */ li r6,MMU_PAGE_64K /* psize */ - ld r7,STK_PARM(r8)(r1) /* local */ + ld r7,STK_PARM(r9)(r1) /* ssize */ + ld r8,STK_PARM(r8)(r1) /* local */ bl .flush_hash_page b htab_insert_pte diff --git a/arch/powerpc/mm/hash_utils_64.c b/arch/powerpc/mm/hash_utils_64.c index c78dc91..f09730b 100644 --- a/arch/powerpc/mm/hash_utils_64.c +++ b/arch/powerpc/mm/hash_utils_64.c @@ -51,6 +51,7 @@ #include <asm/cputable.h> #include <asm/sections.h> #include <asm/spu.h> +#include <asm/udbg.h> #ifdef DEBUG #define DBG(fmt...) udbg_printf(fmt) @@ -791,8 +792,7 @@ int hash_page(unsigned long ea, unsigned long access, unsigned long trap) } if (user_region) { if (psize != get_paca()->context.user_psize) { - get_paca()->context.user_psize = - mm->context.user_psize; + get_paca()->context = mm->context; slb_flush_and_rebolt(); } } else if (get_paca()->vmalloc_sllp != @@ -885,6 +885,9 @@ void hash_preload(struct mm_struct *mm, unsigned long ea, local_irq_restore(flags); } +/* WARNING: This is called from hash_low_64.S, if you change this prototype, + * do not forget to update the assembly call site ! + */ void flush_hash_page(unsigned long va, real_pte_t pte, int psize, int ssize, int local) { diff --git a/arch/powerpc/mm/init_64.c b/arch/powerpc/mm/init_64.c index d9c82d3..c0f5cff 100644 --- a/arch/powerpc/mm/init_64.c +++ b/arch/powerpc/mm/init_64.c @@ -19,8 +19,6 @@ * */ -#undef DEBUG - #include <linux/signal.h> #include <linux/sched.h> #include <linux/kernel.h> @@ -66,12 +64,6 @@ #include "mmu_decl.h" -#ifdef DEBUG -#define DBG(fmt...) printk(fmt) -#else -#define DBG(fmt...) -#endif - #if PGTABLE_RANGE > USER_VSID_RANGE #warning Limited user VSID range means pagetable space is wasted #endif @@ -175,8 +167,8 @@ void pgtable_cache_init(void) int size = pgtable_cache_size[i]; const char *name = pgtable_cache_name[i]; - DBG("Allocating page table cache %s (#%d) " - "for size: %08x...\n", name, i, size); + pr_debug("Allocating page table cache %s (#%d) " + "for size: %08x...\n", name, i, size); pgtable_cache[i] = kmem_cache_create(name, size, size, SLAB_PANIC, @@ -239,8 +231,8 @@ int __meminit vmemmap_populate(struct page *start_page, if (!p) return -ENOMEM; - printk(KERN_WARNING "vmemmap %08lx allocated at %p, " - "physical %08lx.\n", start, p, __pa(p)); + pr_debug("vmemmap %08lx allocated at %p, physical %08lx.\n", + start, p, __pa(p)); mapped = htab_bolt_mapping(start, start + page_size, __pa(p), mode_rw, mmu_linear_psize, diff --git a/arch/powerpc/mm/mem.c b/arch/powerpc/mm/mem.c index 81eb96e..5402fb6 100644 --- a/arch/powerpc/mm/mem.c +++ b/arch/powerpc/mm/mem.c @@ -464,7 +464,7 @@ void update_mmu_cache(struct vm_area_struct *vma, unsigned long address, * we invalidate the TLB here, thus avoiding dcbst * misbehaviour. */ - _tlbie(address); + _tlbie(address, 0 /* 8xx doesn't care about PID */); #endif if (!PageReserved(page) && !test_bit(PG_arch_1, &page->flags)) { diff --git a/arch/powerpc/mm/mmu_decl.h b/arch/powerpc/mm/mmu_decl.h index c94a64f..ebfd13d 100644 --- a/arch/powerpc/mm/mmu_decl.h +++ b/arch/powerpc/mm/mmu_decl.h @@ -56,17 +56,17 @@ extern unsigned long total_lowmem; * architectures. -- Dan */ #if defined(CONFIG_8xx) -#define flush_HPTE(X, va, pg) _tlbie(va) +#define flush_HPTE(X, va, pg) _tlbie(va, 0 /* 8xx doesn't care about PID */) #define MMU_init_hw() do { } while(0) #define mmu_mapin_ram() (0UL) #elif defined(CONFIG_4xx) -#define flush_HPTE(X, va, pg) _tlbie(va) +#define flush_HPTE(pid, va, pg) _tlbie(va, pid) extern void MMU_init_hw(void); extern unsigned long mmu_mapin_ram(void); #elif defined(CONFIG_FSL_BOOKE) -#define flush_HPTE(X, va, pg) _tlbie(va) +#define flush_HPTE(pid, va, pg) _tlbie(va, pid) extern void MMU_init_hw(void); extern unsigned long mmu_mapin_ram(void); extern void adjust_total_lowmem(void); diff --git a/arch/powerpc/mm/slb.c b/arch/powerpc/mm/slb.c index bbd2c51..27922df 100644 --- a/arch/powerpc/mm/slb.c +++ b/arch/powerpc/mm/slb.c @@ -25,6 +25,7 @@ #include <asm/smp.h> #include <asm/firmware.h> #include <linux/compiler.h> +#include <asm/udbg.h> #ifdef DEBUG #define DBG(fmt...) udbg_printf(fmt) @@ -148,6 +149,35 @@ void slb_vmalloc_update(void) slb_flush_and_rebolt(); } +/* Helper function to compare esids. There are four cases to handle. + * 1. The system is not 1T segment size capable. Use the GET_ESID compare. + * 2. The system is 1T capable, both addresses are < 1T, use the GET_ESID compare. + * 3. The system is 1T capable, only one of the two addresses is > 1T. This is not a match. + * 4. The system is 1T capable, both addresses are > 1T, use the GET_ESID_1T macro to compare. + */ +static inline int esids_match(unsigned long addr1, unsigned long addr2) +{ + int esid_1t_count; + + /* System is not 1T segment size capable. */ + if (!cpu_has_feature(CPU_FTR_1T_SEGMENT)) + return (GET_ESID(addr1) == GET_ESID(addr2)); + + esid_1t_count = (((addr1 >> SID_SHIFT_1T) != 0) + + ((addr2 >> SID_SHIFT_1T) != 0)); + + /* both addresses are < 1T */ + if (esid_1t_count == 0) + return (GET_ESID(addr1) == GET_ESID(addr2)); + + /* One address < 1T, the other > 1T. Not a match */ + if (esid_1t_count == 1) + return 0; + + /* Both addresses are > 1T. */ + return (GET_ESID_1T(addr1) == GET_ESID_1T(addr2)); +} + /* Flush all user entries from the segment table of the current processor. */ void switch_slb(struct task_struct *tsk, struct mm_struct *mm) { @@ -193,15 +223,14 @@ void switch_slb(struct task_struct *tsk, struct mm_struct *mm) return; slb_allocate(pc); - if (GET_ESID(pc) == GET_ESID(stack)) + if (esids_match(pc,stack)) return; if (is_kernel_addr(stack)) return; slb_allocate(stack); - if ((GET_ESID(pc) == GET_ESID(unmapped_base)) - || (GET_ESID(stack) == GET_ESID(unmapped_base))) + if (esids_match(pc,unmapped_base) || esids_match(stack,unmapped_base)) return; if (is_kernel_addr(unmapped_base)) diff --git a/arch/powerpc/mm/stab.c b/arch/powerpc/mm/stab.c index 9e85bda..50448d5 100644 --- a/arch/powerpc/mm/stab.c +++ b/arch/powerpc/mm/stab.c @@ -20,6 +20,7 @@ #include <asm/lmb.h> #include <asm/abs_addr.h> #include <asm/firmware.h> +#include <asm/iseries/hv_call.h> struct stab_entry { unsigned long esid_data; diff --git a/arch/powerpc/mm/tlb_64.c b/arch/powerpc/mm/tlb_64.c index eafbca5..e2d867c 100644 --- a/arch/powerpc/mm/tlb_64.c +++ b/arch/powerpc/mm/tlb_64.c @@ -54,12 +54,10 @@ unsigned long pte_freelist_forced_free; ((PAGE_SIZE - sizeof(struct pte_freelist_batch)) \ / sizeof(pgtable_free_t)) -#ifdef CONFIG_SMP static void pte_free_smp_sync(void *arg) { /* Do nothing, just ensure we sync with all CPUs */ } -#endif /* This is only called when we are critically out of memory * (and fail to get a page in pte_free_tlb). diff --git a/arch/powerpc/platforms/40x/walnut.c b/arch/powerpc/platforms/40x/walnut.c index eb0c136..ff6db24 100644 --- a/arch/powerpc/platforms/40x/walnut.c +++ b/arch/powerpc/platforms/40x/walnut.c @@ -17,12 +17,13 @@ */ #include <linux/init.h> +#include <linux/of_platform.h> + #include <asm/machdep.h> #include <asm/prom.h> #include <asm/udbg.h> #include <asm/time.h> #include <asm/uic.h> -#include <asm/of_platform.h> static struct of_device_id walnut_of_bus[] = { { .compatible = "ibm,plb3", }, diff --git a/arch/powerpc/platforms/44x/bamboo.c b/arch/powerpc/platforms/44x/bamboo.c index 470e1a3..be23f11 100644 --- a/arch/powerpc/platforms/44x/bamboo.c +++ b/arch/powerpc/platforms/44x/bamboo.c @@ -14,12 +14,13 @@ * option) any later version. */ #include <linux/init.h> +#include <linux/of_platform.h> + #include <asm/machdep.h> #include <asm/prom.h> #include <asm/udbg.h> #include <asm/time.h> #include <asm/uic.h> -#include <asm/of_platform.h> #include "44x.h" static struct of_device_id bamboo_of_bus[] = { diff --git a/arch/powerpc/platforms/44x/ebony.c b/arch/powerpc/platforms/44x/ebony.c index 40e18fc..6cd3476 100644 --- a/arch/powerpc/platforms/44x/ebony.c +++ b/arch/powerpc/platforms/44x/ebony.c @@ -17,12 +17,13 @@ */ #include <linux/init.h> +#include <linux/of_platform.h> + #include <asm/machdep.h> #include <asm/prom.h> #include <asm/udbg.h> #include <asm/time.h> #include <asm/uic.h> -#include <asm/of_platform.h> #include "44x.h" diff --git a/arch/powerpc/platforms/44x/sequoia.c b/arch/powerpc/platforms/44x/sequoia.c index 30700b3..21a9dd1 100644 --- a/arch/powerpc/platforms/44x/sequoia.c +++ b/arch/powerpc/platforms/44x/sequoia.c @@ -14,12 +14,13 @@ * option) any later version. */ #include <linux/init.h> +#include <linux/of_platform.h> + #include <asm/machdep.h> #include <asm/prom.h> #include <asm/udbg.h> #include <asm/time.h> #include <asm/uic.h> -#include <asm/of_platform.h> #include "44x.h" static struct of_device_id sequoia_of_bus[] = { diff --git a/arch/powerpc/platforms/83xx/mpc832x_mds.c b/arch/powerpc/platforms/83xx/mpc832x_mds.c index 972fa85..39ee7a1 100644 --- a/arch/powerpc/platforms/83xx/mpc832x_mds.c +++ b/arch/powerpc/platforms/83xx/mpc832x_mds.c @@ -90,10 +90,11 @@ static void __init mpc832x_sys_setup_arch(void) if ((np = of_find_compatible_node(NULL, "network", "ucc_geth")) != NULL){ - /* Reset the Ethernet PHY */ - bcsr_regs[9] &= ~0x20; + /* Reset the Ethernet PHYs */ +#define BCSR8_FETH_RST 0x50 + bcsr_regs[8] &= ~BCSR8_FETH_RST; udelay(1000); - bcsr_regs[9] |= 0x20; + bcsr_regs[8] |= BCSR8_FETH_RST; iounmap(bcsr_regs); of_node_put(np); } @@ -145,30 +146,6 @@ static void __init mpc832x_sys_init_IRQ(void) #endif /* CONFIG_QUICC_ENGINE */ } -#if defined(CONFIG_I2C_MPC) && defined(CONFIG_SENSORS_DS1374) -extern ulong ds1374_get_rtc_time(void); -extern int ds1374_set_rtc_time(ulong); - -static int __init mpc832x_rtc_hookup(void) -{ - struct timespec tv; - - if (!machine_is(mpc832x_mds)) - return 0; - - ppc_md.get_rtc_time = ds1374_get_rtc_time; - ppc_md.set_rtc_time = ds1374_set_rtc_time; - - tv.tv_nsec = 0; - tv.tv_sec = (ppc_md.get_rtc_time) (); - do_settimeofday(&tv); - - return 0; -} - -late_initcall(mpc832x_rtc_hookup); -#endif - /* * Called very early, MMU is off, device-tree isn't unflattened */ diff --git a/arch/powerpc/platforms/83xx/mpc832x_rdb.c b/arch/powerpc/platforms/83xx/mpc832x_rdb.c index fbca336..d4bd040 100644 --- a/arch/powerpc/platforms/83xx/mpc832x_rdb.c +++ b/arch/powerpc/platforms/83xx/mpc832x_rdb.c @@ -15,7 +15,10 @@ */ #include <linux/pci.h> +#include <linux/interrupt.h> #include <linux/spi/spi.h> +#include <linux/spi/mmc_spi.h> +#include <linux/mmc/host.h> #include <asm/of_platform.h> #include <asm/time.h> @@ -46,15 +49,16 @@ static void mpc83xx_spi_deactivate_cs(u8 cs, u8 polarity) par_io_data_set(3, 13, !polarity); } +static struct mmc_spi_platform_data mpc832x_mmc_pdata = { + .ocr_mask = MMC_VDD_33_34, +}; + static struct spi_board_info mpc832x_spi_boardinfo = { .bus_num = 0x4c0, .chip_select = 0, .max_speed_hz = 50000000, - /* - * XXX: This is spidev (spi in userspace) stub, should - * be replaced by "mmc_spi" when mmc_spi will hit mainline. - */ - .modalias = "spidev", + .modalias = "mmc_spi", + .platform_data = &mpc832x_mmc_pdata, }; static int __init mpc832x_spi_init(void) diff --git a/arch/powerpc/platforms/83xx/mpc834x_mds.c b/arch/powerpc/platforms/83xx/mpc834x_mds.c index 00aed7c..a81bb3c 100644 --- a/arch/powerpc/platforms/83xx/mpc834x_mds.c +++ b/arch/powerpc/platforms/83xx/mpc834x_mds.c @@ -106,30 +106,6 @@ static void __init mpc834x_mds_init_IRQ(void) ipic_set_default_priority(); } -#if defined(CONFIG_I2C_MPC) && defined(CONFIG_SENSORS_DS1374) -extern ulong ds1374_get_rtc_time(void); -extern int ds1374_set_rtc_time(ulong); - -static int __init mpc834x_rtc_hookup(void) -{ - struct timespec tv; - - if (!machine_is(mpc834x_mds)) - return 0; - - ppc_md.get_rtc_time = ds1374_get_rtc_time; - ppc_md.set_rtc_time = ds1374_set_rtc_time; - - tv.tv_nsec = 0; - tv.tv_sec = (ppc_md.get_rtc_time) (); - do_settimeofday(&tv); - - return 0; -} - -late_initcall(mpc834x_rtc_hookup); -#endif - /* * Called very early, MMU is off, device-tree isn't unflattened */ diff --git a/arch/powerpc/platforms/83xx/mpc836x_mds.c b/arch/powerpc/platforms/83xx/mpc836x_mds.c index 0f3855c..e40012f 100644 --- a/arch/powerpc/platforms/83xx/mpc836x_mds.c +++ b/arch/powerpc/platforms/83xx/mpc836x_mds.c @@ -96,14 +96,39 @@ static void __init mpc836x_mds_setup_arch(void) if ((np = of_find_compatible_node(NULL, "network", "ucc_geth")) != NULL){ + uint svid; + /* Reset the Ethernet PHY */ - bcsr_regs[9] &= ~0x20; +#define BCSR9_GETHRST 0x20 + clrbits8(&bcsr_regs[9], BCSR9_GETHRST); udelay(1000); - bcsr_regs[9] |= 0x20; + setbits8(&bcsr_regs[9], BCSR9_GETHRST); + + /* handle mpc8360ea rev.2.1 erratum 2: RGMII Timing */ + svid = mfspr(SPRN_SVR); + if (svid == 0x80480021) { + void __iomem *immap; + + immap = ioremap(get_immrbase() + 0x14a8, 8); + + /* + * IMMR + 0x14A8[4:5] = 11 (clk delay for UCC 2) + * IMMR + 0x14A8[18:19] = 11 (clk delay for UCC 1) + */ + setbits32(immap, 0x0c003000); + + /* + * IMMR + 0x14AC[20:27] = 10101010 + * (data delay for both UCC's) + */ + clrsetbits_be32(immap + 4, 0xff0, 0xaa0); + + iounmap(immap); + } + iounmap(bcsr_regs); of_node_put(np); } - #endif /* CONFIG_QUICC_ENGINE */ } @@ -152,30 +177,6 @@ static void __init mpc836x_mds_init_IRQ(void) #endif /* CONFIG_QUICC_ENGINE */ } -#if defined(CONFIG_I2C_MPC) && defined(CONFIG_SENSORS_DS1374) -extern ulong ds1374_get_rtc_time(void); -extern int ds1374_set_rtc_time(ulong); - -static int __init mpc8360_rtc_hookup(void) -{ - struct timespec tv; - - if (!machine_is(mpc836x_mds)) - return 0; - - ppc_md.get_rtc_time = ds1374_get_rtc_time; - ppc_md.set_rtc_time = ds1374_set_rtc_time; - - tv.tv_nsec = 0; - tv.tv_sec = (ppc_md.get_rtc_time) (); - do_settimeofday(&tv); - - return 0; -} - -late_initcall(mpc8360_rtc_hookup); -#endif - /* * Called very early, MMU is off, device-tree isn't unflattened */ diff --git a/arch/powerpc/platforms/83xx/usb.c b/arch/powerpc/platforms/83xx/usb.c index eafe760..b45160f 100644 --- a/arch/powerpc/platforms/83xx/usb.c +++ b/arch/powerpc/platforms/83xx/usb.c @@ -130,7 +130,7 @@ int mpc831x_usb_cfg(void) out_be32(immap + MPC83XX_SCCR_OFFS, temp); /* Configure pin mux for ULPI. There is no pin mux for UTMI */ - if (!strcmp(prop, "ulpi")) { + if (prop && !strcmp(prop, "ulpi")) { temp = in_be32(immap + MPC83XX_SICRL_OFFS); temp &= ~MPC831X_SICRL_USB_MASK; temp |= MPC831X_SICRL_USB_ULPI; @@ -153,13 +153,13 @@ int mpc831x_usb_cfg(void) usb_regs = ioremap(res.start, res.end - res.start + 1); /* Using on-chip PHY */ - if (!strcmp(prop, "utmi_wide") || - !strcmp(prop, "utmi")) { + if (prop && (!strcmp(prop, "utmi_wide") || + !strcmp(prop, "utmi"))) { /* Set UTMI_PHY_EN, REFSEL to 48MHZ */ out_be32(usb_regs + FSL_USB2_CONTROL_OFFS, CONTROL_UTMI_PHY_EN | CONTROL_REFSEL_48MHZ); /* Using external UPLI PHY */ - } else if (!strcmp(prop, "ulpi")) { + } else if (prop && !strcmp(prop, "ulpi")) { /* Set PHY_CLK_SEL to ULPI */ temp = CONTROL_PHY_CLK_SEL_ULPI; #ifdef CONFIG_USB_OTG diff --git a/arch/powerpc/platforms/cell/interrupt.c b/arch/powerpc/platforms/cell/interrupt.c index 151fd8b..04f74f9 100644 --- a/arch/powerpc/platforms/cell/interrupt.c +++ b/arch/powerpc/platforms/cell/interrupt.c @@ -158,6 +158,18 @@ static unsigned int iic_get_irq(void) return virq; } +void iic_setup_cpu(void) +{ + out_be64(&__get_cpu_var(iic).regs->prio, 0xff); +} + +u8 iic_get_target_id(int cpu) +{ + return per_cpu(iic, cpu).target_id; +} + +EXPORT_SYMBOL_GPL(iic_get_target_id); + #ifdef CONFIG_SMP /* Use the highest interrupt priorities for IPI */ @@ -166,29 +178,17 @@ static inline int iic_ipi_to_irq(int ipi) return IIC_IRQ_TYPE_IPI + 0xf - ipi; } -void iic_setup_cpu(void) -{ - out_be64(&__get_cpu_var(iic).regs->prio, 0xff); -} - void iic_cause_IPI(int cpu, int mesg) { out_be64(&per_cpu(iic, cpu).regs->generate, (0xf - mesg) << 4); } -u8 iic_get_target_id(int cpu) -{ - return per_cpu(iic, cpu).target_id; -} -EXPORT_SYMBOL_GPL(iic_get_target_id); - struct irq_host *iic_get_irq_host(int node) { return iic_host; } EXPORT_SYMBOL_GPL(iic_get_irq_host); - static irqreturn_t iic_ipi_action(int irq, void *dev_id) { int ipi = (int)(long)dev_id; diff --git a/arch/powerpc/platforms/cell/smp.c b/arch/powerpc/platforms/cell/smp.c index 1c0acba..e443845 100644 --- a/arch/powerpc/platforms/cell/smp.c +++ b/arch/powerpc/platforms/cell/smp.c @@ -44,6 +44,7 @@ #include <asm/rtas.h> #include "interrupt.h" +#include <asm/udbg.h> #ifdef DEBUG #define DBG(fmt...) udbg_printf(fmt) diff --git a/arch/powerpc/platforms/cell/spufs/inode.c b/arch/powerpc/platforms/cell/spufs/inode.c index 0966d09..c0e968a 100644 --- a/arch/powerpc/platforms/cell/spufs/inode.c +++ b/arch/powerpc/platforms/cell/spufs/inode.c @@ -171,6 +171,7 @@ static int spufs_rmdir(struct inode *parent, struct dentry *dir) { /* remove all entries */ spufs_prune_dir(dir); + d_drop(dir); return simple_rmdir(parent, dir); } diff --git a/arch/powerpc/platforms/celleb/setup.c b/arch/powerpc/platforms/celleb/setup.c index 1769d75..ddfb35a 100644 --- a/arch/powerpc/platforms/celleb/setup.c +++ b/arch/powerpc/platforms/celleb/setup.c @@ -49,6 +49,7 @@ #include <asm/machdep.h> #include <asm/cputable.h> #include <asm/irq.h> +#include <asm/time.h> #include <asm/spu_priv1.h> #include <asm/firmware.h> #include <asm/of_platform.h> diff --git a/arch/powerpc/platforms/embedded6xx/prpmc2800.c b/arch/powerpc/platforms/embedded6xx/prpmc2800.c index e484cac..653a5eb 100644 --- a/arch/powerpc/platforms/embedded6xx/prpmc2800.c +++ b/arch/powerpc/platforms/embedded6xx/prpmc2800.c @@ -144,6 +144,7 @@ static int __init prpmc2800_probe(void) strncpy(prpmc2800_platform_name, m, min((int)len, PLATFORM_NAME_MAX - 1)); + _set_L2CR(_get_L2CR() | L2CR_L2E); return 1; } diff --git a/arch/powerpc/platforms/iseries/irq.h b/arch/powerpc/platforms/iseries/irq.h index 69f1b43..a1c2360 100644 --- a/arch/powerpc/platforms/iseries/irq.h +++ b/arch/powerpc/platforms/iseries/irq.h @@ -1,9 +1,13 @@ #ifndef _ISERIES_IRQ_H #define _ISERIES_IRQ_H +#ifdef CONFIG_PCI extern void iSeries_init_IRQ(void); extern int iSeries_allocate_IRQ(HvBusNumber, HvSubBusNumber, u32); extern void iSeries_activate_IRQs(void); +#else +#define iSeries_init_IRQ NULL +#endif extern unsigned int iSeries_get_irq(void); #endif /* _ISERIES_IRQ_H */ diff --git a/arch/powerpc/platforms/iseries/setup.c b/arch/powerpc/platforms/iseries/setup.c index 37ae07e..0877a88 100644 --- a/arch/powerpc/platforms/iseries/setup.c +++ b/arch/powerpc/platforms/iseries/setup.c @@ -617,10 +617,6 @@ static void iseries_dedicated_idle(void) } } -#ifndef CONFIG_PCI -void __init iSeries_init_IRQ(void) { } -#endif - static void __iomem *iseries_ioremap(phys_addr_t address, unsigned long size, unsigned long flags) { diff --git a/arch/powerpc/platforms/iseries/vio.c b/arch/powerpc/platforms/iseries/vio.c index d6435b0..be06cfd 100644 --- a/arch/powerpc/platforms/iseries/vio.c +++ b/arch/powerpc/platforms/iseries/vio.c @@ -523,15 +523,16 @@ static void __init get_viotape_info(struct device_node *vio_root) static int __init iseries_vio_init(void) { struct device_node *vio_root; + int ret = -ENODEV; if (!firmware_has_feature(FW_FEATURE_ISERIES)) - return -ENODEV; + goto out; iommu_vio_init(); vio_root = of_find_node_by_path("/vdevice"); if (!vio_root) - return -ENODEV; + goto out; if (viopath_hostLp == HvLpIndexInvalid) { vio_set_hostlp(); @@ -544,10 +545,11 @@ static int __init iseries_vio_init(void) get_viocd_info(vio_root); get_viotape_info(vio_root); - return 0; + ret = 0; put_node: of_node_put(vio_root); - return -ENODEV; + out: + return ret; } arch_initcall(iseries_vio_init); diff --git a/arch/powerpc/platforms/pasemi/setup.c b/arch/powerpc/platforms/pasemi/setup.c index 3a5d112..3d62060 100644 --- a/arch/powerpc/platforms/pasemi/setup.c +++ b/arch/powerpc/platforms/pasemi/setup.c @@ -214,7 +214,7 @@ static __init void pas_init_IRQ(void) printk(KERN_DEBUG "OpenPIC addr: %lx\n", openpic_addr); mpic = mpic_alloc(mpic_node, openpic_addr, - MPIC_PRIMARY|MPIC_LARGE_VECTORS|MPIC_WANTS_RESET, + MPIC_PRIMARY|MPIC_LARGE_VECTORS, 0, 0, " PAS-OPIC "); BUG_ON(!mpic); diff --git a/arch/powerpc/platforms/pseries/Kconfig b/arch/powerpc/platforms/pseries/Kconfig index 16e4e40..306a9d0 100644 --- a/arch/powerpc/platforms/pseries/Kconfig +++ b/arch/powerpc/platforms/pseries/Kconfig @@ -21,7 +21,7 @@ config PPC_SPLPAR config EEH bool "PCI Extended Error Handling (EEH)" if EMBEDDED - depends on PPC_PSERIES + depends on PPC_PSERIES && PCI default y if !EMBEDDED config SCANLOG diff --git a/arch/powerpc/platforms/pseries/eeh.c b/arch/powerpc/platforms/pseries/eeh.c index 22322b3..fb3d636 100644 --- a/arch/powerpc/platforms/pseries/eeh.c +++ b/arch/powerpc/platforms/pseries/eeh.c @@ -186,6 +186,11 @@ static size_t gather_pci_data(struct pci_dn *pdn, char * buf, size_t len) n += scnprintf(buf+n, len-n, "cmd/stat:%x\n", cfg); printk(KERN_WARNING "EEH: PCI cmd/status register: %08x\n", cfg); + if (!dev) { + printk(KERN_WARNING "EEH: no PCI device for this of node\n"); + return n; + } + /* Gather bridge-specific registers */ if (dev->class >> 16 == PCI_BASE_CLASS_BRIDGE) { rtas_read_config(pdn, PCI_SEC_STATUS, 2, &cfg); @@ -198,7 +203,7 @@ static size_t gather_pci_data(struct pci_dn *pdn, char * buf, size_t len) } /* Dump out the PCI-X command and status regs */ - cap = pci_find_capability(pdn->pcidev, PCI_CAP_ID_PCIX); + cap = pci_find_capability(dev, PCI_CAP_ID_PCIX); if (cap) { rtas_read_config(pdn, cap, 4, &cfg); n += scnprintf(buf+n, len-n, "pcix-cmd:%x\n", cfg); @@ -210,7 +215,7 @@ static size_t gather_pci_data(struct pci_dn *pdn, char * buf, size_t len) } /* If PCI-E capable, dump PCI-E cap 10, and the AER */ - cap = pci_find_capability(pdn->pcidev, PCI_CAP_ID_EXP); + cap = pci_find_capability(dev, PCI_CAP_ID_EXP); if (cap) { n += scnprintf(buf+n, len-n, "pci-e cap10:\n"); printk(KERN_WARNING @@ -222,7 +227,7 @@ static size_t gather_pci_data(struct pci_dn *pdn, char * buf, size_t len) printk(KERN_WARNING "EEH: PCI-E %02x: %08x\n", i, cfg); } - cap = pci_find_ext_capability(pdn->pcidev, PCI_EXT_CAP_ID_ERR); + cap = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR); if (cap) { n += scnprintf(buf+n, len-n, "pci-e AER:\n"); printk(KERN_WARNING @@ -318,7 +323,7 @@ eeh_wait_for_slot_status(struct pci_dn *pdn, int max_wait_msecs) if (rets[2] == 0) return -1; /* permanently unavailable */ - if (max_wait_msecs <= 0) return -1; + if (max_wait_msecs <= 0) break; mwait = rets[2]; if (mwait <= 0) { diff --git a/arch/powerpc/platforms/pseries/eeh_driver.c b/arch/powerpc/platforms/pseries/eeh_driver.c index 15e015e..57e025e 100644 --- a/arch/powerpc/platforms/pseries/eeh_driver.c +++ b/arch/powerpc/platforms/pseries/eeh_driver.c @@ -105,17 +105,18 @@ static void eeh_report_error(struct pci_dev *dev, void *userdata) return; rc = driver->err_handler->error_detected (dev, pci_channel_io_frozen); + + /* A driver that needs a reset trumps all others */ + if (rc == PCI_ERS_RESULT_NEED_RESET) *res = rc; if (*res == PCI_ERS_RESULT_NONE) *res = rc; - if (*res == PCI_ERS_RESULT_DISCONNECT && - rc == PCI_ERS_RESULT_NEED_RESET) *res = rc; } /** * eeh_report_mmio_enabled - tell drivers that MMIO has been enabled * - * Report an EEH error to each device driver, collect up and - * merge the device driver responses. Cumulative response - * passed back in "userdata". + * Tells each device driver that IO ports, MMIO and config space I/O + * are now enabled. Collects up and merges the device driver responses. + * Cumulative response passed back in "userdata". */ static void eeh_report_mmio_enabled(struct pci_dev *dev, void *userdata) @@ -123,17 +124,16 @@ static void eeh_report_mmio_enabled(struct pci_dev *dev, void *userdata) enum pci_ers_result rc, *res = userdata; struct pci_driver *driver = dev->driver; - // dev->error_state = pci_channel_mmio_enabled; - if (!driver || !driver->err_handler || !driver->err_handler->mmio_enabled) return; rc = driver->err_handler->mmio_enabled (dev); + + /* A driver that needs a reset trumps all others */ + if (rc == PCI_ERS_RESULT_NEED_RESET) *res = rc; if (*res == PCI_ERS_RESULT_NONE) *res = rc; - if (*res == PCI_ERS_RESULT_DISCONNECT && - rc == PCI_ERS_RESULT_NEED_RESET) *res = rc; } /** diff --git a/arch/powerpc/platforms/pseries/firmware.c b/arch/powerpc/platforms/pseries/firmware.c index 8b18a1c..b765b7c 100644 --- a/arch/powerpc/platforms/pseries/firmware.c +++ b/arch/powerpc/platforms/pseries/firmware.c @@ -25,6 +25,7 @@ #include <asm/firmware.h> #include <asm/prom.h> +#include <asm/udbg.h> #ifdef DEBUG #define DBG(fmt...) udbg_printf(fmt) diff --git a/arch/powerpc/platforms/pseries/msi.c b/arch/powerpc/platforms/pseries/msi.c index 2793a1b..f15222b 100644 --- a/arch/powerpc/platforms/pseries/msi.c +++ b/arch/powerpc/platforms/pseries/msi.c @@ -171,6 +171,7 @@ static int rtas_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type) struct pci_dn *pdn; int hwirq, virq, i, rc; struct msi_desc *entry; + struct msi_msg msg; pdn = get_pdn(pdev); if (!pdn) @@ -213,6 +214,11 @@ static int rtas_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type) dev_dbg(&pdev->dev, "rtas_msi: allocated virq %d\n", virq); set_irq_msi(virq, entry); + + /* Read config space back so we can restore after reset */ + read_msi_msg(virq, &msg); + entry->msg = msg; + unmask_msi_irq(virq); } diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c index fdb9b1c..fdeefe5 100644 --- a/arch/powerpc/platforms/pseries/setup.c +++ b/arch/powerpc/platforms/pseries/setup.c @@ -507,7 +507,8 @@ define_machine(pseries) { .restart = rtas_restart, .power_off = pSeries_power_off, .halt = rtas_halt, - .panic = rtas_os_term, + .panic = rtas_panic_msg, + .machine_shutdown = rtas_os_term, .get_boot_time = rtas_get_boot_time, .get_rtc_time = rtas_get_rtc_time, .set_rtc_time = rtas_set_rtc_time, diff --git a/arch/powerpc/sysdev/cpm_common.c b/arch/powerpc/sysdev/cpm_common.c index 66c8ad4..165981c 100644 --- a/arch/powerpc/sysdev/cpm_common.c +++ b/arch/powerpc/sysdev/cpm_common.c @@ -77,8 +77,6 @@ int __init cpm_muram_init(void) int i = 0; int ret = 0; - printk("cpm_muram_init\n"); - spin_lock_init(&cpm_muram_lock); /* initialize the info header */ rh_init(&cpm_muram_info, 1, @@ -193,7 +191,7 @@ void __iomem *cpm_muram_addr(unsigned long offset) EXPORT_SYMBOL(cpm_muram_addr); /** - * cpm_muram_phys - turn a muram virtual address into a DMA address + * cpm_muram_dma - turn a muram virtual address into a DMA address * @offset: virtual address from cpm_muram_addr() to convert */ dma_addr_t cpm_muram_dma(void __iomem *addr) diff --git a/arch/powerpc/sysdev/i8259.c b/arch/powerpc/sysdev/i8259.c index 7c1b27a..216c0f5 100644 --- a/arch/powerpc/sysdev/i8259.c +++ b/arch/powerpc/sysdev/i8259.c @@ -137,6 +137,7 @@ static void i8259_unmask_irq(unsigned int irq_nr) static struct irq_chip i8259_pic = { .typename = " i8259 ", .mask = i8259_mask_irq, + .disable = i8259_mask_irq, .unmask = i8259_unmask_irq, .mask_ack = i8259_mask_and_ack_irq, }; diff --git a/arch/powerpc/sysdev/mv64x60_pci.c b/arch/powerpc/sysdev/mv64x60_pci.c index 9b3baa7..6933f9c 100644 --- a/arch/powerpc/sysdev/mv64x60_pci.c +++ b/arch/powerpc/sysdev/mv64x60_pci.c @@ -24,8 +24,9 @@ #define MV64X60_VAL_LEN_MAX 11 #define MV64X60_PCICFG_CPCI_HOTSWAP 0x68 -static ssize_t mv64x60_hs_reg_read(struct kobject *kobj, char *buf, loff_t off, - size_t count) +static ssize_t mv64x60_hs_reg_read(struct kobject *kobj, + struct bin_attribute *attr, char *buf, + loff_t off, size_t count) { struct pci_dev *phb; u32 v; @@ -44,8 +45,9 @@ static ssize_t mv64x60_hs_reg_read(struct kobject *kobj, char *buf, loff_t off, return sprintf(buf, "0x%08x\n", v); } -static ssize_t mv64x60_hs_reg_write(struct kobject *kobj, char *buf, loff_t off, - size_t count) +static ssize_t mv64x60_hs_reg_write(struct kobject *kobj, + struct bin_attribute *attr, char *buf, + loff_t off, size_t count) { struct pci_dev *phb; u32 v; diff --git a/arch/powerpc/sysdev/uic.c b/arch/powerpc/sysdev/uic.c index 5149716..847a549 100644 --- a/arch/powerpc/sysdev/uic.c +++ b/arch/powerpc/sysdev/uic.c @@ -97,6 +97,22 @@ static void uic_ack_irq(unsigned int virq) spin_unlock_irqrestore(&uic->lock, flags); } +static void uic_mask_ack_irq(unsigned int virq) +{ + struct uic *uic = get_irq_chip_data(virq); + unsigned int src = uic_irq_to_hw(virq); + unsigned long flags; + u32 er, sr; + + sr = 1 << (31-src); + spin_lock_irqsave(&uic->lock, flags); + er = mfdcr(uic->dcrbase + UIC_ER); + er &= ~sr; + mtdcr(uic->dcrbase + UIC_ER, er); + mtdcr(uic->dcrbase + UIC_SR, sr); + spin_unlock_irqrestore(&uic->lock, flags); +} + static int uic_set_irq_type(unsigned int virq, unsigned int flow_type) { struct uic *uic = get_irq_chip_data(virq); @@ -152,7 +168,7 @@ static struct irq_chip uic_irq_chip = { .typename = " UIC ", .unmask = uic_unmask_irq, .mask = uic_mask_irq, -/* .mask_ack = uic_mask_irq_and_ack, */ + .mask_ack = uic_mask_ack_irq, .ack = uic_ack_irq, .set_type = uic_set_irq_type, }; diff --git a/arch/ppc/kernel/entry.S b/arch/ppc/kernel/entry.S index fba7ca1..59e77eb 100644 --- a/arch/ppc/kernel/entry.S +++ b/arch/ppc/kernel/entry.S @@ -244,6 +244,16 @@ syscall_exit_cont: andis. r10,r0,DBCR0_IC@h bnel- load_dbcr0 #endif +#ifdef CONFIG_44x + lis r4,icache_44x_need_flush@ha + lwz r5,icache_44x_need_flush@l(r4) + cmplwi cr0,r5,0 + bne- 2f +1: +#endif /* CONFIG_44x */ +BEGIN_FTR_SECTION + lwarx r7,0,r1 +END_FTR_SECTION_IFSET(CPU_FTR_NEED_PAIRED_STWCX) stwcx. r0,0,r1 /* to clear the reservation */ lwz r4,_LINK(r1) lwz r5,_CCR(r1) @@ -258,6 +268,12 @@ syscall_exit_cont: mtspr SPRN_SRR1,r8 SYNC RFI +#ifdef CONFIG_44x +2: li r7,0 + iccci r0,r0 + stw r7,icache_44x_need_flush@l(r4) + b 1b +#endif /* CONFIG_44x */ 66: li r3,-ENOSYS b ret_from_syscall @@ -679,6 +695,16 @@ resume_kernel: /* interrupts are hard-disabled at this point */ restore: +#ifdef CONFIG_44x + lis r4,icache_44x_need_flush@ha + lwz r5,icache_44x_need_flush@l(r4) + cmplwi cr0,r5,0 + beq+ 1f + li r6,0 + iccci r0,r0 + stw r6,icache_44x_need_flush@l(r4) +1: +#endif /* CONFIG_44x */ lwz r0,GPR0(r1) lwz r2,GPR2(r1) REST_4GPRS(3, r1) @@ -690,6 +716,9 @@ restore: mtctr r11 PPC405_ERR77(0,r1) +BEGIN_FTR_SECTION + lwarx r11,0,r1 +END_FTR_SECTION_IFSET(CPU_FTR_NEED_PAIRED_STWCX) stwcx. r0,0,r1 /* to clear the reservation */ #if !(defined(CONFIG_4xx) || defined(CONFIG_BOOKE)) diff --git a/arch/ppc/kernel/misc.S b/arch/ppc/kernel/misc.S index a22e1f4..e0c850d 100644 --- a/arch/ppc/kernel/misc.S +++ b/arch/ppc/kernel/misc.S @@ -224,7 +224,16 @@ _GLOBAL(_tlbia) */ _GLOBAL(_tlbie) #if defined(CONFIG_40x) + /* We run the search with interrupts disabled because we have to change + * the PID and I don't want to preempt when that happens. + */ + mfmsr r5 + mfspr r6,SPRN_PID + wrteei 0 + mtspr SPRN_PID,r4 tlbsx. r3, 0, r3 + mtspr SPRN_PID,r6 + wrtee r5 bne 10f sync /* There are only 64 TLB entries, so r3 < 64, which means bit 25 is clear. @@ -234,22 +243,21 @@ _GLOBAL(_tlbie) isync 10: #elif defined(CONFIG_44x) - mfspr r4,SPRN_MMUCR - mfspr r5,SPRN_PID /* Get PID */ - rlwimi r4,r5,0,24,31 /* Set TID */ + mfspr r5,SPRN_MMUCR + rlwimi r5,r4,0,24,31 /* Set TID */ /* We have to run the search with interrupts disabled, even critical * and debug interrupts (in fact the only critical exceptions we have * are debug and machine check). Otherwise an interrupt which causes * a TLB miss can clobber the MMUCR between the mtspr and the tlbsx. */ - mfmsr r5 + mfmsr r4 lis r6,(MSR_EE|MSR_CE|MSR_ME|MSR_DE)@ha addi r6,r6,(MSR_EE|MSR_CE|MSR_ME|MSR_DE)@l - andc r6,r5,r6 + andc r6,r4,r6 mtmsr r6 - mtspr SPRN_MMUCR,r4 + mtspr SPRN_MMUCR,r5 tlbsx. r3, 0, r3 - mtmsr r5 + mtmsr r4 bne 10f sync /* There are only 64 TLB entries, so r3 < 64, @@ -491,12 +499,21 @@ END_FTR_SECTION_IFSET(CPU_FTR_COHERENT_ICACHE) addi r3,r3,L1_CACHE_BYTES bdnz 0b sync +#ifndef CONFIG_44x + /* We don't flush the icache on 44x. Those have a virtual icache + * and we don't have access to the virtual address here (it's + * not the page vaddr but where it's mapped in user space). The + * flushing of the icache on these is handled elsewhere, when + * a change in the address space occurs, before returning to + * user space + */ mtctr r4 1: icbi 0,r6 addi r6,r6,L1_CACHE_BYTES bdnz 1b sync isync +#endif /* CONFIG_44x */ blr /* diff --git a/arch/ppc/kernel/setup.c b/arch/ppc/kernel/setup.c index aac88c2..5255bd8 100644 --- a/arch/ppc/kernel/setup.c +++ b/arch/ppc/kernel/setup.c @@ -312,7 +312,14 @@ early_init(int r3, int r4, int r5) * Identify the CPU type and fix up code sections * that depend on which cpu we have. */ +#if defined(CONFIG_440EP) && defined(CONFIG_PPC_FPU) + /* We pass the virtual PVR here for 440EP as 440EP and 440GR have + * identical PVRs and there is no reliable way to check for the FPU + */ + spec = identify_cpu(offset, (mfspr(SPRN_PVR) | 0x8)); +#else spec = identify_cpu(offset, mfspr(SPRN_PVR)); +#endif do_feature_fixups(spec->cpu_features, PTRRELOC(&__start___ftr_fixup), PTRRELOC(&__stop___ftr_fixup)); diff --git a/arch/ppc/mm/44x_mmu.c b/arch/ppc/mm/44x_mmu.c index 0a0a0487b..6536a25 100644 --- a/arch/ppc/mm/44x_mmu.c +++ b/arch/ppc/mm/44x_mmu.c @@ -61,6 +61,7 @@ extern char etext[], _stext[]; */ unsigned int tlb_44x_index = 0; unsigned int tlb_44x_hwater = 62; +int icache_44x_need_flush; /* * "Pins" a 256MB TLB entry in AS0 for kernel lowmem diff --git a/arch/ppc/mm/4xx_mmu.c b/arch/ppc/mm/4xx_mmu.c index 838e09d..ea785db 100644 --- a/arch/ppc/mm/4xx_mmu.c +++ b/arch/ppc/mm/4xx_mmu.c @@ -99,13 +99,12 @@ unsigned long __init mmu_mapin_ram(void) v = KERNELBASE; p = PPC_MEMSTART; - s = 0; + s = total_lowmem; - if (__map_without_ltlbs) { - return s; - } + if (__map_without_ltlbs) + return 0; - while (s <= (total_lowmem - LARGE_PAGE_SIZE_16M)) { + while (s >= LARGE_PAGE_SIZE_16M) { pmd_t *pmdp; unsigned long val = p | _PMD_SIZE_16M | _PAGE_HWEXEC | _PAGE_HWWRITE; @@ -117,10 +116,10 @@ unsigned long __init mmu_mapin_ram(void) v += LARGE_PAGE_SIZE_16M; p += LARGE_PAGE_SIZE_16M; - s += LARGE_PAGE_SIZE_16M; + s -= LARGE_PAGE_SIZE_16M; } - while (s <= (total_lowmem - LARGE_PAGE_SIZE_4M)) { + while (s >= LARGE_PAGE_SIZE_4M) { pmd_t *pmdp; unsigned long val = p | _PMD_SIZE_4M | _PAGE_HWEXEC | _PAGE_HWWRITE; @@ -129,8 +128,8 @@ unsigned long __init mmu_mapin_ram(void) v += LARGE_PAGE_SIZE_4M; p += LARGE_PAGE_SIZE_4M; - s += LARGE_PAGE_SIZE_4M; + s -= LARGE_PAGE_SIZE_4M; } - return s; + return total_lowmem - s; } diff --git a/arch/ppc/mm/fault.c b/arch/ppc/mm/fault.c index 254c23b..36c0e75 100644 --- a/arch/ppc/mm/fault.c +++ b/arch/ppc/mm/fault.c @@ -227,7 +227,7 @@ good_area: set_bit(PG_arch_1, &page->flags); } pte_update(ptep, 0, _PAGE_HWEXEC); - _tlbie(address); + _tlbie(address, mm->context.id); pte_unmap_unlock(ptep, ptl); up_read(&mm->mmap_sem); return 0; diff --git a/arch/ppc/mm/init.c b/arch/ppc/mm/init.c index 390dd19..dd898d3 100644 --- a/arch/ppc/mm/init.c +++ b/arch/ppc/mm/init.c @@ -561,7 +561,7 @@ void update_mmu_cache(struct vm_area_struct *vma, unsigned long address, * That means the zeroed TLB has to be invalidated * whenever a page miss occurs. */ - _tlbie(address); + _tlbie(address, 0 /* 8xx doesn't care about PID */); #endif if (!PageReserved(page) && !test_bit(PG_arch_1, &page->flags)) { diff --git a/arch/ppc/mm/mmu_decl.h b/arch/ppc/mm/mmu_decl.h index 540f329..b298b60 100644 --- a/arch/ppc/mm/mmu_decl.h +++ b/arch/ppc/mm/mmu_decl.h @@ -49,17 +49,17 @@ extern unsigned int num_tlbcam_entries; * architectures. -- Dan */ #if defined(CONFIG_8xx) -#define flush_HPTE(X, va, pg) _tlbie(va) +#define flush_HPTE(X, va, pg) _tlbie(va, 0 /* 8xx doesn't care about PID */) #define MMU_init_hw() do { } while(0) #define mmu_mapin_ram() (0UL) #elif defined(CONFIG_4xx) -#define flush_HPTE(X, va, pg) _tlbie(va) +#define flush_HPTE(pid, va, pg) _tlbie(va, pid) extern void MMU_init_hw(void); extern unsigned long mmu_mapin_ram(void); #elif defined(CONFIG_FSL_BOOKE) -#define flush_HPTE(X, va, pg) _tlbie(va) +#define flush_HPTE(pid, va, pg) _tlbie(va, pid) extern void MMU_init_hw(void); extern unsigned long mmu_mapin_ram(void); extern void adjust_total_lowmem(void); diff --git a/arch/ppc/platforms/4xx/ebony.c b/arch/ppc/platforms/4xx/ebony.c index 05d7184..453643a 100644 --- a/arch/ppc/platforms/4xx/ebony.c +++ b/arch/ppc/platforms/4xx/ebony.c @@ -236,7 +236,7 @@ ebony_early_serial_map(void) gen550_init(0, &port); /* Purge TLB entry added in head_44x.S for early serial access */ - _tlbie(UART0_IO_BASE); + _tlbie(UART0_IO_BASE, 0); #endif port.membase = ioremap64(PPC440GP_UART1_ADDR, 8); diff --git a/arch/ppc/platforms/4xx/luan.c b/arch/ppc/platforms/4xx/luan.c index 4b16961..b79ebb8 100644 --- a/arch/ppc/platforms/4xx/luan.c +++ b/arch/ppc/platforms/4xx/luan.c @@ -230,9 +230,14 @@ luan_setup_hoses(void) /* Allocate hoses for PCIX1 and PCIX2 */ hose1 = pcibios_alloc_controller(); + if (!hose1) + return; + hose2 = pcibios_alloc_controller(); - if (!hose1 || !hose2) + if (!hose2) { + pcibios_free_controller(hose1); return; + } /* Setup PCIX1 */ hose1->first_busno = 0; diff --git a/arch/ppc/platforms/4xx/ocotea.c b/arch/ppc/platforms/4xx/ocotea.c index fd0f971..28a712c 100644 --- a/arch/ppc/platforms/4xx/ocotea.c +++ b/arch/ppc/platforms/4xx/ocotea.c @@ -259,7 +259,7 @@ ocotea_early_serial_map(void) gen550_init(0, &port); /* Purge TLB entry added in head_44x.S for early serial access */ - _tlbie(UART0_IO_BASE); + _tlbie(UART0_IO_BASE, 0); #endif port.membase = ioremap64(PPC440GX_UART1_ADDR, 8); diff --git a/arch/ppc/platforms/4xx/taishan.c b/arch/ppc/platforms/4xx/taishan.c index 888c492..f6a0c66 100644 --- a/arch/ppc/platforms/4xx/taishan.c +++ b/arch/ppc/platforms/4xx/taishan.c @@ -316,7 +316,7 @@ taishan_early_serial_map(void) gen550_init(0, &port); /* Purge TLB entry added in head_44x.S for early serial access */ - _tlbie(UART0_IO_BASE); + _tlbie(UART0_IO_BASE, 0); #endif port.membase = ioremap64(PPC440GX_UART1_ADDR, 8); diff --git a/arch/ppc/platforms/4xx/yucca.c b/arch/ppc/platforms/4xx/yucca.c index a83b0ba..66a44ff 100644 --- a/arch/ppc/platforms/4xx/yucca.c +++ b/arch/ppc/platforms/4xx/yucca.c @@ -211,6 +211,7 @@ static void __init yucca_setup_pcie_fpga_rootpoint(int port) break; default: + iounmap(pcie_reg_fpga_base); return; } diff --git a/arch/ppc/syslib/i8259.c b/arch/ppc/syslib/i8259.c index 1e5a00a4..559f27c 100644 --- a/arch/ppc/syslib/i8259.c +++ b/arch/ppc/syslib/i8259.c @@ -127,6 +127,7 @@ static void i8259_unmask_irq(unsigned int irq_nr) static struct irq_chip i8259_pic = { .typename = " i8259 ", .mask = i8259_mask_irq, + .disable = i8259_mask_irq, .unmask = i8259_unmask_irq, .mask_ack = i8259_mask_and_ack_irq, }; diff --git a/arch/ppc/syslib/m8260_setup.c b/arch/ppc/syslib/m8260_setup.c index 15f0d73..46588fa 100644 --- a/arch/ppc/syslib/m8260_setup.c +++ b/arch/ppc/syslib/m8260_setup.c @@ -25,6 +25,7 @@ #include <asm/machdep.h> #include <asm/bootinfo.h> #include <asm/time.h> +#include <asm/ppc_sys.h> #include "cpm2_pic.h" @@ -61,7 +62,7 @@ m8260_setup_arch(void) #endif identify_ppc_sys_by_name_and_id(BOARD_CHIP_NAME, - in_be32(CPM_MAP_ADDR + CPM_IMMR_OFFSET)); + in_be32((void *)CPM_MAP_ADDR + CPM_IMMR_OFFSET)); m82xx_board_setup(); } @@ -147,12 +148,12 @@ m8260_show_cpuinfo(struct seq_file *m) seq_printf(m, "vendor\t\t: %s\n" "machine\t\t: %s\n" "\n" - "mem size\t\t: 0x%08x\n" - "console baud\t\t: %d\n" + "mem size\t\t: 0x%08lx\n" + "console baud\t\t: %ld\n" "\n" - "core clock\t: %u MHz\n" - "CPM clock\t: %u MHz\n" - "bus clock\t: %u MHz\n", + "core clock\t: %lu MHz\n" + "CPM clock\t: %lu MHz\n" + "bus clock\t: %lu MHz\n", CPUINFO_VENDOR, CPUINFO_MACHINE, bp->bi_memsize, bp->bi_baudrate, bp->bi_intfreq / 1000000, bp->bi_cpmfreq / 1000000, bp->bi_busfreq / 1000000); diff --git a/arch/ppc/syslib/virtex_devices.c b/arch/ppc/syslib/virtex_devices.c index ace4ec0..f658ff3 100644 --- a/arch/ppc/syslib/virtex_devices.c +++ b/arch/ppc/syslib/virtex_devices.c @@ -87,6 +87,29 @@ }, \ } +#define XPAR_AC97_CONTROLLER_REFERENCE(num) { \ + .name = "ml403_ac97cr", \ + .id = num, \ + .num_resources = 3, \ + .resource = (struct resource[]) { \ + { \ + .start = XPAR_OPB_AC97_CONTROLLER_REF_##num##_BASEADDR, \ + .end = XPAR_OPB_AC97_CONTROLLER_REF_##num##_HIGHADDR, \ + .flags = IORESOURCE_MEM, \ + }, \ + { \ + .start = XPAR_OPB_INTC_0_OPB_AC97_CONTROLLER_REF_##num##_PLAYBACK_INTERRUPT_INTR, \ + .end = XPAR_OPB_INTC_0_OPB_AC97_CONTROLLER_REF_##num##_PLAYBACK_INTERRUPT_INTR, \ + .flags = IORESOURCE_IRQ, \ + }, \ + { \ + .start = XPAR_OPB_INTC_0_OPB_AC97_CONTROLLER_REF_##num##_RECORD_INTERRUPT_INTR, \ + .end = XPAR_OPB_INTC_0_OPB_AC97_CONTROLLER_REF_##num##_RECORD_INTERRUPT_INTR, \ + .flags = IORESOURCE_IRQ, \ + }, \ + }, \ +} + /* UART 8250 driver platform data table */ struct plat_serial8250_port virtex_serial_platform_data[] = { #if defined(XPAR_UARTNS550_0_BASEADDR) @@ -173,6 +196,14 @@ struct platform_device virtex_platform_devices[] = { #if defined(XPAR_TFT_3_BASEADDR) XPAR_TFT(3), #endif + + /* AC97 Controller Reference instances */ +#if defined(XPAR_OPB_AC97_CONTROLLER_REF_0_BASEADDR) + XPAR_AC97_CONTROLLER_REFERENCE(0), +#endif +#if defined(XPAR_OPB_AC97_CONTROLLER_REF_1_BASEADDR) + XPAR_AC97_CONTROLLER_REFERENCE(1), +#endif }; /* Early serial support functions */ diff --git a/arch/s390/appldata/appldata.h b/arch/s390/appldata/appldata.h index 4069b81..db3ae85 100644 --- a/arch/s390/appldata/appldata.h +++ b/arch/s390/appldata/appldata.h @@ -45,7 +45,6 @@ struct appldata_ops { int active; /* monitoring status */ /* fill in from here */ - unsigned int ctl_nr; /* sysctl ID */ char name[APPLDATA_PROC_NAME_LENGTH]; /* name of /proc fs node */ unsigned char record_nr; /* Record Nr. for Product ID */ void (*callback)(void *data); /* callback function */ diff --git a/arch/s390/appldata/appldata_base.c b/arch/s390/appldata/appldata_base.c index ac61cf4..655d525 100644 --- a/arch/s390/appldata/appldata_base.c +++ b/arch/s390/appldata/appldata_base.c @@ -53,29 +53,26 @@ static int appldata_interval_handler(ctl_table *ctl, int write, static struct ctl_table_header *appldata_sysctl_header; static struct ctl_table appldata_table[] = { { - .ctl_name = CTL_APPLDATA_TIMER, .procname = "timer", .mode = S_IRUGO | S_IWUSR, .proc_handler = &appldata_timer_handler, }, { - .ctl_name = CTL_APPLDATA_INTERVAL, .procname = "interval", .mode = S_IRUGO | S_IWUSR, .proc_handler = &appldata_interval_handler, }, - { .ctl_name = 0 } + { }, }; static struct ctl_table appldata_dir_table[] = { { - .ctl_name = CTL_APPLDATA, .procname = appldata_proc_name, .maxlen = 0, .mode = S_IRUGO | S_IXUGO, .child = appldata_table, }, - { .ctl_name = 0 } + { }, }; /* @@ -441,75 +438,38 @@ out: */ int appldata_register_ops(struct appldata_ops *ops) { - struct list_head *lh; - struct appldata_ops *tmp_ops; - int i; - - i = 0; + if ((ops->size > APPLDATA_MAX_REC_SIZE) || (ops->size < 0)) + return -EINVAL; - if ((ops->size > APPLDATA_MAX_REC_SIZE) || - (ops->size < 0)){ - P_ERROR("Invalid size of %s record = %i, maximum = %i!\n", - ops->name, ops->size, APPLDATA_MAX_REC_SIZE); - return -ENOMEM; - } - if ((ops->ctl_nr == CTL_APPLDATA) || - (ops->ctl_nr == CTL_APPLDATA_TIMER) || - (ops->ctl_nr == CTL_APPLDATA_INTERVAL)) { - P_ERROR("ctl_nr %i already in use!\n", ops->ctl_nr); - return -EBUSY; - } - ops->ctl_table = kzalloc(4*sizeof(struct ctl_table), GFP_KERNEL); - if (ops->ctl_table == NULL) { - P_ERROR("Not enough memory for %s ctl_table!\n", ops->name); + ops->ctl_table = kzalloc(4 * sizeof(struct ctl_table), GFP_KERNEL); + if (!ops->ctl_table) return -ENOMEM; - } spin_lock(&appldata_ops_lock); - list_for_each(lh, &appldata_ops_list) { - tmp_ops = list_entry(lh, struct appldata_ops, list); - P_DEBUG("register_ops loop: %i) name = %s, ctl = %i\n", - ++i, tmp_ops->name, tmp_ops->ctl_nr); - P_DEBUG("Comparing %s (ctl %i) with %s (ctl %i)\n", - tmp_ops->name, tmp_ops->ctl_nr, ops->name, - ops->ctl_nr); - if (strncmp(tmp_ops->name, ops->name, - APPLDATA_PROC_NAME_LENGTH) == 0) { - P_ERROR("Name \"%s\" already registered!\n", ops->name); - kfree(ops->ctl_table); - spin_unlock(&appldata_ops_lock); - return -EBUSY; - } - if (tmp_ops->ctl_nr == ops->ctl_nr) { - P_ERROR("ctl_nr %i already registered!\n", ops->ctl_nr); - kfree(ops->ctl_table); - spin_unlock(&appldata_ops_lock); - return -EBUSY; - } - } list_add(&ops->list, &appldata_ops_list); spin_unlock(&appldata_ops_lock); - ops->ctl_table[0].ctl_name = CTL_APPLDATA; ops->ctl_table[0].procname = appldata_proc_name; ops->ctl_table[0].maxlen = 0; ops->ctl_table[0].mode = S_IRUGO | S_IXUGO; ops->ctl_table[0].child = &ops->ctl_table[2]; - ops->ctl_table[1].ctl_name = 0; - - ops->ctl_table[2].ctl_name = ops->ctl_nr; ops->ctl_table[2].procname = ops->name; ops->ctl_table[2].mode = S_IRUGO | S_IWUSR; ops->ctl_table[2].proc_handler = appldata_generic_handler; ops->ctl_table[2].data = ops; - ops->ctl_table[3].ctl_name = 0; - ops->sysctl_header = register_sysctl_table(ops->ctl_table); - + if (!ops->sysctl_header) + goto out; P_INFO("%s-ops registered!\n", ops->name); return 0; +out: + spin_lock(&appldata_ops_lock); + list_del(&ops->list); + spin_unlock(&appldata_ops_lock); + kfree(ops->ctl_table); + return -ENOMEM; } /* @@ -519,15 +479,11 @@ int appldata_register_ops(struct appldata_ops *ops) */ void appldata_unregister_ops(struct appldata_ops *ops) { - void *table; spin_lock(&appldata_ops_lock); list_del(&ops->list); - /* at that point any incoming access will fail */ - table = ops->ctl_table; - ops->ctl_table = NULL; spin_unlock(&appldata_ops_lock); unregister_sysctl_table(ops->sysctl_header); - kfree(table); + kfree(ops->ctl_table); P_INFO("%s-ops unregistered!\n", ops->name); } /********************** module-ops management <END> **************************/ diff --git a/arch/s390/appldata/appldata_mem.c b/arch/s390/appldata/appldata_mem.c index 697eb30..51181cc 100644 --- a/arch/s390/appldata/appldata_mem.c +++ b/arch/s390/appldata/appldata_mem.c @@ -147,7 +147,6 @@ static void appldata_get_mem_data(void *data) static struct appldata_ops ops = { - .ctl_nr = CTL_APPLDATA_MEM, .name = "mem", .record_nr = APPLDATA_RECORD_MEM_ID, .size = sizeof(struct appldata_mem_data), diff --git a/arch/s390/appldata/appldata_net_sum.c b/arch/s390/appldata/appldata_net_sum.c index 6c1815a..4d83443 100644 --- a/arch/s390/appldata/appldata_net_sum.c +++ b/arch/s390/appldata/appldata_net_sum.c @@ -142,7 +142,6 @@ static void appldata_get_net_sum_data(void *data) static struct appldata_ops ops = { - .ctl_nr = CTL_APPLDATA_NET_SUM, .name = "net_sum", .record_nr = APPLDATA_RECORD_NET_SUM_ID, .size = sizeof(struct appldata_net_sum_data), diff --git a/arch/s390/appldata/appldata_os.c b/arch/s390/appldata/appldata_os.c index 76a1552..6b3eafe 100644 --- a/arch/s390/appldata/appldata_os.c +++ b/arch/s390/appldata/appldata_os.c @@ -82,7 +82,6 @@ struct appldata_os_data { static struct appldata_os_data *appldata_os_data; static struct appldata_ops ops = { - .ctl_nr = CTL_APPLDATA_OS, .name = "os", .record_nr = APPLDATA_RECORD_OS_ID, .owner = THIS_MODULE, diff --git a/arch/s390/kernel/early.c b/arch/s390/kernel/early.c index 8bf4ae1..1b3af7d 100644 --- a/arch/s390/kernel/early.c +++ b/arch/s390/kernel/early.c @@ -200,7 +200,7 @@ static noinline __init void find_memory_chunks(unsigned long memsize) cc = __tprot(addr); while (cc == old_cc) { addr += CHUNK_INCR; - if (addr >= memsize) + if (memsize && addr >= memsize) break; #ifndef CONFIG_64BIT if (addr == ADDR2G) diff --git a/arch/s390/kernel/entry.S b/arch/s390/kernel/entry.S index 139ca15..b2b2edc 100644 --- a/arch/s390/kernel/entry.S +++ b/arch/s390/kernel/entry.S @@ -69,13 +69,31 @@ STACK_SIZE = 1 << STACK_SHIFT basr %r14,%r1 .endm - .macro LOCKDEP_SYS_EXIT - l %r1,BASED(.Llockdep_sys_exit) + .macro TRACE_IRQS_CHECK + tm SP_PSW(%r15),0x03 # irqs enabled? + jz 0f + l %r1,BASED(.Ltrace_irq_on) basr %r14,%r1 + j 1f +0: l %r1,BASED(.Ltrace_irq_off) + basr %r14,%r1 +1: .endm #else #define TRACE_IRQS_ON #define TRACE_IRQS_OFF +#define TRACE_IRQS_CHECK +#endif + +#ifdef CONFIG_LOCKDEP + .macro LOCKDEP_SYS_EXIT + tm SP_PSW+1(%r15),0x01 # returning to user ? + jz 0f + l %r1,BASED(.Llockdep_sys_exit) + basr %r14,%r1 +0: + .endm +#else #define LOCKDEP_SYS_EXIT #endif @@ -234,8 +252,6 @@ sysc_saveall: lh %r7,0x8a # get svc number from lowcore #ifdef CONFIG_VIRT_CPU_ACCOUNTING sysc_vtime: - tm SP_PSW+1(%r15),0x01 # interrupting from user ? - bz BASED(sysc_do_svc) UPDATE_VTIME __LC_EXIT_TIMER,__LC_SYNC_ENTER_TIMER,__LC_USER_TIMER sysc_stime: UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER @@ -263,19 +279,34 @@ sysc_do_restart: sysc_return: tm SP_PSW+1(%r15),0x01 # returning to user ? - bno BASED(sysc_leave) + bno BASED(sysc_restore) tm __TI_flags+3(%r9),_TIF_WORK_SVC bnz BASED(sysc_work) # there is work to do (signals etc.) +sysc_restore: +#ifdef CONFIG_TRACE_IRQFLAGS + la %r1,BASED(sysc_restore_trace_psw) + lpsw 0(%r1) +sysc_restore_trace: + TRACE_IRQS_CHECK LOCKDEP_SYS_EXIT +#endif sysc_leave: RESTORE_ALL __LC_RETURN_PSW,1 +sysc_done: + +#ifdef CONFIG_TRACE_IRQFLAGS + .align 8 + .globl sysc_restore_trace_psw +sysc_restore_trace_psw: + .long 0, sysc_restore_trace + 0x80000000 +#endif # # recheck if there is more work to do # sysc_work_loop: tm __TI_flags+3(%r9),_TIF_WORK_SVC - bz BASED(sysc_leave) # there is no work to do + bz BASED(sysc_restore) # there is no work to do # # One of the work bits is on. Find out which one. # @@ -290,8 +321,8 @@ sysc_work: bo BASED(sysc_restart) tm __TI_flags+3(%r9),_TIF_SINGLE_STEP bo BASED(sysc_singlestep) - LOCKDEP_SYS_EXIT - b BASED(sysc_leave) + b BASED(sysc_restore) +sysc_work_done: # # _TIF_NEED_RESCHED is set, call schedule @@ -458,6 +489,7 @@ pgm_check_handler: pgm_no_vtime: #endif l %r9,__LC_THREAD_INFO # load pointer to thread_info struct + TRACE_IRQS_OFF l %r3,__LC_PGM_ILC # load program interruption code la %r8,0x7f nr %r8,%r3 @@ -497,6 +529,7 @@ pgm_per_std: pgm_no_vtime2: #endif l %r9,__LC_THREAD_INFO # load pointer to thread_info struct + TRACE_IRQS_OFF l %r1,__TI_task(%r9) mvc __THREAD_per+__PER_atmid(2,%r1),__LC_PER_ATMID mvc __THREAD_per+__PER_address(4,%r1),__LC_PER_ADDRESS @@ -517,15 +550,13 @@ pgm_svcper: SAVE_ALL_SYNC __LC_SVC_OLD_PSW,__LC_SAVE_AREA CREATE_STACK_FRAME __LC_SVC_OLD_PSW,__LC_SAVE_AREA #ifdef CONFIG_VIRT_CPU_ACCOUNTING - tm SP_PSW+1(%r15),0x01 # interrupting from user ? - bz BASED(pgm_no_vtime3) UPDATE_VTIME __LC_EXIT_TIMER,__LC_SYNC_ENTER_TIMER,__LC_USER_TIMER UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER mvc __LC_LAST_UPDATE_TIMER(8),__LC_SYNC_ENTER_TIMER -pgm_no_vtime3: #endif lh %r7,0x8a # get svc number from lowcore l %r9,__LC_THREAD_INFO # load pointer to thread_info struct + TRACE_IRQS_OFF l %r1,__TI_task(%r9) mvc __THREAD_per+__PER_atmid(2,%r1),__LC_PER_ATMID mvc __THREAD_per+__PER_address(4,%r1),__LC_PER_ADDRESS @@ -542,7 +573,7 @@ kernel_per: mvi SP_TRAP+1(%r15),0x28 # set trap indication to pgm check la %r2,SP_PTREGS(%r15) # address of register-save area l %r1,BASED(.Lhandle_per) # load adr. of per handler - la %r14,BASED(sysc_leave) # load adr. of system return + la %r14,BASED(sysc_restore)# load adr. of system return br %r1 # branch to do_single_step /* @@ -569,26 +600,38 @@ io_no_vtime: l %r1,BASED(.Ldo_IRQ) # load address of do_IRQ la %r2,SP_PTREGS(%r15) # address of register-save area basr %r14,%r1 # branch to standard irq handler - TRACE_IRQS_ON - io_return: tm SP_PSW+1(%r15),0x01 # returning to user ? #ifdef CONFIG_PREEMPT bno BASED(io_preempt) # no -> check for preemptive scheduling #else - bno BASED(io_leave) # no-> skip resched & signal + bno BASED(io_restore) # no-> skip resched & signal #endif tm __TI_flags+3(%r9),_TIF_WORK_INT bnz BASED(io_work) # there is work to do (signals etc.) +io_restore: +#ifdef CONFIG_TRACE_IRQFLAGS + la %r1,BASED(io_restore_trace_psw) + lpsw 0(%r1) +io_restore_trace: + TRACE_IRQS_CHECK LOCKDEP_SYS_EXIT +#endif io_leave: RESTORE_ALL __LC_RETURN_PSW,0 io_done: +#ifdef CONFIG_TRACE_IRQFLAGS + .align 8 + .globl io_restore_trace_psw +io_restore_trace_psw: + .long 0, io_restore_trace + 0x80000000 +#endif + #ifdef CONFIG_PREEMPT io_preempt: icm %r0,15,__TI_precount(%r9) - bnz BASED(io_leave) + bnz BASED(io_restore) l %r1,SP_R15(%r15) s %r1,BASED(.Lc_spsize) mvc SP_PTREGS(__PT_SIZE,%r1),SP_PTREGS(%r15) @@ -596,14 +639,10 @@ io_preempt: lr %r15,%r1 io_resume_loop: tm __TI_flags+3(%r9),_TIF_NEED_RESCHED - bno BASED(io_leave) - mvc __TI_precount(4,%r9),BASED(.Lc_pactive) - stosm __SF_EMPTY(%r15),0x03 # reenable interrupts - l %r1,BASED(.Lschedule) - basr %r14,%r1 # call schedule - stnsm __SF_EMPTY(%r15),0xfc # disable I/O and ext. interrupts - xc __TI_precount(4,%r9),__TI_precount(%r9) - b BASED(io_resume_loop) + bno BASED(io_restore) + l %r1,BASED(.Lpreempt_schedule_irq) + la %r14,BASED(io_resume_loop) + br %r1 # call schedule #endif # @@ -627,40 +666,42 @@ io_work_loop: bo BASED(io_reschedule) tm __TI_flags+3(%r9),(_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK) bnz BASED(io_sigpending) - LOCKDEP_SYS_EXIT - b BASED(io_leave) + b BASED(io_restore) +io_work_done: # # _TIF_MCCK_PENDING is set, call handler # io_mcck_pending: - TRACE_IRQS_OFF l %r1,BASED(.Ls390_handle_mcck) basr %r14,%r1 # TIF bit will be cleared by handler - TRACE_IRQS_ON b BASED(io_work_loop) # # _TIF_NEED_RESCHED is set, call schedule # io_reschedule: + TRACE_IRQS_ON l %r1,BASED(.Lschedule) stosm __SF_EMPTY(%r15),0x03 # reenable interrupts basr %r14,%r1 # call scheduler stnsm __SF_EMPTY(%r15),0xfc # disable I/O and ext. interrupts + TRACE_IRQS_OFF tm __TI_flags+3(%r9),_TIF_WORK_INT - bz BASED(io_leave) # there is no work to do + bz BASED(io_restore) # there is no work to do b BASED(io_work_loop) # # _TIF_SIGPENDING or _TIF_RESTORE_SIGMASK is set, call do_signal # io_sigpending: + TRACE_IRQS_ON stosm __SF_EMPTY(%r15),0x03 # reenable interrupts la %r2,SP_PTREGS(%r15) # load pt_regs l %r1,BASED(.Ldo_signal) basr %r14,%r1 # call do_signal stnsm __SF_EMPTY(%r15),0xfc # disable I/O and ext. interrupts + TRACE_IRQS_OFF b BASED(io_work_loop) /* @@ -688,7 +729,6 @@ ext_no_vtime: lh %r3,__LC_EXT_INT_CODE # get interruption code l %r1,BASED(.Ldo_extint) basr %r14,%r1 - TRACE_IRQS_ON b BASED(io_return) __critical_end: @@ -853,15 +893,15 @@ cleanup_table_system_call: cleanup_table_sysc_return: .long sysc_return + 0x80000000, sysc_leave + 0x80000000 cleanup_table_sysc_leave: - .long sysc_leave + 0x80000000, sysc_work_loop + 0x80000000 + .long sysc_leave + 0x80000000, sysc_done + 0x80000000 cleanup_table_sysc_work_loop: - .long sysc_work_loop + 0x80000000, sysc_reschedule + 0x80000000 + .long sysc_work_loop + 0x80000000, sysc_work_done + 0x80000000 cleanup_table_io_return: .long io_return + 0x80000000, io_leave + 0x80000000 cleanup_table_io_leave: .long io_leave + 0x80000000, io_done + 0x80000000 cleanup_table_io_work_loop: - .long io_work_loop + 0x80000000, io_mcck_pending + 0x80000000 + .long io_work_loop + 0x80000000, io_work_done + 0x80000000 cleanup_critical: clc 4(4,%r12),BASED(cleanup_table_system_call) @@ -930,8 +970,6 @@ cleanup_system_call: cleanup_vtime: clc __LC_RETURN_PSW+4(4),BASED(cleanup_system_call_insn+12) bhe BASED(cleanup_stime) - tm SP_PSW+1(%r15),0x01 # interrupting from user ? - bz BASED(cleanup_novtime) UPDATE_VTIME __LC_EXIT_TIMER,__LC_SYNC_ENTER_TIMER,__LC_USER_TIMER cleanup_stime: clc __LC_RETURN_PSW+4(4),BASED(cleanup_system_call_insn+16) @@ -939,7 +977,6 @@ cleanup_stime: UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER cleanup_update: mvc __LC_LAST_UPDATE_TIMER(8),__LC_SYNC_ENTER_TIMER -cleanup_novtime: #endif mvc __LC_RETURN_PSW+4(4),BASED(cleanup_table_system_call+4) la %r12,__LC_RETURN_PSW @@ -978,10 +1015,10 @@ cleanup_sysc_leave: 2: la %r12,__LC_RETURN_PSW br %r14 cleanup_sysc_leave_insn: + .long sysc_done - 4 + 0x80000000 #ifdef CONFIG_VIRT_CPU_ACCOUNTING - .long sysc_leave + 14 + 0x80000000 + .long sysc_done - 8 + 0x80000000 #endif - .long sysc_leave + 10 + 0x80000000 cleanup_io_return: mvc __LC_RETURN_PSW(4),0(%r12) @@ -1008,10 +1045,10 @@ cleanup_io_leave: 2: la %r12,__LC_RETURN_PSW br %r14 cleanup_io_leave_insn: + .long io_done - 4 + 0x80000000 #ifdef CONFIG_VIRT_CPU_ACCOUNTING - .long io_leave + 18 + 0x80000000 + .long io_done - 8 + 0x80000000 #endif - .long io_leave + 14 + 0x80000000 /* * Integer constants @@ -1019,7 +1056,6 @@ cleanup_io_leave_insn: .align 4 .Lc_spsize: .long SP_SIZE .Lc_overhead: .long STACK_FRAME_OVERHEAD -.Lc_pactive: .long PREEMPT_ACTIVE .Lnr_syscalls: .long NR_syscalls .L0x018: .short 0x018 .L0x020: .short 0x020 @@ -1043,6 +1079,8 @@ cleanup_io_leave_insn: .Lexecve_tail: .long execve_tail .Ljump_table: .long pgm_check_table .Lschedule: .long schedule +.Lpreempt_schedule_irq: + .long preempt_schedule_irq .Ltrace: .long syscall_trace .Lschedtail: .long schedule_tail .Lsysc_table: .long sys_call_table diff --git a/arch/s390/kernel/entry64.S b/arch/s390/kernel/entry64.S index 05e26d1..a3e47b8 100644 --- a/arch/s390/kernel/entry64.S +++ b/arch/s390/kernel/entry64.S @@ -67,12 +67,28 @@ _TIF_WORK_INT = (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK | _TIF_NEED_RESCHED | \ brasl %r14,trace_hardirqs_off .endm - .macro LOCKDEP_SYS_EXIT - brasl %r14,lockdep_sys_exit + .macro TRACE_IRQS_CHECK + tm SP_PSW(%r15),0x03 # irqs enabled? + jz 0f + brasl %r14,trace_hardirqs_on + j 1f +0: brasl %r14,trace_hardirqs_off +1: .endm #else #define TRACE_IRQS_ON #define TRACE_IRQS_OFF +#define TRACE_IRQS_CHECK +#endif + +#ifdef CONFIG_LOCKDEP + .macro LOCKDEP_SYS_EXIT + tm SP_PSW+1(%r15),0x01 # returning to user ? + jz 0f + brasl %r14,lockdep_sys_exit +0: + .endm +#else #define LOCKDEP_SYS_EXIT #endif @@ -222,8 +238,6 @@ sysc_saveall: llgh %r7,__LC_SVC_INT_CODE # get svc number from lowcore #ifdef CONFIG_VIRT_CPU_ACCOUNTING sysc_vtime: - tm SP_PSW+1(%r15),0x01 # interrupting from user ? - jz sysc_do_svc UPDATE_VTIME __LC_EXIT_TIMER,__LC_SYNC_ENTER_TIMER,__LC_USER_TIMER sysc_stime: UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER @@ -257,19 +271,34 @@ sysc_noemu: sysc_return: tm SP_PSW+1(%r15),0x01 # returning to user ? - jno sysc_leave + jno sysc_restore tm __TI_flags+7(%r9),_TIF_WORK_SVC jnz sysc_work # there is work to do (signals etc.) +sysc_restore: +#ifdef CONFIG_TRACE_IRQFLAGS + larl %r1,sysc_restore_trace_psw + lpswe 0(%r1) +sysc_restore_trace: + TRACE_IRQS_CHECK LOCKDEP_SYS_EXIT +#endif sysc_leave: RESTORE_ALL __LC_RETURN_PSW,1 +sysc_done: + +#ifdef CONFIG_TRACE_IRQFLAGS + .align 8 + .globl sysc_restore_trace_psw +sysc_restore_trace_psw: + .quad 0, sysc_restore_trace +#endif # # recheck if there is more work to do # sysc_work_loop: tm __TI_flags+7(%r9),_TIF_WORK_SVC - jz sysc_leave # there is no work to do + jz sysc_restore # there is no work to do # # One of the work bits is on. Find out which one. # @@ -284,8 +313,8 @@ sysc_work: jo sysc_restart tm __TI_flags+7(%r9),_TIF_SINGLE_STEP jo sysc_singlestep - LOCKDEP_SYS_EXIT - j sysc_leave + j sysc_restore +sysc_work_done: # # _TIF_NEED_RESCHED is set, call schedule @@ -445,6 +474,7 @@ pgm_check_handler: pgm_no_vtime: #endif lg %r9,__LC_THREAD_INFO # load pointer to thread_info struct + TRACE_IRQS_OFF lgf %r3,__LC_PGM_ILC # load program interruption code lghi %r8,0x7f ngr %r8,%r3 @@ -484,6 +514,7 @@ pgm_per_std: pgm_no_vtime2: #endif lg %r9,__LC_THREAD_INFO # load pointer to thread_info struct + TRACE_IRQS_OFF lg %r1,__TI_task(%r9) tm SP_PSW+1(%r15),0x01 # kernel per event ? jz kernel_per @@ -504,12 +535,9 @@ pgm_svcper: SAVE_ALL_SYNC __LC_SVC_OLD_PSW,__LC_SAVE_AREA CREATE_STACK_FRAME __LC_SVC_OLD_PSW,__LC_SAVE_AREA #ifdef CONFIG_VIRT_CPU_ACCOUNTING - tm SP_PSW+1(%r15),0x01 # interrupting from user ? - jz pgm_no_vtime3 UPDATE_VTIME __LC_EXIT_TIMER,__LC_SYNC_ENTER_TIMER,__LC_USER_TIMER UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER mvc __LC_LAST_UPDATE_TIMER(8),__LC_SYNC_ENTER_TIMER -pgm_no_vtime3: #endif llgh %r7,__LC_SVC_INT_CODE # get svc number from lowcore lg %r9,__LC_THREAD_INFO # load pointer to thread_info struct @@ -529,7 +557,7 @@ kernel_per: lhi %r0,__LC_PGM_OLD_PSW sth %r0,SP_TRAP(%r15) # set trap indication to pgm check la %r2,SP_PTREGS(%r15) # address of register-save area - larl %r14,sysc_leave # load adr. of system ret, no work + larl %r14,sysc_restore # load adr. of system ret, no work jg do_single_step # branch to do_single_step /* @@ -554,26 +582,38 @@ io_no_vtime: TRACE_IRQS_OFF la %r2,SP_PTREGS(%r15) # address of register-save area brasl %r14,do_IRQ # call standard irq handler - TRACE_IRQS_ON - io_return: tm SP_PSW+1(%r15),0x01 # returning to user ? #ifdef CONFIG_PREEMPT jno io_preempt # no -> check for preemptive scheduling #else - jno io_leave # no-> skip resched & signal + jno io_restore # no-> skip resched & signal #endif tm __TI_flags+7(%r9),_TIF_WORK_INT jnz io_work # there is work to do (signals etc.) +io_restore: +#ifdef CONFIG_TRACE_IRQFLAGS + larl %r1,io_restore_trace_psw + lpswe 0(%r1) +io_restore_trace: + TRACE_IRQS_CHECK LOCKDEP_SYS_EXIT +#endif io_leave: RESTORE_ALL __LC_RETURN_PSW,0 io_done: +#ifdef CONFIG_TRACE_IRQFLAGS + .align 8 + .globl io_restore_trace_psw +io_restore_trace_psw: + .quad 0, io_restore_trace +#endif + #ifdef CONFIG_PREEMPT io_preempt: icm %r0,15,__TI_precount(%r9) - jnz io_leave + jnz io_restore # switch to kernel stack lg %r1,SP_R15(%r15) aghi %r1,-SP_SIZE @@ -582,14 +622,9 @@ io_preempt: lgr %r15,%r1 io_resume_loop: tm __TI_flags+7(%r9),_TIF_NEED_RESCHED - jno io_leave - larl %r1,.Lc_pactive - mvc __TI_precount(4,%r9),0(%r1) - stosm __SF_EMPTY(%r15),0x03 # reenable interrupts - brasl %r14,schedule # call schedule - stnsm __SF_EMPTY(%r15),0xfc # disable I/O and ext. interrupts - xc __TI_precount(4,%r9),__TI_precount(%r9) - j io_resume_loop + jno io_restore + larl %r14,io_resume_loop + jg preempt_schedule_irq #endif # @@ -613,37 +648,39 @@ io_work_loop: jo io_reschedule tm __TI_flags+7(%r9),(_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK) jnz io_sigpending - LOCKDEP_SYS_EXIT - j io_leave + j io_restore +io_work_done: # # _TIF_MCCK_PENDING is set, call handler # io_mcck_pending: - TRACE_IRQS_OFF brasl %r14,s390_handle_mcck # TIF bit will be cleared by handler - TRACE_IRQS_ON j io_work_loop # # _TIF_NEED_RESCHED is set, call schedule # io_reschedule: + TRACE_IRQS_ON stosm __SF_EMPTY(%r15),0x03 # reenable interrupts brasl %r14,schedule # call scheduler stnsm __SF_EMPTY(%r15),0xfc # disable I/O and ext. interrupts + TRACE_IRQS_OFF tm __TI_flags+7(%r9),_TIF_WORK_INT - jz io_leave # there is no work to do + jz io_restore # there is no work to do j io_work_loop # # _TIF_SIGPENDING or _TIF_RESTORE_SIGMASK is set, call do_signal # io_sigpending: + TRACE_IRQS_ON stosm __SF_EMPTY(%r15),0x03 # reenable interrupts la %r2,SP_PTREGS(%r15) # load pt_regs brasl %r14,do_signal # call do_signal stnsm __SF_EMPTY(%r15),0xfc # disable I/O and ext. interrupts + TRACE_IRQS_OFF j io_work_loop /* @@ -669,7 +706,6 @@ ext_no_vtime: la %r2,SP_PTREGS(%r15) # address of register-save area llgh %r3,__LC_EXT_INT_CODE # get interruption code brasl %r14,do_extint - TRACE_IRQS_ON j io_return __critical_end: @@ -824,15 +860,15 @@ cleanup_table_system_call: cleanup_table_sysc_return: .quad sysc_return, sysc_leave cleanup_table_sysc_leave: - .quad sysc_leave, sysc_work_loop + .quad sysc_leave, sysc_done cleanup_table_sysc_work_loop: - .quad sysc_work_loop, sysc_reschedule + .quad sysc_work_loop, sysc_work_done cleanup_table_io_return: .quad io_return, io_leave cleanup_table_io_leave: .quad io_leave, io_done cleanup_table_io_work_loop: - .quad io_work_loop, io_mcck_pending + .quad io_work_loop, io_work_done cleanup_critical: clc 8(8,%r12),BASED(cleanup_table_system_call) @@ -901,8 +937,6 @@ cleanup_system_call: cleanup_vtime: clc __LC_RETURN_PSW+8(8),BASED(cleanup_system_call_insn+24) jhe cleanup_stime - tm SP_PSW+1(%r15),0x01 # interrupting from user ? - jz cleanup_novtime UPDATE_VTIME __LC_EXIT_TIMER,__LC_SYNC_ENTER_TIMER,__LC_USER_TIMER cleanup_stime: clc __LC_RETURN_PSW+8(8),BASED(cleanup_system_call_insn+32) @@ -910,7 +944,6 @@ cleanup_stime: UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER cleanup_update: mvc __LC_LAST_UPDATE_TIMER(8),__LC_SYNC_ENTER_TIMER -cleanup_novtime: #endif mvc __LC_RETURN_PSW+8(8),BASED(cleanup_table_system_call+8) la %r12,__LC_RETURN_PSW @@ -949,10 +982,10 @@ cleanup_sysc_leave: 2: la %r12,__LC_RETURN_PSW br %r14 cleanup_sysc_leave_insn: + .quad sysc_done - 4 #ifdef CONFIG_VIRT_CPU_ACCOUNTING - .quad sysc_leave + 16 + .quad sysc_done - 8 #endif - .quad sysc_leave + 12 cleanup_io_return: mvc __LC_RETURN_PSW(8),0(%r12) @@ -979,17 +1012,16 @@ cleanup_io_leave: 2: la %r12,__LC_RETURN_PSW br %r14 cleanup_io_leave_insn: + .quad io_done - 4 #ifdef CONFIG_VIRT_CPU_ACCOUNTING - .quad io_leave + 20 + .quad io_done - 8 #endif - .quad io_leave + 16 /* * Integer constants */ .align 4 .Lconst: -.Lc_pactive: .long PREEMPT_ACTIVE .Lnr_syscalls: .long NR_syscalls .L0x0130: .short 0x130 .L0x0140: .short 0x140 diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c index 7e1bfb9..50f8f1e 100644 --- a/arch/s390/kernel/setup.c +++ b/arch/s390/kernel/setup.c @@ -347,7 +347,7 @@ void (*_machine_power_off)(void) = do_machine_power_off_nonsmp; void machine_restart(char *command) { - if (!in_interrupt() || oops_in_progress) + if ((!in_interrupt() && !in_atomic()) || oops_in_progress) /* * Only unblank the console if we are called in enabled * context or a bust_spinlocks cleared the way for us. @@ -492,6 +492,10 @@ static void setup_addressing_mode(void) printk("S390 address spaces switched, "); set_amode_and_uaccess(PSW_ASC_PRIMARY, PSW32_ASC_PRIMARY); } +#ifdef CONFIG_TRACE_IRQFLAGS + sysc_restore_trace_psw.mask = psw_kernel_bits & ~PSW_MASK_MCHECK; + io_restore_trace_psw.mask = psw_kernel_bits & ~PSW_MASK_MCHECK; +#endif } static void __init diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c index b05ae85..264ea90 100644 --- a/arch/s390/kernel/smp.c +++ b/arch/s390/kernel/smp.c @@ -193,72 +193,30 @@ int smp_call_function_single(int cpu, void (*func) (void *info), void *info, } EXPORT_SYMBOL(smp_call_function_single); -static void do_send_stop(void) +void smp_send_stop(void) { int cpu, rc; - /* stop all processors */ - for_each_online_cpu(cpu) { - if (cpu == smp_processor_id()) - continue; - do { - rc = signal_processor(cpu, sigp_stop); - } while (rc == sigp_busy); - } -} + /* Disable all interrupts/machine checks */ + __load_psw_mask(psw_kernel_bits & ~PSW_MASK_MCHECK); -static void do_store_status(void) -{ - int cpu, rc; + /* write magic number to zero page (absolute 0) */ + lowcore_ptr[smp_processor_id()]->panic_magic = __PANIC_MAGIC; - /* store status of all processors in their lowcores (real 0) */ + /* stop all processors */ for_each_online_cpu(cpu) { if (cpu == smp_processor_id()) continue; do { - rc = signal_processor_p( - (__u32)(unsigned long) lowcore_ptr[cpu], cpu, - sigp_store_status_at_address); + rc = signal_processor(cpu, sigp_stop); } while (rc == sigp_busy); - } -} -static void do_wait_for_stop(void) -{ - int cpu; - - /* Wait for all other cpus to enter stopped state */ - for_each_online_cpu(cpu) { - if (cpu == smp_processor_id()) - continue; while (!smp_cpu_not_running(cpu)) cpu_relax(); } } /* - * this function sends a 'stop' sigp to all other CPUs in the system. - * it goes straight through. - */ -void smp_send_stop(void) -{ - /* Disable all interrupts/machine checks */ - __load_psw_mask(psw_kernel_bits & ~PSW_MASK_MCHECK); - - /* write magic number to zero page (absolute 0) */ - lowcore_ptr[smp_processor_id()]->panic_magic = __PANIC_MAGIC; - - /* stop other processors. */ - do_send_stop(); - - /* wait until other processors are stopped */ - do_wait_for_stop(); - - /* store status of other processors. */ - do_store_status(); -} - -/* * Reboot, halt and power_off routines for SMP. */ void machine_restart_smp(char *__unused) diff --git a/arch/s390/kernel/time.c b/arch/s390/kernel/time.c index a963fe8..22b800c 100644 --- a/arch/s390/kernel/time.c +++ b/arch/s390/kernel/time.c @@ -145,12 +145,8 @@ void account_ticks(u64 time) do_timer(ticks); #endif -#ifdef CONFIG_VIRT_CPU_ACCOUNTING - account_tick_vtime(current); -#else while (ticks--) update_process_times(user_mode(get_irq_regs())); -#endif s390_do_profile(); } diff --git a/arch/s390/kernel/traps.c b/arch/s390/kernel/traps.c index 8ec9def..8ed16a8 100644 --- a/arch/s390/kernel/traps.c +++ b/arch/s390/kernel/traps.c @@ -260,6 +260,7 @@ void die(const char * str, struct pt_regs * regs, long err) bust_spinlocks(1); printk("%s: %04lx [#%d]\n", str, err & 0xffff, ++die_counter); print_modules(); + notify_die(DIE_OOPS, str, regs, err, current->thread.trap_no, SIGSEGV); show_regs(regs); bust_spinlocks(0); add_taint(TAINT_DIE); diff --git a/arch/s390/kernel/vtime.c b/arch/s390/kernel/vtime.c index 84ff78d..c5f05b3 100644 --- a/arch/s390/kernel/vtime.c +++ b/arch/s390/kernel/vtime.c @@ -32,7 +32,7 @@ static DEFINE_PER_CPU(struct vtimer_queue, virt_cpu_timer); * Update process times based on virtual cpu times stored by entry.S * to the lowcore fields user_timer, system_timer & steal_clock. */ -void account_tick_vtime(struct task_struct *tsk) +void account_process_tick(struct task_struct *tsk, int user_tick) { cputime_t cputime; __u64 timer, clock; @@ -64,12 +64,6 @@ void account_tick_vtime(struct task_struct *tsk) S390_lowcore.steal_clock -= cputime << 12; account_steal_time(tsk, cputime); } - - run_local_timers(); - if (rcu_pending(smp_processor_id())) - rcu_check_callbacks(smp_processor_id(), rcu_user_flag); - scheduler_tick(); - run_posix_cpu_timers(tsk); } /* diff --git a/arch/s390/mm/cmm.c b/arch/s390/mm/cmm.c index d4ed93d..413c240 100644 --- a/arch/s390/mm/cmm.c +++ b/arch/s390/mm/cmm.c @@ -341,19 +341,16 @@ cmm_timeout_handler(ctl_table *ctl, int write, struct file *filp, static struct ctl_table cmm_table[] = { { - .ctl_name = VM_CMM_PAGES, .procname = "cmm_pages", .mode = 0644, .proc_handler = &cmm_pages_handler, }, { - .ctl_name = VM_CMM_TIMED_PAGES, .procname = "cmm_timed_pages", .mode = 0644, .proc_handler = &cmm_pages_handler, }, { - .ctl_name = VM_CMM_TIMEOUT, .procname = "cmm_timeout", .mode = 0644, .proc_handler = &cmm_timeout_handler, diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig index 22a3eb3..496d635 100644 --- a/arch/sh/Kconfig +++ b/arch/sh/Kconfig @@ -211,10 +211,12 @@ config SH_SOLUTION_ENGINE bool "SolutionEngine" select SOLUTION_ENGINE select CPU_HAS_IPR_IRQ - depends on CPU_SUBTYPE_SH7709 || CPU_SUBTYPE_SH7750 + depends on CPU_SUBTYPE_SH7705 || CPU_SUBTYPE_SH7709 || CPU_SUBTYPE_SH7710 || \ + CPU_SUBTYPE_SH7712 || CPU_SUBTYPE_SH7750 || CPU_SUBTYPE_SH7750S || \ + CPU_SUBTYPE_SH7750R help - Select SolutionEngine if configuring for a Hitachi SH7709 - or SH7750 evaluation board. + Select SolutionEngine if configuring for a Hitachi SH7705, SH7709, + SH7710, SH7712, SH7750, SH7750S or SH7750R evaluation board. config SH_7206_SOLUTION_ENGINE bool "SolutionEngine7206" @@ -603,7 +605,7 @@ config BOOT_LINK_OFFSET config UBC_WAKEUP bool "Wakeup UBC on startup" - depends on CPU_SH4 + depends on CPU_SH4 && !CPU_SH4A help Selecting this option will wakeup the User Break Controller (UBC) on startup. Although the UBC is left in an awake state when the processor diff --git a/arch/sh/Kconfig.debug b/arch/sh/Kconfig.debug index ab2f9f3..722da68 100644 --- a/arch/sh/Kconfig.debug +++ b/arch/sh/Kconfig.debug @@ -124,12 +124,13 @@ config KGDB_NMI config SH_KGDB_CONSOLE bool "Console messages through GDB" - depends on !SERIAL_SH_SCI_CONSOLE + depends on !SERIAL_SH_SCI_CONSOLE && SERIAL_SH_SCI=y select SERIAL_CORE_CONSOLE default n config KGDB_SYSRQ bool "Allow SysRq 'G' to enter KGDB" + depends on MAGIC_SYSRQ default y comment "Serial port setup" diff --git a/arch/sh/boards/renesas/hs7751rvoip/irq.c b/arch/sh/boards/renesas/hs7751rvoip/irq.c index 943f93a..e55c668 100644 --- a/arch/sh/boards/renesas/hs7751rvoip/irq.c +++ b/arch/sh/boards/renesas/hs7751rvoip/irq.c @@ -12,6 +12,7 @@ #include <linux/init.h> #include <linux/irq.h> +#include <linux/interrupt.h> #include <asm/io.h> #include <asm/irq.h> #include <asm/hs7751rvoip.h> diff --git a/arch/sh/boards/renesas/hs7751rvoip/setup.c b/arch/sh/boards/renesas/hs7751rvoip/setup.c index fa5fa39..c056259 100644 --- a/arch/sh/boards/renesas/hs7751rvoip/setup.c +++ b/arch/sh/boards/renesas/hs7751rvoip/setup.c @@ -15,20 +15,6 @@ #include <asm/io.h> #include <asm/machvec.h> -static struct ipr_data hs77501rvoip_ipr_map[] = { -#if defined(CONFIG_HS7751RVOIP_CODEC) - { DMTE0_IRQ, DMA_IPR_ADDR, DMA_IPR_POS, DMA_PRIORITY }, - { DMTE1_IRQ, DMA_IPR_ADDR, DMA_IPR_POS, DMA_PRIORITY }, -#endif -}; - -static void __init hs7751rvoip_init_irq(void) -{ - make_ipr_irq(hs77501rvoip_ipr_map, ARRAY_SIZE(hs77501rvoip_ipr_map)); - - init_hs7751rvoip_IRQ(); -} - static void hs7751rvoip_power_off(void) { ctrl_outw(ctrl_inw(PA_OUTPORTR) & 0xffdf, PA_OUTPORTR); @@ -75,14 +61,13 @@ static int __init hs7751rvoip_cf_init(void) return 0; } +device_initcall(hs7751rvoip_cf_init); /* * Initialize the board */ static void __init hs7751rvoip_setup(char **cmdline_p) { - device_initcall(hs7751rvoip_cf_init); - ctrl_outb(0xf0, PA_OUTPORTR); pm_power_off = hs7751rvoip_power_off; @@ -115,6 +100,6 @@ static struct sh_machine_vector mv_hs7751rvoip __initmv = { .mv_outsw = hs7751rvoip_outsw, .mv_outsl = hs7751rvoip_outsl, - .mv_init_irq = hs7751rvoip_init_irq, + .mv_init_irq = init_hs7751rvoip_IRQ, .mv_ioport_map = hs7751rvoip_ioport_map, }; diff --git a/arch/sh/boards/renesas/rts7751r2d/setup.c b/arch/sh/boards/renesas/rts7751r2d/setup.c index 37f2c0b..8125d20 100644 --- a/arch/sh/boards/renesas/rts7751r2d/setup.c +++ b/arch/sh/boards/renesas/rts7751r2d/setup.c @@ -53,10 +53,12 @@ static struct resource cf_ide_resources[] = { .end = PA_AREA5_IO + 0x80c, .flags = IORESOURCE_MEM, }, +#ifndef CONFIG_RTS7751R2D_1 /* For R2D-1 polling is preferred */ [2] = { .start = IRQ_CF_IDE, .flags = IORESOURCE_IRQ, }, +#endif }; static struct pata_platform_info pata_info = { diff --git a/arch/sh/boards/renesas/sh7710voipgw/setup.c b/arch/sh/boards/renesas/sh7710voipgw/setup.c index 2dce8bd..0d56fd8 100644 --- a/arch/sh/boards/renesas/sh7710voipgw/setup.c +++ b/arch/sh/boards/renesas/sh7710voipgw/setup.c @@ -11,7 +11,6 @@ #include <asm/machvec.h> #include <asm/irq.h> #include <asm/io.h> -#include <asm/irq.h> static struct ipr_data sh7710voipgw_ipr_map[] = { { TIMER2_IRQ, TIMER2_IPR_ADDR, TIMER2_IPR_POS, TIMER2_PRIORITY }, diff --git a/arch/sh/boards/se/7206/irq.c b/arch/sh/boards/se/7206/irq.c index 27da884..9d5bfc7 100644 --- a/arch/sh/boards/se/7206/irq.c +++ b/arch/sh/boards/se/7206/irq.c @@ -9,7 +9,6 @@ #include <linux/init.h> #include <linux/irq.h> #include <linux/io.h> -#include <linux/irq.h> #include <linux/interrupt.h> #include <asm/se7206.h> diff --git a/arch/sh/boards/se/770x/setup.c b/arch/sh/boards/se/770x/setup.c index d07a336..318bc8a 100644 --- a/arch/sh/boards/se/770x/setup.c +++ b/arch/sh/boards/se/770x/setup.c @@ -94,6 +94,7 @@ static unsigned char heartbeat_bit_pos[] = { 8, 9, 10, 11, 12, 13, 14, 15 }; static struct heartbeat_data heartbeat_data = { .bit_pos = heartbeat_bit_pos, .nr_bits = ARRAY_SIZE(heartbeat_bit_pos), + .regsize = 16, }; static struct resource heartbeat_resources[] = { diff --git a/arch/sh/boards/se/7722/setup.c b/arch/sh/boards/se/7722/setup.c index 20f0640..eb97dca 100644 --- a/arch/sh/boards/se/7722/setup.c +++ b/arch/sh/boards/se/7722/setup.c @@ -16,8 +16,13 @@ #include <asm/machvec.h> #include <asm/se7722.h> #include <asm/io.h> +#include <asm/heartbeat.h> /* Heartbeat */ +static struct heartbeat_data heartbeat_data = { + .regsize = 16, +}; + static struct resource heartbeat_resources[] = { [0] = { .start = PA_LED, @@ -29,6 +34,9 @@ static struct resource heartbeat_resources[] = { static struct platform_device heartbeat_device = { .name = "heartbeat", .id = -1, + .dev = { + .platform_data = &heartbeat_data, + }, .num_resources = ARRAY_SIZE(heartbeat_resources), .resource = heartbeat_resources, }; diff --git a/arch/sh/boards/se/7780/setup.c b/arch/sh/boards/se/7780/setup.c index 76e53b2..0f08ab3 100644 --- a/arch/sh/boards/se/7780/setup.c +++ b/arch/sh/boards/se/7780/setup.c @@ -14,8 +14,13 @@ #include <asm/machvec.h> #include <asm/se7780.h> #include <asm/io.h> +#include <asm/heartbeat.h> /* Heartbeat */ +static struct heartbeat_data heartbeat_data = { + .regsize = 16, +}; + static struct resource heartbeat_resources[] = { [0] = { .start = PA_LED, @@ -27,6 +32,9 @@ static struct resource heartbeat_resources[] = { static struct platform_device heartbeat_device = { .name = "heartbeat", .id = -1, + .dev = { + .platform_data = &heartbeat_data, + }, .num_resources = ARRAY_SIZE(heartbeat_resources), .resource = heartbeat_resources, }; diff --git a/arch/sh/boards/snapgear/Makefile b/arch/sh/boards/snapgear/Makefile index 59fc976..d2d2f4b 100644 --- a/arch/sh/boards/snapgear/Makefile +++ b/arch/sh/boards/snapgear/Makefile @@ -2,5 +2,4 @@ # Makefile for the SnapGear specific parts of the kernel # -obj-y := setup.o io.o rtc.o - +obj-y := setup.o io.o diff --git a/arch/sh/boards/snapgear/rtc.c b/arch/sh/boards/snapgear/rtc.c deleted file mode 100644 index edb3dd9..0000000 --- a/arch/sh/boards/snapgear/rtc.c +++ /dev/null @@ -1,309 +0,0 @@ -/****************************************************************************/ -/* - * linux/arch/sh/boards/snapgear/rtc.c -- Secureedge5410 RTC code - * - * Copyright (C) 2002 David McCullough <davidm@snapgear.com> - * Copyright (C) 2003 Paul Mundt <lethal@linux-sh.org> - * - * The SecureEdge5410 can have one of 2 real time clocks, the SH - * built in version or the preferred external DS1302. Here we work out - * each to see what we have and then run with it. - */ -/****************************************************************************/ - -#include <linux/init.h> -#include <linux/kernel.h> -#include <linux/sched.h> -#include <linux/time.h> -#include <linux/rtc.h> -#include <linux/mc146818rtc.h> -#include <asm/io.h> - -static int use_ds1302; - -/****************************************************************************/ -/* - * we need to implement a DS1302 driver here that can operate in - * conjunction with the builtin rtc driver which is already quite friendly - */ -/*****************************************************************************/ - -#define RTC_CMD_READ 0x81 /* Read command */ -#define RTC_CMD_WRITE 0x80 /* Write command */ - -#define RTC_ADDR_YEAR 0x06 /* Address of year register */ -#define RTC_ADDR_DAY 0x05 /* Address of day of week register */ -#define RTC_ADDR_MON 0x04 /* Address of month register */ -#define RTC_ADDR_DATE 0x03 /* Address of day of month register */ -#define RTC_ADDR_HOUR 0x02 /* Address of hour register */ -#define RTC_ADDR_MIN 0x01 /* Address of minute register */ -#define RTC_ADDR_SEC 0x00 /* Address of second register */ - -#define RTC_RESET 0x1000 -#define RTC_IODATA 0x0800 -#define RTC_SCLK 0x0400 - -#define set_dirp(x) -#define get_dirp(x) 0 -#define set_dp(x) SECUREEDGE_WRITE_IOPORT(x, 0x1c00) -#define get_dp(x) SECUREEDGE_READ_IOPORT() - -static void ds1302_sendbits(unsigned int val) -{ - int i; - - for (i = 8; (i); i--, val >>= 1) { - set_dp((get_dp() & ~RTC_IODATA) | ((val & 0x1) ? RTC_IODATA : 0)); - set_dp(get_dp() | RTC_SCLK); // clock high - set_dp(get_dp() & ~RTC_SCLK); // clock low - } -} - -static unsigned int ds1302_recvbits(void) -{ - unsigned int val; - int i; - - for (i = 0, val = 0; (i < 8); i++) { - val |= (((get_dp() & RTC_IODATA) ? 1 : 0) << i); - set_dp(get_dp() | RTC_SCLK); // clock high - set_dp(get_dp() & ~RTC_SCLK); // clock low - } - return(val); -} - -static unsigned int ds1302_readbyte(unsigned int addr) -{ - unsigned int val; - unsigned long flags; - - local_irq_save(flags); - set_dirp(get_dirp() | RTC_RESET | RTC_IODATA | RTC_SCLK); - set_dp(get_dp() & ~(RTC_RESET | RTC_IODATA | RTC_SCLK)); - - set_dp(get_dp() | RTC_RESET); - ds1302_sendbits(((addr & 0x3f) << 1) | RTC_CMD_READ); - set_dirp(get_dirp() & ~RTC_IODATA); - val = ds1302_recvbits(); - set_dp(get_dp() & ~RTC_RESET); - local_irq_restore(flags); - - return(val); -} - -static void ds1302_writebyte(unsigned int addr, unsigned int val) -{ - unsigned long flags; - - local_irq_save(flags); - set_dirp(get_dirp() | RTC_RESET | RTC_IODATA | RTC_SCLK); - set_dp(get_dp() & ~(RTC_RESET | RTC_IODATA | RTC_SCLK)); - set_dp(get_dp() | RTC_RESET); - ds1302_sendbits(((addr & 0x3f) << 1) | RTC_CMD_WRITE); - ds1302_sendbits(val); - set_dp(get_dp() & ~RTC_RESET); - local_irq_restore(flags); -} - -static void ds1302_reset(void) -{ - unsigned long flags; - /* Hardware dependent reset/init */ - local_irq_save(flags); - set_dirp(get_dirp() | RTC_RESET | RTC_IODATA | RTC_SCLK); - set_dp(get_dp() & ~(RTC_RESET | RTC_IODATA | RTC_SCLK)); - local_irq_restore(flags); -} - -/*****************************************************************************/ - -static inline int bcd2int(int val) -{ - return((((val & 0xf0) >> 4) * 10) + (val & 0xf)); -} - -static inline int int2bcd(int val) -{ - return(((val / 10) << 4) + (val % 10)); -} - -/*****************************************************************************/ -/* - * Write and Read some RAM in the DS1302, if it works assume it's there - * Otherwise use the SH4 internal RTC - */ - -void snapgear_rtc_gettimeofday(struct timespec *); -int snapgear_rtc_settimeofday(const time_t); - -void __init secureedge5410_rtc_init(void) -{ - unsigned char *test = "snapgear"; - int i; - - ds1302_reset(); - - use_ds1302 = 1; - - for (i = 0; test[i]; i++) - ds1302_writebyte(32 + i, test[i]); - - for (i = 0; test[i]; i++) - if (ds1302_readbyte(32 + i) != test[i]) { - use_ds1302 = 0; - break; - } - - if (use_ds1302) { - rtc_sh_get_time = snapgear_rtc_gettimeofday; - rtc_sh_set_time = snapgear_rtc_settimeofday; - } - - printk("SnapGear RTC: using %s rtc.\n", use_ds1302 ? "ds1302" : "internal"); -} - -/****************************************************************************/ -/* - * our generic interface that chooses the correct code to use - */ - -void snapgear_rtc_gettimeofday(struct timespec *ts) -{ - unsigned int sec, min, hr, day, mon, yr; - - if (!use_ds1302) - return; - - sec = bcd2int(ds1302_readbyte(RTC_ADDR_SEC)); - min = bcd2int(ds1302_readbyte(RTC_ADDR_MIN)); - hr = bcd2int(ds1302_readbyte(RTC_ADDR_HOUR)); - day = bcd2int(ds1302_readbyte(RTC_ADDR_DATE)); - mon = bcd2int(ds1302_readbyte(RTC_ADDR_MON)); - yr = bcd2int(ds1302_readbyte(RTC_ADDR_YEAR)); - -bad_time: - if (yr > 99 || mon < 1 || mon > 12 || day > 31 || day < 1 || - hr > 23 || min > 59 || sec > 59) { - printk(KERN_ERR - "SnapGear RTC: invalid value, resetting to 1 Jan 2000\n"); - ds1302_writebyte(RTC_ADDR_MIN, min = 0); - ds1302_writebyte(RTC_ADDR_HOUR, hr = 0); - ds1302_writebyte(RTC_ADDR_DAY, 7); - ds1302_writebyte(RTC_ADDR_DATE, day = 1); - ds1302_writebyte(RTC_ADDR_MON, mon = 1); - ds1302_writebyte(RTC_ADDR_YEAR, yr = 0); - ds1302_writebyte(RTC_ADDR_SEC, sec = 0); - } - - ts->tv_sec = mktime(2000 + yr, mon, day, hr, min, sec); - if (ts->tv_sec < 0) { -#if 0 - printk("BAD TIME %d %d %d %d %d %d\n", yr, mon, day, hr, min, sec); -#endif - yr = 100; - goto bad_time; - } - ts->tv_nsec = 0; -} - -int snapgear_rtc_settimeofday(const time_t secs) -{ - int retval = 0; - int real_seconds, real_minutes, cmos_minutes; - unsigned long nowtime; - - if (!use_ds1302) - return 0; - -/* - * This is called direct from the kernel timer handling code. - * It is supposed to synchronize the kernel clock to the RTC. - */ - - nowtime = secs; - - /* STOP RTC */ - ds1302_writebyte(RTC_ADDR_SEC, ds1302_readbyte(RTC_ADDR_SEC) | 0x80); - - cmos_minutes = bcd2int(ds1302_readbyte(RTC_ADDR_MIN)); - - /* - * since we're only adjusting minutes and seconds, - * don't interfere with hour overflow. This avoids - * messing with unknown time zones but requires your - * RTC not to be off by more than 15 minutes - */ - real_seconds = nowtime % 60; - real_minutes = nowtime / 60; - if (((abs(real_minutes - cmos_minutes) + 15)/30) & 1) - real_minutes += 30; /* correct for half hour time zone */ - real_minutes %= 60; - - if (abs(real_minutes - cmos_minutes) < 30) { - ds1302_writebyte(RTC_ADDR_MIN, int2bcd(real_minutes)); - ds1302_writebyte(RTC_ADDR_SEC, int2bcd(real_seconds)); - } else { - printk(KERN_WARNING - "SnapGear RTC: can't update from %d to %d\n", - cmos_minutes, real_minutes); - retval = -1; - } - - /* START RTC */ - ds1302_writebyte(RTC_ADDR_SEC, ds1302_readbyte(RTC_ADDR_SEC) & ~0x80); - return(0); -} - -unsigned char secureedge5410_cmos_read(int addr) -{ - unsigned char val = 0; - - if (!use_ds1302) - return(__CMOS_READ(addr, w)); - - switch(addr) { - case RTC_SECONDS: val = ds1302_readbyte(RTC_ADDR_SEC); break; - case RTC_SECONDS_ALARM: break; - case RTC_MINUTES: val = ds1302_readbyte(RTC_ADDR_MIN); break; - case RTC_MINUTES_ALARM: break; - case RTC_HOURS: val = ds1302_readbyte(RTC_ADDR_HOUR); break; - case RTC_HOURS_ALARM: break; - case RTC_DAY_OF_WEEK: val = ds1302_readbyte(RTC_ADDR_DAY); break; - case RTC_DAY_OF_MONTH: val = ds1302_readbyte(RTC_ADDR_DATE); break; - case RTC_MONTH: val = ds1302_readbyte(RTC_ADDR_MON); break; - case RTC_YEAR: val = ds1302_readbyte(RTC_ADDR_YEAR); break; - case RTC_REG_A: /* RTC_FREQ_SELECT */ break; - case RTC_REG_B: /* RTC_CONTROL */ break; - case RTC_REG_C: /* RTC_INTR_FLAGS */ break; - case RTC_REG_D: val = RTC_VRT /* RTC_VALID */; break; - default: break; - } - - return(val); -} - -void secureedge5410_cmos_write(unsigned char val, int addr) -{ - if (!use_ds1302) { - __CMOS_WRITE(val, addr, w); - return; - } - - switch(addr) { - case RTC_SECONDS: ds1302_writebyte(RTC_ADDR_SEC, val); break; - case RTC_SECONDS_ALARM: break; - case RTC_MINUTES: ds1302_writebyte(RTC_ADDR_MIN, val); break; - case RTC_MINUTES_ALARM: break; - case RTC_HOURS: ds1302_writebyte(RTC_ADDR_HOUR, val); break; - case RTC_HOURS_ALARM: break; - case RTC_DAY_OF_WEEK: ds1302_writebyte(RTC_ADDR_DAY, val); break; - case RTC_DAY_OF_MONTH: ds1302_writebyte(RTC_ADDR_DATE, val); break; - case RTC_MONTH: ds1302_writebyte(RTC_ADDR_MON, val); break; - case RTC_YEAR: ds1302_writebyte(RTC_ADDR_YEAR, val); break; - case RTC_REG_A: /* RTC_FREQ_SELECT */ break; - case RTC_REG_B: /* RTC_CONTROL */ break; - case RTC_REG_C: /* RTC_INTR_FLAGS */ break; - case RTC_REG_D: /* RTC_VALID */ break; - default: break; - } -} diff --git a/arch/sh/boards/snapgear/setup.c b/arch/sh/boards/snapgear/setup.c index 2b594f6..7022483 100644 --- a/arch/sh/boards/snapgear/setup.c +++ b/arch/sh/boards/snapgear/setup.c @@ -22,20 +22,15 @@ #include <asm/snapgear.h> #include <asm/irq.h> #include <asm/io.h> -#include <asm/rtc.h> #include <asm/cpu/timer.h> -extern void secureedge5410_rtc_init(void); -extern void pcibios_init(void); - -/****************************************************************************/ /* * EraseConfig handling functions */ static irqreturn_t eraseconfig_interrupt(int irq, void *dev_id) { - volatile char dummy __attribute__((unused)) = * (volatile char *) 0xb8000000; + (void)ctrl_inb(0xb8000000); /* dummy read */ printk("SnapGear: erase switch interrupt!\n"); @@ -76,19 +71,10 @@ static void __init init_snapgear_IRQ(void) } /* - * Initialize the board - */ -static void __init snapgear_setup(char **cmdline_p) -{ - board_time_init = secureedge5410_rtc_init; -} - -/* * The Machine Vector */ static struct sh_machine_vector mv_snapgear __initmv = { .mv_name = "SnapGear SecureEdge5410", - .mv_setup = snapgear_setup, .mv_nr_irqs = 72, .mv_inb = snapgear_inb, diff --git a/arch/sh/boot/Makefile b/arch/sh/boot/Makefile index 4c5ffdc..1b0f5be 100644 --- a/arch/sh/boot/Makefile +++ b/arch/sh/boot/Makefile @@ -39,7 +39,7 @@ KERNEL_LOAD := $(shell /bin/bash -c 'printf "0x%8x" \ quiet_cmd_uimage = UIMAGE $@ cmd_uimage = $(CONFIG_SHELL) $(MKIMAGE) -A sh -O linux -T kernel \ - -C gzip -a $(KERNEL_LOAD) -e $(KERNEL_LOAD) \ + -C none -a $(KERNEL_LOAD) -e $(KERNEL_LOAD) \ -n 'Linux-$(KERNELRELEASE)' -d $< $@ $(obj)/uImage: $(obj)/zImage FORCE diff --git a/arch/sh/cchips/hd6446x/Makefile b/arch/sh/cchips/hd6446x/Makefile index a106dd9..f7de407 100644 --- a/arch/sh/cchips/hd6446x/Makefile +++ b/arch/sh/cchips/hd6446x/Makefile @@ -1,2 +1,4 @@ obj-$(CONFIG_HD64461) += hd64461.o obj-$(CONFIG_HD64465) += hd64465/ + +EXTRA_CFLAGS += -Werror diff --git a/arch/sh/cchips/voyagergx/Makefile b/arch/sh/cchips/voyagergx/Makefile index 085de72..f73963c 100644 --- a/arch/sh/cchips/voyagergx/Makefile +++ b/arch/sh/cchips/voyagergx/Makefile @@ -6,3 +6,4 @@ obj-y := irq.o setup.o obj-$(CONFIG_USB_OHCI_HCD) += consistent.o +EXTRA_CFLAGS += -Werror diff --git a/arch/sh/configs/r7780mp_defconfig b/arch/sh/configs/r7780mp_defconfig index ac4de49..2ad804e 100644 --- a/arch/sh/configs/r7780mp_defconfig +++ b/arch/sh/configs/r7780mp_defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.22-rc4 -# Mon Jun 11 10:24:57 2007 +# Linux kernel version: 2.6.24-rc2 +# Tue Nov 13 20:32:39 2007 # CONFIG_SUPERH=y CONFIG_RWSEM_GENERIC_SPINLOCK=y @@ -13,38 +13,39 @@ CONFIG_GENERIC_IRQ_PROBE=y CONFIG_GENERIC_CALIBRATE_DELAY=y CONFIG_GENERIC_TIME=y CONFIG_GENERIC_CLOCKEVENTS=y +CONFIG_SYS_SUPPORTS_PCI=y CONFIG_STACKTRACE_SUPPORT=y CONFIG_LOCKDEP_SUPPORT=y # CONFIG_ARCH_HAS_ILOG2_U32 is not set # CONFIG_ARCH_HAS_ILOG2_U64 is not set +CONFIG_ARCH_NO_VIRT_TO_BUS=y CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" # -# Code maturity level options +# General setup # CONFIG_EXPERIMENTAL=y CONFIG_BROKEN_ON_SMP=y CONFIG_LOCK_KERNEL=y CONFIG_INIT_ENV_ARG_LIMIT=32 - -# -# General setup -# CONFIG_LOCALVERSION="" CONFIG_LOCALVERSION_AUTO=y CONFIG_SWAP=y CONFIG_SYSVIPC=y -# CONFIG_IPC_NS is not set CONFIG_SYSVIPC_SYSCTL=y # CONFIG_POSIX_MQUEUE is not set CONFIG_BSD_PROCESS_ACCT=y # CONFIG_BSD_PROCESS_ACCT_V3 is not set # CONFIG_TASKSTATS is not set -# CONFIG_UTS_NS is not set +# CONFIG_USER_NS is not set # CONFIG_AUDIT is not set CONFIG_IKCONFIG=y CONFIG_IKCONFIG_PROC=y CONFIG_LOG_BUF_SHIFT=14 +# CONFIG_CGROUPS is not set +CONFIG_FAIR_GROUP_SCHED=y +CONFIG_FAIR_USER_SCHED=y +# CONFIG_FAIR_CGROUP_SCHED is not set # CONFIG_SYSFS_DEPRECATED is not set # CONFIG_RELAY is not set # CONFIG_BLK_DEV_INITRD is not set @@ -65,7 +66,6 @@ CONFIG_BASE_FULL=y CONFIG_ANON_INODES=y # CONFIG_EPOLL is not set CONFIG_SIGNALFD=y -CONFIG_TIMERFD=y CONFIG_EVENTFD=y CONFIG_SHMEM=y CONFIG_VM_EVENT_COUNTERS=y @@ -74,24 +74,17 @@ CONFIG_SLAB=y # CONFIG_SLOB is not set # CONFIG_TINY_SHMEM is not set CONFIG_BASE_SMALL=0 - -# -# Loadable module support -# CONFIG_MODULES=y CONFIG_MODULE_UNLOAD=y # CONFIG_MODULE_FORCE_UNLOAD is not set # CONFIG_MODVERSIONS is not set # CONFIG_MODULE_SRCVERSION_ALL is not set CONFIG_KMOD=y - -# -# Block layer -# CONFIG_BLOCK=y # CONFIG_LBD is not set # CONFIG_BLK_DEV_IO_TRACE is not set # CONFIG_LSF is not set +# CONFIG_BLK_DEV_BSG is not set # # IO Schedulers @@ -113,7 +106,6 @@ CONFIG_CPU_SH4=y CONFIG_CPU_SH4A=y # CONFIG_CPU_SUBTYPE_SH7619 is not set # CONFIG_CPU_SUBTYPE_SH7206 is not set -# CONFIG_CPU_SUBTYPE_SH7300 is not set # CONFIG_CPU_SUBTYPE_SH7705 is not set # CONFIG_CPU_SUBTYPE_SH7706 is not set # CONFIG_CPU_SUBTYPE_SH7707 is not set @@ -121,6 +113,7 @@ CONFIG_CPU_SH4A=y # CONFIG_CPU_SUBTYPE_SH7709 is not set # CONFIG_CPU_SUBTYPE_SH7710 is not set # CONFIG_CPU_SUBTYPE_SH7712 is not set +# CONFIG_CPU_SUBTYPE_SH7720 is not set # CONFIG_CPU_SUBTYPE_SH7750 is not set # CONFIG_CPU_SUBTYPE_SH7091 is not set # CONFIG_CPU_SUBTYPE_SH7750R is not set @@ -129,12 +122,10 @@ CONFIG_CPU_SH4A=y # CONFIG_CPU_SUBTYPE_SH7751R is not set # CONFIG_CPU_SUBTYPE_SH7760 is not set # CONFIG_CPU_SUBTYPE_SH4_202 is not set -# CONFIG_CPU_SUBTYPE_ST40STB1 is not set -# CONFIG_CPU_SUBTYPE_ST40GX1 is not set # CONFIG_CPU_SUBTYPE_SH7770 is not set CONFIG_CPU_SUBTYPE_SH7780=y # CONFIG_CPU_SUBTYPE_SH7785 is not set -# CONFIG_CPU_SUBTYPE_SH73180 is not set +# CONFIG_CPU_SUBTYPE_SHX3 is not set # CONFIG_CPU_SUBTYPE_SH7343 is not set # CONFIG_CPU_SUBTYPE_SH7722 is not set @@ -169,6 +160,7 @@ CONFIG_FLATMEM_MANUAL=y CONFIG_FLATMEM=y CONFIG_FLAT_NODE_MEM_MAP=y CONFIG_SPARSEMEM_STATIC=y +# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set CONFIG_SPLIT_PTLOCK_CPUS=4 # CONFIG_RESOURCES_64BIT is not set CONFIG_ZONE_DMA_FLAG=0 @@ -178,8 +170,9 @@ CONFIG_NR_QUICK=2 # Cache configuration # # CONFIG_SH_DIRECT_MAPPED is not set -# CONFIG_SH_WRITETHROUGH is not set -# CONFIG_SH_OCRAM is not set +CONFIG_CACHE_WRITEBACK=y +# CONFIG_CACHE_WRITETHROUGH is not set +# CONFIG_CACHE_OFF is not set # # Processor features @@ -187,12 +180,11 @@ CONFIG_NR_QUICK=2 CONFIG_CPU_LITTLE_ENDIAN=y # CONFIG_CPU_BIG_ENDIAN is not set CONFIG_SH_FPU=y -# CONFIG_SH_DSP is not set CONFIG_SH_STORE_QUEUES=y CONFIG_SPECULATIVE_EXECUTION=y CONFIG_CPU_HAS_INTEVT=y -CONFIG_CPU_HAS_INTC_IRQ=y CONFIG_CPU_HAS_SR_RB=y +CONFIG_CPU_HAS_FPU=y # # Board support @@ -212,6 +204,7 @@ CONFIG_SH_PCLK_FREQ=32000000 # CONFIG_TICK_ONESHOT is not set # CONFIG_NO_HZ is not set # CONFIG_HIGH_RES_TIMERS is not set +CONFIG_GENERIC_CLOCKEVENTS_BUILD=y # # CPU Frequency scaling @@ -226,7 +219,6 @@ CONFIG_SH_PCLK_FREQ=32000000 # # Companion Chips # -# CONFIG_HD6446X_SERIES is not set # # Additional SuperH Device Drivers @@ -244,18 +236,17 @@ CONFIG_HZ_250=y CONFIG_HZ=250 CONFIG_KEXEC=y # CONFIG_CRASH_DUMP is not set -# CONFIG_SMP is not set # CONFIG_PREEMPT_NONE is not set # CONFIG_PREEMPT_VOLUNTARY is not set CONFIG_PREEMPT=y CONFIG_PREEMPT_BKL=y +CONFIG_GUSA=y # # Boot options # CONFIG_ZERO_PAGE_OFFSET=0x00001000 CONFIG_BOOT_LINK_OFFSET=0x00800000 -# CONFIG_UBC_WAKEUP is not set CONFIG_CMDLINE_BOOL=y CONFIG_CMDLINE="console=ttySC0,115200 root=/dev/sda1" @@ -267,11 +258,8 @@ CONFIG_SH_PCIDMA_NONCOHERENT=y CONFIG_PCI_AUTO=y CONFIG_PCI_AUTO_UPDATE_RESOURCES=y # CONFIG_ARCH_SUPPORTS_MSI is not set +CONFIG_PCI_LEGACY=y # CONFIG_PCI_DEBUG is not set - -# -# PCCARD (PCMCIA/CardBus) support -# # CONFIG_PCCARD is not set # CONFIG_HOTPLUG_PCI is not set @@ -282,11 +270,6 @@ CONFIG_BINFMT_ELF=y # CONFIG_BINFMT_MISC is not set # -# Power management options (EXPERIMENTAL) -# -# CONFIG_PM is not set - -# # Networking # CONFIG_NET=y @@ -327,6 +310,7 @@ CONFIG_IP_PNP_DHCP=y CONFIG_INET_XFRM_MODE_TRANSPORT=y CONFIG_INET_XFRM_MODE_TUNNEL=y CONFIG_INET_XFRM_MODE_BEET=y +# CONFIG_INET_LRO is not set CONFIG_INET_DIAG=y CONFIG_INET_TCP_DIAG=y # CONFIG_TCP_CONG_ADVANCED is not set @@ -353,10 +337,6 @@ CONFIG_LLC=m # CONFIG_LAPB is not set # CONFIG_ECONET is not set # CONFIG_WAN_ROUTER is not set - -# -# QoS and/or fair queueing -# # CONFIG_NET_SCHED is not set # @@ -376,6 +356,7 @@ CONFIG_WIRELESS_EXT=y # CONFIG_MAC80211 is not set # CONFIG_IEEE80211 is not set # CONFIG_RFKILL is not set +# CONFIG_NET_9P is not set # # Device Drivers @@ -384,33 +365,17 @@ CONFIG_WIRELESS_EXT=y # # Generic Driver Options # +CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" CONFIG_STANDALONE=y CONFIG_PREVENT_FIRMWARE_BUILD=y CONFIG_FW_LOADER=m # CONFIG_DEBUG_DRIVER is not set # CONFIG_DEBUG_DEVRES is not set # CONFIG_SYS_HYPERVISOR is not set - -# -# Connector - unified userspace <-> kernelspace linker -# # CONFIG_CONNECTOR is not set # CONFIG_MTD is not set - -# -# Parallel port support -# # CONFIG_PARPORT is not set - -# -# Plug and Play support -# -# CONFIG_PNPACPI is not set - -# -# Block devices -# -# CONFIG_BLK_CPQ_DA is not set +CONFIG_BLK_DEV=y # CONFIG_BLK_CPQ_CISS_DA is not set # CONFIG_BLK_DEV_DAC960 is not set # CONFIG_BLK_DEV_UMEM is not set @@ -424,14 +389,11 @@ CONFIG_BLK_DEV_RAM_SIZE=4096 CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024 # CONFIG_CDROM_PKTCDVD is not set # CONFIG_ATA_OVER_ETH is not set - -# -# Misc devices -# +CONFIG_MISC_DEVICES=y # CONFIG_PHANTOM is not set +CONFIG_EEPROM_93CX6=y # CONFIG_SGI_IOC4 is not set # CONFIG_TIFM_CORE is not set -# CONFIG_BLINK is not set # CONFIG_IDE is not set # @@ -439,6 +401,7 @@ CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024 # # CONFIG_RAID_ATTRS is not set CONFIG_SCSI=y +CONFIG_SCSI_DMA=y # CONFIG_SCSI_TGT is not set # CONFIG_SCSI_NETLINK is not set CONFIG_SCSI_PROC_FS=y @@ -468,12 +431,9 @@ CONFIG_SCSI_WAIT_SCAN=m # CONFIG_SCSI_SPI_ATTRS is not set # CONFIG_SCSI_FC_ATTRS is not set # CONFIG_SCSI_ISCSI_ATTRS is not set -# CONFIG_SCSI_SAS_ATTRS is not set # CONFIG_SCSI_SAS_LIBSAS is not set - -# -# SCSI low-level drivers -# +# CONFIG_SCSI_SRP_ATTRS is not set +CONFIG_SCSI_LOWLEVEL=y # CONFIG_ISCSI_TCP is not set # CONFIG_BLK_DEV_3W_XXXX_RAID is not set # CONFIG_SCSI_3W_9XXX is not set @@ -483,7 +443,6 @@ CONFIG_SCSI_WAIT_SCAN=m # CONFIG_SCSI_AIC7XXX_OLD is not set # CONFIG_SCSI_AIC79XX is not set # CONFIG_SCSI_AIC94XX is not set -# CONFIG_SCSI_DPT_I2O is not set # CONFIG_SCSI_ARCMSR is not set # CONFIG_MEGARAID_NEWGEN is not set # CONFIG_MEGARAID_LEGACY is not set @@ -548,6 +507,7 @@ CONFIG_SATA_SIL=y # CONFIG_PATA_OLDPIIX is not set # CONFIG_PATA_NETCELL is not set # CONFIG_PATA_NS87410 is not set +# CONFIG_PATA_NS87415 is not set # CONFIG_PATA_OPTI is not set # CONFIG_PATA_OPTIDMA is not set # CONFIG_PATA_PDC_OLD is not set @@ -561,59 +521,43 @@ CONFIG_SATA_SIL=y # CONFIG_PATA_VIA is not set # CONFIG_PATA_WINBOND is not set CONFIG_PATA_PLATFORM=y - -# -# Multi-device support (RAID and LVM) -# # CONFIG_MD is not set - -# -# Fusion MPT device support -# # CONFIG_FUSION is not set -# CONFIG_FUSION_SPI is not set -# CONFIG_FUSION_FC is not set -# CONFIG_FUSION_SAS is not set # # IEEE 1394 (FireWire) support # # CONFIG_FIREWIRE is not set # CONFIG_IEEE1394 is not set - -# -# I2O device support -# # CONFIG_I2O is not set - -# -# Network device support -# CONFIG_NETDEVICES=y +# CONFIG_NETDEVICES_MULTIQUEUE is not set # CONFIG_DUMMY is not set # CONFIG_BONDING is not set +# CONFIG_MACVLAN is not set # CONFIG_EQUALIZER is not set # CONFIG_TUN is not set +# CONFIG_VETH is not set +# CONFIG_IP1000 is not set # CONFIG_ARCNET is not set # CONFIG_PHYLIB is not set - -# -# Ethernet (10 or 100Mbit) -# CONFIG_NET_ETHERNET=y CONFIG_MII=y +CONFIG_AX88796=y +CONFIG_AX88796_93CX6=y # CONFIG_STNIC is not set # CONFIG_HAPPYMEAL is not set # CONFIG_SUNGEM is not set # CONFIG_CASSINI is not set # CONFIG_NET_VENDOR_3COM is not set # CONFIG_SMC91X is not set - -# -# Tulip family network device support -# +# CONFIG_SMC911X is not set # CONFIG_NET_TULIP is not set # CONFIG_HP100 is not set +# CONFIG_IBM_NEW_EMAC_ZMII is not set +# CONFIG_IBM_NEW_EMAC_RGMII is not set +# CONFIG_IBM_NEW_EMAC_TAH is not set +# CONFIG_IBM_NEW_EMAC_EMAC4 is not set CONFIG_NET_PCI=y CONFIG_PCNET32=m # CONFIG_PCNET32_NAPI is not set @@ -621,7 +565,6 @@ CONFIG_PCNET32=m # CONFIG_ADAPTEC_STARFIRE is not set # CONFIG_B44 is not set # CONFIG_FORCEDETH is not set -# CONFIG_DGRS is not set # CONFIG_EEPRO100 is not set # CONFIG_E100 is not set # CONFIG_FEALNX is not set @@ -647,6 +590,7 @@ CONFIG_NETDEV_1000=y CONFIG_E1000=m # CONFIG_E1000_NAPI is not set # CONFIG_E1000_DISABLE_PACKET_SPLIT is not set +# CONFIG_E1000E is not set # CONFIG_NS83820 is not set # CONFIG_HAMACHI is not set # CONFIG_YELLOWFIN is not set @@ -664,11 +608,14 @@ CONFIG_R8169=y CONFIG_NETDEV_10000=y # CONFIG_CHELSIO_T1 is not set # CONFIG_CHELSIO_T3 is not set +# CONFIG_IXGBE is not set # CONFIG_IXGB is not set # CONFIG_S2IO is not set # CONFIG_MYRI10GE is not set # CONFIG_NETXEN_NIC is not set +# CONFIG_NIU is not set # CONFIG_MLX4_CORE is not set +# CONFIG_TEHUTI is not set # CONFIG_TR is not set # @@ -686,15 +633,7 @@ CONFIG_NETDEV_10000=y # CONFIG_NETCONSOLE is not set # CONFIG_NETPOLL is not set # CONFIG_NET_POLL_CONTROLLER is not set - -# -# ISDN subsystem -# # CONFIG_ISDN is not set - -# -# Telephony Support -# # CONFIG_PHONE is not set # @@ -702,6 +641,7 @@ CONFIG_NETDEV_10000=y # CONFIG_INPUT=y # CONFIG_INPUT_FF_MEMLESS is not set +# CONFIG_INPUT_POLLDEV is not set # # Userland interfaces @@ -711,7 +651,6 @@ CONFIG_INPUT_MOUSEDEV=y CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 # CONFIG_INPUT_JOYDEV is not set -# CONFIG_INPUT_TSDEV is not set # CONFIG_INPUT_EVDEV is not set # CONFIG_INPUT_EVBUG is not set @@ -765,21 +704,11 @@ CONFIG_SERIAL_CORE_CONSOLE=y CONFIG_UNIX98_PTYS=y CONFIG_LEGACY_PTYS=y CONFIG_LEGACY_PTY_COUNT=256 - -# -# IPMI -# # CONFIG_IPMI_HANDLER is not set -# CONFIG_WATCHDOG is not set CONFIG_HW_RANDOM=y # CONFIG_R3964 is not set # CONFIG_APPLICOM is not set -# CONFIG_DRM is not set # CONFIG_RAW_DRIVER is not set - -# -# TPM devices -# # CONFIG_TCG_TPM is not set CONFIG_DEVPORT=y # CONFIG_I2C is not set @@ -789,21 +718,31 @@ CONFIG_DEVPORT=y # # CONFIG_SPI is not set # CONFIG_SPI_MASTER is not set - -# -# Dallas's 1-wire bus -# # CONFIG_W1 is not set +# CONFIG_POWER_SUPPLY is not set CONFIG_HWMON=y # CONFIG_HWMON_VID is not set -# CONFIG_SENSORS_ABITUGURU is not set # CONFIG_SENSORS_F71805F is not set +# CONFIG_SENSORS_F71882FG is not set +# CONFIG_SENSORS_IT87 is not set +# CONFIG_SENSORS_PC87360 is not set # CONFIG_SENSORS_PC87427 is not set +# CONFIG_SENSORS_SIS5595 is not set # CONFIG_SENSORS_SMSC47M1 is not set # CONFIG_SENSORS_SMSC47B397 is not set +# CONFIG_SENSORS_VIA686A is not set # CONFIG_SENSORS_VT1211 is not set +# CONFIG_SENSORS_VT8231 is not set # CONFIG_SENSORS_W83627HF is not set +# CONFIG_SENSORS_W83627EHF is not set # CONFIG_HWMON_DEBUG_CHIP is not set +# CONFIG_WATCHDOG is not set + +# +# Sonics Silicon Backplane +# +CONFIG_SSB_POSSIBLE=y +# CONFIG_SSB is not set # # Multifunction device drivers @@ -820,14 +759,16 @@ CONFIG_DAB=y # # Graphics support # +# CONFIG_DRM is not set +# CONFIG_VGASTATE is not set +# CONFIG_VIDEO_OUTPUT_CONTROL is not set +# CONFIG_FB is not set # CONFIG_BACKLIGHT_LCD_SUPPORT is not set # # Display device support # # CONFIG_DISPLAY_SUPPORT is not set -# CONFIG_VGASTATE is not set -# CONFIG_FB is not set # # Sound @@ -843,20 +784,14 @@ CONFIG_SOUND=m # Open Sound System # CONFIG_SOUND_PRIME=m -# CONFIG_OSS_OBSOLETE is not set # CONFIG_SOUND_TRIDENT is not set # CONFIG_SOUND_MSNDCLAS is not set # CONFIG_SOUND_MSNDPIN is not set - -# -# HID Devices -# +CONFIG_HID_SUPPORT=y CONFIG_HID=y # CONFIG_HID_DEBUG is not set - -# -# USB support -# +# CONFIG_HIDRAW is not set +CONFIG_USB_SUPPORT=y CONFIG_USB_ARCH_HAS_HCD=y CONFIG_USB_ARCH_HAS_OHCI=y CONFIG_USB_ARCH_HAS_EHCI=y @@ -871,32 +806,8 @@ CONFIG_USB_ARCH_HAS_EHCI=y # # CONFIG_USB_GADGET is not set # CONFIG_MMC is not set - -# -# LED devices -# # CONFIG_NEW_LEDS is not set - -# -# LED drivers -# - -# -# LED Triggers -# - -# -# InfiniBand support -# # CONFIG_INFINIBAND is not set - -# -# EDAC - error detection and reporting (RAS) (EXPERIMENTAL) -# - -# -# Real Time Clock -# CONFIG_RTC_LIB=y CONFIG_RTC_CLASS=y CONFIG_RTC_HCTOSYS=y @@ -913,10 +824,6 @@ CONFIG_RTC_INTF_DEV=y # CONFIG_RTC_DRV_TEST is not set # -# I2C RTC drivers -# - -# # SPI RTC drivers # @@ -924,8 +831,10 @@ CONFIG_RTC_INTF_DEV=y # Platform RTC drivers # # CONFIG_RTC_DRV_DS1553 is not set +# CONFIG_RTC_DRV_STK17TA8 is not set # CONFIG_RTC_DRV_DS1742 is not set # CONFIG_RTC_DRV_M48T86 is not set +# CONFIG_RTC_DRV_M48T59 is not set # CONFIG_RTC_DRV_V3020 is not set # @@ -934,17 +843,9 @@ CONFIG_RTC_INTF_DEV=y CONFIG_RTC_DRV_SH=y # -# DMA Engine support -# -# CONFIG_DMA_ENGINE is not set - -# -# DMA Clients -# - -# -# DMA Devices +# Userspace I/O # +# CONFIG_UIO is not set # # File systems @@ -1005,7 +906,6 @@ CONFIG_TMPFS=y # CONFIG_TMPFS_POSIX_ACL is not set CONFIG_HUGETLBFS=y CONFIG_HUGETLB_PAGE=y -CONFIG_RAMFS=y CONFIG_CONFIGFS_FS=m # @@ -1024,10 +924,7 @@ CONFIG_CONFIGFS_FS=m # CONFIG_QNX4FS_FS is not set # CONFIG_SYSV_FS is not set # CONFIG_UFS_FS is not set - -# -# Network File Systems -# +CONFIG_NETWORK_FILESYSTEMS=y CONFIG_NFS_FS=y CONFIG_NFS_V3=y # CONFIG_NFS_V3_ACL is not set @@ -1053,17 +950,12 @@ CONFIG_RPCSEC_GSS_KRB5=y # CONFIG_NCP_FS is not set # CONFIG_CODA_FS is not set # CONFIG_AFS_FS is not set -# CONFIG_9P_FS is not set # # Partition Types # # CONFIG_PARTITION_ADVANCED is not set CONFIG_MSDOS_PARTITION=y - -# -# Native Language Support -# CONFIG_NLS=y CONFIG_NLS_DEFAULT="iso8859-1" CONFIG_NLS_CODEPAGE_437=y @@ -1104,23 +996,18 @@ CONFIG_NLS_ISO8859_1=y # CONFIG_NLS_KOI8_R is not set # CONFIG_NLS_KOI8_U is not set # CONFIG_NLS_UTF8 is not set - -# -# Distributed Lock Manager -# # CONFIG_DLM is not set - -# -# Profiling support -# +CONFIG_INSTRUMENTATION=y CONFIG_PROFILING=y CONFIG_OPROFILE=m +# CONFIG_MARKERS is not set # # Kernel hacking # CONFIG_TRACE_IRQFLAGS_SUPPORT=y # CONFIG_PRINTK_TIME is not set +CONFIG_ENABLE_WARN_DEPRECATED=y CONFIG_ENABLE_MUST_CHECK=y CONFIG_MAGIC_SYSRQ=y # CONFIG_UNUSED_SYMBOLS is not set @@ -1129,6 +1016,7 @@ CONFIG_DEBUG_FS=y CONFIG_DEBUG_KERNEL=y # CONFIG_DEBUG_SHIRQ is not set CONFIG_DETECT_SOFTLOCKUP=y +CONFIG_SCHED_DEBUG=y # CONFIG_SCHEDSTATS is not set # CONFIG_TIMER_STATS is not set # CONFIG_DEBUG_SLAB is not set @@ -1137,6 +1025,7 @@ CONFIG_DETECT_SOFTLOCKUP=y # CONFIG_DEBUG_MUTEXES is not set # CONFIG_DEBUG_LOCK_ALLOC is not set # CONFIG_PROVE_LOCKING is not set +# CONFIG_LOCK_STAT is not set # CONFIG_DEBUG_SPINLOCK_SLEEP is not set # CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set # CONFIG_DEBUG_KOBJECT is not set @@ -1144,10 +1033,13 @@ CONFIG_DEBUG_BUGVERBOSE=y CONFIG_DEBUG_INFO=y # CONFIG_DEBUG_VM is not set # CONFIG_DEBUG_LIST is not set +# CONFIG_DEBUG_SG is not set # CONFIG_FRAME_POINTER is not set CONFIG_FORCED_INLINING=y +# CONFIG_BOOT_PRINTK_DELAY is not set # CONFIG_RCU_TORTURE_TEST is not set # CONFIG_FAULT_INJECTION is not set +# CONFIG_SAMPLES is not set CONFIG_SH_STANDARD_BIOS=y # CONFIG_EARLY_SCIF_CONSOLE is not set CONFIG_EARLY_PRINTK=y @@ -1155,6 +1047,7 @@ CONFIG_EARLY_PRINTK=y CONFIG_DEBUG_STACKOVERFLOW=y # CONFIG_DEBUG_STACK_USAGE is not set # CONFIG_4KSTACKS is not set +# CONFIG_IRQSTACKS is not set # CONFIG_SH_KGDB is not set # @@ -1162,10 +1055,7 @@ CONFIG_DEBUG_STACKOVERFLOW=y # # CONFIG_KEYS is not set # CONFIG_SECURITY is not set - -# -# Cryptographic options -# +# CONFIG_SECURITY_FILE_CAPABILITIES is not set CONFIG_CRYPTO=y CONFIG_CRYPTO_ALGAPI=y CONFIG_CRYPTO_BLKCIPHER=y @@ -1186,6 +1076,7 @@ CONFIG_CRYPTO_ECB=m CONFIG_CRYPTO_CBC=y CONFIG_CRYPTO_PCBC=m # CONFIG_CRYPTO_LRW is not set +# CONFIG_CRYPTO_XTS is not set # CONFIG_CRYPTO_CRYPTD is not set CONFIG_CRYPTO_DES=y # CONFIG_CRYPTO_FCRYPT is not set @@ -1199,15 +1090,14 @@ CONFIG_CRYPTO_DES=y # CONFIG_CRYPTO_ARC4 is not set # CONFIG_CRYPTO_KHAZAD is not set # CONFIG_CRYPTO_ANUBIS is not set +# CONFIG_CRYPTO_SEED is not set # CONFIG_CRYPTO_DEFLATE is not set # CONFIG_CRYPTO_MICHAEL_MIC is not set # CONFIG_CRYPTO_CRC32C is not set # CONFIG_CRYPTO_CAMELLIA is not set # CONFIG_CRYPTO_TEST is not set - -# -# Hardware crypto devices -# +# CONFIG_CRYPTO_AUTHENC is not set +CONFIG_CRYPTO_HW=y # # Library routines @@ -1217,6 +1107,7 @@ CONFIG_BITREVERSE=y # CONFIG_CRC16 is not set # CONFIG_CRC_ITU_T is not set CONFIG_CRC32=y +# CONFIG_CRC7 is not set # CONFIG_LIBCRC32C is not set CONFIG_HAS_IOMEM=y CONFIG_HAS_IOPORT=y diff --git a/arch/sh/configs/r7785rp_defconfig b/arch/sh/configs/r7785rp_defconfig index 158e03f..2e43a2a 100644 --- a/arch/sh/configs/r7785rp_defconfig +++ b/arch/sh/configs/r7785rp_defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.24-rc1 -# Fri Nov 2 14:30:49 2007 +# Linux kernel version: 2.6.24-rc2 +# Tue Nov 13 20:34:57 2007 # CONFIG_SUPERH=y CONFIG_RWSEM_GENERIC_SPINLOCK=y @@ -124,8 +124,6 @@ CONFIG_CPU_SHX2=y # CONFIG_CPU_SUBTYPE_SH7751R is not set # CONFIG_CPU_SUBTYPE_SH7760 is not set # CONFIG_CPU_SUBTYPE_SH4_202 is not set -# CONFIG_CPU_SUBTYPE_ST40STB1 is not set -# CONFIG_CPU_SUBTYPE_ST40GX1 is not set # CONFIG_CPU_SUBTYPE_SH7770 is not set # CONFIG_CPU_SUBTYPE_SH7780 is not set CONFIG_CPU_SUBTYPE_SH7785=y @@ -254,7 +252,6 @@ CONFIG_GUSA=y # CONFIG_ZERO_PAGE_OFFSET=0x00001000 CONFIG_BOOT_LINK_OFFSET=0x00800000 -# CONFIG_UBC_WAKEUP is not set CONFIG_CMDLINE_BOOL=y CONFIG_CMDLINE="console=ttySC0,115200 root=/dev/sda1" @@ -266,6 +263,7 @@ CONFIG_SH_PCIDMA_NONCOHERENT=y CONFIG_PCI_AUTO=y CONFIG_PCI_AUTO_UPDATE_RESOURCES=y # CONFIG_ARCH_SUPPORTS_MSI is not set +CONFIG_PCI_LEGACY=y # CONFIG_PCI_DEBUG is not set # CONFIG_PCCARD is not set # CONFIG_HOTPLUG_PCI is not set @@ -550,6 +548,8 @@ CONFIG_NETDEVICES=y # CONFIG_PHYLIB is not set CONFIG_NET_ETHERNET=y CONFIG_MII=y +CONFIG_AX88796=y +CONFIG_AX88796_93CX6=y # CONFIG_STNIC is not set # CONFIG_HAPPYMEAL is not set # CONFIG_SUNGEM is not set diff --git a/arch/sh/drivers/pci/Makefile b/arch/sh/drivers/pci/Makefile index 2f65ac7..fba6b5b 100644 --- a/arch/sh/drivers/pci/Makefile +++ b/arch/sh/drivers/pci/Makefile @@ -5,7 +5,6 @@ obj-y += pci.o obj-$(CONFIG_PCI_AUTO) += pci-auto.o -obj-$(CONFIG_CPU_SUBTYPE_ST40STB1) += pci-st40.o obj-$(CONFIG_CPU_SUBTYPE_SH7751) += pci-sh7751.o ops-sh4.o obj-$(CONFIG_CPU_SUBTYPE_SH7751R) += pci-sh7751.o ops-sh4.o obj-$(CONFIG_CPU_SUBTYPE_SH7780) += pci-sh7780.o ops-sh4.o diff --git a/arch/sh/drivers/pci/pci-st40.c b/arch/sh/drivers/pci/pci-st40.c deleted file mode 100644 index 0814a5a..0000000 --- a/arch/sh/drivers/pci/pci-st40.c +++ /dev/null @@ -1,488 +0,0 @@ -/* - * Copyright (C) 2001 David J. Mckay (david.mckay@st.com) - * - * May be copied or modified under the terms of the GNU General Public - * License. See linux/COPYING for more information. - * - * Support functions for the ST40 PCI hardware. - */ - -#include <linux/kernel.h> -#include <linux/smp.h> -#include <linux/init.h> -#include <linux/errno.h> -#include <linux/pci.h> -#include <linux/delay.h> -#include <linux/types.h> -#include <asm/pci.h> -#include <linux/irq.h> -#include <linux/interrupt.h> /* irqreturn_t */ - -#include "pci-st40.h" - -/* This is in P2 of course */ -#define ST40PCI_BASE_ADDRESS (0xb0000000) -#define ST40PCI_MEM_ADDRESS (ST40PCI_BASE_ADDRESS+0x0) -#define ST40PCI_IO_ADDRESS (ST40PCI_BASE_ADDRESS+0x06000000) -#define ST40PCI_REG_ADDRESS (ST40PCI_BASE_ADDRESS+0x07000000) - -#define ST40PCI_REG(x) (ST40PCI_REG_ADDRESS+(ST40PCI_##x)) -#define ST40PCI_REG_INDEXED(reg, index) \ - (ST40PCI_REG(reg##0) + \ - ((ST40PCI_REG(reg##1) - ST40PCI_REG(reg##0))*index)) - -#define ST40PCI_WRITE(reg,val) writel((val),ST40PCI_REG(reg)) -#define ST40PCI_WRITE_SHORT(reg,val) writew((val),ST40PCI_REG(reg)) -#define ST40PCI_WRITE_BYTE(reg,val) writeb((val),ST40PCI_REG(reg)) -#define ST40PCI_WRITE_INDEXED(reg, index, val) \ - writel((val), ST40PCI_REG_INDEXED(reg, index)); - -#define ST40PCI_READ(reg) readl(ST40PCI_REG(reg)) -#define ST40PCI_READ_SHORT(reg) readw(ST40PCI_REG(reg)) -#define ST40PCI_READ_BYTE(reg) readb(ST40PCI_REG(reg)) - -#define ST40PCI_SERR_IRQ 64 -#define ST40PCI_ERR_IRQ 65 - - -/* Macros to extract PLL params */ -#define PLL_MDIV(reg) ( ((unsigned)reg) & 0xff ) -#define PLL_NDIV(reg) ( (((unsigned)reg)>>8) & 0xff ) -#define PLL_PDIV(reg) ( (((unsigned)reg)>>16) & 0x3 ) -#define PLL_SETUP(reg) ( (((unsigned)reg)>>19) & 0x1ff ) - -/* Build up the appropriate settings */ -#define PLL_SET(mdiv,ndiv,pdiv,setup) \ -( ((mdiv)&0xff) | (((ndiv)&0xff)<<8) | (((pdiv)&3)<<16)| (((setup)&0x1ff)<<19)) - -#define PLLPCICR (0xbb040000+0x10) - -#define PLLPCICR_POWERON (1<<28) -#define PLLPCICR_OUT_EN (1<<29) -#define PLLPCICR_LOCKSELECT (1<<30) -#define PLLPCICR_LOCK (1<<31) - - -#define PLL_25MHZ 0x793c8512 -#define PLL_33MHZ PLL_SET(18,88,3,295) - -static void pci_set_rbar_region(unsigned int region, unsigned long localAddr, - unsigned long pciOffset, unsigned long regionSize); - -static __init void SetPCIPLL(void) -{ - { - /* Lets play with the PLL values */ - unsigned long pll1cr1; - unsigned long mdiv, ndiv, pdiv; - unsigned long muxcr; - unsigned int muxcr_ratios[4] = { 8, 16, 21, 1 }; - unsigned int freq; - -#define CLKGENA 0xbb040000 -#define CLKGENA_PLL2_MUXCR CLKGENA + 0x48 - pll1cr1 = ctrl_inl(PLLPCICR); - printk("PLL1CR1 %08lx\n", pll1cr1); - mdiv = PLL_MDIV(pll1cr1); - ndiv = PLL_NDIV(pll1cr1); - pdiv = PLL_PDIV(pll1cr1); - printk("mdiv %02lx ndiv %02lx pdiv %02lx\n", mdiv, ndiv, pdiv); - freq = ((2*27*ndiv)/mdiv) / (1 << pdiv); - printk("PLL freq %dMHz\n", freq); - muxcr = ctrl_inl(CLKGENA_PLL2_MUXCR); - printk("PCI freq %dMhz\n", freq / muxcr_ratios[muxcr & 3]); - } -} - - -struct pci_err { - unsigned mask; - const char *error_string; -}; - -static struct pci_err int_error[]={ - { INT_MNLTDIM,"MNLTDIM: Master non-lock transfer"}, - { INT_TTADI, "TTADI: Illegal byte enable in I/O transfer"}, - { INT_TMTO, "TMTO: Target memory read/write timeout"}, - { INT_MDEI, "MDEI: Master function disable error"}, - { INT_APEDI, "APEDI: Address parity error"}, - { INT_SDI, "SDI: SERR detected"}, - { INT_DPEITW, "DPEITW: Data parity error target write"}, - { INT_PEDITR, "PEDITR: PERR detected"}, - { INT_TADIM, "TADIM: Target abort detected"}, - { INT_MADIM, "MADIM: Master abort detected"}, - { INT_MWPDI, "MWPDI: PERR from target at data write"}, - { INT_MRDPEI, "MRDPEI: Master read data parity error"} -}; -#define NUM_PCI_INT_ERRS ARRAY_SIZE(int_error) - -static struct pci_err aint_error[]={ - { AINT_MBI, "MBI: Master broken"}, - { AINT_TBTOI, "TBTOI: Target bus timeout"}, - { AINT_MBTOI, "MBTOI: Master bus timeout"}, - { AINT_TAI, "TAI: Target abort"}, - { AINT_MAI, "MAI: Master abort"}, - { AINT_RDPEI, "RDPEI: Read data parity"}, - { AINT_WDPE, "WDPE: Write data parity"} -}; - -#define NUM_PCI_AINT_ERRS ARRAY_SIZE(aint_error) - -static void print_pci_errors(unsigned reg,struct pci_err *error,int num_errors) -{ - int i; - - for(i=0;i<num_errors;i++) { - if(reg & error[i].mask) { - printk("%s\n",error[i].error_string); - } - } - -} - - -static char * pci_commands[16]={ - "Int Ack", - "Special Cycle", - "I/O Read", - "I/O Write", - "Reserved", - "Reserved", - "Memory Read", - "Memory Write", - "Reserved", - "Reserved", - "Configuration Read", - "Configuration Write", - "Memory Read Multiple", - "Dual Address Cycle", - "Memory Read Line", - "Memory Write-and-Invalidate" -}; - -static irqreturn_t st40_pci_irq(int irq, void *dev_instance) -{ - unsigned pci_int, pci_air, pci_cir, pci_aint; - static int count=0; - - - pci_int = ST40PCI_READ(INT);pci_aint = ST40PCI_READ(AINT); - pci_cir = ST40PCI_READ(CIR);pci_air = ST40PCI_READ(AIR); - - /* Reset state to stop multiple interrupts */ - ST40PCI_WRITE(INT, ~0); ST40PCI_WRITE(AINT, ~0); - - - if(++count>1) return IRQ_HANDLED; - - printk("** PCI ERROR **\n"); - - if(pci_int) { - printk("** INT register status\n"); - print_pci_errors(pci_int,int_error,NUM_PCI_INT_ERRS); - } - - if(pci_aint) { - printk("** AINT register status\n"); - print_pci_errors(pci_aint,aint_error,NUM_PCI_AINT_ERRS); - } - - printk("** Address and command info\n"); - - printk("** Command %s : Address 0x%x\n", - pci_commands[pci_cir&0xf],pci_air); - - if(pci_cir&CIR_PIOTEM) { - printk("CIR_PIOTEM:PIO transfer error for master\n"); - } - if(pci_cir&CIR_RWTET) { - printk("CIR_RWTET:Read/Write transfer error for target\n"); - } - - return IRQ_HANDLED; -} - - -/* Rounds a number UP to the nearest power of two. Used for - * sizing the PCI window. - */ -static u32 r2p2(u32 num) -{ - int i = 31; - u32 tmp = num; - - if (num == 0) - return 0; - - do { - if (tmp & (1 << 31)) - break; - i--; - tmp <<= 1; - } while (i >= 0); - - tmp = 1 << i; - /* If the original number isn't a power of 2, round it up */ - if (tmp != num) - tmp <<= 1; - - return tmp; -} - -static void __init pci_fixup_ide_bases(struct pci_dev *d) -{ - int i; - - /* - * PCI IDE controllers use non-standard I/O port decoding, respect it. - */ - if ((d->class >> 8) != PCI_CLASS_STORAGE_IDE) - return; - printk("PCI: IDE base address fixup for %s\n", pci_name(d)); - for(i=0; i<4; i++) { - struct resource *r = &d->resource[i]; - if ((r->start & ~0x80) == 0x374) { - r->start |= 2; - r->end = r->start; - } - } -} -DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, pci_fixup_ide_bases); - -int __init st40pci_init(unsigned memStart, unsigned memSize) -{ - u32 lsr0; - - SetPCIPLL(); - - /* Initialises the ST40 pci subsystem, performing a reset, then programming - * up the address space decoders appropriately - */ - - /* Should reset core here as well methink */ - - ST40PCI_WRITE(CR, CR_LOCK_MASK | CR_SOFT_RESET); - - /* Loop while core resets */ - while (ST40PCI_READ(CR) & CR_SOFT_RESET); - - /* Switch off interrupts */ - ST40PCI_WRITE(INTM, 0); - ST40PCI_WRITE(AINT, 0); - - /* Now, lets reset all the cards on the bus with extreme prejudice */ - ST40PCI_WRITE(CR, CR_LOCK_MASK | CR_RSTCTL); - udelay(250); - - /* Set bus active, take it out of reset */ - ST40PCI_WRITE(CR, CR_LOCK_MASK | CR_BMAM | CR_CFINT | CR_PFCS | CR_PFE); - - /* The PCI spec says that no access must be made to the bus until 1 second - * after reset. This seem ludicrously long, but some delay is needed here - */ - mdelay(1000); - - /* Switch off interrupts */ - ST40PCI_WRITE(INTM, 0); - ST40PCI_WRITE(AINT, 0); - - /* Allow it to be a master */ - - ST40PCI_WRITE_SHORT(CSR_CMD, - PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER | - PCI_COMMAND_IO); - - /* Access to the 0xb0000000 -> 0xb6000000 area will go through to 0x10000000 -> 0x16000000 - * on the PCI bus. This allows a nice 1-1 bus to phys mapping. - */ - - - ST40PCI_WRITE(MBR, 0x10000000); - /* Always set the max size 128M (actually, it is only 96MB wide) */ - ST40PCI_WRITE(MBMR, 0x07ff0000); - - /* I/O addresses are mapped at 0xb6000000 -> 0xb7000000. These are changed to 0, to - * allow cards that have legacy io such as vga to function correctly. This gives a - * maximum of 64K of io/space as only the bottom 16 bits of the address are copied - * over to the bus when the transaction is made. 64K of io space is more than enough - */ - ST40PCI_WRITE(IOBR, 0x0); - /* Set up the 64K window */ - ST40PCI_WRITE(IOBMR, 0x0); - - /* Now we set up the mbars so the PCI bus can see the local memory */ - /* Expose a 256M window starting at PCI address 0... */ - ST40PCI_WRITE(CSR_MBAR0, 0); - ST40PCI_WRITE(LSR0, 0x0fff0001); - - /* ... and set up the initial incoming window to expose all of RAM */ - pci_set_rbar_region(7, memStart, memStart, memSize); - - /* Maximise timeout values */ - ST40PCI_WRITE_BYTE(CSR_TRDY, 0xff); - ST40PCI_WRITE_BYTE(CSR_RETRY, 0xff); - ST40PCI_WRITE_BYTE(CSR_MIT, 0xff); - - ST40PCI_WRITE_BYTE(PERF,PERF_MASTER_WRITE_POSTING); - - return 1; -} - -char * __devinit pcibios_setup(char *str) -{ - return str; -} - - -#define SET_CONFIG_BITS(bus,devfn,where)\ - (((bus) << 16) | ((devfn) << 8) | ((where) & ~3) | (bus!=0)) - -#define CONFIG_CMD(bus, devfn, where) SET_CONFIG_BITS(bus->number,devfn,where) - - -static int CheckForMasterAbort(void) -{ - if (ST40PCI_READ(INT) & INT_MADIM) { - /* Should we clear config space version as well ??? */ - ST40PCI_WRITE(INT, INT_MADIM); - ST40PCI_WRITE_SHORT(CSR_STATUS, 0); - return 1; - } - - return 0; -} - -/* Write to config register */ -static int st40pci_read(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 * val) -{ - ST40PCI_WRITE(PAR, CONFIG_CMD(bus, devfn, where)); - switch (size) { - case 1: - *val = (u8)ST40PCI_READ_BYTE(PDR + (where & 3)); - break; - case 2: - *val = (u16)ST40PCI_READ_SHORT(PDR + (where & 2)); - break; - case 4: - *val = ST40PCI_READ(PDR); - break; - } - - if (CheckForMasterAbort()){ - switch (size) { - case 1: - *val = (u8)0xff; - break; - case 2: - *val = (u16)0xffff; - break; - case 4: - *val = 0xffffffff; - break; - } - } - - return PCIBIOS_SUCCESSFUL; -} - -static int st40pci_write(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 val) -{ - ST40PCI_WRITE(PAR, CONFIG_CMD(bus, devfn, where)); - - switch (size) { - case 1: - ST40PCI_WRITE_BYTE(PDR + (where & 3), (u8)val); - break; - case 2: - ST40PCI_WRITE_SHORT(PDR + (where & 2), (u16)val); - break; - case 4: - ST40PCI_WRITE(PDR, val); - break; - } - - CheckForMasterAbort(); - - return PCIBIOS_SUCCESSFUL; -} - -struct pci_ops st40pci_config_ops = { - .read = st40pci_read, - .write = st40pci_write, -}; - - -/* Everything hangs off this */ -static struct pci_bus *pci_root_bus; - -static int __init pcibios_init(void) -{ - extern unsigned long memory_start, memory_end; - - printk(KERN_ALERT "pci-st40.c: pcibios_init\n"); - - if (sh_mv.mv_init_pci != NULL) { - sh_mv.mv_init_pci(); - } - - /* The pci subsytem needs to know where memory is and how much - * of it there is. I've simply made these globals. A better mechanism - * is probably needed. - */ - st40pci_init(PHYSADDR(memory_start), - PHYSADDR(memory_end) - PHYSADDR(memory_start)); - - if (request_irq(ST40PCI_ERR_IRQ, st40_pci_irq, - IRQF_DISABLED, "st40pci", NULL)) { - printk(KERN_ERR "st40pci: Cannot hook interrupt\n"); - return -EIO; - } - - /* Enable the PCI interrupts on the device */ - ST40PCI_WRITE(INTM, ~0); - ST40PCI_WRITE(AINT, ~0); - - /* Map the io address apprioately */ -#ifdef CONFIG_HD64465 - hd64465_port_map(PCIBIOS_MIN_IO, (64 * 1024) - PCIBIOS_MIN_IO + 1, - ST40_IO_ADDR + PCIBIOS_MIN_IO, 0); -#endif - - /* ok, do the scan man */ - pci_root_bus = pci_scan_bus(0, &st40pci_config_ops, NULL); - pci_assign_unassigned_resources(); - - return 0; -} -subsys_initcall(pcibios_init); - -/* - * Publish a region of local address space over the PCI bus - * to other devices. - */ -static void pci_set_rbar_region(unsigned int region, unsigned long localAddr, - unsigned long pciOffset, unsigned long regionSize) -{ - unsigned long mask; - - if (region > 7) - return; - - if (regionSize > (512 * 1024 * 1024)) - return; - - mask = r2p2(regionSize) - 0x10000; - - /* Disable the region (in case currently in use, should never happen) */ - ST40PCI_WRITE_INDEXED(RSR, region, 0); - - /* Start of local address space to publish */ - ST40PCI_WRITE_INDEXED(RLAR, region, PHYSADDR(localAddr) ); - - /* Start of region in PCI address space as an offset from MBAR0 */ - ST40PCI_WRITE_INDEXED(RBAR, region, pciOffset); - - /* Size of region */ - ST40PCI_WRITE_INDEXED(RSR, region, mask | 1); -} - diff --git a/arch/sh/drivers/pci/pci-st40.h b/arch/sh/drivers/pci/pci-st40.h deleted file mode 100644 index cf0d35b..0000000 --- a/arch/sh/drivers/pci/pci-st40.h +++ /dev/null @@ -1,136 +0,0 @@ -/* - * Copyright (C) 2001 David J. Mckay (david.mckay@st.com) - * - * May be copied or modified under the terms of the GNU General Public - * License. See linux/COPYING for more information. - * - * Definitions for the ST40 PCI hardware. - */ - -#ifndef __PCI_ST40_H__ -#define __PCI_ST40_H__ - -#define ST40PCI_VCR_STATUS 0x00 - -#define ST40PCI_VCR_VERSION 0x08 - -#define ST40PCI_CR 0x10 - -#define CR_SOFT_RESET (1<<12) -#define CR_PFCS (1<<11) -#define CR_PFE (1<<9) -#define CR_BMAM (1<<6) -#define CR_HOST (1<<5) -#define CR_CLKEN (1<<4) -#define CR_SOCS (1<<3) -#define CR_IOCS (1<<2) -#define CR_RSTCTL (1<<1) -#define CR_CFINT (1<<0) -#define CR_LOCK_MASK 0x5a000000 - - -#define ST40PCI_LSR0 0X14 -#define ST40PCI_LAR0 0x1c - -#define ST40PCI_INT 0x24 -#define INT_MNLTDIM (1<<15) -#define INT_TTADI (1<<14) -#define INT_TMTO (1<<9) -#define INT_MDEI (1<<8) -#define INT_APEDI (1<<7) -#define INT_SDI (1<<6) -#define INT_DPEITW (1<<5) -#define INT_PEDITR (1<<4) -#define INT_TADIM (1<<3) -#define INT_MADIM (1<<2) -#define INT_MWPDI (1<<1) -#define INT_MRDPEI (1<<0) - - -#define ST40PCI_INTM 0x28 -#define ST40PCI_AIR 0x2c - -#define ST40PCI_CIR 0x30 -#define CIR_PIOTEM (1<<31) -#define CIR_RWTET (1<<26) - -#define ST40PCI_AINT 0x40 -#define AINT_MBI (1<<13) -#define AINT_TBTOI (1<<12) -#define AINT_MBTOI (1<<11) -#define AINT_TAI (1<<3) -#define AINT_MAI (1<<2) -#define AINT_RDPEI (1<<1) -#define AINT_WDPE (1<<0) - -#define ST40PCI_AINTM 0x44 -#define ST40PCI_BMIR 0x48 -#define ST40PCI_PAR 0x4c -#define ST40PCI_MBR 0x50 -#define ST40PCI_IOBR 0x54 -#define ST40PCI_PINT 0x58 -#define ST40PCI_PINTM 0x5c -#define ST40PCI_MBMR 0x70 -#define ST40PCI_IOBMR 0x74 -#define ST40PCI_PDR 0x78 - -/* H8 specific registers start here */ -#define ST40PCI_WCBAR 0x7c -#define ST40PCI_LOCCFG_UNLOCK 0x34 - -#define ST40PCI_RBAR0 0x100 -#define ST40PCI_RSR0 0x104 -#define ST40PCI_RLAR0 0x108 - -#define ST40PCI_RBAR1 0x110 -#define ST40PCI_RSR1 0x114 -#define ST40PCI_RLAR1 0x118 - - -#define ST40PCI_RBAR2 0x120 -#define ST40PCI_RSR2 0x124 -#define ST40PCI_RLAR2 0x128 - -#define ST40PCI_RBAR3 0x130 -#define ST40PCI_RSR3 0x134 -#define ST40PCI_RLAR3 0x138 - -#define ST40PCI_RBAR4 0x140 -#define ST40PCI_RSR4 0x144 -#define ST40PCI_RLAR4 0x148 - -#define ST40PCI_RBAR5 0x150 -#define ST40PCI_RSR5 0x154 -#define ST40PCI_RLAR5 0x158 - -#define ST40PCI_RBAR6 0x160 -#define ST40PCI_RSR6 0x164 -#define ST40PCI_RLAR6 0x168 - -#define ST40PCI_RBAR7 0x170 -#define ST40PCI_RSR7 0x174 -#define ST40PCI_RLAR7 0x178 - - -#define ST40PCI_RBAR(n) (0x100+(0x10*(n))) -#define ST40PCI_RSR(n) (0x104+(0x10*(n))) -#define ST40PCI_RLAR(n) (0x108+(0x10*(n))) - -#define ST40PCI_PERF 0x80 -#define PERF_MASTER_WRITE_POSTING (1<<4) -/* H8 specific registers end here */ - - -/* These are configs space registers */ -#define ST40PCI_CSR_VID 0x10000 -#define ST40PCI_CSR_DID 0x10002 -#define ST40PCI_CSR_CMD 0x10004 -#define ST40PCI_CSR_STATUS 0x10006 -#define ST40PCI_CSR_MBAR0 0x10010 -#define ST40PCI_CSR_TRDY 0x10040 -#define ST40PCI_CSR_RETRY 0x10041 -#define ST40PCI_CSR_MIT 0x1000d - -#define ST40_IO_ADDR 0xb6000000 - -#endif /* __PCI_ST40_H__ */ diff --git a/arch/sh/kernel/Makefile b/arch/sh/kernel/Makefile index 1f141a8..4b81d9c 100644 --- a/arch/sh/kernel/Makefile +++ b/arch/sh/kernel/Makefile @@ -10,7 +10,6 @@ obj-y := debugtraps.o io.o io_generic.o irq.o machvec.o process.o ptrace.o \ obj-y += cpu/ timers/ obj-$(CONFIG_VSYSCALL) += vsyscall/ - obj-$(CONFIG_SMP) += smp.o obj-$(CONFIG_CF_ENABLER) += cf-enabler.o obj-$(CONFIG_SH_STANDARD_BIOS) += sh_bios.o @@ -22,3 +21,5 @@ obj-$(CONFIG_KEXEC) += machine_kexec.o relocate_kernel.o obj-$(CONFIG_CRASH_DUMP) += crash_dump.o obj-$(CONFIG_PM) += pm.o obj-$(CONFIG_STACKTRACE) += stacktrace.o + +EXTRA_CFLAGS += -Werror diff --git a/arch/sh/kernel/cpu/sh3/ex.S b/arch/sh/kernel/cpu/sh3/ex.S index 2b2a9e0..b6abf38 100644 --- a/arch/sh/kernel/cpu/sh3/ex.S +++ b/arch/sh/kernel/cpu/sh3/ex.S @@ -46,7 +46,7 @@ ENTRY(exception_handling_table) .long exception_error ! illegal_slot_instruction (filled by trap_init) /*1A0*/ ENTRY(nmi_slot) #if defined (CONFIG_KGDB_NMI) - .long debug_enter /* 1C0 */ ! Allow trap to debugger + .long kgdb_handle_exception /* 1C0 */ ! Allow trap to debugger #else .long exception_none /* 1C0 */ ! Not implemented yet #endif diff --git a/arch/sh/kernel/cpu/sh4/probe.c b/arch/sh/kernel/cpu/sh4/probe.c index 21375d7..bc9c28a 100644 --- a/arch/sh/kernel/cpu/sh4/probe.c +++ b/arch/sh/kernel/cpu/sh4/probe.c @@ -139,14 +139,6 @@ int __init detect_cpu_and_cache_system(void) boot_cpu_data.flags |= CPU_HAS_FPU | CPU_HAS_PERF_COUNTER | CPU_HAS_LLSC; break; - case 0x8000: - boot_cpu_data.type = CPU_ST40RA; - boot_cpu_data.flags |= CPU_HAS_FPU; - break; - case 0x8100: - boot_cpu_data.type = CPU_ST40GX1; - boot_cpu_data.flags |= CPU_HAS_FPU; - break; case 0x700: boot_cpu_data.type = CPU_SH4_501; boot_cpu_data.icache.ways = 2; diff --git a/arch/sh/kernel/irq.c b/arch/sh/kernel/irq.c index 348da19..0586bc6 100644 --- a/arch/sh/kernel/irq.c +++ b/arch/sh/kernel/irq.c @@ -11,7 +11,6 @@ #include <linux/module.h> #include <linux/kernel_stat.h> #include <linux/seq_file.h> -#include <linux/irq.h> #include <asm/processor.h> #include <asm/machvec.h> #include <asm/uaccess.h> diff --git a/arch/sh/kernel/kgdb_stub.c b/arch/sh/kernel/kgdb_stub.c index 2fdc700..d453c3a 100644 --- a/arch/sh/kernel/kgdb_stub.c +++ b/arch/sh/kernel/kgdb_stub.c @@ -102,6 +102,7 @@ #include <linux/init.h> #include <linux/console.h> #include <linux/sysrq.h> +#include <linux/module.h> #include <asm/system.h> #include <asm/cacheflush.h> #include <asm/current.h> @@ -116,7 +117,9 @@ kgdb_debug_hook_t *kgdb_debug_hook; kgdb_bus_error_hook_t *kgdb_bus_err_hook; int (*kgdb_getchar)(void); +EXPORT_SYMBOL_GPL(kgdb_getchar); void (*kgdb_putchar)(int); +EXPORT_SYMBOL_GPL(kgdb_putchar); static void put_debug_char(int c) { @@ -136,7 +139,7 @@ static int get_debug_char(void) #define NUMREGBYTES (MAXREG*4) #define OUTBUFMAX (NUMREGBYTES*2+512) -enum regs { +enum { R0 = 0, R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11, R12, R13, R14, R15, PC, PR, GBR, VBR, MACH, MACL, SR, @@ -176,9 +179,13 @@ int kgdb_nofault; /* Boolean to ignore bus errs (i.e. in GDB) */ /* SCI/UART settings, used in kgdb_console_setup() */ int kgdb_portnum = CONFIG_KGDB_DEFPORT; +EXPORT_SYMBOL_GPL(kgdb_portnum); int kgdb_baud = CONFIG_KGDB_DEFBAUD; +EXPORT_SYMBOL_GPL(kgdb_baud); char kgdb_parity = CONFIG_KGDB_DEFPARITY; +EXPORT_SYMBOL_GPL(kgdb_parity); char kgdb_bits = CONFIG_KGDB_DEFBITS; +EXPORT_SYMBOL_GPL(kgdb_bits); /* Jump buffer for setjmp/longjmp */ static jmp_buf rem_com_env; diff --git a/arch/sh/kernel/setup.c b/arch/sh/kernel/setup.c index 0b8c45d..4156aac 100644 --- a/arch/sh/kernel/setup.c +++ b/arch/sh/kernel/setup.c @@ -303,7 +303,6 @@ static const char *cpu_name[] = { [CPU_SH7750S] = "SH7750S", [CPU_SH7750R] = "SH7750R", [CPU_SH7751] = "SH7751", [CPU_SH7751R] = "SH7751R", [CPU_SH7760] = "SH7760", - [CPU_ST40RA] = "ST40RA", [CPU_ST40GX1] = "ST40GX1", [CPU_SH4_202] = "SH4-202", [CPU_SH4_501] = "SH4-501", [CPU_SH7770] = "SH7770", [CPU_SH7780] = "SH7780", [CPU_SH7781] = "SH7781", [CPU_SH7343] = "SH7343", diff --git a/arch/sh/kernel/sh_ksyms.c b/arch/sh/kernel/sh_ksyms.c index 548e428..e1a6de9 100644 --- a/arch/sh/kernel/sh_ksyms.c +++ b/arch/sh/kernel/sh_ksyms.c @@ -106,7 +106,6 @@ DECLARE_EXPORT(__movmem); DECLARE_EXPORT(__movstr); #endif -#ifdef CONFIG_CPU_SH4 #if __GNUC__ == 4 DECLARE_EXPORT(__movmem_i4_even); DECLARE_EXPORT(__movmem_i4_odd); @@ -126,7 +125,6 @@ DECLARE_EXPORT(__movstr_i4_even); DECLARE_EXPORT(__movstr_i4_odd); DECLARE_EXPORT(__movstrSI12_i4); #endif /* __GNUC__ == 4 */ -#endif #if !defined(CONFIG_CACHE_OFF) && (defined(CONFIG_CPU_SH4) || \ defined(CONFIG_SH7705_CACHE_32KB)) diff --git a/arch/sh/lib/Makefile b/arch/sh/lib/Makefile index e23dd1a..9dc7b69 100644 --- a/arch/sh/lib/Makefile +++ b/arch/sh/lib/Makefile @@ -9,3 +9,5 @@ memcpy-y := memcpy.o memcpy-$(CONFIG_CPU_SH4) := memcpy-sh4.o lib-y += $(memcpy-y) + +EXTRA_CFLAGS += -Werror diff --git a/arch/sh/mm/Kconfig b/arch/sh/mm/Kconfig index cf446bb..1265f20 100644 --- a/arch/sh/mm/Kconfig +++ b/arch/sh/mm/Kconfig @@ -17,7 +17,7 @@ config CPU_SH4 bool select CPU_HAS_INTEVT select CPU_HAS_SR_RB - select CPU_HAS_PTEA if (!CPU_SUBTYPE_ST40 && !CPU_SH4A) || CPU_SHX2 + select CPU_HAS_PTEA if !CPU_SH4A || CPU_SHX2 select CPU_HAS_FPU if !CPU_SH4AL_DSP config CPU_SH4A @@ -29,10 +29,6 @@ config CPU_SH4AL_DSP select CPU_SH4A select CPU_HAS_DSP -config CPU_SUBTYPE_ST40 - bool - select CPU_SH4 - config CPU_SHX2 bool @@ -152,21 +148,6 @@ config CPU_SUBTYPE_SH4_202 bool "Support SH4-202 processor" select CPU_SH4 -# ST40 Processor Support - -config CPU_SUBTYPE_ST40STB1 - bool "Support ST40STB1/ST40RA processors" - select CPU_SUBTYPE_ST40 - help - Select ST40STB1 if you have a ST40RA CPU. - This was previously called the ST40STB1, hence the option name. - -config CPU_SUBTYPE_ST40GX1 - bool "Support ST40GX1 processor" - select CPU_SUBTYPE_ST40 - help - Select ST40GX1 if you have a ST40GX1 CPU. - # SH-4A Processor Support config CPU_SUBTYPE_SH7770 diff --git a/arch/sh/mm/Makefile b/arch/sh/mm/Makefile index ee30fb4..aa44607 100644 --- a/arch/sh/mm/Makefile +++ b/arch/sh/mm/Makefile @@ -33,3 +33,5 @@ endif obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o obj-$(CONFIG_32BIT) += pmb.o obj-$(CONFIG_NUMA) += numa.o + +EXTRA_CFLAGS += -Werror diff --git a/arch/sh/mm/clear_page.S b/arch/sh/mm/clear_page.S index 8a70613..7a7c81e 100644 --- a/arch/sh/mm/clear_page.S +++ b/arch/sh/mm/clear_page.S @@ -150,48 +150,3 @@ ENTRY(__clear_user) .long 8b, .Lbad_clear_user .long 9b, .Lbad_clear_user .previous - -#if defined(CONFIG_CPU_SH4) -/* - * __clear_user_page - * @to: P3 address (with same color) - * @orig_to: P1 address - * - * void __clear_user_page(void *to, void *orig_to) - */ - -/* - * r0 --- scratch - * r4 --- to - * r5 --- orig_to - * r6 --- to + PAGE_SIZE - */ -ENTRY(__clear_user_page) - mov.l .Lpsz,r0 - mov r4,r6 - add r0,r6 - mov #0,r0 - ! -1: ocbi @r5 - add #32,r5 - movca.l r0,@r4 - mov r4,r1 - add #32,r4 - mov.l r0,@-r4 - mov.l r0,@-r4 - mov.l r0,@-r4 - mov.l r0,@-r4 - mov.l r0,@-r4 - mov.l r0,@-r4 - mov.l r0,@-r4 - add #28,r4 - cmp/eq r6,r4 - bf/s 1b - ocbwb @r1 - ! - rts - nop -.Lpsz: .long PAGE_SIZE - -#endif - diff --git a/arch/sh/mm/copy_page.S b/arch/sh/mm/copy_page.S index 3d8409d..4068501 100644 --- a/arch/sh/mm/copy_page.S +++ b/arch/sh/mm/copy_page.S @@ -68,67 +68,6 @@ ENTRY(copy_page_slow) rts nop -#if defined(CONFIG_CPU_SH4) -/* - * __copy_user_page - * @to: P1 address (with same color) - * @from: P1 address - * @orig_to: P1 address - * - * void __copy_user_page(void *to, void *from, void *orig_to) - */ - -/* - * r0, r1, r2, r3, r4, r5, r6, r7 --- scratch - * r8 --- from + PAGE_SIZE - * r9 --- orig_to - * r10 --- to - * r11 --- from - */ -ENTRY(__copy_user_page) - mov.l r8,@-r15 - mov.l r9,@-r15 - mov.l r10,@-r15 - mov.l r11,@-r15 - mov r4,r10 - mov r5,r11 - mov r6,r9 - mov r5,r8 - mov.l .Lpsz,r0 - add r0,r8 - ! -1: ocbi @r9 - add #32,r9 - mov.l @r11+,r0 - mov.l @r11+,r1 - mov.l @r11+,r2 - mov.l @r11+,r3 - mov.l @r11+,r4 - mov.l @r11+,r5 - mov.l @r11+,r6 - mov.l @r11+,r7 - movca.l r0,@r10 - mov r10,r0 - add #32,r10 - mov.l r7,@-r10 - mov.l r6,@-r10 - mov.l r5,@-r10 - mov.l r4,@-r10 - mov.l r3,@-r10 - mov.l r2,@-r10 - mov.l r1,@-r10 - ocbwb @r0 - cmp/eq r11,r8 - bf/s 1b - add #28,r10 - ! - mov.l @r15+,r11 - mov.l @r15+,r10 - mov.l @r15+,r9 - mov.l @r15+,r8 - rts - nop -#endif .align 2 .Lpsz: .long PAGE_SIZE /* diff --git a/arch/sh/mm/fault.c b/arch/sh/mm/fault.c index f33cedb..60d74f7 100644 --- a/arch/sh/mm/fault.c +++ b/arch/sh/mm/fault.c @@ -258,9 +258,6 @@ asmlinkage int __kprobes __do_page_fault(struct pt_regs *regs, pmd_t *pmd; pte_t *pte; pte_t entry; - struct mm_struct *mm = current->mm; - spinlock_t *ptl = NULL; - int ret = 1; #ifdef CONFIG_SH_KGDB if (kgdb_nofault && kgdb_bus_err_hook) @@ -274,12 +271,11 @@ asmlinkage int __kprobes __do_page_fault(struct pt_regs *regs, */ if (address >= P3SEG && address < P3_ADDR_MAX) { pgd = pgd_offset_k(address); - mm = NULL; } else { - if (unlikely(address >= TASK_SIZE || !mm)) + if (unlikely(address >= TASK_SIZE || !current->mm)) return 1; - pgd = pgd_offset(mm, address); + pgd = pgd_offset(current->mm, address); } pud = pud_offset(pgd, address); @@ -289,34 +285,19 @@ asmlinkage int __kprobes __do_page_fault(struct pt_regs *regs, if (pmd_none_or_clear_bad(pmd)) return 1; - if (mm) - pte = pte_offset_map_lock(mm, pmd, address, &ptl); - else - pte = pte_offset_kernel(pmd, address); - + pte = pte_offset_kernel(pmd, address); entry = *pte; if (unlikely(pte_none(entry) || pte_not_present(entry))) - goto unlock; + return 1; if (unlikely(writeaccess && !pte_write(entry))) - goto unlock; + return 1; if (writeaccess) entry = pte_mkdirty(entry); entry = pte_mkyoung(entry); -#ifdef CONFIG_CPU_SH4 - /* - * ITLB is not affected by "ldtlb" instruction. - * So, we need to flush the entry by ourselves. - */ - local_flush_tlb_one(get_asid(), address & PAGE_MASK); -#endif - set_pte(pte, entry); update_mmu_cache(NULL, address, entry); - ret = 0; -unlock: - if (mm) - pte_unmap_unlock(pte, ptl); - return ret; + + return 0; } diff --git a/arch/sh/mm/pg-sh4.c b/arch/sh/mm/pg-sh4.c index 25f5c6f..8c7a9ca 100644 --- a/arch/sh/mm/pg-sh4.c +++ b/arch/sh/mm/pg-sh4.c @@ -9,6 +9,8 @@ #include <linux/mm.h> #include <linux/mutex.h> #include <linux/fs.h> +#include <linux/highmem.h> +#include <linux/module.h> #include <asm/mmu_context.h> #include <asm/cacheflush.h> @@ -50,34 +52,61 @@ static inline void kunmap_coherent(struct page *page) void clear_user_page(void *to, unsigned long address, struct page *page) { __set_bit(PG_mapped, &page->flags); - if (((address ^ (unsigned long)to) & CACHE_ALIAS) == 0) - clear_page(to); - else { - void *vto = kmap_coherent(page, address); - __clear_user_page(vto, to); - kunmap_coherent(vto); - } + + clear_page(to); + if ((((address & PAGE_MASK) ^ (unsigned long)to) & CACHE_ALIAS)) + __flush_wback_region(to, PAGE_SIZE); } -/* - * copy_user_page - * @to: P1 address - * @from: P1 address - * @address: U0 address to be mapped - * @page: page (virt_to_page(to)) - */ -void copy_user_page(void *to, void *from, unsigned long address, - struct page *page) +void copy_to_user_page(struct vm_area_struct *vma, struct page *page, + unsigned long vaddr, void *dst, const void *src, + unsigned long len) { + void *vto; + __set_bit(PG_mapped, &page->flags); - if (((address ^ (unsigned long)to) & CACHE_ALIAS) == 0) - copy_page(to, from); - else { - void *vfrom = kmap_coherent(page, address); - __copy_user_page(vfrom, from, to); - kunmap_coherent(vfrom); - } + + vto = kmap_coherent(page, vaddr) + (vaddr & ~PAGE_MASK); + memcpy(vto, src, len); + kunmap_coherent(vto); + + if (vma->vm_flags & VM_EXEC) + flush_cache_page(vma, vaddr, page_to_pfn(page)); +} + +void copy_from_user_page(struct vm_area_struct *vma, struct page *page, + unsigned long vaddr, void *dst, const void *src, + unsigned long len) +{ + void *vfrom; + + __set_bit(PG_mapped, &page->flags); + + vfrom = kmap_coherent(page, vaddr) + (vaddr & ~PAGE_MASK); + memcpy(dst, vfrom, len); + kunmap_coherent(vfrom); +} + +void copy_user_highpage(struct page *to, struct page *from, + unsigned long vaddr, struct vm_area_struct *vma) +{ + void *vfrom, *vto; + + __set_bit(PG_mapped, &to->flags); + + vto = kmap_atomic(to, KM_USER1); + vfrom = kmap_coherent(from, vaddr); + copy_page(vto, vfrom); + kunmap_coherent(vfrom); + + if (((vaddr ^ (unsigned long)vto) & CACHE_ALIAS)) + __flush_wback_region(vto, PAGE_SIZE); + + kunmap_atomic(vto, KM_USER1); + /* Make sure this page is cleared on other CPU's too before using it */ + smp_wmb(); } +EXPORT_SYMBOL(copy_user_highpage); /* * For SH-4, we have our own implementation for ptep_get_and_clear diff --git a/arch/sh/oprofile/Makefile b/arch/sh/oprofile/Makefile index 1f25d9b..2efc2e7 100644 --- a/arch/sh/oprofile/Makefile +++ b/arch/sh/oprofile/Makefile @@ -15,3 +15,4 @@ profdrvr-$(CONFIG_CPU_SUBTYPE_SH7091) := op_model_sh7750.o oprofile-y := $(DRIVER_OBJS) $(profdrvr-y) +EXTRA_CFLAGS += -Werror diff --git a/arch/sh64/kernel/process.c b/arch/sh64/kernel/process.c index ceb9458..0761af4 100644 --- a/arch/sh64/kernel/process.c +++ b/arch/sh64/kernel/process.c @@ -26,6 +26,7 @@ #include <linux/reboot.h> #include <linux/init.h> #include <linux/module.h> +#include <linux/proc_fs.h> #include <asm/uaccess.h> #include <asm/pgtable.h> @@ -656,9 +657,6 @@ unsigned long get_wchan(struct task_struct *p) */ #if defined(CONFIG_SH64_PROC_ASIDS) -#include <linux/init.h> -#include <linux/proc_fs.h> - static int asids_proc_info(char *buf, char **start, off_t fpos, int length, int *eof, void *data) { @@ -686,10 +684,8 @@ asids_proc_info(char *buf, char **start, off_t fpos, int length, int *eof, void static int __init register_proc_asids(void) { - create_proc_read_entry("asids", 0, NULL, asids_proc_info, NULL); - return 0; + create_proc_read_entry("asids", 0, NULL, asids_proc_info, NULL); + return 0; } - __initcall(register_proc_asids); #endif - diff --git a/arch/sh64/kernel/traps.c b/arch/sh64/kernel/traps.c index c03101f..f32df38 100644 --- a/arch/sh64/kernel/traps.c +++ b/arch/sh64/kernel/traps.c @@ -30,7 +30,6 @@ #include <linux/interrupt.h> #include <linux/sysctl.h> #include <linux/module.h> - #include <asm/system.h> #include <asm/uaccess.h> #include <asm/io.h> @@ -242,9 +241,6 @@ DO_ERROR(12, SIGILL, "reserved instruction", reserved_inst, current) #endif /* CONFIG_SH64_ID2815_WORKAROUND */ - -#include <asm/system.h> - /* Called with interrupts disabled */ asmlinkage void do_exception_error(unsigned long ex, struct pt_regs *regs) { @@ -984,4 +980,3 @@ asmlinkage void do_debug_interrupt(unsigned long code, struct pt_regs *regs) /* Clear all DEBUGINT causes */ poke_real_address_q(DM_EXP_CAUSE_PHY, 0x0); } - diff --git a/arch/sparc/kernel/irq.c b/arch/sparc/kernel/irq.c index e1e24f3..01a6756 100644 --- a/arch/sparc/kernel/irq.c +++ b/arch/sparc/kernel/irq.c @@ -18,7 +18,6 @@ #include <linux/linkage.h> #include <linux/kernel_stat.h> #include <linux/signal.h> -#include <linux/sched.h> #include <linux/interrupt.h> #include <linux/slab.h> #include <linux/random.h> diff --git a/arch/sparc64/kernel/ds.c b/arch/sparc64/kernel/ds.c index 9f472a7..eeb5a2f 100644 --- a/arch/sparc64/kernel/ds.c +++ b/arch/sparc64/kernel/ds.c @@ -6,7 +6,6 @@ #include <linux/kernel.h> #include <linux/module.h> #include <linux/types.h> -#include <linux/module.h> #include <linux/string.h> #include <linux/slab.h> #include <linux/sched.h> diff --git a/arch/sparc64/kernel/module.c b/arch/sparc64/kernel/module.c index 5798715..158484b 100644 --- a/arch/sparc64/kernel/module.c +++ b/arch/sparc64/kernel/module.c @@ -11,7 +11,6 @@ #include <linux/fs.h> #include <linux/string.h> #include <linux/slab.h> -#include <linux/vmalloc.h> #include <linux/mm.h> #include <asm/processor.h> diff --git a/arch/sparc64/kernel/sys_sparc32.c b/arch/sparc64/kernel/sys_sparc32.c index 78caff9..98c4688 100644 --- a/arch/sparc64/kernel/sys_sparc32.c +++ b/arch/sparc64/kernel/sys_sparc32.c @@ -51,7 +51,6 @@ #include <linux/vfs.h> #include <linux/netfilter_ipv4/ip_tables.h> #include <linux/ptrace.h> -#include <linux/highuid.h> #include <asm/types.h> #include <asm/uaccess.h> diff --git a/arch/sparc64/kernel/sys_sunos32.c b/arch/sparc64/kernel/sys_sunos32.c index 170d6ca..cfc22d3 100644 --- a/arch/sparc64/kernel/sys_sunos32.c +++ b/arch/sparc64/kernel/sys_sunos32.c @@ -57,7 +57,6 @@ #include <linux/personality.h> /* For SOCKET_I */ -#include <linux/socket.h> #include <net/sock.h> #include <net/compat.h> diff --git a/arch/sparc64/kernel/time.c b/arch/sparc64/kernel/time.c index a2cf955..4352ee4 100644 --- a/arch/sparc64/kernel/time.c +++ b/arch/sparc64/kernel/time.c @@ -28,7 +28,6 @@ #include <linux/jiffies.h> #include <linux/cpufreq.h> #include <linux/percpu.h> -#include <linux/profile.h> #include <linux/miscdevice.h> #include <linux/rtc.h> #include <linux/kernel_stat.h> @@ -47,7 +46,6 @@ #include <asm/sections.h> #include <asm/cpudata.h> #include <asm/uaccess.h> -#include <asm/prom.h> #include <asm/irq_regs.h> DEFINE_SPINLOCK(mostek_lock); diff --git a/arch/um/Kconfig.i386 b/arch/um/Kconfig.i386 index e0ac74e..717f5d3 100644 --- a/arch/um/Kconfig.i386 +++ b/arch/um/Kconfig.i386 @@ -8,6 +8,13 @@ config UML_X86 bool default y +config X86_32 + bool + default y + +config RWSEM_XCHGADD_ALGORITHM + def_bool y + config 64BIT bool default n diff --git a/arch/um/Makefile b/arch/um/Makefile index 768a5d1..ba6813a 100644 --- a/arch/um/Makefile +++ b/arch/um/Makefile @@ -168,7 +168,7 @@ ifneq ($(KBUILD_SRC),) $(Q)mkdir -p $(objtree)/include/asm-um $(Q)ln -fsn $(srctree)/include/asm-$(HEADER_ARCH) include/asm-um/arch else - $(Q)cd $(TOPDIR)/include/asm-um && ln -sf ../asm-$(HEADER_ARCH) arch + $(Q)cd $(TOPDIR)/include/asm-um && ln -fsn ../asm-$(HEADER_ARCH) arch endif $(objtree)/$(ARCH_DIR)/include: @@ -180,7 +180,7 @@ $(ARCH_DIR)/include/sysdep: $(objtree)/$(ARCH_DIR)/include ifneq ($(KBUILD_SRC),) $(Q)ln -fsn $(srctree)/$(ARCH_DIR)/include/sysdep-$(SUBARCH) $(ARCH_DIR)/include/sysdep else - $(Q)cd $(ARCH_DIR)/include && ln -sf sysdep-$(SUBARCH) sysdep + $(Q)cd $(ARCH_DIR)/include && ln -fsn sysdep-$(SUBARCH) sysdep endif $(ARCH_DIR)/os: @@ -188,7 +188,7 @@ $(ARCH_DIR)/os: ifneq ($(KBUILD_SRC),) $(Q)ln -fsn $(srctree)/$(ARCH_DIR)/os-$(OS) $(ARCH_DIR)/os else - $(Q)cd $(ARCH_DIR) && ln -sf os-$(OS) os + $(Q)cd $(ARCH_DIR) && ln -fsn os-$(OS) os endif # Generated files diff --git a/arch/um/drivers/chan_user.c b/arch/um/drivers/chan_user.c index b88e93b..0257640 100644 --- a/arch/um/drivers/chan_user.c +++ b/arch/um/drivers/chan_user.c @@ -74,10 +74,16 @@ void generic_free(void *data) int generic_console_write(int fd, const char *buf, int n) { + sigset_t old, no_sigio; struct termios save, new; int err; if (isatty(fd)) { + sigemptyset(&no_sigio); + sigaddset(&no_sigio, SIGIO); + if (sigprocmask(SIG_BLOCK, &no_sigio, &old)) + goto error; + CATCH_EINTR(err = tcgetattr(fd, &save)); if (err) goto error; @@ -97,8 +103,11 @@ int generic_console_write(int fd, const char *buf, int n) * Restore raw mode, in any case; we *must* ignore any error apart * EINTR, except for debug. */ - if (isatty(fd)) + if (isatty(fd)) { CATCH_EINTR(tcsetattr(fd, TCSAFLUSH, &save)); + sigprocmask(SIG_SETMASK, &old, NULL); + } + return err; error: return -errno; diff --git a/arch/um/drivers/net_kern.c b/arch/um/drivers/net_kern.c index 8c01fa8..73681f1 100644 --- a/arch/um/drivers/net_kern.c +++ b/arch/um/drivers/net_kern.c @@ -753,6 +753,7 @@ static struct mc_device net_mc = { .remove = net_remove, }; +#ifdef CONFIG_INET static int uml_inetaddr_event(struct notifier_block *this, unsigned long event, void *ptr) { @@ -789,14 +790,13 @@ struct notifier_block uml_inetaddr_notifier = { .notifier_call = uml_inetaddr_event, }; -static int uml_net_init(void) +static void inet_register(void) { struct list_head *ele; struct uml_net_private *lp; struct in_device *ip; struct in_ifaddr *in; - mconsole_register_dev(&net_mc); register_inetaddr_notifier(¨_inetaddr_notifier); /* Devices may have been opened already, so the uml_inetaddr_notifier @@ -816,7 +816,17 @@ static int uml_net_init(void) } } spin_unlock(&opened_lock); +} +#else +static inline void inet_register(void) +{ +} +#endif +static int uml_net_init(void) +{ + mconsole_register_dev(&net_mc); + inet_register(); return 0; } diff --git a/arch/um/drivers/ubd_kern.c b/arch/um/drivers/ubd_kern.c index 7e6cdde..b1a77b1 100644 --- a/arch/um/drivers/ubd_kern.c +++ b/arch/um/drivers/ubd_kern.c @@ -1128,6 +1128,7 @@ static void do_ubd_request(struct request_queue *q) "errno = %d\n", -n); else if(list_empty(&dev->restart)) list_add(&dev->restart, &restart); + kfree(io_req); return; } diff --git a/arch/um/include/user.h b/arch/um/include/user.h index 99033ff..1723fac 100644 --- a/arch/um/include/user.h +++ b/arch/um/include/user.h @@ -1,11 +1,13 @@ /* - * Copyright (C) 2000 Jeff Dike (jdike@karaya.com) + * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) * Licensed under the GPL */ #ifndef __USER_H__ #define __USER_H__ +#include "uml-config.h" + /* * The usual definition - copied here because the kernel provides its own, * fancier, type-safe, definition. Using that one would require @@ -23,8 +25,17 @@ extern void panic(const char *fmt, ...) __attribute__ ((format (printf, 1, 2))); + +#ifdef UML_CONFIG_PRINTK extern int printk(const char *fmt, ...) __attribute__ ((format (printf, 1, 2))); +#else +static inline int printk(const char *fmt, ...) +{ + return 0; +} +#endif + extern void schedule(void); extern int in_aton(char *str); extern int open_gdb_chan(void); diff --git a/arch/um/kernel/irq.c b/arch/um/kernel/irq.c index 70c2d62..ba11ccd 100644 --- a/arch/um/kernel/irq.c +++ b/arch/um/kernel/irq.c @@ -347,14 +347,15 @@ int um_request_irq(unsigned int irq, int fd, int type, { int err; - err = request_irq(irq, handler, irqflags, devname, dev_id); - if (err) - return err; - - if (fd != -1) + if (fd != -1) { err = activate_fd(irq, fd, type, dev_id); - return err; + if (err) + return err; + } + + return request_irq(irq, handler, irqflags, devname, dev_id); } + EXPORT_SYMBOL(um_request_irq); EXPORT_SYMBOL(reactivate_fd); diff --git a/arch/um/kernel/skas/clone.c b/arch/um/kernel/skas/clone.c index d119f4f..8d07a7a 100644 --- a/arch/um/kernel/skas/clone.c +++ b/arch/um/kernel/skas/clone.c @@ -3,7 +3,6 @@ #include <sys/mman.h> #include <sys/time.h> #include <asm/unistd.h> -#include <asm/page.h> #include "as-layout.h" #include "ptrace_user.h" #include "skas.h" diff --git a/arch/um/os-Linux/file.c b/arch/um/os-Linux/file.c index b542a3a..f834627 100644 --- a/arch/um/os-Linux/file.c +++ b/arch/um/os-Linux/file.c @@ -496,8 +496,7 @@ int os_rcv_fd(int fd, int *helper_pid_out) n = recvmsg(fd, &msg, 0); if(n < 0) return -errno; - - else if(n != sizeof(iov.iov_len)) + else if(n != iov.iov_len) *helper_pid_out = -1; cmsg = CMSG_FIRSTHDR(&msg); diff --git a/arch/um/os-Linux/time.c b/arch/um/os-Linux/time.c index e34e1ef..e492805 100644 --- a/arch/um/os-Linux/time.c +++ b/arch/um/os-Linux/time.c @@ -59,7 +59,7 @@ long long disable_timer(void) { struct itimerval time = ((struct itimerval) { { 0, 0 }, { 0, 0 } }); - if(setitimer(ITIMER_VIRTUAL, &time, &time) < 0) + if (setitimer(ITIMER_VIRTUAL, &time, &time) < 0) printk(UM_KERN_ERR "disable_timer - setitimer failed, " "errno = %d\n", errno); @@ -74,13 +74,62 @@ long long os_nsecs(void) return timeval_to_ns(&tv); } +#ifdef UML_CONFIG_NO_HZ +static int after_sleep_interval(struct timespec *ts) +{ + return 0; +} +#else +static inline long long timespec_to_us(const struct timespec *ts) +{ + return ((long long) ts->tv_sec * UM_USEC_PER_SEC) + + ts->tv_nsec / UM_NSEC_PER_USEC; +} + +static int after_sleep_interval(struct timespec *ts) +{ + int usec = UM_USEC_PER_SEC / UM_HZ; + long long start_usecs = timespec_to_us(ts); + struct timeval tv; + struct itimerval interval; + + /* + * It seems that rounding can increase the value returned from + * setitimer to larger than the one passed in. Over time, + * this will cause the remaining time to be greater than the + * tick interval. If this happens, then just reduce the first + * tick to the interval value. + */ + if (start_usecs > usec) + start_usecs = usec; + tv = ((struct timeval) { .tv_sec = start_usecs / UM_USEC_PER_SEC, + .tv_usec = start_usecs % UM_USEC_PER_SEC }); + interval = ((struct itimerval) { { 0, usec }, tv }); + + if (setitimer(ITIMER_VIRTUAL, &interval, NULL) == -1) + return -errno; + + return 0; +} +#endif + extern void alarm_handler(int sig, struct sigcontext *sc); void idle_sleep(unsigned long long nsecs) { - struct timespec ts = { .tv_sec = nsecs / UM_NSEC_PER_SEC, - .tv_nsec = nsecs % UM_NSEC_PER_SEC }; + struct timespec ts; + + /* + * nsecs can come in as zero, in which case, this starts a + * busy loop. To prevent this, reset nsecs to the tick + * interval if it is zero. + */ + if (nsecs == 0) + nsecs = UM_NSEC_PER_SEC / UM_HZ; + ts = ((struct timespec) { .tv_sec = nsecs / UM_NSEC_PER_SEC, + .tv_nsec = nsecs % UM_NSEC_PER_SEC }); if (nanosleep(&ts, &ts) == 0) alarm_handler(SIGVTALRM, NULL); + after_sleep_interval(&ts); } diff --git a/arch/x86/Kconfig.i386 b/arch/x86/Kconfig index 7331efe..368864d 100644 --- a/arch/x86/Kconfig.i386 +++ b/arch/x86/Kconfig @@ -1,18 +1,24 @@ -# -# For a description of the syntax of this configuration file, -# see Documentation/kbuild/kconfig-language.txt. -# +# x86 configuration +mainmenu "Linux Kernel Configuration for x86" -mainmenu "Linux Kernel Configuration" +# Select 32 or 64 bit +config 64BIT + bool "64-bit kernel" if ARCH = "x86" + default ARCH = "x86_64" + help + Say yes to build a 64-bit kernel - formerly known as x86_64 + Say no to build a 32-bit kernel - formerly known as i386 config X86_32 + def_bool !64BIT + +config X86_64 + def_bool 64BIT + +### Arch settings +config X86 bool default y - help - This is Linux's home port. Linux was originally native to the Intel - 386, and runs on all the later x86 processors including the Intel - 486, 586, Pentiums, and various instruction-set-compatible chips by - AMD, Cyrix, and others. config GENERIC_TIME bool @@ -33,7 +39,7 @@ config GENERIC_CLOCKEVENTS config GENERIC_CLOCKEVENTS_BROADCAST bool default y - depends on X86_LOCAL_APIC + depends on X86_64 || (X86_32 && X86_LOCAL_APIC) config LOCKDEP_SUPPORT bool @@ -47,10 +53,6 @@ config SEMAPHORE_SLEEPERS bool default y -config X86 - bool - default y - config MMU bool default y @@ -61,7 +63,7 @@ config ZONE_DMA config QUICKLIST bool - default y + default X86_32 config SBUS bool @@ -91,6 +93,76 @@ config DMI bool default y +config RWSEM_GENERIC_SPINLOCK + def_bool !X86_XADD + +config RWSEM_XCHGADD_ALGORITHM + def_bool X86_XADD + +config ARCH_HAS_ILOG2_U32 + def_bool n + +config ARCH_HAS_ILOG2_U64 + def_bool n + +config GENERIC_CALIBRATE_DELAY + def_bool y + +config GENERIC_TIME_VSYSCALL + bool + default X86_64 + + + + + +config ZONE_DMA32 + bool + default X86_64 + +config ARCH_POPULATES_NODE_MAP + def_bool y + +config AUDIT_ARCH + bool + default X86_64 + +# Use the generic interrupt handling code in kernel/irq/: +config GENERIC_HARDIRQS + bool + default y + +config GENERIC_IRQ_PROBE + bool + default y + +config GENERIC_PENDING_IRQ + bool + depends on GENERIC_HARDIRQS && SMP + default y + +config X86_SMP + bool + depends on X86_32 && SMP && !X86_VOYAGER + default y + +config X86_HT + bool + depends on SMP && !(X86_VISWS || X86_VOYAGER || MK8) + default y + +config X86_BIOS_REBOOT + bool + depends on X86_32 && !(X86_VISWS || X86_VOYAGER) + default y + +config X86_TRAMPOLINE + bool + depends on X86_SMP || (X86_VOYAGER && SMP) + default y + +config KTIME_SCALAR + def_bool X86_32 source "init/Kconfig" menu "Processor type and features" @@ -137,6 +209,7 @@ config X86_PC config X86_ELAN bool "AMD Elan" + depends on X86_32 help Select this for an AMD Elan processor. @@ -146,6 +219,7 @@ config X86_ELAN config X86_VOYAGER bool "Voyager (NCR)" + depends on X86_32 select SMP if !BROKEN help Voyager is an MCA-based 32-way capable SMP architecture proprietary @@ -160,6 +234,7 @@ config X86_NUMAQ bool "NUMAQ (IBM/Sequent)" select SMP select NUMA + depends on X86_32 help This option is used for getting Linux to run on a (IBM/Sequent) NUMA multiquad box. This changes the way that processors are bootstrapped, @@ -169,7 +244,7 @@ config X86_NUMAQ config X86_SUMMIT bool "Summit/EXA (IBM x440)" - depends on SMP + depends on X86_32 && SMP help This option is needed for IBM systems that use the Summit/EXA chipset. In particular, it is needed for the x440. @@ -179,7 +254,7 @@ config X86_SUMMIT config X86_BIGSMP bool "Support for other sub-arch SMP systems with more than 8 CPUs" - depends on SMP + depends on X86_32 && SMP help This option is needed for the systems that have more than 8 CPUs and if the system is not of any sub-arch type above. @@ -188,6 +263,7 @@ config X86_BIGSMP config X86_VISWS bool "SGI 320/540 (Visual Workstation)" + depends on X86_32 help The SGI Visual Workstation series is an IA32-based workstation based on SGI systems chips with some legacy PC hardware attached. @@ -199,6 +275,7 @@ config X86_VISWS config X86_GENERICARCH bool "Generic architecture (Summit, bigsmp, ES7000, default)" + depends on X86_32 help This option compiles in the Summit, bigsmp, ES7000, default subarchitectures. It is intended for a generic binary kernel. @@ -206,18 +283,27 @@ config X86_GENERICARCH config X86_ES7000 bool "Support for Unisys ES7000 IA32 series" - depends on SMP + depends on X86_32 && SMP help Support for Unisys ES7000 systems. Say 'Y' here if this kernel is supposed to run on an IA32-based Unisys ES7000 system. Only choose this option if you have such a system, otherwise you should say N here. +config X86_VSMP + bool "Support for ScaleMP vSMP" + depends on X86_64 && PCI + help + Support for ScaleMP vSMP systems. Say 'Y' here if this kernel is + supposed to run on these EM64T-based machines. Only choose this option + if you have one of these machines. + endchoice config SCHED_NO_NO_OMIT_FRAME_POINTER bool "Single-depth WCHAN output" default y + depends on X86_32 help Calculate simpler /proc/<PID>/wchan values. If this option is disabled then wchan values will recurse back to the @@ -228,7 +314,7 @@ config SCHED_NO_NO_OMIT_FRAME_POINTER config PARAVIRT bool - depends on !(X86_VISWS || X86_VOYAGER) + depends on X86_32 && !(X86_VISWS || X86_VOYAGER) help This changes the kernel so it can modify itself when it is run under a hypervisor, potentially improving performance significantly @@ -237,6 +323,7 @@ config PARAVIRT menuconfig PARAVIRT_GUEST bool "Paravirtualized guest support" + depends on X86_32 help Say Y here to get to see options related to running Linux under various hypervisors. This option alone does not add any kernel code. @@ -264,7 +351,7 @@ endif config ACPI_SRAT bool default y - depends on ACPI && NUMA && (X86_SUMMIT || X86_GENERICARCH) + depends on X86_32 && ACPI && NUMA && (X86_SUMMIT || X86_GENERICARCH) select ACPI_NUMA config HAVE_ARCH_PARSE_SRAT @@ -275,12 +362,12 @@ config HAVE_ARCH_PARSE_SRAT config X86_SUMMIT_NUMA bool default y - depends on NUMA && (X86_SUMMIT || X86_GENERICARCH) + depends on X86_32 && NUMA && (X86_SUMMIT || X86_GENERICARCH) config X86_CYCLONE_TIMER bool default y - depends on X86_SUMMIT || X86_GENERICARCH + depends on X86_32 && X86_SUMMIT || X86_GENERICARCH config ES7000_CLUSTERED_APIC bool @@ -290,21 +377,89 @@ config ES7000_CLUSTERED_APIC source "arch/x86/Kconfig.cpu" config HPET_TIMER - bool "HPET Timer Support" + bool + prompt "HPET Timer Support" if X86_32 + default X86_64 help - This enables the use of the HPET for the kernel's internal timer. - HPET is the next generation timer replacing legacy 8254s. - You can safely choose Y here. However, HPET will only be - activated if the platform and the BIOS support this feature. - Otherwise the 8254 will be used for timing services. + Use the IA-PC HPET (High Precision Event Timer) to manage + time in preference to the PIT and RTC, if a HPET is + present. + HPET is the next generation timer replacing legacy 8254s. + The HPET provides a stable time base on SMP + systems, unlike the TSC, but it is more expensive to access, + as it is off-chip. You can find the HPET spec at + <http://www.intel.com/hardwaredesign/hpetspec.htm>. + + You can safely choose Y here. However, HPET will only be + activated if the platform and the BIOS support this feature. + Otherwise the 8254 will be used for timing services. - Choose N to continue using the legacy 8254 timer. + Choose N to continue using the legacy 8254 timer. config HPET_EMULATE_RTC bool depends on HPET_TIMER && RTC=y default y +# Mark as embedded because too many people got it wrong. +# The code disables itself when not needed. +config GART_IOMMU + bool "GART IOMMU support" if EMBEDDED + default y + select SWIOTLB + select AGP + depends on X86_64 && PCI + help + Support for full DMA access of devices with 32bit memory access only + on systems with more than 3GB. This is usually needed for USB, + sound, many IDE/SATA chipsets and some other devices. + Provides a driver for the AMD Athlon64/Opteron/Turion/Sempron GART + based hardware IOMMU and a software bounce buffer based IOMMU used + on Intel systems and as fallback. + The code is only active when needed (enough memory and limited + device) unless CONFIG_IOMMU_DEBUG or iommu=force is specified + too. + +config CALGARY_IOMMU + bool "IBM Calgary IOMMU support" + select SWIOTLB + depends on X86_64 && PCI && EXPERIMENTAL + help + Support for hardware IOMMUs in IBM's xSeries x366 and x460 + systems. Needed to run systems with more than 3GB of memory + properly with 32-bit PCI devices that do not support DAC + (Double Address Cycle). Calgary also supports bus level + isolation, where all DMAs pass through the IOMMU. This + prevents them from going anywhere except their intended + destination. This catches hard-to-find kernel bugs and + mis-behaving drivers and devices that do not use the DMA-API + properly to set up their DMA buffers. The IOMMU can be + turned off at boot time with the iommu=off parameter. + Normally the kernel will make the right choice by itself. + If unsure, say Y. + +config CALGARY_IOMMU_ENABLED_BY_DEFAULT + bool "Should Calgary be enabled by default?" + default y + depends on CALGARY_IOMMU + help + Should Calgary be enabled by default? if you choose 'y', Calgary + will be used (if it exists). If you choose 'n', Calgary will not be + used even if it exists. If you choose 'n' and would like to use + Calgary anyway, pass 'iommu=calgary' on the kernel command line. + If unsure, say Y. + +# need this always selected by IOMMU for the VIA workaround +config SWIOTLB + bool + help + Support for software bounce buffers used on x86-64 systems + which don't have a hardware IOMMU (e.g. the current generation + of Intel's x86-64 CPUs). Using this PCI devices which can only + access 32-bits of memory can be used on systems with more than + 3 GB of memory. If unsure, say Y. + + config NR_CPUS int "Maximum number of CPUs (2-255)" range 2 255 @@ -321,7 +476,7 @@ config NR_CPUS config SCHED_SMT bool "SMT (Hyperthreading) scheduler support" - depends on X86_HT + depends on (X86_64 && SMP) || (X86_32 && X86_HT) help SMT scheduler support improves the CPU scheduler's decision making when dealing with Intel Pentium 4 chips with HyperThreading at a @@ -330,7 +485,7 @@ config SCHED_SMT config SCHED_MC bool "Multi-core scheduler support" - depends on X86_HT + depends on (X86_64 && SMP) || (X86_32 && X86_HT) default y help Multi-core scheduler support improves the CPU scheduler's decision @@ -341,7 +496,7 @@ source "kernel/Kconfig.preempt" config X86_UP_APIC bool "Local APIC support on uniprocessors" - depends on !SMP && !(X86_VISWS || X86_VOYAGER || X86_GENERICARCH) + depends on X86_32 && !SMP && !(X86_VISWS || X86_VOYAGER || X86_GENERICARCH) help A local APIC (Advanced Programmable Interrupt Controller) is an integrated interrupt controller in the CPU. If you have a single-CPU @@ -366,17 +521,17 @@ config X86_UP_IOAPIC config X86_LOCAL_APIC bool - depends on X86_UP_APIC || ((X86_VISWS || SMP) && !X86_VOYAGER) || X86_GENERICARCH + depends on X86_64 || (X86_32 && (X86_UP_APIC || ((X86_VISWS || SMP) && !X86_VOYAGER) || X86_GENERICARCH)) default y config X86_IO_APIC bool - depends on X86_UP_IOAPIC || (SMP && !(X86_VISWS || X86_VOYAGER)) || X86_GENERICARCH + depends on X86_64 || (X86_32 && (X86_UP_IOAPIC || (SMP && !(X86_VISWS || X86_VOYAGER)) || X86_GENERICARCH)) default y config X86_VISWS_APIC bool - depends on X86_VISWS + depends on X86_32 && X86_VISWS default y config X86_MCE @@ -396,9 +551,25 @@ config X86_MCE to disable it. MCE support simply ignores non-MCE processors like the 386 and 486, so nearly everyone can say Y here. +config X86_MCE_INTEL + bool "Intel MCE features" + depends on X86_64 && X86_MCE && X86_LOCAL_APIC + default y + help + Additional support for intel specific MCE features such as + the thermal monitor. + +config X86_MCE_AMD + bool "AMD MCE features" + depends on X86_64 && X86_MCE && X86_LOCAL_APIC + default y + help + Additional support for AMD specific MCE features such as + the DRAM Error Threshold. + config X86_MCE_NONFATAL tristate "Check for non-fatal errors on AMD Athlon/Duron / Intel Pentium 4" - depends on X86_MCE + depends on X86_32 && X86_MCE help Enabling this feature starts a timer that triggers every 5 seconds which will look at the machine check registers to see if anything happened. @@ -411,14 +582,15 @@ config X86_MCE_NONFATAL config X86_MCE_P4THERMAL bool "check for P4 thermal throttling interrupt." - depends on X86_MCE && (X86_UP_APIC || SMP) && !X86_VISWS + depends on X86_32 && X86_MCE && (X86_UP_APIC || SMP) && !X86_VISWS help Enabling this feature will cause a message to be printed when the P4 enters thermal throttling. config VM86 - default y bool "Enable VM86 support" if EMBEDDED + default y + depends on X86_32 help This option is required by programs like DOSEMU to run 16-bit legacy code on X86 processors. It also may be needed by software like @@ -427,6 +599,7 @@ config VM86 config TOSHIBA tristate "Toshiba Laptop support" + depends on X86_32 ---help--- This adds a driver to safely access the System Management Mode of the CPU on Toshiba portables with a genuine Toshiba BIOS. It does @@ -442,6 +615,7 @@ config TOSHIBA config I8K tristate "Dell laptop support" + depends on X86_32 ---help--- This adds a driver to safely access the System Management Mode of the CPU on the Dell Inspiron 8000. The System Management Mode @@ -462,7 +636,7 @@ config I8K config X86_REBOOTFIXUPS bool "Enable X86 board specific fixups for reboot" - depends on X86 + depends on X86_32 && X86 default n ---help--- This enables chipset and/or board specific fixups to be done @@ -517,12 +691,11 @@ config X86_CPUID with major 203 and minors 0 to 31 for /dev/cpu/0/cpuid to /dev/cpu/31/cpuid. -source "drivers/firmware/Kconfig" - choice prompt "High Memory Support" default HIGHMEM4G if !X86_NUMAQ default HIGHMEM64G if X86_NUMAQ + depends on X86_32 config NOHIGHMEM bool "off" @@ -582,6 +755,7 @@ choice depends on EXPERIMENTAL prompt "Memory split" if EMBEDDED default VMSPLIT_3G + depends on X86_32 help Select the desired split between kernel and user memory. @@ -619,16 +793,17 @@ config PAGE_OFFSET default 0x78000000 if VMSPLIT_2G_OPT default 0x40000000 if VMSPLIT_1G default 0xC0000000 + depends on X86_32 config HIGHMEM bool - depends on HIGHMEM64G || HIGHMEM4G + depends on X86_32 && (HIGHMEM64G || HIGHMEM4G) default y config X86_PAE bool "PAE (Physical Address Extension) Support" default n - depends on !HIGHMEM4G + depends on X86_32 && !HIGHMEM4G select RESOURCES_64BIT help PAE is required for NX support, and furthermore enables @@ -639,46 +814,82 @@ config X86_PAE # Common NUMA Features config NUMA bool "Numa Memory Allocation and Scheduler Support (EXPERIMENTAL)" - depends on SMP && HIGHMEM64G && (X86_NUMAQ || (X86_SUMMIT || X86_GENERICARCH) && ACPI) && EXPERIMENTAL + depends on SMP + depends on X86_64 || (X86_32 && HIGHMEM64G && (X86_NUMAQ || (X86_SUMMIT || X86_GENERICARCH) && ACPI) && EXPERIMENTAL) default n if X86_PC default y if (X86_NUMAQ || X86_SUMMIT) help - NUMA support for i386. This is currently highly experimental - and should be only used for kernel development. It might also - cause boot failures. + Enable NUMA (Non Uniform Memory Access) support. + The kernel will try to allocate memory used by a CPU on the + local memory controller of the CPU and add some more + NUMA awareness to the kernel. + + For i386 this is currently highly experimental and should be only + used for kernel development. It might also cause boot failures. + For x86_64 this is recommended on all multiprocessor Opteron systems. + If the system is EM64T, you should say N unless your system is + EM64T NUMA. comment "NUMA (Summit) requires SMP, 64GB highmem support, ACPI" - depends on X86_SUMMIT && (!HIGHMEM64G || !ACPI) + depends on X86_32 && X86_SUMMIT && (!HIGHMEM64G || !ACPI) + +config K8_NUMA + bool "Old style AMD Opteron NUMA detection" + depends on X86_64 && NUMA && PCI + default y + help + Enable K8 NUMA node topology detection. You should say Y here if + you have a multi processor AMD K8 system. This uses an old + method to read the NUMA configuration directly from the builtin + Northbridge of Opteron. It is recommended to use X86_64_ACPI_NUMA + instead, which also takes priority if both are compiled in. + +config X86_64_ACPI_NUMA + bool "ACPI NUMA detection" + depends on X86_64 && NUMA && ACPI && PCI + select ACPI_NUMA + default y + help + Enable ACPI SRAT based node topology detection. + +config NUMA_EMU + bool "NUMA emulation" + depends on X86_64 && NUMA + help + Enable NUMA emulation. A flat machine will be split + into virtual nodes when booted with "numa=fake=N", where N is the + number of nodes. This is only useful for debugging. config NODES_SHIFT int + default "6" if X86_64 default "4" if X86_NUMAQ default "3" depends on NEED_MULTIPLE_NODES config HAVE_ARCH_BOOTMEM_NODE bool - depends on NUMA + depends on X86_32 && NUMA default y config ARCH_HAVE_MEMORY_PRESENT bool - depends on DISCONTIGMEM + depends on X86_32 && DISCONTIGMEM default y config NEED_NODE_MEMMAP_SIZE bool - depends on DISCONTIGMEM || SPARSEMEM + depends on X86_32 && (DISCONTIGMEM || SPARSEMEM) default y config HAVE_ARCH_ALLOC_REMAP bool - depends on NUMA + depends on X86_32 && NUMA default y config ARCH_FLATMEM_ENABLE def_bool y - depends on (ARCH_SELECT_MEMORY_MODEL && X86_PC) + depends on (X86_32 && ARCH_SELECT_MEMORY_MODEL && X86_PC) || (X86_64 && !NUMA) config ARCH_DISCONTIGMEM_ENABLE def_bool y @@ -690,21 +901,23 @@ config ARCH_DISCONTIGMEM_DEFAULT config ARCH_SPARSEMEM_ENABLE def_bool y - depends on (NUMA || (X86_PC && EXPERIMENTAL)) - select SPARSEMEM_STATIC + depends on NUMA || (EXPERIMENTAL && (X86_PC || X86_64)) + select SPARSEMEM_STATIC if X86_32 + select SPARSEMEM_VMEMMAP_ENABLE if X86_64 config ARCH_SELECT_MEMORY_MODEL def_bool y - depends on ARCH_SPARSEMEM_ENABLE + depends on X86_32 && ARCH_SPARSEMEM_ENABLE -config ARCH_POPULATES_NODE_MAP - def_bool y +config ARCH_MEMORY_PROBE + def_bool X86_64 + depends on MEMORY_HOTPLUG source "mm/Kconfig" config HIGHPTE bool "Allocate 3rd-level pagetables from highmem" - depends on HIGHMEM4G || HIGHMEM64G + depends on X86_32 && (HIGHMEM4G || HIGHMEM64G) help The VM uses one page table entry for each page of physical memory. For systems with a lot of RAM, this can be wasteful of precious @@ -712,7 +925,8 @@ config HIGHPTE entries in high memory. config MATH_EMULATION - bool "Math emulation" + bool + prompt "Math emulation" if X86_32 ---help--- Linux can emulate a math coprocessor (used for floating point operations) if you don't have one. 486DX and Pentium processors have @@ -772,7 +986,7 @@ config MTRR config EFI bool "Boot from EFI support" - depends on ACPI + depends on X86_32 && ACPI default n ---help--- This enables the kernel to boot on EFI platforms using @@ -789,18 +1003,18 @@ config EFI kernel should continue to boot on existing non-EFI platforms. config IRQBALANCE - bool "Enable kernel irq balancing" - depends on SMP && X86_IO_APIC + bool "Enable kernel irq balancing" + depends on X86_32 && SMP && X86_IO_APIC default y help - The default yes will allow the kernel to do irq load balancing. + The default yes will allow the kernel to do irq load balancing. Saying no will keep the kernel from doing irq load balancing. # turning this on wastes a bunch of space. # Summit needs it only when NUMA is on config BOOT_IOREMAP bool - depends on (((X86_SUMMIT || X86_GENERICARCH) && NUMA) || (X86 && EFI)) + depends on X86_32 && (((X86_SUMMIT || X86_GENERICARCH) && NUMA) || (X86 && EFI)) default y config SECCOMP @@ -820,6 +1034,30 @@ config SECCOMP If unsure, say Y. Only embedded should say N here. +config CC_STACKPROTECTOR + bool "Enable -fstack-protector buffer overflow detection (EXPERIMENTAL)" + depends on X86_64 && EXPERIMENTAL + help + This option turns on the -fstack-protector GCC feature. This + feature puts, at the beginning of critical functions, a canary + value on the stack just before the return address, and validates + the value just before actually returning. Stack based buffer + overflows (that need to overwrite this return address) now also + overwrite the canary, which gets detected and the attack is then + neutralized via a kernel panic. + + This feature requires gcc version 4.2 or above, or a distribution + gcc with the feature backported. Older versions are automatically + detected and for those versions, this configuration option is ignored. + +config CC_STACKPROTECTOR_ALL + bool "Use stack-protector for all functions" + depends on CC_STACKPROTECTOR + help + Normally, GCC only inserts the canary value protection for + functions that use large-ish on-stack buffers. By enabling + this option, GCC will be asked to do this for ALL functions. + source kernel/Kconfig.hz config KEXEC @@ -841,7 +1079,7 @@ config KEXEC config CRASH_DUMP bool "kernel crash dumps (EXPERIMENTAL)" depends on EXPERIMENTAL - depends on HIGHMEM + depends on X86_64 || (X86_32 && HIGHMEM) help Generate crash dump after being started by kexec. This should be normally only set in special crash dump kernels @@ -856,6 +1094,7 @@ config CRASH_DUMP config PHYSICAL_START hex "Physical address where the kernel is loaded" if (EMBEDDED || CRASH_DUMP) default "0x1000000" if X86_NUMAQ + default "0x200000" if X86_64 default "0x100000" help This gives the physical address where the kernel is loaded. @@ -908,25 +1147,31 @@ config RELOCATABLE must live at a different physical address than the primary kernel. + Note: If CONFIG_RELOCATABLE=y, then the kernel runs from the address + it has been loaded at and the compile time physical address + (CONFIG_PHYSICAL_START) is ignored. + config PHYSICAL_ALIGN - hex "Alignment value to which kernel should be aligned" - default "0x100000" + hex + prompt "Alignment value to which kernel should be aligned" if X86_32 + default "0x100000" if X86_32 + default "0x200000" if X86_64 range 0x2000 0x400000 help This value puts the alignment restrictions on physical address - where kernel is loaded and run from. Kernel is compiled for an - address which meets above alignment restriction. - - If bootloader loads the kernel at a non-aligned address and - CONFIG_RELOCATABLE is set, kernel will move itself to nearest - address aligned to above value and run from there. - - If bootloader loads the kernel at a non-aligned address and - CONFIG_RELOCATABLE is not set, kernel will ignore the run time - load address and decompress itself to the address it has been - compiled for and run from there. The address for which kernel is - compiled already meets above alignment restrictions. Hence the - end result is that kernel runs from a physical address meeting + where kernel is loaded and run from. Kernel is compiled for an + address which meets above alignment restriction. + + If bootloader loads the kernel at a non-aligned address and + CONFIG_RELOCATABLE is set, kernel will move itself to nearest + address aligned to above value and run from there. + + If bootloader loads the kernel at a non-aligned address and + CONFIG_RELOCATABLE is not set, kernel will ignore the run time + load address and decompress itself to the address it has been + compiled for and run from there. The address for which kernel is + compiled already meets above alignment restrictions. Hence the + end result is that kernel runs from a physical address meeting above alignment restrictions. Don't change this unless you know what you are doing. @@ -938,10 +1183,13 @@ config HOTPLUG_CPU Say Y here to experiment with turning CPUs off and on, and to enable suspend on SMP systems. CPUs can be controlled through /sys/devices/system/cpu. + Say N if you want to disable CPU hotplug and don't need to + suspend. config COMPAT_VDSO bool "Compat VDSO support" default y + depends on X86_32 help Map the VDSO to the predictable old-style address too. ---help--- @@ -955,18 +1203,35 @@ endmenu config ARCH_ENABLE_MEMORY_HOTPLUG def_bool y - depends on HIGHMEM + depends on X86_64 || (X86_32 && HIGHMEM) + +config MEMORY_HOTPLUG_RESERVE + def_bool X86_64 + depends on (MEMORY_HOTPLUG && DISCONTIGMEM) + +config HAVE_ARCH_EARLY_PFN_TO_NID + def_bool X86_64 + depends on NUMA -menu "Power management options (ACPI, APM)" +config OUT_OF_LINE_PFN_TO_PAGE + def_bool X86_64 + depends on DISCONTIGMEM + +menu "Power management options" depends on !X86_VOYAGER -source kernel/power/Kconfig +config ARCH_HIBERNATION_HEADER + bool + depends on X86_64 && HIBERNATION + default y + +source "kernel/power/Kconfig" source "drivers/acpi/Kconfig" menuconfig APM tristate "APM (Advanced Power Management) BIOS support" - depends on PM_SLEEP && !X86_VISWS + depends on X86_32 && PM_SLEEP && !X86_VISWS ---help--- APM is a BIOS specification for saving power using several different techniques. This is mostly useful for battery powered laptops with @@ -1092,13 +1357,14 @@ config APM_REAL_MODE_POWER_OFF endif # APM -source "arch/x86/kernel/cpu/cpufreq/Kconfig_32" +source "arch/x86/kernel/cpu/cpufreq/Kconfig" source "drivers/cpuidle/Kconfig" endmenu -menu "Bus options (PCI, PCMCIA, EISA, MCA, ISA)" + +menu "Bus options (PCI etc.)" config PCI bool "PCI support" if !X86_VISWS @@ -1118,7 +1384,7 @@ config PCI choice prompt "PCI access mode" - depends on PCI && !X86_VISWS + depends on X86_32 && PCI && !X86_VISWS default PCI_GOANY ---help--- On PCI systems, the BIOS can be used to detect the PCI devices and @@ -1151,17 +1417,18 @@ endchoice config PCI_BIOS bool - depends on !X86_VISWS && PCI && (PCI_GOBIOS || PCI_GOANY) + depends on X86_32 && !X86_VISWS && PCI && (PCI_GOBIOS || PCI_GOANY) default y +# x86-64 doesn't support PCI BIOS access from long mode so always go direct. config PCI_DIRECT bool - depends on PCI && ((PCI_GODIRECT || PCI_GOANY) || X86_VISWS) + depends on PCI && (X86_64 || (PCI_GODIRECT || PCI_GOANY) || X86_VISWS) default y config PCI_MMCONFIG bool - depends on PCI && ACPI && (PCI_GOMMCONFIG || PCI_GOANY) + depends on X86_32 && PCI && ACPI && (PCI_GOMMCONFIG || PCI_GOANY) default y config PCI_DOMAINS @@ -1169,14 +1436,52 @@ config PCI_DOMAINS depends on PCI default y +config PCI_MMCONFIG + bool "Support mmconfig PCI config space access" + depends on X86_64 && PCI && ACPI + +config DMAR + bool "Support for DMA Remapping Devices (EXPERIMENTAL)" + depends on X86_64 && PCI_MSI && ACPI && EXPERIMENTAL + help + DMA remapping (DMAR) devices support enables independent address + translations for Direct Memory Access (DMA) from devices. + These DMA remapping devices are reported via ACPI tables + and include PCI device scope covered by these DMA + remapping devices. + +config DMAR_GFX_WA + bool "Support for Graphics workaround" + depends on DMAR + default y + help + Current Graphics drivers tend to use physical address + for DMA and avoid using DMA APIs. Setting this config + option permits the IOMMU driver to set a unity map for + all the OS-visible memory. Hence the driver can continue + to use physical addresses for DMA. + +config DMAR_FLOPPY_WA + bool + depends on DMAR + default y + help + Floppy disk drivers are know to bypass DMA API calls + thereby failing to work when IOMMU is enabled. This + workaround will setup a 1:1 mapping for the first + 16M to make floppy (an ISA device) work. + source "drivers/pci/pcie/Kconfig" source "drivers/pci/Kconfig" +# x86_64 have no ISA slots, but do have ISA-style DMA. config ISA_DMA_API bool default y +if X86_32 + config ISA bool "ISA support" depends on !(X86_VOYAGER || X86_VISWS) @@ -1248,9 +1553,11 @@ config GEODE_MFGPT_TIMER MFGPTs have a better resolution and max interval than the generic PIT, and are suitable for use as high-res timers. +endif # X86_32 + config K8_NB def_bool y - depends on AGP_AMD64 + depends on AGP_AMD64 || (X86_64 && (GART_IOMMU || (PCI && NUMA))) source "drivers/pcmcia/Kconfig" @@ -1258,16 +1565,48 @@ source "drivers/pci/hotplug/Kconfig" endmenu -menu "Executable file formats" + +menu "Executable file formats / Emulations" source "fs/Kconfig.binfmt" +config IA32_EMULATION + bool "IA32 Emulation" + depends on X86_64 + help + Include code to run 32-bit programs under a 64-bit kernel. You should + likely turn this on, unless you're 100% sure that you don't have any + 32-bit programs left. + +config IA32_AOUT + tristate "IA32 a.out support" + depends on IA32_EMULATION + help + Support old a.out binaries in the 32bit emulation. + +config COMPAT + bool + depends on IA32_EMULATION + default y + +config COMPAT_FOR_U64_ALIGNMENT + def_bool COMPAT + depends on X86_64 + +config SYSVIPC_COMPAT + bool + depends on X86_64 && COMPAT && SYSVIPC + default y + endmenu + source "net/Kconfig" source "drivers/Kconfig" +source "drivers/firmware/Kconfig" + source "fs/Kconfig" source "kernel/Kconfig.instrumentation" @@ -1279,43 +1618,3 @@ source "security/Kconfig" source "crypto/Kconfig" source "lib/Kconfig" - -# -# Use the generic interrupt handling code in kernel/irq/: -# -config GENERIC_HARDIRQS - bool - default y - -config GENERIC_IRQ_PROBE - bool - default y - -config GENERIC_PENDING_IRQ - bool - depends on GENERIC_HARDIRQS && SMP - default y - -config X86_SMP - bool - depends on SMP && !X86_VOYAGER - default y - -config X86_HT - bool - depends on SMP && !(X86_VISWS || X86_VOYAGER) - default y - -config X86_BIOS_REBOOT - bool - depends on !(X86_VISWS || X86_VOYAGER) - default y - -config X86_TRAMPOLINE - bool - depends on X86_SMP || (X86_VOYAGER && SMP) - default y - -config KTIME_SCALAR - bool - default y diff --git a/arch/x86/Kconfig.cpu b/arch/x86/Kconfig.cpu index 0e2adad..c301622 100644 --- a/arch/x86/Kconfig.cpu +++ b/arch/x86/Kconfig.cpu @@ -3,11 +3,12 @@ if !X86_ELAN choice prompt "Processor family" - default M686 + default M686 if X86_32 + default GENERIC_CPU if X86_64 config M386 bool "386" - depends on !UML + depends on X86_32 && !UML ---help--- This is the processor type of your CPU. This information is used for optimizing purposes. In order to compile a kernel that can run on @@ -49,6 +50,7 @@ config M386 config M486 bool "486" + depends on X86_32 help Select this for a 486 series processor, either Intel or one of the compatible processors from AMD, Cyrix, IBM, or Intel. Includes DX, @@ -57,6 +59,7 @@ config M486 config M586 bool "586/K5/5x86/6x86/6x86MX" + depends on X86_32 help Select this for an 586 or 686 series processor such as the AMD K5, the Cyrix 5x86, 6x86 and 6x86MX. This choice does not @@ -64,18 +67,21 @@ config M586 config M586TSC bool "Pentium-Classic" + depends on X86_32 help Select this for a Pentium Classic processor with the RDTSC (Read Time Stamp Counter) instruction for benchmarking. config M586MMX bool "Pentium-MMX" + depends on X86_32 help Select this for a Pentium with the MMX graphics/multimedia extended instructions. config M686 bool "Pentium-Pro" + depends on X86_32 help Select this for Intel Pentium Pro chips. This enables the use of Pentium Pro extended instructions, and disables the init-time guard @@ -83,6 +89,7 @@ config M686 config MPENTIUMII bool "Pentium-II/Celeron(pre-Coppermine)" + depends on X86_32 help Select this for Intel chips based on the Pentium-II and pre-Coppermine Celeron core. This option enables an unaligned @@ -92,6 +99,7 @@ config MPENTIUMII config MPENTIUMIII bool "Pentium-III/Celeron(Coppermine)/Pentium-III Xeon" + depends on X86_32 help Select this for Intel chips based on the Pentium-III and Celeron-Coppermine core. This option enables use of some @@ -100,19 +108,14 @@ config MPENTIUMIII config MPENTIUMM bool "Pentium M" + depends on X86_32 help Select this for Intel Pentium M (not Pentium-4 M) notebook chips. -config MCORE2 - bool "Core 2/newer Xeon" - help - Select this for Intel Core 2 and newer Core 2 Xeons (Xeon 51xx and 53xx) - CPUs. You can distinguish newer from older Xeons by the CPU family - in /proc/cpuinfo. Newer ones have 6 and older ones 15 (not a typo) - config MPENTIUM4 bool "Pentium-4/Celeron(P4-based)/Pentium-4 M/older Xeon" + depends on X86_32 help Select this for Intel Pentium 4 chips. This includes the Pentium 4, Pentium D, P4-based Celeron and Xeon, and @@ -148,6 +151,7 @@ config MPENTIUM4 config MK6 bool "K6/K6-II/K6-III" + depends on X86_32 help Select this for an AMD K6-family processor. Enables use of some extended instructions, and passes appropriate optimization @@ -155,6 +159,7 @@ config MK6 config MK7 bool "Athlon/Duron/K7" + depends on X86_32 help Select this for an AMD Athlon K7-family processor. Enables use of some extended instructions, and passes appropriate optimization @@ -169,6 +174,7 @@ config MK8 config MCRUSOE bool "Crusoe" + depends on X86_32 help Select this for a Transmeta Crusoe processor. Treats the processor like a 586 with TSC, and sets some GCC optimization flags (like a @@ -176,11 +182,13 @@ config MCRUSOE config MEFFICEON bool "Efficeon" + depends on X86_32 help Select this for a Transmeta Efficeon processor. config MWINCHIPC6 bool "Winchip-C6" + depends on X86_32 help Select this for an IDT Winchip C6 chip. Linux and GCC treat this chip as a 586TSC with some extended instructions @@ -188,6 +196,7 @@ config MWINCHIPC6 config MWINCHIP2 bool "Winchip-2" + depends on X86_32 help Select this for an IDT Winchip-2. Linux and GCC treat this chip as a 586TSC with some extended instructions @@ -195,6 +204,7 @@ config MWINCHIP2 config MWINCHIP3D bool "Winchip-2A/Winchip-3" + depends on X86_32 help Select this for an IDT Winchip-2A or 3. Linux and GCC treat this chip as a 586TSC with some extended instructions @@ -204,16 +214,19 @@ config MWINCHIP3D config MGEODEGX1 bool "GeodeGX1" + depends on X86_32 help Select this for a Geode GX1 (Cyrix MediaGX) chip. config MGEODE_LX bool "Geode GX/LX" + depends on X86_32 help Select this for AMD Geode GX and LX processors. config MCYRIXIII bool "CyrixIII/VIA-C3" + depends on X86_32 help Select this for a Cyrix III or C3 chip. Presently Linux and GCC treat this chip as a generic 586. Whilst the CPU is 686 class, @@ -225,6 +238,7 @@ config MCYRIXIII config MVIAC3_2 bool "VIA C3-2 (Nehemiah)" + depends on X86_32 help Select this for a VIA C3 "Nehemiah". Selecting this enables usage of SSE and tells gcc to treat the CPU as a 686. @@ -232,15 +246,42 @@ config MVIAC3_2 config MVIAC7 bool "VIA C7" + depends on X86_32 help Select this for a VIA C7. Selecting this uses the correct cache shift and tells gcc to treat the CPU as a 686. +config MPSC + bool "Intel P4 / older Netburst based Xeon" + depends on X86_64 + help + Optimize for Intel Pentium 4, Pentium D and older Nocona/Dempsey + Xeon CPUs with Intel 64bit which is compatible with x86-64. + Note that the latest Xeons (Xeon 51xx and 53xx) are not based on the + Netburst core and shouldn't use this option. You can distinguish them + using the cpu family field + in /proc/cpuinfo. Family 15 is an older Xeon, Family 6 a newer one. + +config MCORE2 + bool "Core 2/newer Xeon" + help + Select this for Intel Core 2 and newer Core 2 Xeons (Xeon 51xx and 53xx) + CPUs. You can distinguish newer from older Xeons by the CPU family + in /proc/cpuinfo. Newer ones have 6 and older ones 15 (not a typo) + +config GENERIC_CPU + bool "Generic-x86-64" + depends on X86_64 + help + Generic x86-64 CPU. + Run equally well on all x86-64 CPUs. + endchoice config X86_GENERIC - bool "Generic x86 support" - help + bool "Generic x86 support" + depends on X86_32 + help Instead of just including optimizations for the selected x86 variant (e.g. PII, Crusoe or Athlon), include some more generic optimizations as well. This will make the kernel @@ -253,44 +294,31 @@ endif # # Define implied options from the CPU selection here -# +config X86_L1_CACHE_BYTES + int + default "128" if GENERIC_CPU || MPSC + default "64" if MK8 || MCORE2 + depends on X86_64 + +config X86_INTERNODE_CACHE_BYTES + int + default "4096" if X86_VSMP + default X86_L1_CACHE_BYTES if !X86_VSMP + depends on X86_64 + config X86_CMPXCHG - bool - depends on !M386 - default y + def_bool X86_64 || (X86_32 && !M386) config X86_L1_CACHE_SHIFT int - default "7" if MPENTIUM4 || X86_GENERIC + default "7" if MPENTIUM4 || X86_GENERIC || GENERIC_CPU || MPSC default "4" if X86_ELAN || M486 || M386 || MGEODEGX1 default "5" if MWINCHIP3D || MWINCHIP2 || MWINCHIPC6 || MCRUSOE || MEFFICEON || MCYRIXIII || MK6 || MPENTIUMIII || MPENTIUMII || M686 || M586MMX || M586TSC || M586 || MVIAC3_2 || MGEODE_LX default "6" if MK7 || MK8 || MPENTIUMM || MCORE2 || MVIAC7 config X86_XADD bool - depends on !M386 - default y - -config RWSEM_GENERIC_SPINLOCK - bool - depends on !X86_XADD - default y - -config RWSEM_XCHGADD_ALGORITHM - bool - depends on X86_XADD - default y - -config ARCH_HAS_ILOG2_U32 - bool - default n - -config ARCH_HAS_ILOG2_U64 - bool - default n - -config GENERIC_CALIBRATE_DELAY - bool + depends on X86_32 && !M386 default y config X86_PPRO_FENCE @@ -305,22 +333,22 @@ config X86_F00F_BUG config X86_WP_WORKS_OK bool - depends on !M386 + depends on X86_32 && !M386 default y config X86_INVLPG bool - depends on !M386 + depends on X86_32 && !M386 default y config X86_BSWAP bool - depends on !M386 + depends on X86_32 && !M386 default y config X86_POPAD_OK bool - depends on !M386 + depends on X86_32 && !M386 default y config X86_ALIGNMENT_16 @@ -330,7 +358,7 @@ config X86_ALIGNMENT_16 config X86_GOOD_APIC bool - depends on MK7 || MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M686 || M586MMX || MK8 || MEFFICEON || MCORE2 || MVIAC7 + depends on MK7 || MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M686 || M586MMX || MK8 || MEFFICEON || MCORE2 || MVIAC7 || X86_64 default y config X86_INTEL_USERCOPY @@ -355,7 +383,7 @@ config X86_OOSTORE config X86_TSC bool - depends on (MWINCHIP3D || MWINCHIP2 || MCRUSOE || MEFFICEON || MCYRIXIII || MK7 || MK6 || MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M686 || M586MMX || M586TSC || MK8 || MVIAC3_2 || MVIAC7 || MGEODEGX1 || MGEODE_LX || MCORE2) && !X86_NUMAQ + depends on ((MWINCHIP3D || MWINCHIP2 || MCRUSOE || MEFFICEON || MCYRIXIII || MK7 || MK6 || MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M686 || M586MMX || M586TSC || MK8 || MVIAC3_2 || MVIAC7 || MGEODEGX1 || MGEODE_LX || MCORE2) && !X86_NUMAQ) || X86_64 default y # this should be set for all -march=.. options where the compiler @@ -367,6 +395,7 @@ config X86_CMOV config X86_MINIMUM_CPU_FAMILY int - default "4" if X86_XADD || X86_CMPXCHG || X86_BSWAP || X86_WP_WORKS_OK + default "64" if X86_64 + default "4" if X86_32 && (X86_XADD || X86_CMPXCHG || X86_BSWAP || X86_WP_WORKS_OK) default "3" diff --git a/arch/x86/Kconfig.x86_64 b/arch/x86/Kconfig.x86_64 deleted file mode 100644 index cc468ea..0000000 --- a/arch/x86/Kconfig.x86_64 +++ /dev/null @@ -1,839 +0,0 @@ -# -# For a description of the syntax of this configuration file, -# see Documentation/kbuild/kconfig-language.txt. -# -# Note: ISA is disabled and will hopefully never be enabled. -# If you managed to buy an ISA x86-64 box you'll have to fix all the -# ISA drivers you need yourself. -# - -mainmenu "Linux Kernel Configuration" - -config X86_64 - bool - default y - help - Port to the x86-64 architecture. x86-64 is a 64-bit extension to the - classical 32-bit x86 architecture. For details see - <http://www.x86-64.org/>. - -config 64BIT - def_bool y - -config X86 - bool - default y - -config GENERIC_TIME - bool - default y - -config GENERIC_TIME_VSYSCALL - bool - default y - -config GENERIC_CMOS_UPDATE - bool - default y - -config CLOCKSOURCE_WATCHDOG - bool - default y - -config GENERIC_CLOCKEVENTS - bool - default y - -config GENERIC_CLOCKEVENTS_BROADCAST - bool - default y - -config ZONE_DMA32 - bool - default y - -config LOCKDEP_SUPPORT - bool - default y - -config STACKTRACE_SUPPORT - bool - default y - -config SEMAPHORE_SLEEPERS - bool - default y - -config MMU - bool - default y - -config ZONE_DMA - bool - default y - -config ISA - bool - -config SBUS - bool - -config RWSEM_GENERIC_SPINLOCK - bool - default y - -config RWSEM_XCHGADD_ALGORITHM - bool - -config GENERIC_HWEIGHT - bool - default y - -config GENERIC_CALIBRATE_DELAY - bool - default y - -config X86_CMPXCHG - bool - default y - -config GENERIC_ISA_DMA - bool - default y - -config GENERIC_IOMAP - bool - default y - -config ARCH_MAY_HAVE_PC_FDC - bool - default y - -config ARCH_POPULATES_NODE_MAP - def_bool y - -config DMI - bool - default y - -config AUDIT_ARCH - bool - default y - -config GENERIC_BUG - bool - default y - depends on BUG - -config ARCH_HAS_ILOG2_U32 - bool - default n - -config ARCH_HAS_ILOG2_U64 - bool - default n - -source "init/Kconfig" - - -menu "Processor type and features" - -source "kernel/time/Kconfig" - -choice - prompt "Subarchitecture Type" - default X86_PC - -config X86_PC - bool "PC-compatible" - help - Choose this option if your computer is a standard PC or compatible. - -config X86_VSMP - bool "Support for ScaleMP vSMP" - depends on PCI - help - Support for ScaleMP vSMP systems. Say 'Y' here if this kernel is - supposed to run on these EM64T-based machines. Only choose this option - if you have one of these machines. - -endchoice - -choice - prompt "Processor family" - default GENERIC_CPU - -config MK8 - bool "AMD-Opteron/Athlon64" - help - Optimize for AMD Opteron/Athlon64/Hammer/K8 CPUs. - -config MPSC - bool "Intel P4 / older Netburst based Xeon" - help - Optimize for Intel Pentium 4, Pentium D and older Nocona/Dempsey - Xeon CPUs with Intel 64bit which is compatible with x86-64. - Note that the latest Xeons (Xeon 51xx and 53xx) are not based on the - Netburst core and shouldn't use this option. You can distinguish them - using the cpu family field - in /proc/cpuinfo. Family 15 is an older Xeon, Family 6 a newer one. - -config MCORE2 - bool "Intel Core2 / newer Xeon" - help - Optimize for Intel Core2 and newer Xeons (51xx) - You can distinguish the newer Xeons from the older ones using - the cpu family field in /proc/cpuinfo. 15 is an older Xeon - (use CONFIG_MPSC then), 6 is a newer one. - -config GENERIC_CPU - bool "Generic-x86-64" - help - Generic x86-64 CPU. - Run equally well on all x86-64 CPUs. - -endchoice - -# -# Define implied options from the CPU selection here -# -config X86_L1_CACHE_BYTES - int - default "128" if GENERIC_CPU || MPSC - default "64" if MK8 || MCORE2 - -config X86_L1_CACHE_SHIFT - int - default "7" if GENERIC_CPU || MPSC - default "6" if MK8 || MCORE2 - -config X86_INTERNODE_CACHE_BYTES - int - default "4096" if X86_VSMP - default X86_L1_CACHE_BYTES if !X86_VSMP - -config X86_TSC - bool - default y - -config X86_GOOD_APIC - bool - default y - -config MICROCODE - tristate "/dev/cpu/microcode - Intel CPU microcode support" - select FW_LOADER - ---help--- - If you say Y here the 'File systems' section, you will be - able to update the microcode on Intel processors. You will - obviously need the actual microcode binary data itself which is - not shipped with the Linux kernel. - - For latest news and information on obtaining all the required - ingredients for this driver, check: - <http://www.urbanmyth.org/microcode/>. - - To compile this driver as a module, choose M here: the - module will be called microcode. - If you use modprobe or kmod you may also want to add the line - 'alias char-major-10-184 microcode' to your /etc/modules.conf file. - -config MICROCODE_OLD_INTERFACE - bool - depends on MICROCODE - default y - -config X86_MSR - tristate "/dev/cpu/*/msr - Model-specific register support" - help - This device gives privileged processes access to the x86 - Model-Specific Registers (MSRs). It is a character device with - major 202 and minors 0 to 31 for /dev/cpu/0/msr to /dev/cpu/31/msr. - MSR accesses are directed to a specific CPU on multi-processor - systems. - -config X86_CPUID - tristate "/dev/cpu/*/cpuid - CPU information support" - help - This device gives processes access to the x86 CPUID instruction to - be executed on a specific processor. It is a character device - with major 203 and minors 0 to 31 for /dev/cpu/0/cpuid to - /dev/cpu/31/cpuid. - -config X86_HT - bool - depends on SMP && !MK8 - default y - -config MATH_EMULATION - bool - -config MCA - bool - -config EISA - bool - -config X86_IO_APIC - bool - default y - -config X86_LOCAL_APIC - bool - default y - -config MTRR - bool "MTRR (Memory Type Range Register) support" - ---help--- - On Intel P6 family processors (Pentium Pro, Pentium II and later) - the Memory Type Range Registers (MTRRs) may be used to control - processor access to memory ranges. This is most useful if you have - a video (VGA) card on a PCI or AGP bus. Enabling write-combining - allows bus write transfers to be combined into a larger transfer - before bursting over the PCI/AGP bus. This can increase performance - of image write operations 2.5 times or more. Saying Y here creates a - /proc/mtrr file which may be used to manipulate your processor's - MTRRs. Typically the X server should use this. - - This code has a reasonably generic interface so that similar - control registers on other processors can be easily supported - as well. - - Saying Y here also fixes a problem with buggy SMP BIOSes which only - set the MTRRs for the boot CPU and not for the secondary CPUs. This - can lead to all sorts of problems, so it's good to say Y here. - - Just say Y here, all x86-64 machines support MTRRs. - - See <file:Documentation/mtrr.txt> for more information. - -config SMP - bool "Symmetric multi-processing support" - ---help--- - This enables support for systems with more than one CPU. If you have - a system with only one CPU, like most personal computers, say N. If - you have a system with more than one CPU, say Y. - - If you say N here, the kernel will run on single and multiprocessor - machines, but will use only one CPU of a multiprocessor machine. If - you say Y here, the kernel will run on many, but not all, - singleprocessor machines. On a singleprocessor machine, the kernel - will run faster if you say N here. - - If you don't know what to do here, say N. - -config SCHED_SMT - bool "SMT (Hyperthreading) scheduler support" - depends on SMP - default n - help - SMT scheduler support improves the CPU scheduler's decision making - when dealing with Intel Pentium 4 chips with HyperThreading at a - cost of slightly increased overhead in some places. If unsure say - N here. - -config SCHED_MC - bool "Multi-core scheduler support" - depends on SMP - default y - help - Multi-core scheduler support improves the CPU scheduler's decision - making when dealing with multi-core CPU chips at a cost of slightly - increased overhead in some places. If unsure say N here. - -source "kernel/Kconfig.preempt" - -config NUMA - bool "Non Uniform Memory Access (NUMA) Support" - depends on SMP - help - Enable NUMA (Non Uniform Memory Access) support. The kernel - will try to allocate memory used by a CPU on the local memory - controller of the CPU and add some more NUMA awareness to the kernel. - This code is recommended on all multiprocessor Opteron systems. - If the system is EM64T, you should say N unless your system is EM64T - NUMA. - -config K8_NUMA - bool "Old style AMD Opteron NUMA detection" - depends on NUMA && PCI - default y - help - Enable K8 NUMA node topology detection. You should say Y here if - you have a multi processor AMD K8 system. This uses an old - method to read the NUMA configuration directly from the builtin - Northbridge of Opteron. It is recommended to use X86_64_ACPI_NUMA - instead, which also takes priority if both are compiled in. - -config NODES_SHIFT - int - default "6" - depends on NEED_MULTIPLE_NODES - -# Dummy CONFIG option to select ACPI_NUMA from drivers/acpi/Kconfig. - -config X86_64_ACPI_NUMA - bool "ACPI NUMA detection" - depends on NUMA - select ACPI - select PCI - select ACPI_NUMA - default y - help - Enable ACPI SRAT based node topology detection. - -config NUMA_EMU - bool "NUMA emulation" - depends on NUMA - help - Enable NUMA emulation. A flat machine will be split - into virtual nodes when booted with "numa=fake=N", where N is the - number of nodes. This is only useful for debugging. - -config ARCH_DISCONTIGMEM_ENABLE - bool - depends on NUMA - default y - -config ARCH_DISCONTIGMEM_DEFAULT - def_bool y - depends on NUMA - -config ARCH_SPARSEMEM_ENABLE - def_bool y - depends on (NUMA || EXPERIMENTAL) - select SPARSEMEM_VMEMMAP_ENABLE - -config ARCH_MEMORY_PROBE - def_bool y - depends on MEMORY_HOTPLUG - -config ARCH_FLATMEM_ENABLE - def_bool y - depends on !NUMA - -source "mm/Kconfig" - -config MEMORY_HOTPLUG_RESERVE - def_bool y - depends on (MEMORY_HOTPLUG && DISCONTIGMEM) - -config HAVE_ARCH_EARLY_PFN_TO_NID - def_bool y - depends on NUMA - -config OUT_OF_LINE_PFN_TO_PAGE - def_bool y - depends on DISCONTIGMEM - -config NR_CPUS - int "Maximum number of CPUs (2-255)" - range 2 255 - depends on SMP - default "8" - help - This allows you to specify the maximum number of CPUs which this - kernel will support. Current maximum is 255 CPUs due to - APIC addressing limits. Less depending on the hardware. - - This is purely to save memory - each supported CPU requires - memory in the static kernel configuration. - -config PHYSICAL_ALIGN - hex - default "0x200000" - -config HOTPLUG_CPU - bool "Support for suspend on SMP and hot-pluggable CPUs (EXPERIMENTAL)" - depends on SMP && HOTPLUG && EXPERIMENTAL - help - Say Y here to experiment with turning CPUs off and on. CPUs - can be controlled through /sys/devices/system/cpu/cpu#. - This is also required for suspend/hibernation on SMP systems. - - Say N if you want to disable CPU hotplug and don't need to - suspend. - -config ARCH_ENABLE_MEMORY_HOTPLUG - def_bool y - -config HPET_TIMER - bool - default y - help - Use the IA-PC HPET (High Precision Event Timer) to manage - time in preference to the PIT and RTC, if a HPET is - present. The HPET provides a stable time base on SMP - systems, unlike the TSC, but it is more expensive to access, - as it is off-chip. You can find the HPET spec at - <http://www.intel.com/hardwaredesign/hpetspec.htm>. - -config HPET_EMULATE_RTC - bool - depends on HPET_TIMER && RTC=y - default y - -# Mark as embedded because too many people got it wrong. -# The code disables itself when not needed. -config GART_IOMMU - bool "GART IOMMU support" if EMBEDDED - default y - select SWIOTLB - select AGP - depends on PCI - help - Support for full DMA access of devices with 32bit memory access only - on systems with more than 3GB. This is usually needed for USB, - sound, many IDE/SATA chipsets and some other devices. - Provides a driver for the AMD Athlon64/Opteron/Turion/Sempron GART - based hardware IOMMU and a software bounce buffer based IOMMU used - on Intel systems and as fallback. - The code is only active when needed (enough memory and limited - device) unless CONFIG_IOMMU_DEBUG or iommu=force is specified - too. - -config CALGARY_IOMMU - bool "IBM Calgary IOMMU support" - select SWIOTLB - depends on PCI && EXPERIMENTAL - help - Support for hardware IOMMUs in IBM's xSeries x366 and x460 - systems. Needed to run systems with more than 3GB of memory - properly with 32-bit PCI devices that do not support DAC - (Double Address Cycle). Calgary also supports bus level - isolation, where all DMAs pass through the IOMMU. This - prevents them from going anywhere except their intended - destination. This catches hard-to-find kernel bugs and - mis-behaving drivers and devices that do not use the DMA-API - properly to set up their DMA buffers. The IOMMU can be - turned off at boot time with the iommu=off parameter. - Normally the kernel will make the right choice by itself. - If unsure, say Y. - -config CALGARY_IOMMU_ENABLED_BY_DEFAULT - bool "Should Calgary be enabled by default?" - default y - depends on CALGARY_IOMMU - help - Should Calgary be enabled by default? if you choose 'y', Calgary - will be used (if it exists). If you choose 'n', Calgary will not be - used even if it exists. If you choose 'n' and would like to use - Calgary anyway, pass 'iommu=calgary' on the kernel command line. - If unsure, say Y. - -# need this always selected by IOMMU for the VIA workaround -config SWIOTLB - bool - help - Support for software bounce buffers used on x86-64 systems - which don't have a hardware IOMMU (e.g. the current generation - of Intel's x86-64 CPUs). Using this PCI devices which can only - access 32-bits of memory can be used on systems with more than - 3 GB of memory. If unsure, say Y. - -config X86_MCE - bool "Machine check support" if EMBEDDED - default y - help - Include a machine check error handler to report hardware errors. - This version will require the mcelog utility to decode some - machine check error logs. See - ftp://ftp.x86-64.org/pub/linux/tools/mcelog - -config X86_MCE_INTEL - bool "Intel MCE features" - depends on X86_MCE && X86_LOCAL_APIC - default y - help - Additional support for intel specific MCE features such as - the thermal monitor. - -config X86_MCE_AMD - bool "AMD MCE features" - depends on X86_MCE && X86_LOCAL_APIC - default y - help - Additional support for AMD specific MCE features such as - the DRAM Error Threshold. - -config KEXEC - bool "kexec system call" - help - kexec is a system call that implements the ability to shutdown your - current kernel, and to start another kernel. It is like a reboot - but it is independent of the system firmware. And like a reboot - you can start any kernel with it, not just Linux. - - The name comes from the similarity to the exec system call. - - It is an ongoing process to be certain the hardware in a machine - is properly shutdown, so do not be surprised if this code does not - initially work for you. It may help to enable device hotplugging - support. As of this writing the exact hardware interface is - strongly in flux, so no good recommendation can be made. - -config CRASH_DUMP - bool "kernel crash dumps (EXPERIMENTAL)" - depends on EXPERIMENTAL - help - Generate crash dump after being started by kexec. - This should be normally only set in special crash dump kernels - which are loaded in the main kernel with kexec-tools into - a specially reserved region and then later executed after - a crash by kdump/kexec. The crash dump kernel must be compiled - to a memory address not used by the main kernel or BIOS using - PHYSICAL_START, or it must be built as a relocatable image - (CONFIG_RELOCATABLE=y). - For more details see Documentation/kdump/kdump.txt - -config RELOCATABLE - bool "Build a relocatable kernel (EXPERIMENTAL)" - depends on EXPERIMENTAL - help - Builds a relocatable kernel. This enables loading and running - a kernel binary from a different physical address than it has - been compiled for. - - One use is for the kexec on panic case where the recovery kernel - must live at a different physical address than the primary - kernel. - - Note: If CONFIG_RELOCATABLE=y, then the kernel runs from the address - it has been loaded at and the compile time physical address - (CONFIG_PHYSICAL_START) is ignored. - -config PHYSICAL_START - hex "Physical address where the kernel is loaded" if (EMBEDDED || CRASH_DUMP) - default "0x200000" - help - This gives the physical address where the kernel is loaded. It - should be aligned to 2MB boundary. - - If kernel is a not relocatable (CONFIG_RELOCATABLE=n) then - bzImage will decompress itself to above physical address and - run from there. Otherwise, bzImage will run from the address where - it has been loaded by the boot loader and will ignore above physical - address. - - In normal kdump cases one does not have to set/change this option - as now bzImage can be compiled as a completely relocatable image - (CONFIG_RELOCATABLE=y) and be used to load and run from a different - address. This option is mainly useful for the folks who don't want - to use a bzImage for capturing the crash dump and want to use a - vmlinux instead. - - So if you are using bzImage for capturing the crash dump, leave - the value here unchanged to 0x200000 and set CONFIG_RELOCATABLE=y. - Otherwise if you plan to use vmlinux for capturing the crash dump - change this value to start of the reserved region (Typically 16MB - 0x1000000). In other words, it can be set based on the "X" value as - specified in the "crashkernel=YM@XM" command line boot parameter - passed to the panic-ed kernel. Typically this parameter is set as - crashkernel=64M@16M. Please take a look at - Documentation/kdump/kdump.txt for more details about crash dumps. - - Usage of bzImage for capturing the crash dump is advantageous as - one does not have to build two kernels. Same kernel can be used - as production kernel and capture kernel. - - Don't change this unless you know what you are doing. - -config SECCOMP - bool "Enable seccomp to safely compute untrusted bytecode" - depends on PROC_FS - default y - help - This kernel feature is useful for number crunching applications - that may need to compute untrusted bytecode during their - execution. By using pipes or other transports made available to - the process as file descriptors supporting the read/write - syscalls, it's possible to isolate those applications in - their own address space using seccomp. Once seccomp is - enabled via /proc/<pid>/seccomp, it cannot be disabled - and the task is only allowed to execute a few safe syscalls - defined by each seccomp mode. - - If unsure, say Y. Only embedded should say N here. - -config CC_STACKPROTECTOR - bool "Enable -fstack-protector buffer overflow detection (EXPERIMENTAL)" - depends on EXPERIMENTAL - help - This option turns on the -fstack-protector GCC feature. This - feature puts, at the beginning of critical functions, a canary - value on the stack just before the return address, and validates - the value just before actually returning. Stack based buffer - overflows (that need to overwrite this return address) now also - overwrite the canary, which gets detected and the attack is then - neutralized via a kernel panic. - - This feature requires gcc version 4.2 or above, or a distribution - gcc with the feature backported. Older versions are automatically - detected and for those versions, this configuration option is ignored. - -config CC_STACKPROTECTOR_ALL - bool "Use stack-protector for all functions" - depends on CC_STACKPROTECTOR - help - Normally, GCC only inserts the canary value protection for - functions that use large-ish on-stack buffers. By enabling - this option, GCC will be asked to do this for ALL functions. - -source kernel/Kconfig.hz - -config K8_NB - def_bool y - depends on AGP_AMD64 || GART_IOMMU || (PCI && NUMA) - -endmenu - -# -# Use the generic interrupt handling code in kernel/irq/: -# -config GENERIC_HARDIRQS - bool - default y - -config GENERIC_IRQ_PROBE - bool - default y - -# we have no ISA slots, but we do have ISA-style DMA. -config ISA_DMA_API - bool - default y - -config GENERIC_PENDING_IRQ - bool - depends on GENERIC_HARDIRQS && SMP - default y - -menu "Power management options" - -source kernel/power/Kconfig - -config ARCH_HIBERNATION_HEADER - bool - depends on HIBERNATION - default y - -source "drivers/acpi/Kconfig" - -source "arch/x86/kernel/cpu/cpufreq/Kconfig_64" - -source "drivers/cpuidle/Kconfig" - -endmenu - -menu "Bus options (PCI etc.)" - -config PCI - bool "PCI support" - select ARCH_SUPPORTS_MSI if (X86_LOCAL_APIC && X86_IO_APIC) - -# x86-64 doesn't support PCI BIOS access from long mode so always go direct. -config PCI_DIRECT - bool - depends on PCI - default y - -config PCI_MMCONFIG - bool "Support mmconfig PCI config space access" - depends on PCI && ACPI - -config PCI_DOMAINS - bool - depends on PCI - default y - -config DMAR - bool "Support for DMA Remapping Devices (EXPERIMENTAL)" - depends on PCI_MSI && ACPI && EXPERIMENTAL - help - DMA remapping (DMAR) devices support enables independent address - translations for Direct Memory Access (DMA) from devices. - These DMA remapping devices are reported via ACPI tables - and include PCI device scope covered by these DMA - remapping devices. - -config DMAR_GFX_WA - bool "Support for Graphics workaround" - depends on DMAR - default y - help - Current Graphics drivers tend to use physical address - for DMA and avoid using DMA APIs. Setting this config - option permits the IOMMU driver to set a unity map for - all the OS-visible memory. Hence the driver can continue - to use physical addresses for DMA. - -config DMAR_FLOPPY_WA - bool - depends on DMAR - default y - help - Floppy disk drivers are know to bypass DMA API calls - thereby failing to work when IOMMU is enabled. This - workaround will setup a 1:1 mapping for the first - 16M to make floppy (an ISA device) work. - -source "drivers/pci/pcie/Kconfig" - -source "drivers/pci/Kconfig" - -source "drivers/pcmcia/Kconfig" - -source "drivers/pci/hotplug/Kconfig" - -endmenu - - -menu "Executable file formats / Emulations" - -source "fs/Kconfig.binfmt" - -config IA32_EMULATION - bool "IA32 Emulation" - help - Include code to run 32-bit programs under a 64-bit kernel. You should - likely turn this on, unless you're 100% sure that you don't have any - 32-bit programs left. - -config IA32_AOUT - tristate "IA32 a.out support" - depends on IA32_EMULATION - help - Support old a.out binaries in the 32bit emulation. - -config COMPAT - bool - depends on IA32_EMULATION - default y - -config COMPAT_FOR_U64_ALIGNMENT - def_bool COMPAT - -config SYSVIPC_COMPAT - bool - depends on COMPAT && SYSVIPC - default y - -endmenu - -source "net/Kconfig" - -source drivers/Kconfig - -source "drivers/firmware/Kconfig" - -source fs/Kconfig - -source "kernel/Kconfig.instrumentation" - -source "arch/x86/Kconfig.debug" - -source "security/Kconfig" - -source "crypto/Kconfig" - -source "lib/Kconfig" diff --git a/arch/x86/Makefile b/arch/x86/Makefile index 3095973..7aa1dc6 100644 --- a/arch/x86/Makefile +++ b/arch/x86/Makefile @@ -1,16 +1,19 @@ # Unified Makefile for i386 and x86_64 # select defconfig based on actual architecture -KBUILD_DEFCONFIG := $(ARCH)_defconfig +ifeq ($(ARCH),x86) + KBUILD_DEFCONFIG := i386_defconfig +else + KBUILD_DEFCONFIG := $(ARCH)_defconfig +endif -# # No need to remake these files +# No need to remake these files $(srctree)/arch/x86/Makefile%: ; -ifeq ($(ARCH),i386) +ifeq ($(CONFIG_X86_32),y) + UTS_MACHINE := i386 include $(srctree)/arch/x86/Makefile_32 else + UTS_MACHINE := x86_64 include $(srctree)/arch/x86/Makefile_64 endif - - - diff --git a/arch/x86/Makefile_32 b/arch/x86/Makefile_32 index 346ac07..50394da 100644 --- a/arch/x86/Makefile_32 +++ b/arch/x86/Makefile_32 @@ -160,7 +160,7 @@ archclean: $(Q)$(MAKE) $(clean)=arch/x86/boot define archhelp - echo '* bzImage - Compressed kernel image (arch/$(ARCH)/boot/bzImage)' + echo '* bzImage - Compressed kernel image (arch/x86/boot/bzImage)' echo ' install - Install kernel using' echo ' (your) ~/bin/installkernel or' echo ' (distribution) /sbin/installkernel or' @@ -170,6 +170,6 @@ define archhelp echo ' isoimage - Create a boot CD-ROM image' endef -CLEAN_FILES += arch/$(ARCH)/boot/fdimage \ - arch/$(ARCH)/boot/image.iso \ - arch/$(ARCH)/boot/mtools.conf +CLEAN_FILES += arch/x86/boot/fdimage \ + arch/x86/boot/image.iso \ + arch/x86/boot/mtools.conf diff --git a/arch/x86/Makefile_64 b/arch/x86/Makefile_64 index 57e714a..a804860 100644 --- a/arch/x86/Makefile_64 +++ b/arch/x86/Makefile_64 @@ -127,7 +127,7 @@ archclean: $(Q)$(MAKE) $(clean)=$(boot) define archhelp - echo '* bzImage - Compressed kernel image (arch/$(ARCH)/boot/bzImage)' + echo '* bzImage - Compressed kernel image (arch/x86/boot/bzImage)' echo ' install - Install kernel using' echo ' (your) ~/bin/installkernel or' echo ' (distribution) /sbin/installkernel or' @@ -137,8 +137,8 @@ define archhelp echo ' isoimage - Create a boot CD-ROM image' endef -CLEAN_FILES += arch/$(ARCH)/boot/fdimage \ - arch/$(ARCH)/boot/image.iso \ - arch/$(ARCH)/boot/mtools.conf +CLEAN_FILES += arch/x86/boot/fdimage \ + arch/x86/boot/image.iso \ + arch/x86/boot/mtools.conf diff --git a/arch/x86/boot/Makefile b/arch/x86/boot/Makefile index 89dbf97..7a3116c 100644 --- a/arch/x86/boot/Makefile +++ b/arch/x86/boot/Makefile @@ -49,10 +49,10 @@ HOSTCFLAGS_build.o := $(LINUXINCLUDE) # How to compile the 16-bit code. Note we always compile for -march=i386, # that way we can complain to the user if the CPU is insufficient. -cflags-i386 := -cflags-x86_64 := -m32 +cflags-$(CONFIG_X86_32) := +cflags-$(CONFIG_X86_64) := -m32 KBUILD_CFLAGS := $(LINUXINCLUDE) -g -Os -D_SETUP -D__KERNEL__ \ - $(cflags-$(ARCH)) \ + $(cflags-y) \ -Wall -Wstrict-prototypes \ -march=i386 -mregparm=3 \ -include $(srctree)/$(src)/code16gcc.h \ diff --git a/arch/x86/boot/cpucheck.c b/arch/x86/boot/cpucheck.c index e655a89..769065b 100644 --- a/arch/x86/boot/cpucheck.c +++ b/arch/x86/boot/cpucheck.c @@ -42,13 +42,7 @@ static struct cpu_features cpu; static u32 cpu_vendor[3]; static u32 err_flags[NCAPINTS]; -#ifdef CONFIG_X86_64 -static const int req_level = 64; -#elif defined(CONFIG_X86_MINIMUM_CPU_FAMILY) static const int req_level = CONFIG_X86_MINIMUM_CPU_FAMILY; -#else -static const int req_level = 3; -#endif static const u32 req_flags[NCAPINTS] = { diff --git a/arch/x86/boot/header.S b/arch/x86/boot/header.S index 6ef5a06..4cc5b04 100644 --- a/arch/x86/boot/header.S +++ b/arch/x86/boot/header.S @@ -236,39 +236,30 @@ start_of_setup: movw %ax, %es cld -# Apparently some ancient versions of LILO invoked the kernel -# with %ss != %ds, which happened to work by accident for the -# old code. If the CAN_USE_HEAP flag is set in loadflags, or -# %ss != %ds, then adjust the stack pointer. +# Apparently some ancient versions of LILO invoked the kernel with %ss != %ds, +# which happened to work by accident for the old code. Recalculate the stack +# pointer if %ss is invalid. Otherwise leave it alone, LOADLIN sets up the +# stack behind its own code, so we can't blindly put it directly past the heap. - # Smallest possible stack we can tolerate - movw $(_end+STACK_SIZE), %cx - - movw heap_end_ptr, %dx - addw $512, %dx - jnc 1f - xorw %dx, %dx # Wraparound - whole segment available -1: testb $CAN_USE_HEAP, loadflags - jnz 2f - - # No CAN_USE_HEAP movw %ss, %dx cmpw %ax, %dx # %ds == %ss? movw %sp, %dx - # If so, assume %sp is reasonably set, otherwise use - # the smallest possible stack. - jne 4f # -> Smallest possible stack... + je 2f # -> assume %sp is reasonably set + + # Invalid %ss, make up a new stack + movw $_end, %dx + testb $CAN_USE_HEAP, loadflags + jz 1f + movw heap_end_ptr, %dx +1: addw $STACK_SIZE, %dx + jnc 2f + xorw %dx, %dx # Prevent wraparound - # Make sure the stack is at least minimum size. Take a value - # of zero to mean "full segment." -2: +2: # Now %dx should point to the end of our stack space andw $~3, %dx # dword align (might as well...) jnz 3f movw $0xfffc, %dx # Make sure we're not zero -3: cmpw %cx, %dx - jnb 5f -4: movw %cx, %dx # Minimum value we can possibly use -5: movw %ax, %ss +3: movw %ax, %ss movzwl %dx, %esp # Clear upper half of %esp sti # Now we should have a working stack diff --git a/arch/x86/ia32/ia32entry.S b/arch/x86/ia32/ia32entry.S index 18b2318..df588f0 100644 --- a/arch/x86/ia32/ia32entry.S +++ b/arch/x86/ia32/ia32entry.S @@ -159,20 +159,16 @@ sysenter_do_call: sysenter_tracesys: CFI_RESTORE_STATE + xchgl %r9d,%ebp SAVE_REST CLEAR_RREGS + movq %r9,R9(%rsp) movq $-ENOSYS,RAX(%rsp) /* really needed? */ movq %rsp,%rdi /* &pt_regs -> arg1 */ call syscall_trace_enter LOAD_ARGS32 ARGOFFSET /* reload args from stack in case ptrace changed it */ RESTORE_REST - movl %ebp, %ebp - /* no need to do an access_ok check here because rbp has been - 32bit zero extended */ -1: movl (%rbp),%r9d - .section __ex_table,"a" - .quad 1b,ia32_badarg - .previous + xchgl %ebp,%r9d jmp sysenter_do_call CFI_ENDPROC ENDPROC(ia32_sysenter_target) @@ -262,20 +258,17 @@ cstar_do_call: cstar_tracesys: CFI_RESTORE_STATE + xchgl %r9d,%ebp SAVE_REST CLEAR_RREGS + movq %r9,R9(%rsp) movq $-ENOSYS,RAX(%rsp) /* really needed? */ movq %rsp,%rdi /* &pt_regs -> arg1 */ call syscall_trace_enter LOAD_ARGS32 ARGOFFSET /* reload args from stack in case ptrace changed it */ RESTORE_REST + xchgl %ebp,%r9d movl RSP-ARGOFFSET(%rsp), %r8d - /* no need to do an access_ok check here because r8 has been - 32bit zero extended */ -1: movl (%r8),%r9d - .section __ex_table,"a" - .quad 1b,ia32_badarg - .previous jmp cstar_do_call END(ia32_cstar_target) diff --git a/arch/x86/ia32/ptrace32.c b/arch/x86/ia32/ptrace32.c index f52770e..4a233ad 100644 --- a/arch/x86/ia32/ptrace32.c +++ b/arch/x86/ia32/ptrace32.c @@ -228,8 +228,6 @@ static long ptrace32_siginfo(unsigned request, u32 pid, u32 addr, u32 data) return ret; } -#define COMPAT_GDT_ENTRY_TLS_MIN 6 - asmlinkage long sys32_ptrace(long request, u32 pid, u32 addr, u32 data) { struct task_struct *child; @@ -248,6 +246,8 @@ asmlinkage long sys32_ptrace(long request, u32 pid, u32 addr, u32 data) case PTRACE_SYSCALL: case PTRACE_OLDSETOPTIONS: case PTRACE_SETOPTIONS: + case PTRACE_SET_THREAD_AREA: + case PTRACE_GET_THREAD_AREA: return sys_ptrace(request, pid, addr, data); default: @@ -271,12 +271,6 @@ asmlinkage long sys32_ptrace(long request, u32 pid, u32 addr, u32 data) case PTRACE_SETSIGINFO: case PTRACE_GETSIGINFO: return ptrace32_siginfo(request, pid, addr, data); - - case PTRACE_SET_THREAD_AREA: - case PTRACE_GET_THREAD_AREA: - return sys_ptrace(request, pid, - addr + GDT_ENTRY_TLS_MIN - COMPAT_GDT_ENTRY_TLS_MIN, - data); } child = ptrace_get_task_struct(pid); diff --git a/arch/x86/kernel/Makefile_32 b/arch/x86/kernel/Makefile_32 index b9d6798..a7bc93c 100644 --- a/arch/x86/kernel/Makefile_32 +++ b/arch/x86/kernel/Makefile_32 @@ -3,6 +3,7 @@ # extra-y := head_32.o init_task.o vmlinux.lds +CPPFLAGS_vmlinux.lds += -Ui386 obj-y := process_32.o signal_32.o entry_32.o traps_32.o irq_32.o \ ptrace_32.o time_32.o ioport_32.o ldt_32.o setup_32.o i8259_32.o sys_i386_32.o \ @@ -60,7 +61,7 @@ quiet_cmd_syscall = SYSCALL $@ cmd_syscall = $(CC) -m elf_i386 -nostdlib $(SYSCFLAGS_$(@F)) \ -Wl,-T,$(filter-out FORCE,$^) -o $@ -export CPPFLAGS_vsyscall_32.lds += -P -C -U$(ARCH) +export CPPFLAGS_vsyscall_32.lds += -P -C -Ui386 vsyscall-flags = -shared -s -Wl,-soname=linux-gate.so.1 \ $(call ld-option, -Wl$(comma)--hash-style=sysv) diff --git a/arch/x86/kernel/Makefile_64 b/arch/x86/kernel/Makefile_64 index 24671c3..5a88890 100644 --- a/arch/x86/kernel/Makefile_64 +++ b/arch/x86/kernel/Makefile_64 @@ -3,7 +3,9 @@ # extra-y := head_64.o head64.o init_task.o vmlinux.lds +CPPFLAGS_vmlinux.lds += -Ux86_64 EXTRA_AFLAGS := -traditional + obj-y := process_64.o signal_64.o entry_64.o traps_64.o irq_64.o \ ptrace_64.o time_64.o ioport_64.o ldt_64.o setup_64.o i8259_64.o sys_x86_64.o \ x8664_ksyms_64.o i387_64.o syscall_64.o vsyscall_64.o \ diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c index 289247d..0ca27c7 100644 --- a/arch/x86/kernel/acpi/boot.c +++ b/arch/x86/kernel/acpi/boot.c @@ -637,6 +637,38 @@ static int __init acpi_parse_hpet(struct acpi_table_header *table) } hpet_address = hpet_tbl->address.address; + + /* + * Some broken BIOSes advertise HPET at 0x0. We really do not + * want to allocate a resource there. + */ + if (!hpet_address) { + printk(KERN_WARNING PREFIX + "HPET id: %#x base: %#lx is invalid\n", + hpet_tbl->id, hpet_address); + return 0; + } +#ifdef CONFIG_X86_64 + /* + * Some even more broken BIOSes advertise HPET at + * 0xfed0000000000000 instead of 0xfed00000. Fix it up and add + * some noise: + */ + if (hpet_address == 0xfed0000000000000UL) { + if (!hpet_force_user) { + printk(KERN_WARNING PREFIX "HPET id: %#x " + "base: 0xfed0000000000000 is bogus\n " + "try hpet=force on the kernel command line to " + "fix it up to 0xfed00000.\n", hpet_tbl->id); + hpet_address = 0; + return 0; + } + printk(KERN_WARNING PREFIX + "HPET id: %#x base: 0xfed0000000000000 fixed up " + "to 0xfed00000.\n", hpet_tbl->id); + hpet_address >>= 32; + } +#endif printk(KERN_INFO PREFIX "HPET id: %#x base: %#lx\n", hpet_tbl->id, hpet_address); diff --git a/arch/x86/kernel/acpi/processor.c b/arch/x86/kernel/acpi/processor.c index f63e5ff..a25db51 100644 --- a/arch/x86/kernel/acpi/processor.c +++ b/arch/x86/kernel/acpi/processor.c @@ -49,6 +49,9 @@ static void init_intel_pdc(struct acpi_processor *pr, struct cpuinfo_x86 *c) if (cpu_has(c, X86_FEATURE_EST)) buf[2] |= ACPI_PDC_EST_CAPABILITY_SWSMP; + if (cpu_has(c, X86_FEATURE_ACPI)) + buf[2] |= ACPI_PDC_T_FFH; + obj->type = ACPI_TYPE_BUFFER; obj->buffer.length = 12; obj->buffer.pointer = (u8 *) buf; diff --git a/arch/x86/kernel/acpi/sleep_64.c b/arch/x86/kernel/acpi/sleep_64.c index 79475d2..da42de2 100644 --- a/arch/x86/kernel/acpi/sleep_64.c +++ b/arch/x86/kernel/acpi/sleep_64.c @@ -115,6 +115,3 @@ static int __init acpi_sleep_setup(char *str) __setup("acpi_sleep=", acpi_sleep_setup); -void acpi_pci_link_exit(void) -{ -} diff --git a/arch/x86/kernel/apic_32.c b/arch/x86/kernel/apic_32.c index 08b07c1..96986b4 100644 --- a/arch/x86/kernel/apic_32.c +++ b/arch/x86/kernel/apic_32.c @@ -789,7 +789,7 @@ void __init sync_Arb_IDs(void) * Unsupported on P4 - see Intel Dev. Manual Vol. 3, Ch. 8.6.1 And not * needed on AMD. */ - if (modern_apic()) + if (modern_apic() || boot_cpu_data.x86_vendor == X86_VENDOR_AMD) return; /* * Wait for idle. diff --git a/arch/x86/kernel/cpu/cpufreq/Kconfig_32 b/arch/x86/kernel/cpu/cpufreq/Kconfig index d8c6f13..151eda0 100644 --- a/arch/x86/kernel/cpu/cpufreq/Kconfig_32 +++ b/arch/x86/kernel/cpu/cpufreq/Kconfig @@ -19,6 +19,9 @@ config X86_ACPI_CPUFREQ Processor Performance States. This driver also supports Intel Enhanced Speedstep. + To compile this driver as a module, choose M here: the + module will be called acpi-cpufreq. + For details, take a look at <file:Documentation/cpu-freq/>. If in doubt, say N. @@ -26,7 +29,7 @@ config X86_ACPI_CPUFREQ config ELAN_CPUFREQ tristate "AMD Elan SC400 and SC410" select CPU_FREQ_TABLE - depends on X86_ELAN + depends on X86_32 && X86_ELAN ---help--- This adds the CPUFreq driver for AMD Elan SC400 and SC410 processors. @@ -42,7 +45,7 @@ config ELAN_CPUFREQ config SC520_CPUFREQ tristate "AMD Elan SC520" select CPU_FREQ_TABLE - depends on X86_ELAN + depends on X86_32 && X86_ELAN ---help--- This adds the CPUFreq driver for AMD Elan SC520 processor. @@ -54,6 +57,7 @@ config SC520_CPUFREQ config X86_POWERNOW_K6 tristate "AMD Mobile K6-2/K6-3 PowerNow!" select CPU_FREQ_TABLE + depends on X86_32 help This adds the CPUFreq driver for mobile AMD K6-2+ and mobile AMD K6-3+ processors. @@ -65,6 +69,7 @@ config X86_POWERNOW_K6 config X86_POWERNOW_K7 tristate "AMD Mobile Athlon/Duron PowerNow!" select CPU_FREQ_TABLE + depends on X86_32 help This adds the CPUFreq driver for mobile AMD K7 mobile processors. @@ -76,23 +81,27 @@ config X86_POWERNOW_K7_ACPI bool depends on X86_POWERNOW_K7 && ACPI_PROCESSOR depends on !(X86_POWERNOW_K7 = y && ACPI_PROCESSOR = m) + depends on X86_32 default y config X86_POWERNOW_K8 tristate "AMD Opteron/Athlon64 PowerNow!" select CPU_FREQ_TABLE - depends on EXPERIMENTAL help This adds the CPUFreq driver for mobile AMD Opteron/Athlon64 processors. + To compile this driver as a module, choose M here: the + module will be called powernow-k8. + For details, take a look at <file:Documentation/cpu-freq/>. If in doubt, say N. config X86_POWERNOW_K8_ACPI - bool "ACPI Support" - select ACPI_PROCESSOR - depends on ACPI && X86_POWERNOW_K8 + bool + prompt "ACPI Support" if X86_32 + depends on ACPI && X86_POWERNOW_K8 && ACPI_PROCESSOR + depends on !(X86_POWERNOW_K8 = y && ACPI_PROCESSOR = m) default y help This provides access to the K8s Processor Performance States via ACPI. @@ -104,7 +113,7 @@ config X86_POWERNOW_K8_ACPI config X86_GX_SUSPMOD tristate "Cyrix MediaGX/NatSemi Geode Suspend Modulation" - depends on PCI + depends on X86_32 && PCI help This add the CPUFreq driver for NatSemi Geode processors which support suspend modulation. @@ -114,15 +123,20 @@ config X86_GX_SUSPMOD If in doubt, say N. config X86_SPEEDSTEP_CENTRINO - tristate "Intel Enhanced SpeedStep" + tristate "Intel Enhanced SpeedStep (deprecated)" select CPU_FREQ_TABLE - select X86_SPEEDSTEP_CENTRINO_TABLE + select X86_SPEEDSTEP_CENTRINO_TABLE if X86_32 + depends on X86_32 || (X86_64 && ACPI_PROCESSOR) help + This is deprecated and this functionality is now merged into + acpi_cpufreq (X86_ACPI_CPUFREQ). Use that driver instead of + speedstep_centrino. This adds the CPUFreq driver for Enhanced SpeedStep enabled - mobile CPUs. This means Intel Pentium M (Centrino) CPUs. However, - you also need to say Y to "Use ACPI tables to decode..." below - [which might imply enabling ACPI] if you want to use this driver - on non-Banias CPUs. + mobile CPUs. This means Intel Pentium M (Centrino) CPUs + or 64bit enabled Intel Xeons. + + To compile this driver as a module, choose M here: the + module will be called speedstep-centrino. For details, take a look at <file:Documentation/cpu-freq/>. @@ -130,7 +144,7 @@ config X86_SPEEDSTEP_CENTRINO config X86_SPEEDSTEP_CENTRINO_TABLE bool "Built-in tables for Banias CPUs" - depends on X86_SPEEDSTEP_CENTRINO + depends on X86_32 && X86_SPEEDSTEP_CENTRINO default y help Use built-in tables for Banias CPUs if ACPI encoding @@ -141,6 +155,7 @@ config X86_SPEEDSTEP_CENTRINO_TABLE config X86_SPEEDSTEP_ICH tristate "Intel Speedstep on ICH-M chipsets (ioport interface)" select CPU_FREQ_TABLE + depends on X86_32 help This adds the CPUFreq driver for certain mobile Intel Pentium III (Coppermine), all mobile Intel Pentium III-M (Tualatin) and all @@ -154,7 +169,7 @@ config X86_SPEEDSTEP_ICH config X86_SPEEDSTEP_SMI tristate "Intel SpeedStep on 440BX/ZX/MX chipsets (SMI interface)" select CPU_FREQ_TABLE - depends on EXPERIMENTAL + depends on X86_32 && EXPERIMENTAL help This adds the CPUFreq driver for certain mobile Intel Pentium III (Coppermine), all mobile Intel Pentium III-M (Tualatin) @@ -169,15 +184,24 @@ config X86_P4_CLOCKMOD select CPU_FREQ_TABLE help This adds the CPUFreq driver for Intel Pentium 4 / XEON - processors. + processors. When enabled it will lower CPU temperature by skipping + clocks. + + This driver should be only used in exceptional + circumstances when very low power is needed because it causes severe + slowdowns and noticeable latencies. Normally Speedstep should be used + instead. + + To compile this driver as a module, choose M here: the + module will be called p4-clockmod. For details, take a look at <file:Documentation/cpu-freq/>. - If in doubt, say N. + Unless you are absolutely sure say N. config X86_CPUFREQ_NFORCE2 tristate "nVidia nForce2 FSB changing" - depends on EXPERIMENTAL + depends on X86_32 && EXPERIMENTAL help This adds the CPUFreq driver for FSB changing on nVidia nForce2 platforms. @@ -188,6 +212,7 @@ config X86_CPUFREQ_NFORCE2 config X86_LONGRUN tristate "Transmeta LongRun" + depends on X86_32 help This adds the CPUFreq driver for Transmeta Crusoe and Efficeon processors which support LongRun. @@ -199,7 +224,7 @@ config X86_LONGRUN config X86_LONGHAUL tristate "VIA Cyrix III Longhaul" select CPU_FREQ_TABLE - depends on ACPI_PROCESSOR + depends on X86_32 && ACPI_PROCESSOR help This adds the CPUFreq driver for VIA Samuel/CyrixIII, VIA Cyrix Samuel/C3, VIA Cyrix Ezra and VIA Cyrix Ezra-T @@ -212,7 +237,7 @@ config X86_LONGHAUL config X86_E_POWERSAVER tristate "VIA C7 Enhanced PowerSaver (EXPERIMENTAL)" select CPU_FREQ_TABLE - depends on EXPERIMENTAL + depends on X86_32 && EXPERIMENTAL help This adds the CPUFreq driver for VIA C7 processors. @@ -233,11 +258,11 @@ config X86_ACPI_CPUFREQ_PROC_INTF config X86_SPEEDSTEP_LIB tristate - default X86_SPEEDSTEP_ICH || X86_SPEEDSTEP_SMI || X86_P4_CLOCKMOD + default (X86_SPEEDSTEP_ICH || X86_SPEEDSTEP_SMI || X86_P4_CLOCKMOD) config X86_SPEEDSTEP_RELAXED_CAP_CHECK bool "Relaxed speedstep capability checks" - depends on (X86_SPEEDSTEP_SMI || X86_SPEEDSTEP_ICH) + depends on X86_32 && (X86_SPEEDSTEP_SMI || X86_SPEEDSTEP_ICH) help Don't perform all checks for a speedstep capable system which would normally be done. Some ancient or strange systems, though speedstep diff --git a/arch/x86/kernel/cpu/cpufreq/Kconfig_64 b/arch/x86/kernel/cpu/cpufreq/Kconfig_64 deleted file mode 100644 index 9c9699f..0000000 --- a/arch/x86/kernel/cpu/cpufreq/Kconfig_64 +++ /dev/null @@ -1,108 +0,0 @@ -# -# CPU Frequency scaling -# - -menu "CPU Frequency scaling" - -source "drivers/cpufreq/Kconfig" - -if CPU_FREQ - -comment "CPUFreq processor drivers" - -config X86_POWERNOW_K8 - tristate "AMD Opteron/Athlon64 PowerNow!" - select CPU_FREQ_TABLE - help - This adds the CPUFreq driver for mobile AMD Opteron/Athlon64 processors. - - To compile this driver as a module, choose M here: the - module will be called powernow-k8. - - For details, take a look at <file:Documentation/cpu-freq/>. - - If in doubt, say N. - -config X86_POWERNOW_K8_ACPI - bool - depends on X86_POWERNOW_K8 && ACPI_PROCESSOR - depends on !(X86_POWERNOW_K8 = y && ACPI_PROCESSOR = m) - default y - -config X86_SPEEDSTEP_CENTRINO - tristate "Intel Enhanced SpeedStep (deprecated)" - select CPU_FREQ_TABLE - depends on ACPI_PROCESSOR - help - This is deprecated and this functionality is now merged into - acpi_cpufreq (X86_ACPI_CPUFREQ). Use that driver instead of - speedstep_centrino. - This adds the CPUFreq driver for Enhanced SpeedStep enabled - mobile CPUs. This means Intel Pentium M (Centrino) CPUs - or 64bit enabled Intel Xeons. - - To compile this driver as a module, choose M here: the - module will be called speedstep-centrino. - - For details, take a look at <file:Documentation/cpu-freq/>. - - If in doubt, say N. - -config X86_ACPI_CPUFREQ - tristate "ACPI Processor P-States driver" - select CPU_FREQ_TABLE - depends on ACPI_PROCESSOR - help - This driver adds a CPUFreq driver which utilizes the ACPI - Processor Performance States. - This driver also supports Intel Enhanced Speedstep. - - To compile this driver as a module, choose M here: the - module will be called acpi-cpufreq. - - For details, take a look at <file:Documentation/cpu-freq/>. - - If in doubt, say N. - -comment "shared options" - -config X86_ACPI_CPUFREQ_PROC_INTF - bool "/proc/acpi/processor/../performance interface (deprecated)" - depends on PROC_FS - depends on X86_ACPI_CPUFREQ || X86_POWERNOW_K8_ACPI - help - This enables the deprecated /proc/acpi/processor/../performance - interface. While it is helpful for debugging, the generic, - cross-architecture cpufreq interfaces should be used. - - If in doubt, say N. - -config X86_P4_CLOCKMOD - tristate "Intel Pentium 4 clock modulation" - depends on EMBEDDED - select CPU_FREQ_TABLE - help - This adds the clock modulation driver for Intel Pentium 4 / XEON - processors. When enabled it will lower CPU temperature by skipping - clocks. - - This driver should be only used in exceptional - circumstances when very low power is needed because it causes severe - slowdowns and noticeable latencies. Normally Speedstep should be used - instead. - - To compile this driver as a module, choose M here: the - module will be called p4-clockmod. - - For details, take a look at <file:Documentation/cpu-freq/>. - - Unless you are absolutely sure say N. - - -config X86_SPEEDSTEP_LIB - tristate - default X86_P4_CLOCKMOD - -endif - -endmenu diff --git a/arch/x86/kernel/cpu/cpufreq/powernow-k8.c b/arch/x86/kernel/cpu/cpufreq/powernow-k8.c index 9c36a53..99e1ef9 100644 --- a/arch/x86/kernel/cpu/cpufreq/powernow-k8.c +++ b/arch/x86/kernel/cpu/cpufreq/powernow-k8.c @@ -46,7 +46,7 @@ #define PFX "powernow-k8: " #define BFX PFX "BIOS error: " -#define VERSION "version 2.00.00" +#define VERSION "version 2.20.00" #include "powernow-k8.h" /* serialize freq changes */ @@ -73,33 +73,11 @@ static u32 find_khz_freq_from_fid(u32 fid) return 1000 * find_freq_from_fid(fid); } -/* Return a frequency in MHz, given an input fid and did */ -static u32 find_freq_from_fiddid(u32 fid, u32 did) +static u32 find_khz_freq_from_pstate(struct cpufreq_frequency_table *data, u32 pstate) { - if (current_cpu_data.x86 == 0x10) - return 100 * (fid + 0x10) >> did; - else - return 100 * (fid + 0x8) >> did; -} - -static u32 find_khz_freq_from_fiddid(u32 fid, u32 did) -{ - return 1000 * find_freq_from_fiddid(fid, did); -} - -static u32 find_fid_from_pstate(u32 pstate) -{ - u32 hi, lo; - rdmsr(MSR_PSTATE_DEF_BASE + pstate, lo, hi); - return lo & HW_PSTATE_FID_MASK; + return data[pstate].frequency; } -static u32 find_did_from_pstate(u32 pstate) -{ - u32 hi, lo; - rdmsr(MSR_PSTATE_DEF_BASE + pstate, lo, hi); - return (lo & HW_PSTATE_DID_MASK) >> HW_PSTATE_DID_SHIFT; -} /* Return the vco fid for an input fid * @@ -142,9 +120,7 @@ static int query_current_values_with_pending_wait(struct powernow_k8_data *data) if (cpu_family == CPU_HW_PSTATE) { rdmsr(MSR_PSTATE_STATUS, lo, hi); i = lo & HW_PSTATE_MASK; - rdmsr(MSR_PSTATE_DEF_BASE + i, lo, hi); - data->currfid = lo & HW_PSTATE_FID_MASK; - data->currdid = (lo & HW_PSTATE_DID_MASK) >> HW_PSTATE_DID_SHIFT; + data->currpstate = i; return 0; } do { @@ -295,7 +271,7 @@ static int decrease_vid_code_by_step(struct powernow_k8_data *data, u32 reqvid, static int transition_pstate(struct powernow_k8_data *data, u32 pstate) { wrmsr(MSR_PSTATE_CTRL, pstate, 0); - data->currfid = find_fid_from_pstate(pstate); + data->currpstate = pstate; return 0; } @@ -845,17 +821,20 @@ err_out: static int fill_powernow_table_pstate(struct powernow_k8_data *data, struct cpufreq_frequency_table *powernow_table) { int i; + u32 hi = 0, lo = 0; + rdmsr(MSR_PSTATE_CUR_LIMIT, hi, lo); + data->max_hw_pstate = (hi & HW_PSTATE_MAX_MASK) >> HW_PSTATE_MAX_SHIFT; for (i = 0; i < data->acpi_data.state_count; i++) { u32 index; u32 hi = 0, lo = 0; - u32 fid; - u32 did; index = data->acpi_data.states[i].control & HW_PSTATE_MASK; - if (index > MAX_HW_PSTATE) { + if (index > data->max_hw_pstate) { printk(KERN_ERR PFX "invalid pstate %d - bad value %d.\n", i, index); printk(KERN_ERR PFX "Please report to BIOS manufacturer\n"); + powernow_table[i].frequency = CPUFREQ_ENTRY_INVALID; + continue; } rdmsr(MSR_PSTATE_DEF_BASE + index, lo, hi); if (!(hi & HW_PSTATE_VALID_MASK)) { @@ -864,22 +843,9 @@ static int fill_powernow_table_pstate(struct powernow_k8_data *data, struct cpuf continue; } - fid = lo & HW_PSTATE_FID_MASK; - did = (lo & HW_PSTATE_DID_MASK) >> HW_PSTATE_DID_SHIFT; + powernow_table[i].index = index; - dprintk(" %d : fid 0x%x, did 0x%x\n", index, fid, did); - - powernow_table[i].index = index | (fid << HW_FID_INDEX_SHIFT) | (did << HW_DID_INDEX_SHIFT); - - powernow_table[i].frequency = find_khz_freq_from_fiddid(fid, did); - - if (powernow_table[i].frequency != (data->acpi_data.states[i].core_frequency * 1000)) { - printk(KERN_INFO PFX "invalid freq entries %u kHz vs. %u kHz\n", - powernow_table[i].frequency, - (unsigned int) (data->acpi_data.states[i].core_frequency * 1000)); - powernow_table[i].frequency = CPUFREQ_ENTRY_INVALID; - continue; - } + powernow_table[i].frequency = data->acpi_data.states[i].core_frequency * 1000; } return 0; } @@ -1020,22 +986,18 @@ static int transition_frequency_fidvid(struct powernow_k8_data *data, unsigned i /* Take a frequency, and issue the hardware pstate transition command */ static int transition_frequency_pstate(struct powernow_k8_data *data, unsigned int index) { - u32 fid = 0; - u32 did = 0; u32 pstate = 0; int res, i; struct cpufreq_freqs freqs; dprintk("cpu %d transition to index %u\n", smp_processor_id(), index); - /* get fid did for hardware pstate transition */ + /* get MSR index for hardware pstate transition */ pstate = index & HW_PSTATE_MASK; - if (pstate > MAX_HW_PSTATE) + if (pstate > data->max_hw_pstate) return 0; - fid = (index & HW_FID_INDEX_MASK) >> HW_FID_INDEX_SHIFT; - did = (index & HW_DID_INDEX_MASK) >> HW_DID_INDEX_SHIFT; - freqs.old = find_khz_freq_from_fiddid(data->currfid, data->currdid); - freqs.new = find_khz_freq_from_fiddid(fid, did); + freqs.old = find_khz_freq_from_pstate(data->powernow_table, data->currpstate); + freqs.new = find_khz_freq_from_pstate(data->powernow_table, pstate); for_each_cpu_mask(i, *(data->available_cores)) { freqs.cpu = i; @@ -1043,9 +1005,7 @@ static int transition_frequency_pstate(struct powernow_k8_data *data, unsigned i } res = transition_pstate(data, pstate); - data->currfid = find_fid_from_pstate(pstate); - data->currdid = find_did_from_pstate(pstate); - freqs.new = find_khz_freq_from_fiddid(data->currfid, data->currdid); + freqs.new = find_khz_freq_from_pstate(data->powernow_table, pstate); for_each_cpu_mask(i, *(data->available_cores)) { freqs.cpu = i; @@ -1090,10 +1050,7 @@ static int powernowk8_target(struct cpufreq_policy *pol, unsigned targfreq, unsi if (query_current_values_with_pending_wait(data)) goto err_out; - if (cpu_family == CPU_HW_PSTATE) - dprintk("targ: curr fid 0x%x, did 0x%x\n", - data->currfid, data->currdid); - else { + if (cpu_family != CPU_HW_PSTATE) { dprintk("targ: curr fid 0x%x, vid 0x%x\n", data->currfid, data->currvid); @@ -1124,7 +1081,7 @@ static int powernowk8_target(struct cpufreq_policy *pol, unsigned targfreq, unsi mutex_unlock(&fidvid_mutex); if (cpu_family == CPU_HW_PSTATE) - pol->cur = find_khz_freq_from_fiddid(data->currfid, data->currdid); + pol->cur = find_khz_freq_from_pstate(data->powernow_table, newstate); else pol->cur = find_khz_freq_from_fid(data->currfid); ret = 0; @@ -1223,7 +1180,7 @@ static int __cpuinit powernowk8_cpu_init(struct cpufreq_policy *pol) + (3 * (1 << data->irt) * 10)) * 1000; if (cpu_family == CPU_HW_PSTATE) - pol->cur = find_khz_freq_from_fiddid(data->currfid, data->currdid); + pol->cur = find_khz_freq_from_pstate(data->powernow_table, data->currpstate); else pol->cur = find_khz_freq_from_fid(data->currfid); dprintk("policy current frequency %d kHz\n", pol->cur); @@ -1240,8 +1197,7 @@ static int __cpuinit powernowk8_cpu_init(struct cpufreq_policy *pol) cpufreq_frequency_table_get_attr(data->powernow_table, pol->cpu); if (cpu_family == CPU_HW_PSTATE) - dprintk("cpu_init done, current fid 0x%x, did 0x%x\n", - data->currfid, data->currdid); + dprintk("cpu_init done, current pstate 0x%x\n", data->currpstate); else dprintk("cpu_init done, current fid 0x%x, vid 0x%x\n", data->currfid, data->currvid); @@ -1297,7 +1253,7 @@ static unsigned int powernowk8_get (unsigned int cpu) goto out; if (cpu_family == CPU_HW_PSTATE) - khz = find_khz_freq_from_fiddid(data->currfid, data->currdid); + khz = find_khz_freq_from_pstate(data->powernow_table, data->currpstate); else khz = find_khz_freq_from_fid(data->currfid); diff --git a/arch/x86/kernel/cpu/cpufreq/powernow-k8.h b/arch/x86/kernel/cpu/cpufreq/powernow-k8.h index 7c4f6e0..afd2b52 100644 --- a/arch/x86/kernel/cpu/cpufreq/powernow-k8.h +++ b/arch/x86/kernel/cpu/cpufreq/powernow-k8.h @@ -10,6 +10,7 @@ struct powernow_k8_data { u32 numps; /* number of p-states */ u32 batps; /* number of p-states supported on battery */ + u32 max_hw_pstate; /* maximum legal hardware pstate */ /* these values are constant when the PSB is used to determine * vid/fid pairings, but are modified during the ->target() call @@ -21,8 +22,8 @@ struct powernow_k8_data { u32 plllock; /* pll lock time, units 1 us */ u32 exttype; /* extended interface = 1 */ - /* keep track of the current fid / vid or did */ - u32 currvid, currfid, currdid; + /* keep track of the current fid / vid or pstate */ + u32 currvid, currfid, currpstate; /* the powernow_table includes all frequency and vid/fid pairings: * fid are the lower 8 bits of the index, vid are the upper 8 bits. @@ -87,23 +88,14 @@ struct powernow_k8_data { /* Hardware Pstate _PSS and MSR definitions */ #define USE_HW_PSTATE 0x00000080 -#define HW_PSTATE_FID_MASK 0x0000003f -#define HW_PSTATE_DID_MASK 0x000001c0 -#define HW_PSTATE_DID_SHIFT 6 #define HW_PSTATE_MASK 0x00000007 #define HW_PSTATE_VALID_MASK 0x80000000 -#define HW_FID_INDEX_SHIFT 8 -#define HW_FID_INDEX_MASK 0x0000ff00 -#define HW_DID_INDEX_SHIFT 16 -#define HW_DID_INDEX_MASK 0x00ff0000 -#define HW_WATTS_MASK 0xff -#define HW_PWR_DVR_MASK 0x300 -#define HW_PWR_DVR_SHIFT 8 -#define HW_PWR_MAX_MULT 3 -#define MAX_HW_PSTATE 8 /* hw pstate supports up to 8 */ +#define HW_PSTATE_MAX_MASK 0x000000f0 +#define HW_PSTATE_MAX_SHIFT 4 #define MSR_PSTATE_DEF_BASE 0xc0010064 /* base of Pstate MSRs */ #define MSR_PSTATE_STATUS 0xc0010063 /* Pstate Status MSR */ #define MSR_PSTATE_CTRL 0xc0010062 /* Pstate control MSR */ +#define MSR_PSTATE_CUR_LIMIT 0xc0010061 /* pstate current limit MSR */ /* define the two driver architectures */ #define CPU_OPTERON 0 diff --git a/arch/x86/kernel/cpu/mcheck/mce_64.c b/arch/x86/kernel/cpu/mcheck/mce_64.c index b9f802e..4b21d29 100644 --- a/arch/x86/kernel/cpu/mcheck/mce_64.c +++ b/arch/x86/kernel/cpu/mcheck/mce_64.c @@ -802,13 +802,15 @@ static struct sysdev_attribute *mce_attributes[] = { NULL }; +static cpumask_t mce_device_initialized = CPU_MASK_NONE; + /* Per cpu sysdev init. All of the cpus still share the same ctl bank */ static __cpuinit int mce_create_device(unsigned int cpu) { int err; int i; - if (!mce_available(&cpu_data(cpu))) + if (!mce_available(&boot_cpu_data)) return -EIO; memset(&per_cpu(device_mce, cpu).kobj, 0, sizeof(struct kobject)); @@ -825,6 +827,7 @@ static __cpuinit int mce_create_device(unsigned int cpu) if (err) goto error; } + cpu_set(cpu, mce_device_initialized); return 0; error: @@ -841,10 +844,14 @@ static void mce_remove_device(unsigned int cpu) { int i; + if (!cpu_isset(cpu, mce_device_initialized)) + return; + for (i = 0; mce_attributes[i]; i++) sysdev_remove_file(&per_cpu(device_mce,cpu), mce_attributes[i]); sysdev_unregister(&per_cpu(device_mce,cpu)); + cpu_clear(cpu, mce_device_initialized); } /* Get notified when a cpu comes on/off. Be hotplug friendly. */ @@ -852,21 +859,18 @@ static int mce_cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu) { unsigned int cpu = (unsigned long)hcpu; - int err = 0; switch (action) { - case CPU_UP_PREPARE: - case CPU_UP_PREPARE_FROZEN: - err = mce_create_device(cpu); + case CPU_ONLINE: + case CPU_ONLINE_FROZEN: + mce_create_device(cpu); break; - case CPU_UP_CANCELED: - case CPU_UP_CANCELED_FROZEN: case CPU_DEAD: case CPU_DEAD_FROZEN: mce_remove_device(cpu); break; } - return err ? NOTIFY_BAD : NOTIFY_OK; + return NOTIFY_OK; } static struct notifier_block mce_cpu_notifier = { diff --git a/arch/x86/kernel/cpu/mtrr/main.c b/arch/x86/kernel/cpu/mtrr/main.c index 9abbdf7..3b20613 100644 --- a/arch/x86/kernel/cpu/mtrr/main.c +++ b/arch/x86/kernel/cpu/mtrr/main.c @@ -139,13 +139,12 @@ struct set_mtrr_data { mtrr_type smp_type; }; -#ifdef CONFIG_SMP - static void ipi_handler(void *info) /* [SUMMARY] Synchronisation handler. Executed by "other" CPUs. [RETURNS] Nothing. */ { +#ifdef CONFIG_SMP struct set_mtrr_data *data = info; unsigned long flags; @@ -168,9 +167,8 @@ static void ipi_handler(void *info) atomic_dec(&data->count); local_irq_restore(flags); -} - #endif +} static inline int types_compatible(mtrr_type type1, mtrr_type type2) { return type1 == MTRR_TYPE_UNCACHABLE || diff --git a/arch/x86/kernel/cpu/proc.c b/arch/x86/kernel/cpu/proc.c index 066f8c6..3900e46 100644 --- a/arch/x86/kernel/cpu/proc.c +++ b/arch/x86/kernel/cpu/proc.c @@ -89,8 +89,6 @@ static int show_cpuinfo(struct seq_file *m, void *v) int fpu_exception; #ifdef CONFIG_SMP - if (!cpu_online(n)) - return 0; n = c->cpu_index; #endif seq_printf(m, "processor\t: %d\n" @@ -177,14 +175,14 @@ static int show_cpuinfo(struct seq_file *m, void *v) static void *c_start(struct seq_file *m, loff_t *pos) { if (*pos == 0) /* just in case, cpu 0 is not the first */ - *pos = first_cpu(cpu_possible_map); - if ((*pos) < NR_CPUS && cpu_possible(*pos)) + *pos = first_cpu(cpu_online_map); + if ((*pos) < NR_CPUS && cpu_online(*pos)) return &cpu_data(*pos); return NULL; } static void *c_next(struct seq_file *m, void *v, loff_t *pos) { - *pos = next_cpu(*pos, cpu_possible_map); + *pos = next_cpu(*pos, cpu_online_map); return c_start(m, pos); } static void c_stop(struct seq_file *m, void *v) diff --git a/arch/x86/kernel/i386_ksyms_32.c b/arch/x86/kernel/i386_ksyms_32.c index edd39cc..02112fc 100644 --- a/arch/x86/kernel/i386_ksyms_32.c +++ b/arch/x86/kernel/i386_ksyms_32.c @@ -2,6 +2,7 @@ #include <asm/semaphore.h> #include <asm/checksum.h> #include <asm/desc.h> +#include <asm/pgtable.h> EXPORT_SYMBOL(__down_failed); EXPORT_SYMBOL(__down_failed_interruptible); @@ -29,3 +30,4 @@ EXPORT_SYMBOL(__read_lock_failed); #endif EXPORT_SYMBOL(csum_partial); +EXPORT_SYMBOL(empty_zero_page); diff --git a/arch/x86/kernel/i387_64.c b/arch/x86/kernel/i387_64.c index 56c1f11..bfaff28 100644 --- a/arch/x86/kernel/i387_64.c +++ b/arch/x86/kernel/i387_64.c @@ -92,13 +92,14 @@ int save_i387(struct _fpstate __user *buf) if (task_thread_info(tsk)->status & TS_USEDFPU) { err = save_i387_checking((struct i387_fxsave_struct __user *)buf); if (err) return err; + task_thread_info(tsk)->status &= ~TS_USEDFPU; stts(); - } else { - if (__copy_to_user(buf, &tsk->thread.i387.fxsave, + } else { + if (__copy_to_user(buf, &tsk->thread.i387.fxsave, sizeof(struct i387_fxsave_struct))) return -1; - } - return 1; + } + return 1; } /* diff --git a/arch/x86/kernel/io_apic_32.c b/arch/x86/kernel/io_apic_32.c index f35c6eb..6cf2731 100644 --- a/arch/x86/kernel/io_apic_32.c +++ b/arch/x86/kernel/io_apic_32.c @@ -962,7 +962,7 @@ static int EISA_ELCR(unsigned int irq) #define default_MCA_trigger(idx) (1) #define default_MCA_polarity(idx) (0) -static int __init MPBIOS_polarity(int idx) +static int MPBIOS_polarity(int idx) { int bus = mp_irqs[idx].mpc_srcbus; int polarity; @@ -2166,6 +2166,10 @@ static inline void __init check_timer(void) { int apic1, pin1, apic2, pin2; int vector; + unsigned int ver; + + ver = apic_read(APIC_LVR); + ver = GET_APIC_VERSION(ver); /* * get/set the timer IRQ vector: @@ -2179,11 +2183,15 @@ static inline void __init check_timer(void) * mode for the 8259A whenever interrupts are routed * through I/O APICs. Also IRQ0 has to be enabled in * the 8259A which implies the virtual wire has to be - * disabled in the local APIC. + * disabled in the local APIC. Finally timer interrupts + * need to be acknowledged manually in the 8259A for + * timer_interrupt() and for the i82489DX when using + * the NMI watchdog. */ apic_write_around(APIC_LVT0, APIC_LVT_MASKED | APIC_DM_EXTINT); init_8259A(1); - timer_ack = 1; + timer_ack = !cpu_has_tsc; + timer_ack |= (nmi_watchdog == NMI_IO_APIC && !APIC_INTEGRATED(ver)); if (timer_over_8254 > 0) enable_8259A_irq(0); @@ -2830,6 +2838,25 @@ int io_apic_set_pci_routing (int ioapic, int pin, int irq, int edge_level, int a return 0; } +int acpi_get_override_irq(int bus_irq, int *trigger, int *polarity) +{ + int i; + + if (skip_ioapic_setup) + return -1; + + for (i = 0; i < mp_irq_entries; i++) + if (mp_irqs[i].mpc_irqtype == mp_INT && + mp_irqs[i].mpc_srcbusirq == bus_irq) + break; + if (i >= mp_irq_entries) + return -1; + + *trigger = irq_trigger(i); + *polarity = irq_polarity(i); + return 0; +} + #endif /* CONFIG_ACPI */ static int __init parse_disable_timer_pin_1(char *arg) diff --git a/arch/x86/kernel/io_apic_64.c b/arch/x86/kernel/io_apic_64.c index 953328b..435a8c9 100644 --- a/arch/x86/kernel/io_apic_64.c +++ b/arch/x86/kernel/io_apic_64.c @@ -546,7 +546,7 @@ int IO_APIC_get_PCI_irq_vector(int bus, int slot, int pin) #define default_PCI_trigger(idx) (1) #define default_PCI_polarity(idx) (1) -static int __init MPBIOS_polarity(int idx) +static int MPBIOS_polarity(int idx) { int bus = mp_irqs[idx].mpc_srcbus; int polarity; @@ -2222,8 +2222,27 @@ int io_apic_set_pci_routing (int ioapic, int pin, int irq, int triggering, int p return 0; } -#endif /* CONFIG_ACPI */ +int acpi_get_override_irq(int bus_irq, int *trigger, int *polarity) +{ + int i; + + if (skip_ioapic_setup) + return -1; + + for (i = 0; i < mp_irq_entries; i++) + if (mp_irqs[i].mpc_irqtype == mp_INT && + mp_irqs[i].mpc_srcbusirq == bus_irq) + break; + if (i >= mp_irq_entries) + return -1; + + *trigger = irq_trigger(i); + *polarity = irq_polarity(i); + return 0; +} + +#endif /* CONFIG_ACPI */ /* * This function currently is only a helper for the i386 smp boot process where @@ -2260,3 +2279,4 @@ void __init setup_ioapic_dest(void) } } #endif + diff --git a/arch/x86/kernel/kprobes_64.c b/arch/x86/kernel/kprobes_64.c index 3db3611..0c46764 100644 --- a/arch/x86/kernel/kprobes_64.c +++ b/arch/x86/kernel/kprobes_64.c @@ -58,7 +58,7 @@ const int kretprobe_blacklist_size = ARRAY_SIZE(kretprobe_blacklist); /* * returns non-zero if opcode modifies the interrupt flag. */ -static __always_inline int is_IF_modifier(kprobe_opcode_t *insn) +static int __kprobes is_IF_modifier(kprobe_opcode_t *insn) { switch (*insn) { case 0xfa: /* cli */ diff --git a/arch/x86/kernel/nmi_32.c b/arch/x86/kernel/nmi_32.c index f803ed0..f5cc47c 100644 --- a/arch/x86/kernel/nmi_32.c +++ b/arch/x86/kernel/nmi_32.c @@ -25,6 +25,7 @@ #include <asm/smp.h> #include <asm/nmi.h> +#include <asm/timer.h> #include "mach_traps.h" @@ -51,13 +52,13 @@ static int unknown_nmi_panic_callback(struct pt_regs *regs, int cpu); static int endflag __initdata = 0; -#ifdef CONFIG_SMP /* The performance counters used by NMI_LOCAL_APIC don't trigger when * the CPU is idle. To make sure the NMI watchdog really ticks on all * CPUs during the test make them busy. */ static __init void nmi_cpu_busy(void *data) { +#ifdef CONFIG_SMP local_irq_enable_in_hardirq(); /* Intentionally don't use cpu_relax here. This is to make sure that the performance counter really ticks, @@ -67,8 +68,8 @@ static __init void nmi_cpu_busy(void *data) care if they get somewhat less cycles. */ while (endflag == 0) mb(); -} #endif +} static int __init check_nmi_watchdog(void) { @@ -83,7 +84,7 @@ static int __init check_nmi_watchdog(void) prev_nmi_count = kmalloc(NR_CPUS * sizeof(int), GFP_KERNEL); if (!prev_nmi_count) - return -1; + goto error; printk(KERN_INFO "Testing NMI watchdog ... "); @@ -117,7 +118,7 @@ static int __init check_nmi_watchdog(void) if (!atomic_read(&nmi_active)) { kfree(prev_nmi_count); atomic_set(&nmi_active, -1); - return -1; + goto error; } printk("OK.\n"); @@ -128,6 +129,10 @@ static int __init check_nmi_watchdog(void) kfree(prev_nmi_count); return 0; +error: + timer_ack = !cpu_has_tsc; + + return -1; } /* This needs to happen later in boot so counters are working */ late_initcall(check_nmi_watchdog); diff --git a/arch/x86/kernel/paravirt_32.c b/arch/x86/kernel/paravirt_32.c index 6a80d67..f5000799 100644 --- a/arch/x86/kernel/paravirt_32.c +++ b/arch/x86/kernel/paravirt_32.c @@ -465,8 +465,8 @@ struct pv_mmu_ops pv_mmu_ops = { }; EXPORT_SYMBOL_GPL(pv_time_ops); -EXPORT_SYMBOL_GPL(pv_cpu_ops); -EXPORT_SYMBOL_GPL(pv_mmu_ops); +EXPORT_SYMBOL (pv_cpu_ops); +EXPORT_SYMBOL (pv_mmu_ops); EXPORT_SYMBOL_GPL(pv_apic_ops); EXPORT_SYMBOL_GPL(pv_info); EXPORT_SYMBOL (pv_irq_ops); diff --git a/arch/x86/kernel/pci-dma_64.c b/arch/x86/kernel/pci-dma_64.c index aa805b1..5552d23 100644 --- a/arch/x86/kernel/pci-dma_64.c +++ b/arch/x86/kernel/pci-dma_64.c @@ -12,7 +12,7 @@ #include <asm/gart.h> #include <asm/calgary.h> -int iommu_merge __read_mostly = 1; +int iommu_merge __read_mostly = 0; EXPORT_SYMBOL(iommu_merge); dma_addr_t bad_dma_address __read_mostly; diff --git a/arch/x86/kernel/reboot_fixups_32.c b/arch/x86/kernel/reboot_fixups_32.c index 1a07bbe..f452726 100644 --- a/arch/x86/kernel/reboot_fixups_32.c +++ b/arch/x86/kernel/reboot_fixups_32.c @@ -39,6 +39,7 @@ struct device_fixup { static struct device_fixup fixups_table[] = { { PCI_VENDOR_ID_CYRIX, PCI_DEVICE_ID_CYRIX_5530_LEGACY, cs5530a_warm_reset }, { PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CS5536_ISA, cs5536_warm_reset }, +{ PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_SC1100_BRIDGE, cs5530a_warm_reset }, }; /* diff --git a/arch/x86/kernel/setup_64.c b/arch/x86/kernel/setup_64.c index 238633d..30d94d1 100644 --- a/arch/x86/kernel/setup_64.c +++ b/arch/x86/kernel/setup_64.c @@ -892,7 +892,6 @@ void __cpuinit early_identify_cpu(struct cpuinfo_x86 *c) #ifdef CONFIG_SMP c->phys_proc_id = (cpuid_ebx(1) >> 24) & 0xff; - c->cpu_index = 0; #endif } @@ -1078,8 +1077,6 @@ static int show_cpuinfo(struct seq_file *m, void *v) #ifdef CONFIG_SMP - if (!cpu_online(c->cpu_index)) - return 0; cpu = c->cpu_index; #endif @@ -1171,15 +1168,15 @@ static int show_cpuinfo(struct seq_file *m, void *v) static void *c_start(struct seq_file *m, loff_t *pos) { if (*pos == 0) /* just in case, cpu 0 is not the first */ - *pos = first_cpu(cpu_possible_map); - if ((*pos) < NR_CPUS && cpu_possible(*pos)) + *pos = first_cpu(cpu_online_map); + if ((*pos) < NR_CPUS && cpu_online(*pos)) return &cpu_data(*pos); return NULL; } static void *c_next(struct seq_file *m, void *v, loff_t *pos) { - *pos = next_cpu(*pos, cpu_possible_map); + *pos = next_cpu(*pos, cpu_online_map); return c_start(m, pos); } diff --git a/arch/x86/kernel/time_64.c b/arch/x86/kernel/time_64.c index c821edc..368b194 100644 --- a/arch/x86/kernel/time_64.c +++ b/arch/x86/kernel/time_64.c @@ -82,18 +82,15 @@ static int set_rtc_mmss(unsigned long nowtime) int retval = 0; int real_seconds, real_minutes, cmos_minutes; unsigned char control, freq_select; + unsigned long flags; /* - * IRQs are disabled when we're called from the timer interrupt, - * no need for spin_lock_irqsave() + * set_rtc_mmss is called when irqs are enabled, so disable irqs here */ - - spin_lock(&rtc_lock); - + spin_lock_irqsave(&rtc_lock, flags); /* * Tell the clock it's being set and stop it. */ - control = CMOS_READ(RTC_CONTROL); CMOS_WRITE(control | RTC_SET, RTC_CONTROL); @@ -138,7 +135,7 @@ static int set_rtc_mmss(unsigned long nowtime) CMOS_WRITE(control, RTC_CONTROL); CMOS_WRITE(freq_select, RTC_FREQ_SELECT); - spin_unlock(&rtc_lock); + spin_unlock_irqrestore(&rtc_lock, flags); return retval; } @@ -164,21 +161,27 @@ unsigned long read_persistent_clock(void) unsigned century = 0; spin_lock_irqsave(&rtc_lock, flags); + /* + * if UIP is clear, then we have >= 244 microseconds before RTC + * registers will be updated. Spec sheet says that this is the + * reliable way to read RTC - registers invalid (off bus) during update + */ + while ((CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP)) + cpu_relax(); - do { - sec = CMOS_READ(RTC_SECONDS); - min = CMOS_READ(RTC_MINUTES); - hour = CMOS_READ(RTC_HOURS); - day = CMOS_READ(RTC_DAY_OF_MONTH); - mon = CMOS_READ(RTC_MONTH); - year = CMOS_READ(RTC_YEAR); + + /* now read all RTC registers while stable with interrupts disabled */ + sec = CMOS_READ(RTC_SECONDS); + min = CMOS_READ(RTC_MINUTES); + hour = CMOS_READ(RTC_HOURS); + day = CMOS_READ(RTC_DAY_OF_MONTH); + mon = CMOS_READ(RTC_MONTH); + year = CMOS_READ(RTC_YEAR); #ifdef CONFIG_ACPI - if (acpi_gbl_FADT.header.revision >= FADT2_REVISION_ID && - acpi_gbl_FADT.century) - century = CMOS_READ(acpi_gbl_FADT.century); + if (acpi_gbl_FADT.header.revision >= FADT2_REVISION_ID && + acpi_gbl_FADT.century) + century = CMOS_READ(acpi_gbl_FADT.century); #endif - } while (sec != CMOS_READ(RTC_SECONDS)); - spin_unlock_irqrestore(&rtc_lock, flags); /* diff --git a/arch/x86/kernel/traps_32.c b/arch/x86/kernel/traps_32.c index 298d13e..ef60102 100644 --- a/arch/x86/kernel/traps_32.c +++ b/arch/x86/kernel/traps_32.c @@ -283,6 +283,11 @@ void dump_stack(void) { unsigned long stack; + printk("Pid: %d, comm: %.20s %s %s %.*s\n", + current->pid, current->comm, print_tainted(), + init_utsname()->release, + (int)strcspn(init_utsname()->version, " "), + init_utsname()->version); show_trace(current, NULL, &stack); } @@ -828,6 +833,8 @@ fastcall void __kprobes do_debug(struct pt_regs * regs, long error_code) unsigned int condition; struct task_struct *tsk = current; + trace_hardirqs_fixup(); + get_debugreg(condition, 6); if (notify_die(DIE_DEBUG, "debug", regs, condition, error_code, diff --git a/arch/x86/kernel/traps_64.c b/arch/x86/kernel/traps_64.c index 4a6bd49..d11525a 100644 --- a/arch/x86/kernel/traps_64.c +++ b/arch/x86/kernel/traps_64.c @@ -31,6 +31,7 @@ #include <linux/uaccess.h> #include <linux/bug.h> #include <linux/kdebug.h> +#include <linux/utsname.h> #if defined(CONFIG_EDAC) #include <linux/edac.h> @@ -400,6 +401,12 @@ void show_stack(struct task_struct *tsk, unsigned long * rsp) void dump_stack(void) { unsigned long dummy; + + printk("Pid: %d, comm: %.20s %s %s %.*s\n", + current->pid, current->comm, print_tainted(), + init_utsname()->release, + (int)strcspn(init_utsname()->version, " "), + init_utsname()->version); show_trace(NULL, NULL, &dummy); } @@ -846,6 +853,8 @@ asmlinkage void __kprobes do_debug(struct pt_regs * regs, struct task_struct *tsk = current; siginfo_t info; + trace_hardirqs_fixup(); + get_debugreg(condition, 6); if (notify_die(DIE_DEBUG, "debug", regs, condition, error_code, diff --git a/arch/x86/lguest/Kconfig b/arch/x86/lguest/Kconfig index c4dffbe..19626ac 100644 --- a/arch/x86/lguest/Kconfig +++ b/arch/x86/lguest/Kconfig @@ -2,6 +2,7 @@ config LGUEST_GUEST bool "Lguest guest support" select PARAVIRT depends on !X86_PAE + depends on !(X86_VISWS || X86_VOYAGER) select VIRTIO select VIRTIO_RING select VIRTIO_CONSOLE diff --git a/arch/x86/lib/delay_32.c b/arch/x86/lib/delay_32.c index 952e7a8..aad9d95 100644 --- a/arch/x86/lib/delay_32.c +++ b/arch/x86/lib/delay_32.c @@ -12,6 +12,7 @@ #include <linux/module.h> #include <linux/sched.h> +#include <linux/preempt.h> #include <linux/delay.h> #include <asm/processor.h> @@ -42,11 +43,13 @@ static void delay_tsc(unsigned long loops) { unsigned long bclock, now; + preempt_disable(); /* TSC's are per-cpu */ rdtscl(bclock); do { rep_nop(); rdtscl(now); } while ((now-bclock) < loops); + preempt_enable(); } /* diff --git a/arch/x86/lib/delay_64.c b/arch/x86/lib/delay_64.c index 0ebbfb9..45cdd3f 100644 --- a/arch/x86/lib/delay_64.c +++ b/arch/x86/lib/delay_64.c @@ -10,7 +10,9 @@ #include <linux/module.h> #include <linux/sched.h> +#include <linux/preempt.h> #include <linux/delay.h> + #include <asm/delay.h> #include <asm/msr.h> @@ -27,14 +29,15 @@ int read_current_timer(unsigned long *timer_value) void __delay(unsigned long loops) { unsigned bclock, now; - + + preempt_disable(); /* TSC's are pre-cpu */ rdtscl(bclock); - do - { + do { rep_nop(); rdtscl(now); } - while((now-bclock) < loops); + while ((now-bclock) < loops); + preempt_enable(); } EXPORT_SYMBOL(__delay); diff --git a/arch/x86/mach-voyager/voyager_cat.c b/arch/x86/mach-voyager/voyager_cat.c index 26a2d4c..2132ca6 100644 --- a/arch/x86/mach-voyager/voyager_cat.c +++ b/arch/x86/mach-voyager/voyager_cat.c @@ -568,7 +568,7 @@ static voyager_module_t *voyager_initial_module; * boot cpu *after* all memory initialisation has been done (so we can * use kmalloc) but before smp initialisation, so we can probe the SMP * configuration and pick up necessary information. */ -void +void __init voyager_cat_init(void) { voyager_module_t **modpp = &voyager_initial_module; diff --git a/arch/x86/mach-voyager/voyager_smp.c b/arch/x86/mach-voyager/voyager_smp.c index 6937143..88124dd 100644 --- a/arch/x86/mach-voyager/voyager_smp.c +++ b/arch/x86/mach-voyager/voyager_smp.c @@ -1900,7 +1900,7 @@ voyager_smp_prepare_cpus(unsigned int max_cpus) smp_boot_cpus(); } -static void __devinit voyager_smp_prepare_boot_cpu(void) +static void __cpuinit voyager_smp_prepare_boot_cpu(void) { init_gdt(smp_processor_id()); switch_to_new_gdt(); @@ -1911,7 +1911,7 @@ static void __devinit voyager_smp_prepare_boot_cpu(void) cpu_set(smp_processor_id(), cpu_present_map); } -static int __devinit +static int __cpuinit voyager_cpu_up(unsigned int cpu) { /* This only works at boot for x86. See "rewrite" above. */ diff --git a/arch/x86/mm/init_64.c b/arch/x86/mm/init_64.c index a7308b2..0f9c8c8 100644 --- a/arch/x86/mm/init_64.c +++ b/arch/x86/mm/init_64.c @@ -345,7 +345,7 @@ static void __init find_early_table_space(unsigned long end) /* Setup the direct mapping of the physical memory at PAGE_OFFSET. This runs before bootmem is initialized and gets pages directly from the physical memory. To access them they are temporarily mapped. */ -void __meminit init_memory_mapping(unsigned long start, unsigned long end) +void __init_refok init_memory_mapping(unsigned long start, unsigned long end) { unsigned long next; diff --git a/arch/x86/pci/acpi.c b/arch/x86/pci/acpi.c index 2d88f7c..0234f28 100644 --- a/arch/x86/pci/acpi.c +++ b/arch/x86/pci/acpi.c @@ -13,7 +13,7 @@ static int __devinit can_skip_ioresource_align(const struct dmi_system_id *d) return 0; } -static struct dmi_system_id acpi_pciprobe_dmi_table[] = { +static struct dmi_system_id acpi_pciprobe_dmi_table[] __devinitdata = { /* * Systems where PCI IO resource ISA alignment can be skipped * when the ISA enable bit in the bridge control is not set @@ -77,6 +77,9 @@ count_resource(struct acpi_resource *acpi_res, void *data) struct acpi_resource_address64 addr; acpi_status status; + if (info->res_num >= PCI_BUS_NUM_RESOURCES) + return AE_OK; + status = resource_to_addr(acpi_res, &addr); if (ACPI_SUCCESS(status)) info->res_num++; @@ -93,6 +96,9 @@ setup_resource(struct acpi_resource *acpi_res, void *data) unsigned long flags; struct resource *root; + if (info->res_num >= PCI_BUS_NUM_RESOURCES) + return AE_OK; + status = resource_to_addr(acpi_res, &addr); if (!ACPI_SUCCESS(status)) return AE_OK; diff --git a/arch/x86/pci/common.c b/arch/x86/pci/common.c index f438699..8627463 100644 --- a/arch/x86/pci/common.c +++ b/arch/x86/pci/common.c @@ -315,6 +315,22 @@ static struct dmi_system_id __devinitdata pciprobe_dmi_table[] = { }, }, #endif + { + .callback = set_bf_sort, + .ident = "HP ProLiant DL385 G2", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "HP"), + DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant DL385 G2"), + }, + }, + { + .callback = set_bf_sort, + .ident = "HP ProLiant DL585 G2", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "HP"), + DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant DL585 G2"), + }, + }, {} }; diff --git a/arch/x86/vdso/Makefile b/arch/x86/vdso/Makefile index 7a2ba45..e7bff0f 100644 --- a/arch/x86/vdso/Makefile +++ b/arch/x86/vdso/Makefile @@ -20,7 +20,7 @@ quiet_cmd_syscall = SYSCALL $@ cmd_syscall = $(CC) -m elf_x86_64 -nostdlib $(SYSCFLAGS_$(@F)) \ -Wl,-T,$(filter-out FORCE,$^) -o $@ -export CPPFLAGS_vdso.lds += -P -C -U$(ARCH) +export CPPFLAGS_vdso.lds += -P -C vdso-flags = -fPIC -shared -Wl,-soname=linux-vdso.so.1 \ $(call ld-option, -Wl$(comma)--hash-style=sysv) \ diff --git a/arch/x86/vdso/vgetcpu.c b/arch/x86/vdso/vgetcpu.c index 91f6e85..3b1ae1a 100644 --- a/arch/x86/vdso/vgetcpu.c +++ b/arch/x86/vdso/vgetcpu.c @@ -13,32 +13,17 @@ #include <asm/vgtod.h> #include "vextern.h" -long __vdso_getcpu(unsigned *cpu, unsigned *node, struct getcpu_cache *tcache) +long __vdso_getcpu(unsigned *cpu, unsigned *node, struct getcpu_cache *unused) { unsigned int dummy, p; - unsigned long j = 0; - /* Fast cache - only recompute value once per jiffies and avoid - relatively costly rdtscp/cpuid otherwise. - This works because the scheduler usually keeps the process - on the same CPU and this syscall doesn't guarantee its - results anyways. - We do this here because otherwise user space would do it on - its own in a likely inferior way (no access to jiffies). - If you don't like it pass NULL. */ - if (tcache && tcache->blob[0] == (j = *vdso_jiffies)) { - p = tcache->blob[1]; - } else if (*vdso_vgetcpu_mode == VGETCPU_RDTSCP) { + if (*vdso_vgetcpu_mode == VGETCPU_RDTSCP) { /* Load per CPU data from RDTSCP */ rdtscp(dummy, dummy, p); } else { /* Load per CPU data from GDT */ asm("lsl %1,%0" : "=r" (p) : "r" (__PER_CPU_SEG)); } - if (tcache) { - tcache->blob[0] = j; - tcache->blob[1] = p; - } if (cpu) *cpu = p & 0xfff; if (node) diff --git a/arch/x86/xen/mmu.c b/arch/x86/xen/mmu.c index b2e32f9..0ac6c5d 100644 --- a/arch/x86/xen/mmu.c +++ b/arch/x86/xen/mmu.c @@ -244,6 +244,8 @@ pte_t xen_make_pte(unsigned long long pte) if (pte & 1) pte = phys_to_machine(XPADDR(pte)).maddr; + pte &= ~_PAGE_PCD; + return (pte_t){ pte, pte >> 32 }; } @@ -291,6 +293,8 @@ pte_t xen_make_pte(unsigned long pte) if (pte & _PAGE_PRESENT) pte = phys_to_machine(XPADDR(pte)).maddr; + pte &= ~_PAGE_PCD; + return (pte_t){ pte }; } diff --git a/block/blktrace.c b/block/blktrace.c index d00ac39..498a0a5 100644 --- a/block/blktrace.c +++ b/block/blktrace.c @@ -202,6 +202,7 @@ static void blk_remove_tree(struct dentry *dir) static struct dentry *blk_create_tree(const char *blk_name) { struct dentry *dir = NULL; + int created = 0; mutex_lock(&blk_tree_mutex); @@ -209,13 +210,17 @@ static struct dentry *blk_create_tree(const char *blk_name) blk_tree_root = debugfs_create_dir("block", NULL); if (!blk_tree_root) goto err; + created = 1; } dir = debugfs_create_dir(blk_name, blk_tree_root); if (dir) root_users++; - else - blk_remove_root(); + else { + /* Delete root only if we created it */ + if (created) + blk_remove_root(); + } err: mutex_unlock(&blk_tree_mutex); diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c index e47a930..0b4a479 100644 --- a/block/cfq-iosched.c +++ b/block/cfq-iosched.c @@ -789,6 +789,20 @@ static inline void cfq_slice_expired(struct cfq_data *cfqd, int timed_out) __cfq_slice_expired(cfqd, cfqq, timed_out); } +static int start_idle_class_timer(struct cfq_data *cfqd) +{ + unsigned long end = cfqd->last_end_request + CFQ_IDLE_GRACE; + unsigned long now = jiffies; + + if (time_before(now, end) && + time_after_eq(now, cfqd->last_end_request)) { + mod_timer(&cfqd->idle_class_timer, end); + return 1; + } + + return 0; +} + /* * Get next queue for service. Unless we have a queue preemption, * we'll simply select the first cfqq in the service tree. @@ -805,19 +819,14 @@ static struct cfq_queue *cfq_get_next_queue(struct cfq_data *cfqd) cfqq = rb_entry(n, struct cfq_queue, rb_node); if (cfq_class_idle(cfqq)) { - unsigned long end; - /* * if we have idle queues and no rt or be queues had * pending requests, either allow immediate service if * the grace period has passed or arm the idle grace * timer */ - end = cfqd->last_end_request + CFQ_IDLE_GRACE; - if (time_before(jiffies, end)) { - mod_timer(&cfqd->idle_class_timer, end); + if (start_idle_class_timer(cfqd)) cfqq = NULL; - } } return cfqq; @@ -2036,17 +2045,14 @@ out_cont: static void cfq_idle_class_timer(unsigned long data) { struct cfq_data *cfqd = (struct cfq_data *) data; - unsigned long flags, end; + unsigned long flags; spin_lock_irqsave(cfqd->queue->queue_lock, flags); /* * race with a non-idle queue, reset timer */ - end = cfqd->last_end_request + CFQ_IDLE_GRACE; - if (!time_after_eq(jiffies, end)) - mod_timer(&cfqd->idle_class_timer, end); - else + if (!start_idle_class_timer(cfqd)) cfq_schedule_dispatch(cfqd); spin_unlock_irqrestore(cfqd->queue->queue_lock, flags); @@ -2068,9 +2074,10 @@ static void cfq_put_async_queues(struct cfq_data *cfqd) cfq_put_queue(cfqd->async_cfqq[0][i]); if (cfqd->async_cfqq[1][i]) cfq_put_queue(cfqd->async_cfqq[1][i]); - if (cfqd->async_idle_cfqq) - cfq_put_queue(cfqd->async_idle_cfqq); } + + if (cfqd->async_idle_cfqq) + cfq_put_queue(cfqd->async_idle_cfqq); } static void cfq_exit_queue(elevator_t *e) @@ -2125,6 +2132,7 @@ static void *cfq_init_queue(struct request_queue *q) INIT_WORK(&cfqd->unplug_work, cfq_kick_queue); + cfqd->last_end_request = jiffies; cfqd->cfq_quantum = cfq_quantum; cfqd->cfq_fifo_expire[0] = cfq_fifo_expire[0]; cfqd->cfq_fifo_expire[1] = cfq_fifo_expire[1]; diff --git a/block/genhd.c b/block/genhd.c index e609996..f2ac914 100644 --- a/block/genhd.c +++ b/block/genhd.c @@ -715,6 +715,7 @@ struct gendisk *alloc_disk_node(int minors, int node_id) disk->part = kmalloc_node(size, GFP_KERNEL | __GFP_ZERO, node_id); if (!disk->part) { + free_disk_stats(disk); kfree(disk); return NULL; } diff --git a/block/ll_rw_blk.c b/block/ll_rw_blk.c index 75c98d5..8b91994 100644 --- a/block/ll_rw_blk.c +++ b/block/ll_rw_blk.c @@ -1143,22 +1143,9 @@ EXPORT_SYMBOL(blk_queue_start_tag); void blk_queue_invalidate_tags(struct request_queue *q) { struct list_head *tmp, *n; - struct request *rq; - - list_for_each_safe(tmp, n, &q->tag_busy_list) { - rq = list_entry_rq(tmp); - if (rq->tag == -1) { - printk(KERN_ERR - "%s: bad tag found on list\n", __FUNCTION__); - list_del_init(&rq->queuelist); - rq->cmd_flags &= ~REQ_QUEUED; - } else - blk_queue_end_tag(q, rq); - - rq->cmd_flags &= ~REQ_STARTED; - __elv_add_request(q, rq, ELEVATOR_INSERT_BACK, 0); - } + list_for_each_safe(tmp, n, &q->tag_busy_list) + blk_requeue_request(q, list_entry_rq(tmp)); } EXPORT_SYMBOL(blk_queue_invalidate_tags); @@ -1634,15 +1621,7 @@ static void blk_backing_dev_unplug(struct backing_dev_info *bdi, { struct request_queue *q = bdi->unplug_io_data; - /* - * devices don't necessarily have an ->unplug_fn defined - */ - if (q->unplug_fn) { - blk_add_trace_pdu_int(q, BLK_TA_UNPLUG_IO, NULL, - q->rq.count[READ] + q->rq.count[WRITE]); - - q->unplug_fn(q); - } + blk_unplug(q); } static void blk_unplug_work(struct work_struct *work) @@ -1666,6 +1645,20 @@ static void blk_unplug_timeout(unsigned long data) kblockd_schedule_work(&q->unplug_work); } +void blk_unplug(struct request_queue *q) +{ + /* + * devices don't necessarily have an ->unplug_fn defined + */ + if (q->unplug_fn) { + blk_add_trace_pdu_int(q, BLK_TA_UNPLUG_IO, NULL, + q->rq.count[READ] + q->rq.count[WRITE]); + + q->unplug_fn(q); + } +} +EXPORT_SYMBOL(blk_unplug); + /** * blk_start_queue - restart a previously stopped queue * @q: The &struct request_queue in question @@ -4087,23 +4080,7 @@ static ssize_t queue_max_hw_sectors_show(struct request_queue *q, char *page) return queue_var_show(max_hw_sectors_kb, (page)); } -static ssize_t queue_max_segments_show(struct request_queue *q, char *page) -{ - return queue_var_show(q->max_phys_segments, page); -} - -static ssize_t queue_max_segments_store(struct request_queue *q, - const char *page, size_t count) -{ - unsigned long segments; - ssize_t ret = queue_var_store(&segments, page, count); - - spin_lock_irq(q->queue_lock); - q->max_phys_segments = segments; - spin_unlock_irq(q->queue_lock); - return ret; -} static struct queue_sysfs_entry queue_requests_entry = { .attr = {.name = "nr_requests", .mode = S_IRUGO | S_IWUSR }, .show = queue_requests_show, @@ -4127,12 +4104,6 @@ static struct queue_sysfs_entry queue_max_hw_sectors_entry = { .show = queue_max_hw_sectors_show, }; -static struct queue_sysfs_entry queue_max_segments_entry = { - .attr = {.name = "max_segments", .mode = S_IRUGO | S_IWUSR }, - .show = queue_max_segments_show, - .store = queue_max_segments_store, -}; - static struct queue_sysfs_entry queue_iosched_entry = { .attr = {.name = "scheduler", .mode = S_IRUGO | S_IWUSR }, .show = elv_iosched_show, @@ -4144,7 +4115,6 @@ static struct attribute *default_attrs[] = { &queue_ra_entry.attr, &queue_max_hw_sectors_entry.attr, &queue_max_sectors_entry.attr, - &queue_max_segments_entry.attr, &queue_iosched_entry.attr, NULL, }; diff --git a/crypto/algapi.c b/crypto/algapi.c index 8ff8c26..8383282 100644 --- a/crypto/algapi.c +++ b/crypto/algapi.c @@ -95,6 +95,9 @@ static void crypto_remove_spawn(struct crypto_spawn *spawn, return; inst->alg.cra_flags |= CRYPTO_ALG_DEAD; + if (hlist_unhashed(&inst->list)) + return; + if (!tmpl || !crypto_tmpl_get(tmpl)) return; @@ -335,9 +338,6 @@ int crypto_register_instance(struct crypto_template *tmpl, LIST_HEAD(list); int err = -EINVAL; - if (inst->alg.cra_destroy) - goto err; - err = crypto_check_alg(&inst->alg); if (err) goto err; diff --git a/crypto/authenc.c b/crypto/authenc.c index 0b29a6a..126a529 100644 --- a/crypto/authenc.c +++ b/crypto/authenc.c @@ -84,8 +84,8 @@ static int crypto_authenc_hash(struct aead_request *req) .tfm = auth, }; u8 *hash = aead_request_ctx(req); - struct scatterlist *dst; - unsigned int cryptlen; + struct scatterlist *dst = req->dst; + unsigned int cryptlen = req->cryptlen; int err; hash = (u8 *)ALIGN((unsigned long)hash + crypto_hash_alignmask(auth), @@ -100,8 +100,6 @@ static int crypto_authenc_hash(struct aead_request *req) if (err) goto auth_unlock; - cryptlen = req->cryptlen; - dst = req->dst; err = crypto_hash_update(&desc, dst, cryptlen); if (err) goto auth_unlock; @@ -159,8 +157,8 @@ static int crypto_authenc_verify(struct aead_request *req) }; u8 *ohash = aead_request_ctx(req); u8 *ihash; - struct scatterlist *src; - unsigned int cryptlen; + struct scatterlist *src = req->src; + unsigned int cryptlen = req->cryptlen; unsigned int authsize; int err; @@ -177,8 +175,6 @@ static int crypto_authenc_verify(struct aead_request *req) if (err) goto auth_unlock; - cryptlen = req->cryptlen; - src = req->src; err = crypto_hash_update(&desc, src, cryptlen); if (err) goto auth_unlock; diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig index da3a08f..b9f923e 100644 --- a/drivers/acpi/Kconfig +++ b/drivers/acpi/Kconfig @@ -67,7 +67,21 @@ config ACPI_PROCFS and functions which do not yet exist in /sys. Say N to delete /proc/acpi/ files that have moved to /sys/ - +config ACPI_PROCFS_POWER + bool "Deprecated power /proc/acpi folders" + depends on PROC_FS + default y + ---help--- + For backwards compatibility, this option allows + deprecated power /proc/acpi/ folders to exist, even when + they have been replaced by functions in /sys. + The deprecated folders (and their replacements) include: + /proc/acpi/battery/* (/sys/class/power_supply/*) + /proc/acpi/ac_adapter/* (sys/class/power_supply/*) + This option has no effect on /proc/acpi/ folders + and functions, which do not yet exist in /sys + + Say N to delete power /proc/acpi/ folders that have moved to /sys/ config ACPI_PROC_EVENT bool "Deprecated /proc/acpi/event support" depends on PROC_FS diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile index 54e3ab0..456446f 100644 --- a/drivers/acpi/Makefile +++ b/drivers/acpi/Makefile @@ -58,6 +58,6 @@ obj-$(CONFIG_ACPI_NUMA) += numa.o obj-$(CONFIG_ACPI_ASUS) += asus_acpi.o obj-$(CONFIG_ACPI_TOSHIBA) += toshiba_acpi.o obj-$(CONFIG_ACPI_HOTPLUG_MEMORY) += acpi_memhotplug.o -obj-y += cm_sbs.o +obj-$(CONFIG_ACPI_PROCFS_POWER) += cm_sbs.o obj-$(CONFIG_ACPI_SBS) += sbs.o obj-$(CONFIG_ACPI_SBS) += sbshc.o diff --git a/drivers/acpi/ac.c b/drivers/acpi/ac.c index e03de37..76ed4f5 100644 --- a/drivers/acpi/ac.c +++ b/drivers/acpi/ac.c @@ -27,8 +27,10 @@ #include <linux/module.h> #include <linux/init.h> #include <linux/types.h> +#ifdef CONFIG_ACPI_PROCFS_POWER #include <linux/proc_fs.h> #include <linux/seq_file.h> +#endif #include <linux/power_supply.h> #include <acpi/acpi_bus.h> #include <acpi/acpi_drivers.h> @@ -49,12 +51,15 @@ MODULE_AUTHOR("Paul Diefenbaugh"); MODULE_DESCRIPTION("ACPI AC Adapter Driver"); MODULE_LICENSE("GPL"); +#ifdef CONFIG_ACPI_PROCFS_POWER extern struct proc_dir_entry *acpi_lock_ac_dir(void); extern void *acpi_unlock_ac_dir(struct proc_dir_entry *acpi_ac_dir); +static int acpi_ac_open_fs(struct inode *inode, struct file *file); +#endif static int acpi_ac_add(struct acpi_device *device); static int acpi_ac_remove(struct acpi_device *device, int type); -static int acpi_ac_open_fs(struct inode *inode, struct file *file); +static int acpi_ac_resume(struct acpi_device *device); const static struct acpi_device_id ac_device_ids[] = { {"ACPI0003", 0}, @@ -69,6 +74,7 @@ static struct acpi_driver acpi_ac_driver = { .ops = { .add = acpi_ac_add, .remove = acpi_ac_remove, + .resume = acpi_ac_resume, }, }; @@ -80,12 +86,15 @@ struct acpi_ac { #define to_acpi_ac(x) container_of(x, struct acpi_ac, charger); +#ifdef CONFIG_ACPI_PROCFS_POWER static const struct file_operations acpi_ac_fops = { .open = acpi_ac_open_fs, .read = seq_read, .llseek = seq_lseek, .release = single_release, }; +#endif + static int get_ac_property(struct power_supply *psy, enum power_supply_property psp, union power_supply_propval *val) @@ -127,6 +136,7 @@ static int acpi_ac_get_state(struct acpi_ac *ac) return 0; } +#ifdef CONFIG_ACPI_PROCFS_POWER /* -------------------------------------------------------------------------- FS Interface (/proc) -------------------------------------------------------------------------- */ @@ -206,6 +216,7 @@ static int acpi_ac_remove_fs(struct acpi_device *device) return 0; } +#endif /* -------------------------------------------------------------------------- Driver Model @@ -264,7 +275,9 @@ static int acpi_ac_add(struct acpi_device *device) if (result) goto end; +#ifdef CONFIG_ACPI_PROCFS_POWER result = acpi_ac_add_fs(device); +#endif if (result) goto end; ac->charger.name = acpi_device_bid(device); @@ -287,13 +300,30 @@ static int acpi_ac_add(struct acpi_device *device) end: if (result) { +#ifdef CONFIG_ACPI_PROCFS_POWER acpi_ac_remove_fs(device); +#endif kfree(ac); } return result; } +static int acpi_ac_resume(struct acpi_device *device) +{ + struct acpi_ac *ac; + unsigned old_state; + if (!device || !acpi_driver_data(device)) + return -EINVAL; + ac = acpi_driver_data(device); + old_state = ac->state; + if (acpi_ac_get_state(ac)) + return 0; + if (old_state != ac->state) + kobject_uevent(&ac->charger.dev->kobj, KOBJ_CHANGE); + return 0; +} + static int acpi_ac_remove(struct acpi_device *device, int type) { acpi_status status = AE_OK; @@ -309,7 +339,9 @@ static int acpi_ac_remove(struct acpi_device *device, int type) ACPI_ALL_NOTIFY, acpi_ac_notify); if (ac->charger.dev) power_supply_unregister(&ac->charger); +#ifdef CONFIG_ACPI_PROCFS_POWER acpi_ac_remove_fs(device); +#endif kfree(ac); @@ -323,13 +355,17 @@ static int __init acpi_ac_init(void) if (acpi_disabled) return -ENODEV; +#ifdef CONFIG_ACPI_PROCFS_POWER acpi_ac_dir = acpi_lock_ac_dir(); if (!acpi_ac_dir) return -ENODEV; +#endif result = acpi_bus_register_driver(&acpi_ac_driver); if (result < 0) { +#ifdef CONFIG_ACPI_PROCFS_POWER acpi_unlock_ac_dir(acpi_ac_dir); +#endif return -ENODEV; } @@ -341,7 +377,9 @@ static void __exit acpi_ac_exit(void) acpi_bus_unregister_driver(&acpi_ac_driver); +#ifdef CONFIG_ACPI_PROCFS_POWER acpi_unlock_ac_dir(acpi_ac_dir); +#endif return; } diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c index c2ce0ad..7d6be23 100644 --- a/drivers/acpi/battery.c +++ b/drivers/acpi/battery.c @@ -31,7 +31,7 @@ #include <linux/types.h> #include <linux/jiffies.h> -#ifdef CONFIG_ACPI_PROCFS +#ifdef CONFIG_ACPI_PROCFS_POWER #include <linux/proc_fs.h> #include <linux/seq_file.h> #include <asm/uaccess.h> @@ -63,7 +63,7 @@ static unsigned int cache_time = 1000; module_param(cache_time, uint, 0644); MODULE_PARM_DESC(cache_time, "cache time in milliseconds"); -#ifdef CONFIG_ACPI_PROCFS +#ifdef CONFIG_ACPI_PROCFS_POWER extern struct proc_dir_entry *acpi_lock_battery_dir(void); extern void *acpi_unlock_battery_dir(struct proc_dir_entry *acpi_battery_dir); @@ -132,7 +132,7 @@ static int acpi_battery_technology(struct acpi_battery *battery) return POWER_SUPPLY_TECHNOLOGY_UNKNOWN; } -static int acpi_battery_update(struct acpi_battery *battery); +static int acpi_battery_get_state(struct acpi_battery *battery); static int acpi_battery_get_property(struct power_supply *psy, enum power_supply_property psp, @@ -140,10 +140,11 @@ static int acpi_battery_get_property(struct power_supply *psy, { struct acpi_battery *battery = to_acpi_battery(psy); - if ((!acpi_battery_present(battery)) && - psp != POWER_SUPPLY_PROP_PRESENT) + if (acpi_battery_present(battery)) { + /* run battery update only if it is present */ + acpi_battery_get_state(battery); + } else if (psp != POWER_SUPPLY_PROP_PRESENT) return -ENODEV; - acpi_battery_update(battery); switch (psp) { case POWER_SUPPLY_PROP_STATUS: if (battery->state & 0x01) @@ -152,6 +153,8 @@ static int acpi_battery_get_property(struct power_supply *psy, val->intval = POWER_SUPPLY_STATUS_CHARGING; else if (battery->state == 0) val->intval = POWER_SUPPLY_STATUS_FULL; + else + val->intval = POWER_SUPPLY_STATUS_UNKNOWN; break; case POWER_SUPPLY_PROP_PRESENT: val->intval = acpi_battery_present(battery); @@ -220,7 +223,7 @@ static enum power_supply_property energy_battery_props[] = { POWER_SUPPLY_PROP_MANUFACTURER, }; -#ifdef CONFIG_ACPI_PROCFS +#ifdef CONFIG_ACPI_PROCFS_POWER inline char *acpi_battery_units(struct acpi_battery *battery) { return (battery->power_unit)?"mA":"mW"; @@ -457,6 +460,7 @@ static void sysfs_remove_battery(struct acpi_battery *battery) return; device_remove_file(battery->bat.dev, &alarm_attr); power_supply_unregister(&battery->bat); + battery->bat.dev = NULL; } static int acpi_battery_update(struct acpi_battery *battery) @@ -477,7 +481,7 @@ static int acpi_battery_update(struct acpi_battery *battery) FS Interface (/proc) -------------------------------------------------------------------------- */ -#ifdef CONFIG_ACPI_PROCFS +#ifdef CONFIG_ACPI_PROCFS_POWER static struct proc_dir_entry *acpi_battery_dir; static int acpi_battery_print_info(struct seq_file *seq, int result) @@ -784,7 +788,7 @@ static int acpi_battery_add(struct acpi_device *device) acpi_driver_data(device) = battery; mutex_init(&battery->lock); acpi_battery_update(battery); -#ifdef CONFIG_ACPI_PROCFS +#ifdef CONFIG_ACPI_PROCFS_POWER result = acpi_battery_add_fs(device); if (result) goto end; @@ -802,7 +806,7 @@ static int acpi_battery_add(struct acpi_device *device) device->status.battery_present ? "present" : "absent"); end: if (result) { -#ifdef CONFIG_ACPI_PROCFS +#ifdef CONFIG_ACPI_PROCFS_POWER acpi_battery_remove_fs(device); #endif kfree(battery); @@ -821,7 +825,7 @@ static int acpi_battery_remove(struct acpi_device *device, int type) status = acpi_remove_notify_handler(device->handle, ACPI_ALL_NOTIFY, acpi_battery_notify); -#ifdef CONFIG_ACPI_PROCFS +#ifdef CONFIG_ACPI_PROCFS_POWER acpi_battery_remove_fs(device); #endif sysfs_remove_battery(battery); @@ -857,13 +861,13 @@ static int __init acpi_battery_init(void) { if (acpi_disabled) return -ENODEV; -#ifdef CONFIG_ACPI_PROCFS +#ifdef CONFIG_ACPI_PROCFS_POWER acpi_battery_dir = acpi_lock_battery_dir(); if (!acpi_battery_dir) return -ENODEV; #endif if (acpi_bus_register_driver(&acpi_battery_driver) < 0) { -#ifdef CONFIG_ACPI_PROCFS +#ifdef CONFIG_ACPI_PROCFS_POWER acpi_unlock_battery_dir(acpi_battery_dir); #endif return -ENODEV; @@ -874,7 +878,7 @@ static int __init acpi_battery_init(void) static void __exit acpi_battery_exit(void) { acpi_bus_unregister_driver(&acpi_battery_driver); -#ifdef CONFIG_ACPI_PROCFS +#ifdef CONFIG_ACPI_PROCFS_POWER acpi_unlock_battery_dir(acpi_battery_dir); #endif } diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index 06b78e5..d411017 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c @@ -47,6 +47,9 @@ #undef PREFIX #define PREFIX "ACPI: EC: " +/* Uncomment next line to get verbose print outs*/ +/* #define DEBUG */ + /* EC status register */ #define ACPI_EC_FLAG_OBF 0x01 /* Output buffer full */ #define ACPI_EC_FLAG_IBF 0x02 /* Input buffer full */ @@ -75,7 +78,10 @@ enum { EC_FLAGS_WAIT_GPE = 0, /* Don't check status until GPE arrives */ EC_FLAGS_QUERY_PENDING, /* Query is pending */ EC_FLAGS_GPE_MODE, /* Expect GPE to be sent for status change */ - EC_FLAGS_ONLY_IBF_GPE, /* Expect GPE only for IBF = 0 event */ + EC_FLAGS_NO_ADDRESS_GPE, /* Expect GPE only for non-address event */ + EC_FLAGS_ADDRESS, /* Address is being written */ + EC_FLAGS_NO_WDATA_GPE, /* Don't expect WDATA GPE event */ + EC_FLAGS_WDATA, /* Data is being written */ }; static int acpi_ec_remove(struct acpi_device *device, int type); @@ -131,21 +137,27 @@ static struct acpi_ec { static inline u8 acpi_ec_read_status(struct acpi_ec *ec) { - return inb(ec->command_addr); + u8 x = inb(ec->command_addr); + pr_debug(PREFIX "---> status = 0x%2x\n", x); + return x; } static inline u8 acpi_ec_read_data(struct acpi_ec *ec) { + u8 x = inb(ec->data_addr); + pr_debug(PREFIX "---> data = 0x%2x\n", x); return inb(ec->data_addr); } static inline void acpi_ec_write_cmd(struct acpi_ec *ec, u8 command) { + pr_debug(PREFIX "<--- command = 0x%2x\n", command); outb(command, ec->command_addr); } static inline void acpi_ec_write_data(struct acpi_ec *ec, u8 data) { + pr_debug(PREFIX "<--- data = 0x%2x\n", data); outb(data, ec->data_addr); } @@ -166,38 +178,54 @@ static inline int acpi_ec_check_status(struct acpi_ec *ec, enum ec_event event) static int acpi_ec_wait(struct acpi_ec *ec, enum ec_event event, int force_poll) { + int ret = 0; + if (unlikely(test_bit(EC_FLAGS_ADDRESS, &ec->flags) && + test_bit(EC_FLAGS_NO_ADDRESS_GPE, &ec->flags))) + force_poll = 1; + if (unlikely(test_bit(EC_FLAGS_WDATA, &ec->flags) && + test_bit(EC_FLAGS_NO_WDATA_GPE, &ec->flags))) + force_poll = 1; if (likely(test_bit(EC_FLAGS_GPE_MODE, &ec->flags)) && likely(!force_poll)) { if (wait_event_timeout(ec->wait, acpi_ec_check_status(ec, event), msecs_to_jiffies(ACPI_EC_DELAY))) - return 0; + goto end; clear_bit(EC_FLAGS_WAIT_GPE, &ec->flags); if (acpi_ec_check_status(ec, event)) { - if (event == ACPI_EC_EVENT_OBF_1) { - /* miss OBF = 1 GPE, don't expect it anymore */ - printk(KERN_INFO PREFIX "missing OBF_1 confirmation," - "switching to degraded mode.\n"); - set_bit(EC_FLAGS_ONLY_IBF_GPE, &ec->flags); + if (test_bit(EC_FLAGS_ADDRESS, &ec->flags)) { + /* miss address GPE, don't expect it anymore */ + pr_info(PREFIX "missing address confirmation, " + "don't expect it any longer.\n"); + set_bit(EC_FLAGS_NO_ADDRESS_GPE, &ec->flags); + } else if (test_bit(EC_FLAGS_WDATA, &ec->flags)) { + /* miss write data GPE, don't expect it */ + pr_info(PREFIX "missing write data confirmation, " + "don't expect it any longer.\n"); + set_bit(EC_FLAGS_NO_WDATA_GPE, &ec->flags); } else { /* missing GPEs, switch back to poll mode */ - printk(KERN_INFO PREFIX "missing IBF_1 confirmations," - "switch off interrupt mode.\n"); + if (printk_ratelimit()) + pr_info(PREFIX "missing confirmations, " + "switch off interrupt mode.\n"); clear_bit(EC_FLAGS_GPE_MODE, &ec->flags); } - return 0; + goto end; } } else { unsigned long delay = jiffies + msecs_to_jiffies(ACPI_EC_DELAY); clear_bit(EC_FLAGS_WAIT_GPE, &ec->flags); while (time_before(jiffies, delay)) { if (acpi_ec_check_status(ec, event)) - return 0; + goto end; } } - printk(KERN_ERR PREFIX "acpi_ec_wait timeout," + pr_err(PREFIX "acpi_ec_wait timeout," " status = %d, expect_event = %d\n", acpi_ec_read_status(ec), event); - return -ETIME; + ret = -ETIME; + end: + clear_bit(EC_FLAGS_ADDRESS, &ec->flags); + return ret; } static int acpi_ec_transaction_unlocked(struct acpi_ec *ec, u8 command, @@ -208,22 +236,26 @@ static int acpi_ec_transaction_unlocked(struct acpi_ec *ec, u8 command, int result = 0; set_bit(EC_FLAGS_WAIT_GPE, &ec->flags); acpi_ec_write_cmd(ec, command); - + pr_debug(PREFIX "transaction start\n"); for (; wdata_len > 0; --wdata_len) { result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0, force_poll); if (result) { - printk(KERN_ERR PREFIX + pr_err(PREFIX "write_cmd timeout, command = %d\n", command); goto end; } + /* mark the address byte written to EC */ + if (rdata_len + wdata_len > 1) + set_bit(EC_FLAGS_ADDRESS, &ec->flags); set_bit(EC_FLAGS_WAIT_GPE, &ec->flags); acpi_ec_write_data(ec, *(wdata++)); } if (!rdata_len) { + set_bit(EC_FLAGS_WDATA, &ec->flags); result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0, force_poll); if (result) { - printk(KERN_ERR PREFIX + pr_err(PREFIX "finish-write timeout, command = %d\n", command); goto end; } @@ -231,12 +263,9 @@ static int acpi_ec_transaction_unlocked(struct acpi_ec *ec, u8 command, clear_bit(EC_FLAGS_QUERY_PENDING, &ec->flags); for (; rdata_len > 0; --rdata_len) { - if (test_bit(EC_FLAGS_ONLY_IBF_GPE, &ec->flags)) - force_poll = 1; result = acpi_ec_wait(ec, ACPI_EC_EVENT_OBF_1, force_poll); if (result) { - printk(KERN_ERR PREFIX "read timeout, command = %d\n", - command); + pr_err(PREFIX "read timeout, command = %d\n", command); goto end; } /* Don't expect GPE after last read */ @@ -245,6 +274,7 @@ static int acpi_ec_transaction_unlocked(struct acpi_ec *ec, u8 command, *(rdata++) = acpi_ec_read_data(ec); } end: + pr_debug(PREFIX "transaction end\n"); return result; } @@ -273,8 +303,8 @@ static int acpi_ec_transaction(struct acpi_ec *ec, u8 command, status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0, 0); if (status) { - printk(KERN_ERR PREFIX - "input buffer is not empty, aborting transaction\n"); + pr_err(PREFIX "input buffer is not empty, " + "aborting transaction\n"); goto end; } @@ -488,6 +518,7 @@ static u32 acpi_ec_gpe_handler(void *data) acpi_status status = AE_OK; struct acpi_ec *ec = data; + pr_debug(PREFIX "~~~> interrupt\n"); clear_bit(EC_FLAGS_WAIT_GPE, &ec->flags); if (test_bit(EC_FLAGS_GPE_MODE, &ec->flags)) wake_up(&ec->wait); @@ -498,8 +529,9 @@ static u32 acpi_ec_gpe_handler(void *data) acpi_ec_gpe_query, ec); } else if (unlikely(!test_bit(EC_FLAGS_GPE_MODE, &ec->flags))) { /* this is non-query, must be confirmation */ - printk(KERN_INFO PREFIX "non-query interrupt received," - " switching to interrupt mode\n"); + if (printk_ratelimit()) + pr_info(PREFIX "non-query interrupt received," + " switching to interrupt mode\n"); set_bit(EC_FLAGS_GPE_MODE, &ec->flags); } @@ -701,10 +733,10 @@ static void ec_remove_handlers(struct acpi_ec *ec) { if (ACPI_FAILURE(acpi_remove_address_space_handler(ec->handle, ACPI_ADR_SPACE_EC, &acpi_ec_space_handler))) - printk(KERN_ERR PREFIX "failed to remove space handler\n"); + pr_err(PREFIX "failed to remove space handler\n"); if (ACPI_FAILURE(acpi_remove_gpe_handler(NULL, ec->gpe, &acpi_ec_gpe_handler))) - printk(KERN_ERR PREFIX "failed to remove gpe handler\n"); + pr_err(PREFIX "failed to remove gpe handler\n"); ec->handlers_installed = 0; } @@ -747,9 +779,9 @@ static int acpi_ec_add(struct acpi_device *device) first_ec = ec; acpi_driver_data(device) = ec; acpi_ec_add_fs(device); - printk(KERN_INFO PREFIX "GPE = 0x%lx, I/O: command/status = 0x%lx, data = 0x%lx\n", + pr_info(PREFIX "GPE = 0x%lx, I/O: command/status = 0x%lx, data = 0x%lx\n", ec->gpe, ec->command_addr, ec->data_addr); - printk(KERN_INFO PREFIX "driver started in %s mode\n", + pr_info(PREFIX "driver started in %s mode\n", (test_bit(EC_FLAGS_GPE_MODE, &ec->flags))?"interrupt":"poll"); return 0; } @@ -875,18 +907,26 @@ int __init acpi_ec_ecdt_probe(void) status = acpi_get_table(ACPI_SIG_ECDT, 1, (struct acpi_table_header **)&ecdt_ptr); if (ACPI_SUCCESS(status)) { - printk(KERN_INFO PREFIX "EC description table is found, configuring boot EC\n"); + pr_info(PREFIX "EC description table is found, configuring boot EC\n"); boot_ec->command_addr = ecdt_ptr->control.address; boot_ec->data_addr = ecdt_ptr->data.address; boot_ec->gpe = ecdt_ptr->gpe; boot_ec->handle = ACPI_ROOT_OBJECT; } else { + /* This workaround is needed only on some broken machines, + * which require early EC, but fail to provide ECDT */ + acpi_handle x; printk(KERN_DEBUG PREFIX "Look up EC in DSDT\n"); status = acpi_get_devices(ec_device_ids[0].id, ec_parse_device, boot_ec, NULL); /* Check that acpi_get_devices actually find something */ if (ACPI_FAILURE(status) || !boot_ec->handle) goto error; + /* We really need to limit this workaround, the only ASUS, + * which needs it, has fake EC._INI method, so use it as flag. + */ + if (ACPI_FAILURE(acpi_get_handle(boot_ec->handle, "_INI", &x))) + goto error; } ret = ec_install_handlers(boot_ec); diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c index aabc6ca..e3a673a 100644 --- a/drivers/acpi/osl.c +++ b/drivers/acpi/osl.c @@ -387,17 +387,14 @@ acpi_status acpi_os_read_port(acpi_io_address port, u32 * value, u32 width) if (!value) value = &dummy; - switch (width) { - case 8: + *value = 0; + if (width <= 8) { *(u8 *) value = inb(port); - break; - case 16: + } else if (width <= 16) { *(u16 *) value = inw(port); - break; - case 32: + } else if (width <= 32) { *(u32 *) value = inl(port); - break; - default: + } else { BUG(); } @@ -408,17 +405,13 @@ EXPORT_SYMBOL(acpi_os_read_port); acpi_status acpi_os_write_port(acpi_io_address port, u32 value, u32 width) { - switch (width) { - case 8: + if (width <= 8) { outb(value, port); - break; - case 16: + } else if (width <= 16) { outw(value, port); - break; - case 32: + } else if (width <= 32) { outl(value, port); - break; - default: + } else { BUG(); } diff --git a/drivers/acpi/processor_core.c b/drivers/acpi/processor_core.c index 235a51e..e48ee4f 100644 --- a/drivers/acpi/processor_core.c +++ b/drivers/acpi/processor_core.c @@ -494,7 +494,7 @@ static int get_cpu_id(acpi_handle handle, u32 acpi_id) if (apic_id == -1) return apic_id; - for (i = 0; i < NR_CPUS; ++i) { + for_each_possible_cpu(i) { if (cpu_physical_id(i) == apic_id) return i; } @@ -612,12 +612,6 @@ static int acpi_processor_get_info(struct acpi_processor *pr, unsigned has_uid) request_region(pr->throttling.address, 6, "ACPI CPU throttle"); } -#ifdef CONFIG_CPU_FREQ - acpi_processor_ppc_has_changed(pr); -#endif - acpi_processor_get_throttling_info(pr); - acpi_processor_get_limit_info(pr); - return 0; } @@ -638,7 +632,7 @@ static int __cpuinit acpi_processor_start(struct acpi_device *device) return 0; } - BUG_ON((pr->id >= NR_CPUS) || (pr->id < 0)); + BUG_ON((pr->id >= nr_cpu_ids) || (pr->id < 0)); /* * Buggy BIOS check @@ -647,7 +641,7 @@ static int __cpuinit acpi_processor_start(struct acpi_device *device) */ if (processor_device_array[pr->id] != NULL && processor_device_array[pr->id] != device) { - printk(KERN_WARNING "BIOS reported wrong ACPI id" + printk(KERN_WARNING "BIOS reported wrong ACPI id " "for the processor\n"); return -ENODEV; } @@ -665,6 +659,12 @@ static int __cpuinit acpi_processor_start(struct acpi_device *device) /* _PDC call should be done before doing anything else (if reqd.). */ arch_acpi_processor_init_pdc(pr); acpi_processor_set_pdc(pr); +#ifdef CONFIG_CPU_FREQ + acpi_processor_ppc_has_changed(pr); +#endif + acpi_processor_get_throttling_info(pr); + acpi_processor_get_limit_info(pr); + acpi_processor_power_init(pr, device); @@ -684,7 +684,7 @@ static void acpi_processor_notify(acpi_handle handle, u32 event, void *data) { struct acpi_processor *pr = data; struct acpi_device *device = NULL; - + int saved; if (!pr) return; @@ -694,7 +694,10 @@ static void acpi_processor_notify(acpi_handle handle, u32 event, void *data) switch (event) { case ACPI_PROCESSOR_NOTIFY_PERFORMANCE: + saved = pr->performance_platform_limit; acpi_processor_ppc_has_changed(pr); + if (saved == pr->performance_platform_limit) + break; acpi_bus_generate_proc_event(device, event, pr->performance_platform_limit); acpi_bus_generate_netlink_event(device->pnp.device_class, @@ -771,7 +774,7 @@ static int acpi_processor_remove(struct acpi_device *device, int type) pr = acpi_driver_data(device); - if (pr->id >= NR_CPUS) { + if (pr->id >= nr_cpu_ids) { kfree(pr); return 0; } @@ -842,7 +845,7 @@ int acpi_processor_device_add(acpi_handle handle, struct acpi_device **device) if (!pr) return -ENODEV; - if ((pr->id >= 0) && (pr->id < NR_CPUS)) { + if ((pr->id >= 0) && (pr->id < nr_cpu_ids)) { kobject_uevent(&(*device)->dev.kobj, KOBJ_ONLINE); } return 0; @@ -880,13 +883,13 @@ acpi_processor_hotplug_notify(acpi_handle handle, u32 event, void *data) break; } - if (pr->id >= 0 && (pr->id < NR_CPUS)) { + if (pr->id >= 0 && (pr->id < nr_cpu_ids)) { kobject_uevent(&device->dev.kobj, KOBJ_OFFLINE); break; } result = acpi_processor_start(device); - if ((!result) && ((pr->id >= 0) && (pr->id < NR_CPUS))) { + if ((!result) && ((pr->id >= 0) && (pr->id < nr_cpu_ids))) { kobject_uevent(&device->dev.kobj, KOBJ_ONLINE); } else { printk(KERN_ERR PREFIX "Device [%s] failed to start\n", @@ -909,7 +912,7 @@ acpi_processor_hotplug_notify(acpi_handle handle, u32 event, void *data) return; } - if ((pr->id < NR_CPUS) && (cpu_present(pr->id))) + if ((pr->id < nr_cpu_ids) && (cpu_present(pr->id))) kobject_uevent(&device->dev.kobj, KOBJ_OFFLINE); break; default: diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c index f996d0e..b1fbee3 100644 --- a/drivers/acpi/processor_idle.c +++ b/drivers/acpi/processor_idle.c @@ -197,6 +197,19 @@ static inline u32 ticks_elapsed_in_us(u32 t1, u32 t2) return PM_TIMER_TICKS_TO_US((0xFFFFFFFF - t1) + t2); } +static void acpi_safe_halt(void) +{ + current_thread_info()->status &= ~TS_POLLING; + /* + * TS_POLLING-cleared state must be visible before we + * test NEED_RESCHED: + */ + smp_mb(); + if (!need_resched()) + safe_halt(); + current_thread_info()->status |= TS_POLLING; +} + #ifndef CONFIG_CPU_IDLE static void @@ -239,19 +252,6 @@ acpi_processor_power_activate(struct acpi_processor *pr, return; } -static void acpi_safe_halt(void) -{ - current_thread_info()->status &= ~TS_POLLING; - /* - * TS_POLLING-cleared state must be visible before we - * test NEED_RESCHED: - */ - smp_mb(); - if (!need_resched()) - safe_halt(); - current_thread_info()->status |= TS_POLLING; -} - static atomic_t c3_cpu_count; /* Common C-state entry for C2, C3, .. */ @@ -1373,15 +1373,7 @@ static int acpi_idle_enter_c1(struct cpuidle_device *dev, if (pr->flags.bm_check) acpi_idle_update_bm_rld(pr, cx); - current_thread_info()->status &= ~TS_POLLING; - /* - * TS_POLLING-cleared state must be visible before we test - * NEED_RESCHED: - */ - smp_mb(); - if (!need_resched()) - safe_halt(); - current_thread_info()->status |= TS_POLLING; + acpi_safe_halt(); cx->usage++; @@ -1399,6 +1391,8 @@ static int acpi_idle_enter_simple(struct cpuidle_device *dev, struct acpi_processor *pr; struct acpi_processor_cx *cx = cpuidle_get_statedata(state); u32 t1, t2; + int sleep_ticks = 0; + pr = processors[smp_processor_id()]; if (unlikely(!pr)) @@ -1428,6 +1422,8 @@ static int acpi_idle_enter_simple(struct cpuidle_device *dev, ACPI_FLUSH_CPU_CACHE(); t1 = inl(acpi_gbl_FADT.xpm_timer_block.address); + /* Tell the scheduler that we are going deep-idle: */ + sched_clock_idle_sleep_event(); acpi_state_timer_broadcast(pr, cx, 1); acpi_idle_do_entry(cx); t2 = inl(acpi_gbl_FADT.xpm_timer_block.address); @@ -1436,6 +1432,10 @@ static int acpi_idle_enter_simple(struct cpuidle_device *dev, /* TSC could halt in idle, so notify users */ mark_tsc_unstable("TSC halts in idle");; #endif + sleep_ticks = ticks_elapsed(t1, t2); + + /* Tell the scheduler how much we idled: */ + sched_clock_idle_wakeup_event(sleep_ticks*PM_TIMER_TICK_NS); local_irq_enable(); current_thread_info()->status |= TS_POLLING; @@ -1443,7 +1443,7 @@ static int acpi_idle_enter_simple(struct cpuidle_device *dev, cx->usage++; acpi_state_timer_broadcast(pr, cx, 0); - cx->time += ticks_elapsed(t1, t2); + cx->time += sleep_ticks; return ticks_elapsed_in_us(t1, t2); } @@ -1463,6 +1463,8 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev, struct acpi_processor *pr; struct acpi_processor_cx *cx = cpuidle_get_statedata(state); u32 t1, t2; + int sleep_ticks = 0; + pr = processors[smp_processor_id()]; if (unlikely(!pr)) @@ -1471,6 +1473,15 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev, if (acpi_idle_suspend) return(acpi_idle_enter_c1(dev, state)); + if (acpi_idle_bm_check()) { + if (dev->safe_state) { + return dev->safe_state->enter(dev, dev->safe_state); + } else { + acpi_safe_halt(); + return 0; + } + } + local_irq_disable(); current_thread_info()->status &= ~TS_POLLING; /* @@ -1485,38 +1496,45 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev, return 0; } + /* Tell the scheduler that we are going deep-idle: */ + sched_clock_idle_sleep_event(); /* * Must be done before busmaster disable as we might need to * access HPET ! */ acpi_state_timer_broadcast(pr, cx, 1); - if (acpi_idle_bm_check()) { - cx = pr->power.bm_state; - - acpi_idle_update_bm_rld(pr, cx); - - t1 = inl(acpi_gbl_FADT.xpm_timer_block.address); - acpi_idle_do_entry(cx); - t2 = inl(acpi_gbl_FADT.xpm_timer_block.address); - } else { - acpi_idle_update_bm_rld(pr, cx); + acpi_idle_update_bm_rld(pr, cx); + /* + * disable bus master + * bm_check implies we need ARB_DIS + * !bm_check implies we need cache flush + * bm_control implies whether we can do ARB_DIS + * + * That leaves a case where bm_check is set and bm_control is + * not set. In that case we cannot do much, we enter C3 + * without doing anything. + */ + if (pr->flags.bm_check && pr->flags.bm_control) { spin_lock(&c3_lock); c3_cpu_count++; /* Disable bus master arbitration when all CPUs are in C3 */ if (c3_cpu_count == num_online_cpus()) acpi_set_register(ACPI_BITREG_ARB_DISABLE, 1); spin_unlock(&c3_lock); + } else if (!pr->flags.bm_check) { + ACPI_FLUSH_CPU_CACHE(); + } - t1 = inl(acpi_gbl_FADT.xpm_timer_block.address); - acpi_idle_do_entry(cx); - t2 = inl(acpi_gbl_FADT.xpm_timer_block.address); + t1 = inl(acpi_gbl_FADT.xpm_timer_block.address); + acpi_idle_do_entry(cx); + t2 = inl(acpi_gbl_FADT.xpm_timer_block.address); + /* Re-enable bus master arbitration */ + if (pr->flags.bm_check && pr->flags.bm_control) { spin_lock(&c3_lock); - /* Re-enable bus master arbitration */ - if (c3_cpu_count == num_online_cpus()) - acpi_set_register(ACPI_BITREG_ARB_DISABLE, 0); + acpi_set_register(ACPI_BITREG_ARB_DISABLE, 0); c3_cpu_count--; spin_unlock(&c3_lock); } @@ -1525,6 +1543,9 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev, /* TSC could halt in idle, so notify users */ mark_tsc_unstable("TSC halts in idle"); #endif + sleep_ticks = ticks_elapsed(t1, t2); + /* Tell the scheduler how much we idled: */ + sched_clock_idle_wakeup_event(sleep_ticks*PM_TIMER_TICK_NS); local_irq_enable(); current_thread_info()->status |= TS_POLLING; @@ -1532,7 +1553,7 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev, cx->usage++; acpi_state_timer_broadcast(pr, cx, 0); - cx->time += ticks_elapsed(t1, t2); + cx->time += sleep_ticks; return ticks_elapsed_in_us(t1, t2); } @@ -1584,12 +1605,14 @@ static int acpi_processor_setup_cpuidle(struct acpi_processor *pr) case ACPI_STATE_C1: state->flags |= CPUIDLE_FLAG_SHALLOW; state->enter = acpi_idle_enter_c1; + dev->safe_state = state; break; case ACPI_STATE_C2: state->flags |= CPUIDLE_FLAG_BALANCED; state->flags |= CPUIDLE_FLAG_TIME_VALID; state->enter = acpi_idle_enter_simple; + dev->safe_state = state; break; case ACPI_STATE_C3: @@ -1610,14 +1633,6 @@ static int acpi_processor_setup_cpuidle(struct acpi_processor *pr) if (!count) return -EINVAL; - /* find the deepest state that can handle active BM */ - if (pr->flags.bm_check) { - for (i = 1; i < ACPI_PROCESSOR_MAX_POWER && i <= max_cstate; i++) - if (pr->power.states[i].type == ACPI_STATE_C3) - break; - pr->power.bm_state = &pr->power.states[i-1]; - } - return 0; } @@ -1658,6 +1673,7 @@ int __cpuinit acpi_processor_power_init(struct acpi_processor *pr, if (!first_run) { dmi_check_system(processor_power_dmi_table); + max_cstate = acpi_processor_cstate_check(max_cstate); if (max_cstate < ACPI_C_STATES_MAX) printk(KERN_NOTICE "ACPI: processor limited to max C-state %d\n", diff --git a/drivers/acpi/processor_throttling.c b/drivers/acpi/processor_throttling.c index 0b8204e..c26c61f 100644 --- a/drivers/acpi/processor_throttling.c +++ b/drivers/acpi/processor_throttling.c @@ -70,7 +70,55 @@ static int acpi_processor_get_platform_limit(struct acpi_processor *pr) int acpi_processor_tstate_has_changed(struct acpi_processor *pr) { - return acpi_processor_get_platform_limit(pr); + int result = 0; + int throttling_limit; + int current_state; + struct acpi_processor_limit *limit; + int target_state; + + result = acpi_processor_get_platform_limit(pr); + if (result) { + /* Throttling Limit is unsupported */ + return result; + } + + throttling_limit = pr->throttling_platform_limit; + if (throttling_limit >= pr->throttling.state_count) { + /* Uncorrect Throttling Limit */ + return -EINVAL; + } + + current_state = pr->throttling.state; + if (current_state > throttling_limit) { + /* + * The current state can meet the requirement of + * _TPC limit. But it is reasonable that OSPM changes + * t-states from high to low for better performance. + * Of course the limit condition of thermal + * and user should be considered. + */ + limit = &pr->limit; + target_state = throttling_limit; + if (limit->thermal.tx > target_state) + target_state = limit->thermal.tx; + if (limit->user.tx > target_state) + target_state = limit->user.tx; + } else if (current_state == throttling_limit) { + /* + * Unnecessary to change the throttling state + */ + return 0; + } else { + /* + * If the current state is lower than the limit of _TPC, it + * will be forced to switch to the throttling state defined + * by throttling_platfor_limit. + * Because the previous state meets with the limit condition + * of thermal and user, it is unnecessary to check it again. + */ + target_state = throttling_limit; + } + return acpi_processor_set_throttling(pr, target_state); } /* @@ -83,6 +131,7 @@ static int acpi_processor_get_throttling_control(struct acpi_processor *pr) struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; union acpi_object *ptc = NULL; union acpi_object obj = { 0 }; + struct acpi_processor_throttling *throttling; status = acpi_evaluate_object(pr->handle, "_PTC", NULL, &buffer); if (ACPI_FAILURE(status)) { @@ -134,6 +183,22 @@ static int acpi_processor_get_throttling_control(struct acpi_processor *pr) memcpy(&pr->throttling.status_register, obj.buffer.pointer, sizeof(struct acpi_ptc_register)); + throttling = &pr->throttling; + + if ((throttling->control_register.bit_width + + throttling->control_register.bit_offset) > 32) { + printk(KERN_ERR PREFIX "Invalid _PTC control register\n"); + result = -EFAULT; + goto end; + } + + if ((throttling->status_register.bit_width + + throttling->status_register.bit_offset) > 32) { + printk(KERN_ERR PREFIX "Invalid _PTC status register\n"); + result = -EFAULT; + goto end; + } + end: kfree(buffer.pointer); @@ -328,44 +393,132 @@ static int acpi_processor_get_throttling_fadt(struct acpi_processor *pr) return 0; } -static int acpi_read_throttling_status(struct acpi_processor_throttling - *throttling) +#ifdef CONFIG_X86 +static int acpi_throttling_rdmsr(struct acpi_processor *pr, + acpi_integer * value) { - int value = -1; + struct cpuinfo_x86 *c; + u64 msr_high, msr_low; + unsigned int cpu; + u64 msr = 0; + int ret = -1; + + cpu = pr->id; + c = &cpu_data(cpu); + + if ((c->x86_vendor != X86_VENDOR_INTEL) || + !cpu_has(c, X86_FEATURE_ACPI)) { + printk(KERN_ERR PREFIX + "HARDWARE addr space,NOT supported yet\n"); + } else { + msr_low = 0; + msr_high = 0; + rdmsr_on_cpu(cpu, MSR_IA32_THERM_CONTROL, + (u32 *)&msr_low , (u32 *) &msr_high); + msr = (msr_high << 32) | msr_low; + *value = (acpi_integer) msr; + ret = 0; + } + return ret; +} + +static int acpi_throttling_wrmsr(struct acpi_processor *pr, acpi_integer value) +{ + struct cpuinfo_x86 *c; + unsigned int cpu; + int ret = -1; + u64 msr; + + cpu = pr->id; + c = &cpu_data(cpu); + + if ((c->x86_vendor != X86_VENDOR_INTEL) || + !cpu_has(c, X86_FEATURE_ACPI)) { + printk(KERN_ERR PREFIX + "HARDWARE addr space,NOT supported yet\n"); + } else { + msr = value; + wrmsr_on_cpu(cpu, MSR_IA32_THERM_CONTROL, + msr & 0xffffffff, msr >> 32); + ret = 0; + } + return ret; +} +#else +static int acpi_throttling_rdmsr(struct acpi_processor *pr, + acpi_integer * value) +{ + printk(KERN_ERR PREFIX + "HARDWARE addr space,NOT supported yet\n"); + return -1; +} + +static int acpi_throttling_wrmsr(struct acpi_processor *pr, acpi_integer value) +{ + printk(KERN_ERR PREFIX + "HARDWARE addr space,NOT supported yet\n"); + return -1; +} +#endif + +static int acpi_read_throttling_status(struct acpi_processor *pr, + acpi_integer *value) +{ + u32 bit_width, bit_offset; + u64 ptc_value; + u64 ptc_mask; + struct acpi_processor_throttling *throttling; + int ret = -1; + + throttling = &pr->throttling; switch (throttling->status_register.space_id) { case ACPI_ADR_SPACE_SYSTEM_IO: + ptc_value = 0; + bit_width = throttling->status_register.bit_width; + bit_offset = throttling->status_register.bit_offset; + acpi_os_read_port((acpi_io_address) throttling->status_register. - address, &value, - (u32) throttling->status_register.bit_width * - 8); + address, (u32 *) &ptc_value, + (u32) (bit_width + bit_offset)); + ptc_mask = (1 << bit_width) - 1; + *value = (acpi_integer) ((ptc_value >> bit_offset) & ptc_mask); + ret = 0; break; case ACPI_ADR_SPACE_FIXED_HARDWARE: - printk(KERN_ERR PREFIX - "HARDWARE addr space,NOT supported yet\n"); + ret = acpi_throttling_rdmsr(pr, value); break; default: printk(KERN_ERR PREFIX "Unknown addr space %d\n", (u32) (throttling->status_register.space_id)); } - return value; + return ret; } -static int acpi_write_throttling_state(struct acpi_processor_throttling - *throttling, int value) +static int acpi_write_throttling_state(struct acpi_processor *pr, + acpi_integer value) { + u32 bit_width, bit_offset; + u64 ptc_value; + u64 ptc_mask; + struct acpi_processor_throttling *throttling; int ret = -1; + throttling = &pr->throttling; switch (throttling->control_register.space_id) { case ACPI_ADR_SPACE_SYSTEM_IO: + bit_width = throttling->control_register.bit_width; + bit_offset = throttling->control_register.bit_offset; + ptc_mask = (1 << bit_width) - 1; + ptc_value = value & ptc_mask; + acpi_os_write_port((acpi_io_address) throttling-> - control_register.address, value, - (u32) throttling->control_register. - bit_width * 8); + control_register.address, + (u32) (ptc_value << bit_offset), + (u32) (bit_width + bit_offset)); ret = 0; break; case ACPI_ADR_SPACE_FIXED_HARDWARE: - printk(KERN_ERR PREFIX - "HARDWARE addr space,NOT supported yet\n"); + ret = acpi_throttling_wrmsr(pr, value); break; default: printk(KERN_ERR PREFIX "Unknown addr space %d\n", @@ -374,7 +527,8 @@ static int acpi_write_throttling_state(struct acpi_processor_throttling return ret; } -static int acpi_get_throttling_state(struct acpi_processor *pr, int value) +static int acpi_get_throttling_state(struct acpi_processor *pr, + acpi_integer value) { int i; @@ -390,22 +544,26 @@ static int acpi_get_throttling_state(struct acpi_processor *pr, int value) return i; } -static int acpi_get_throttling_value(struct acpi_processor *pr, int state) +static int acpi_get_throttling_value(struct acpi_processor *pr, + int state, acpi_integer *value) { - int value = -1; + int ret = -1; + if (state >= 0 && state <= pr->throttling.state_count) { struct acpi_processor_tx_tss *tx = (struct acpi_processor_tx_tss *)&(pr->throttling. states_tss[state]); - value = tx->control; + *value = tx->control; + ret = 0; } - return value; + return ret; } static int acpi_processor_get_throttling_ptc(struct acpi_processor *pr) { int state = 0; - u32 value = 0; + int ret; + acpi_integer value; if (!pr) return -EINVAL; @@ -415,8 +573,9 @@ static int acpi_processor_get_throttling_ptc(struct acpi_processor *pr) pr->throttling.state = 0; local_irq_disable(); - value = acpi_read_throttling_status(&pr->throttling); - if (value >= 0) { + value = 0; + ret = acpi_read_throttling_status(pr, &value); + if (ret >= 0) { state = acpi_get_throttling_state(pr, value); pr->throttling.state = state; } @@ -430,6 +589,40 @@ static int acpi_processor_get_throttling(struct acpi_processor *pr) return pr->throttling.acpi_processor_get_throttling(pr); } +static int acpi_processor_get_fadt_info(struct acpi_processor *pr) +{ + int i, step; + + if (!pr->throttling.address) { + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "No throttling register\n")); + return -EINVAL; + } else if (!pr->throttling.duty_width) { + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "No throttling states\n")); + return -EINVAL; + } + /* TBD: Support duty_cycle values that span bit 4. */ + else if ((pr->throttling.duty_offset + pr->throttling.duty_width) > 4) { + printk(KERN_WARNING PREFIX "duty_cycle spans bit 4\n"); + return -EINVAL; + } + + pr->throttling.state_count = 1 << acpi_gbl_FADT.duty_width; + + /* + * Compute state values. Note that throttling displays a linear power + * performance relationship (at 50% performance the CPU will consume + * 50% power). Values are in 1/10th of a percent to preserve accuracy. + */ + + step = (1000 / pr->throttling.state_count); + + for (i = 0; i < pr->throttling.state_count; i++) { + pr->throttling.states[i].performance = 1000 - step * i; + pr->throttling.states[i].power = 1000 - step * i; + } + return 0; +} + static int acpi_processor_set_throttling_fadt(struct acpi_processor *pr, int state) { @@ -506,7 +699,8 @@ static int acpi_processor_set_throttling_fadt(struct acpi_processor *pr, static int acpi_processor_set_throttling_ptc(struct acpi_processor *pr, int state) { - u32 value = 0; + int ret; + acpi_integer value; if (!pr) return -EINVAL; @@ -524,10 +718,10 @@ static int acpi_processor_set_throttling_ptc(struct acpi_processor *pr, return -EPERM; local_irq_disable(); - - value = acpi_get_throttling_value(pr, state); - if (value >= 0) { - acpi_write_throttling_state(&pr->throttling, value); + value = 0; + ret = acpi_get_throttling_value(pr, state, &value); + if (ret >= 0) { + acpi_write_throttling_state(pr, value); pr->throttling.state = state; } local_irq_enable(); @@ -543,8 +737,6 @@ int acpi_processor_set_throttling(struct acpi_processor *pr, int state) int acpi_processor_get_throttling_info(struct acpi_processor *pr) { int result = 0; - int step = 0; - int i = 0; ACPI_DEBUG_PRINT((ACPI_DB_INFO, "pblk_address[0x%08x] duty_offset[%d] duty_width[%d]\n", @@ -563,6 +755,8 @@ int acpi_processor_get_throttling_info(struct acpi_processor *pr) acpi_processor_get_throttling_states(pr) || acpi_processor_get_platform_limit(pr)) { + if (acpi_processor_get_fadt_info(pr)) + return 0; pr->throttling.acpi_processor_get_throttling = &acpi_processor_get_throttling_fadt; pr->throttling.acpi_processor_set_throttling = @@ -576,19 +770,6 @@ int acpi_processor_get_throttling_info(struct acpi_processor *pr) acpi_processor_get_tsd(pr); - if (!pr->throttling.address) { - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "No throttling register\n")); - return 0; - } else if (!pr->throttling.duty_width) { - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "No throttling states\n")); - return 0; - } - /* TBD: Support duty_cycle values that span bit 4. */ - else if ((pr->throttling.duty_offset + pr->throttling.duty_width) > 4) { - printk(KERN_WARNING PREFIX "duty_cycle spans bit 4\n"); - return 0; - } - /* * PIIX4 Errata: We don't support throttling on the original PIIX4. * This shouldn't be an issue as few (if any) mobile systems ever @@ -600,21 +781,6 @@ int acpi_processor_get_throttling_info(struct acpi_processor *pr) return 0; } - pr->throttling.state_count = 1 << acpi_gbl_FADT.duty_width; - - /* - * Compute state values. Note that throttling displays a linear power/ - * performance relationship (at 50% performance the CPU will consume - * 50% power). Values are in 1/10th of a percent to preserve accuracy. - */ - - step = (1000 / pr->throttling.state_count); - - for (i = 0; i < pr->throttling.state_count; i++) { - pr->throttling.states[i].performance = step * i; - pr->throttling.states[i].power = step * i; - } - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found %d throttling states\n", pr->throttling.state_count)); diff --git a/drivers/acpi/sbs.c b/drivers/acpi/sbs.c index 90fd09c..6045cdb 100644 --- a/drivers/acpi/sbs.c +++ b/drivers/acpi/sbs.c @@ -29,7 +29,7 @@ #include <linux/moduleparam.h> #include <linux/kernel.h> -#ifdef CONFIG_ACPI_PROCFS +#ifdef CONFIG_ACPI_PROCFS_POWER #include <linux/proc_fs.h> #include <linux/seq_file.h> #include <asm/uaccess.h> @@ -88,7 +88,7 @@ MODULE_DEVICE_TABLE(acpi, sbs_device_ids); struct acpi_battery { struct power_supply bat; struct acpi_sbs *sbs; -#ifdef CONFIG_ACPI_PROCFS +#ifdef CONFIG_ACPI_PROCFS_POWER struct proc_dir_entry *proc_entry; #endif unsigned long update_time; @@ -113,6 +113,7 @@ struct acpi_battery { u16 spec; u8 id; u8 present:1; + u8 have_sysfs_alarm:1; }; #define to_acpi_battery(x) container_of(x, struct acpi_battery, bat); @@ -122,7 +123,7 @@ struct acpi_sbs { struct acpi_device *device; struct acpi_smb_hc *hc; struct mutex lock; -#ifdef CONFIG_ACPI_PROCFS +#ifdef CONFIG_ACPI_PROCFS_POWER struct proc_dir_entry *charger_entry; #endif struct acpi_battery battery[MAX_SBS_BAT]; @@ -468,7 +469,7 @@ static struct device_attribute alarm_attr = { FS Interface (/proc/acpi) -------------------------------------------------------------------------- */ -#ifdef CONFIG_ACPI_PROCFS +#ifdef CONFIG_ACPI_PROCFS_POWER /* Generic Routines */ static int acpi_sbs_add_fs(struct proc_dir_entry **dir, @@ -789,7 +790,7 @@ static int acpi_battery_add(struct acpi_sbs *sbs, int id) return result; sprintf(battery->name, ACPI_BATTERY_DIR_NAME, id); -#ifdef CONFIG_ACPI_PROCFS +#ifdef CONFIG_ACPI_PROCFS_POWER acpi_sbs_add_fs(&battery->proc_entry, acpi_battery_dir, battery->name, &acpi_battery_info_fops, &acpi_battery_state_fops, &acpi_battery_alarm_fops, @@ -808,7 +809,13 @@ static int acpi_battery_add(struct acpi_sbs *sbs, int id) } battery->bat.get_property = acpi_sbs_battery_get_property; result = power_supply_register(&sbs->device->dev, &battery->bat); - device_create_file(battery->bat.dev, &alarm_attr); + if (result) + goto end; + result = device_create_file(battery->bat.dev, &alarm_attr); + if (result) + goto end; + battery->have_sysfs_alarm = 1; + end: printk(KERN_INFO PREFIX "%s [%s]: Battery Slot [%s] (battery %s)\n", ACPI_SBS_DEVICE_NAME, acpi_device_bid(sbs->device), battery->name, sbs->battery->present ? "present" : "absent"); @@ -817,14 +824,16 @@ static int acpi_battery_add(struct acpi_sbs *sbs, int id) static void acpi_battery_remove(struct acpi_sbs *sbs, int id) { - if (sbs->battery[id].bat.dev) - device_remove_file(sbs->battery[id].bat.dev, &alarm_attr); - power_supply_unregister(&sbs->battery[id].bat); -#ifdef CONFIG_ACPI_PROCFS - if (sbs->battery[id].proc_entry) { - acpi_sbs_remove_fs(&(sbs->battery[id].proc_entry), - acpi_battery_dir); + struct acpi_battery *battery = &sbs->battery[id]; + + if (battery->bat.dev) { + if (battery->have_sysfs_alarm) + device_remove_file(battery->bat.dev, &alarm_attr); + power_supply_unregister(&battery->bat); } +#ifdef CONFIG_ACPI_PROCFS_POWER + if (battery->proc_entry) + acpi_sbs_remove_fs(&battery->proc_entry, acpi_battery_dir); #endif } @@ -835,7 +844,7 @@ static int acpi_charger_add(struct acpi_sbs *sbs) result = acpi_ac_get_present(sbs); if (result) goto end; -#ifdef CONFIG_ACPI_PROCFS +#ifdef CONFIG_ACPI_PROCFS_POWER result = acpi_sbs_add_fs(&sbs->charger_entry, acpi_ac_dir, ACPI_AC_DIR_NAME, NULL, &acpi_ac_state_fops, NULL, sbs); @@ -859,7 +868,7 @@ static void acpi_charger_remove(struct acpi_sbs *sbs) { if (sbs->charger.dev) power_supply_unregister(&sbs->charger); -#ifdef CONFIG_ACPI_PROCFS +#ifdef CONFIG_ACPI_PROCFS_POWER if (sbs->charger_entry) acpi_sbs_remove_fs(&sbs->charger_entry, acpi_ac_dir); #endif @@ -965,7 +974,7 @@ static int acpi_sbs_remove(struct acpi_device *device, int type) static void acpi_sbs_rmdirs(void) { -#ifdef CONFIG_ACPI_PROCFS +#ifdef CONFIG_ACPI_PROCFS_POWER if (acpi_ac_dir) { acpi_unlock_ac_dir(acpi_ac_dir); acpi_ac_dir = NULL; @@ -1004,7 +1013,7 @@ static int __init acpi_sbs_init(void) if (acpi_disabled) return -ENODEV; -#ifdef CONFIG_ACPI_PROCFS +#ifdef CONFIG_ACPI_PROCFS_POWER acpi_ac_dir = acpi_lock_ac_dir(); if (!acpi_ac_dir) return -ENODEV; diff --git a/drivers/acpi/tables/tbutils.c b/drivers/acpi/tables/tbutils.c index 5f1d85f..010f196 100644 --- a/drivers/acpi/tables/tbutils.c +++ b/drivers/acpi/tables/tbutils.c @@ -449,7 +449,7 @@ acpi_tb_parse_root_table(acpi_physical_address rsdp_address, u8 flags) /* XSDT has NULL entry, RSDT is used */ address = rsdt_address; table_entry_size = sizeof(u32); - ACPI_WARNING((AE_INFO, "BIOS XSDT has NULL entry," + ACPI_WARNING((AE_INFO, "BIOS XSDT has NULL entry, " "using RSDT")); } } diff --git a/drivers/acpi/toshiba_acpi.c b/drivers/acpi/toshiba_acpi.c index a736ef7..9e8c20c 100644 --- a/drivers/acpi/toshiba_acpi.c +++ b/drivers/acpi/toshiba_acpi.c @@ -591,9 +591,12 @@ static int __init toshiba_acpi_init(void) NULL, &toshiba_backlight_data); if (IS_ERR(toshiba_backlight_device)) { + int ret = PTR_ERR(toshiba_backlight_device); + printk(KERN_ERR "Could not register toshiba backlight device\n"); toshiba_backlight_device = NULL; toshiba_acpi_exit(); + return ret; } toshiba_backlight_device->props.max_brightness = HCI_LCD_BRIGHTNESS_LEVELS - 1; diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c index bac956b..44a0d9b 100644 --- a/drivers/acpi/video.c +++ b/drivers/acpi/video.c @@ -29,6 +29,7 @@ #include <linux/init.h> #include <linux/types.h> #include <linux/list.h> +#include <linux/mutex.h> #include <linux/proc_fs.h> #include <linux/seq_file.h> #include <linux/input.h> @@ -135,8 +136,8 @@ struct acpi_video_bus { u8 attached_count; struct acpi_video_bus_cap cap; struct acpi_video_bus_flags flags; - struct semaphore sem; struct list_head video_device_list; + struct mutex device_list_lock; /* protects video_device_list */ struct proc_dir_entry *dir; struct input_dev *input; char phys[32]; /* for input device */ @@ -896,7 +897,7 @@ acpi_video_device_write_brightness(struct file *file, { struct seq_file *m = file->private_data; struct acpi_video_device *dev = m->private; - char str[4] = { 0 }; + char str[5] = { 0 }; unsigned int level = 0; int i; @@ -1436,9 +1437,9 @@ acpi_video_bus_get_one_device(struct acpi_device *device, return -ENODEV; } - down(&video->sem); + mutex_lock(&video->device_list_lock); list_add_tail(&data->entry, &video->video_device_list); - up(&video->sem); + mutex_unlock(&video->device_list_lock); acpi_video_device_add_fs(device); @@ -1462,12 +1463,14 @@ acpi_video_bus_get_one_device(struct acpi_device *device, static void acpi_video_device_rebind(struct acpi_video_bus *video) { - struct list_head *node, *next; - list_for_each_safe(node, next, &video->video_device_list) { - struct acpi_video_device *dev = - container_of(node, struct acpi_video_device, entry); + struct acpi_video_device *dev; + + mutex_lock(&video->device_list_lock); + + list_for_each_entry(dev, &video->video_device_list, entry) acpi_video_device_bind(video, dev); - } + + mutex_unlock(&video->device_list_lock); } /* @@ -1592,30 +1595,33 @@ static int acpi_video_device_enumerate(struct acpi_video_bus *video) static int acpi_video_switch_output(struct acpi_video_bus *video, int event) { - struct list_head *node, *next; + struct list_head *node; struct acpi_video_device *dev = NULL; struct acpi_video_device *dev_next = NULL; struct acpi_video_device *dev_prev = NULL; unsigned long state; int status = 0; + mutex_lock(&video->device_list_lock); - list_for_each_safe(node, next, &video->video_device_list) { + list_for_each(node, &video->video_device_list) { dev = container_of(node, struct acpi_video_device, entry); status = acpi_video_device_get_state(dev, &state); if (state & 0x2) { - dev_next = - container_of(node->next, struct acpi_video_device, - entry); - dev_prev = - container_of(node->prev, struct acpi_video_device, - entry); + dev_next = container_of(node->next, + struct acpi_video_device, entry); + dev_prev = container_of(node->prev, + struct acpi_video_device, entry); goto out; } } + dev_next = container_of(node->next, struct acpi_video_device, entry); dev_prev = container_of(node->prev, struct acpi_video_device, entry); - out: + + out: + mutex_unlock(&video->device_list_lock); + switch (event) { case ACPI_VIDEO_NOTIFY_CYCLE: case ACPI_VIDEO_NOTIFY_NEXT_OUTPUT: @@ -1691,24 +1697,17 @@ acpi_video_bus_get_devices(struct acpi_video_bus *video, struct acpi_device *device) { int status = 0; - struct list_head *node, *next; - + struct acpi_device *dev; acpi_video_device_enumerate(video); - list_for_each_safe(node, next, &device->children) { - struct acpi_device *dev = - list_entry(node, struct acpi_device, node); - - if (!dev) - continue; + list_for_each_entry(dev, &device->children, node) { status = acpi_video_bus_get_one_device(dev, video); if (ACPI_FAILURE(status)) { ACPI_EXCEPTION((AE_INFO, status, "Cant attach device")); continue; } - } return status; } @@ -1724,9 +1723,6 @@ static int acpi_video_bus_put_one_device(struct acpi_video_device *device) video = device->video; - down(&video->sem); - list_del(&device->entry); - up(&video->sem); acpi_video_device_remove_fs(device->dev); status = acpi_remove_notify_handler(device->dev->handle, @@ -1734,32 +1730,34 @@ static int acpi_video_bus_put_one_device(struct acpi_video_device *device) acpi_video_device_notify); backlight_device_unregister(device->backlight); video_output_unregister(device->output_dev); + return 0; } static int acpi_video_bus_put_devices(struct acpi_video_bus *video) { int status; - struct list_head *node, *next; + struct acpi_video_device *dev, *next; + mutex_lock(&video->device_list_lock); - list_for_each_safe(node, next, &video->video_device_list) { - struct acpi_video_device *data = - list_entry(node, struct acpi_video_device, entry); - if (!data) - continue; + list_for_each_entry_safe(dev, next, &video->video_device_list, entry) { - status = acpi_video_bus_put_one_device(data); + status = acpi_video_bus_put_one_device(dev); if (ACPI_FAILURE(status)) printk(KERN_WARNING PREFIX "hhuuhhuu bug in acpi video driver.\n"); - if (data->brightness) - kfree(data->brightness->levels); - kfree(data->brightness); - kfree(data); + if (dev->brightness) { + kfree(dev->brightness->levels); + kfree(dev->brightness); + } + list_del(&dev->entry); + kfree(dev); } + mutex_unlock(&video->device_list_lock); + return 0; } @@ -1782,9 +1780,6 @@ static void acpi_video_bus_notify(acpi_handle handle, u32 event, void *data) struct input_dev *input; int keycode; - - printk("video bus notify\n"); - if (!video) return; @@ -1897,14 +1892,10 @@ static void acpi_video_device_notify(acpi_handle handle, u32 event, void *data) static int instance; static int acpi_video_bus_add(struct acpi_device *device) { - int result = 0; - acpi_status status = 0; - struct acpi_video_bus *video = NULL; + acpi_status status; + struct acpi_video_bus *video; struct input_dev *input; - - - if (!device) - return -EINVAL; + int error; video = kzalloc(sizeof(struct acpi_video_bus), GFP_KERNEL); if (!video) @@ -1923,15 +1914,15 @@ static int acpi_video_bus_add(struct acpi_device *device) acpi_driver_data(device) = video; acpi_video_bus_find_cap(video); - result = acpi_video_bus_check(video); - if (result) - goto end; + error = acpi_video_bus_check(video); + if (error) + goto err_free_video; - result = acpi_video_bus_add_fs(device); - if (result) - goto end; + error = acpi_video_bus_add_fs(device); + if (error) + goto err_free_video; - init_MUTEX(&video->sem); + mutex_init(&video->device_list_lock); INIT_LIST_HEAD(&video->video_device_list); acpi_video_bus_get_devices(video, device); @@ -1943,16 +1934,15 @@ static int acpi_video_bus_add(struct acpi_device *device) if (ACPI_FAILURE(status)) { ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error installing notify handler\n")); - acpi_video_bus_stop_devices(video); - acpi_video_bus_put_devices(video); - kfree(video->attached_array); - acpi_video_bus_remove_fs(device); - result = -ENODEV; - goto end; + error = -ENODEV; + goto err_stop_video; } - video->input = input = input_allocate_device(); + if (!input) { + error = -ENOMEM; + goto err_uninstall_notify; + } snprintf(video->phys, sizeof(video->phys), "%s/video/input0", acpi_device_hid(video->device)); @@ -1961,6 +1951,7 @@ static int acpi_video_bus_add(struct acpi_device *device) input->phys = video->phys; input->id.bustype = BUS_HOST; input->id.product = 0x06; + input->dev.parent = &device->dev; input->evbit[0] = BIT(EV_KEY); set_bit(KEY_SWITCHVIDEOMODE, input->keybit); set_bit(KEY_VIDEO_NEXT, input->keybit); @@ -1971,18 +1962,10 @@ static int acpi_video_bus_add(struct acpi_device *device) set_bit(KEY_BRIGHTNESS_ZERO, input->keybit); set_bit(KEY_DISPLAY_OFF, input->keybit); set_bit(KEY_UNKNOWN, input->keybit); - result = input_register_device(input); - if (result) { - acpi_remove_notify_handler(video->device->handle, - ACPI_DEVICE_NOTIFY, - acpi_video_bus_notify); - acpi_video_bus_stop_devices(video); - acpi_video_bus_put_devices(video); - kfree(video->attached_array); - acpi_video_bus_remove_fs(device); - goto end; - } + error = input_register_device(input); + if (error) + goto err_free_input_dev; printk(KERN_INFO PREFIX "%s [%s] (multi-head: %s rom: %s post: %s)\n", ACPI_VIDEO_DEVICE_NAME, acpi_device_bid(device), @@ -1990,11 +1973,23 @@ static int acpi_video_bus_add(struct acpi_device *device) video->flags.rom ? "yes" : "no", video->flags.post ? "yes" : "no"); - end: - if (result) - kfree(video); + return 0; + + err_free_input_dev: + input_free_device(input); + err_uninstall_notify: + acpi_remove_notify_handler(device->handle, ACPI_DEVICE_NOTIFY, + acpi_video_bus_notify); + err_stop_video: + acpi_video_bus_stop_devices(video); + acpi_video_bus_put_devices(video); + kfree(video->attached_array); + acpi_video_bus_remove_fs(device); + err_free_video: + kfree(video); + acpi_driver_data(device) = NULL; - return result; + return error; } static int acpi_video_bus_remove(struct acpi_device *device, int type) diff --git a/drivers/ata/ata_piix.c b/drivers/ata/ata_piix.c index f08cca2..b538e1d 100644 --- a/drivers/ata/ata_piix.c +++ b/drivers/ata/ata_piix.c @@ -119,18 +119,19 @@ enum { PIIX_80C_SEC = (1 << 7) | (1 << 6), /* controller IDs */ - piix_pata_33 = 0, /* PIIX4 at 33Mhz */ - ich_pata_33 = 1, /* ICH up to UDMA 33 only */ - ich_pata_66 = 2, /* ICH up to 66 Mhz */ - ich_pata_100 = 3, /* ICH up to UDMA 100 */ - ich5_sata = 5, - ich6_sata = 6, - ich6_sata_ahci = 7, - ich6m_sata_ahci = 8, - ich8_sata_ahci = 9, - piix_pata_mwdma = 10, /* PIIX3 MWDMA only */ - tolapai_sata_ahci = 11, - ich9_2port_sata = 12, + piix_pata_mwdma = 0, /* PIIX3 MWDMA only */ + piix_pata_33, /* PIIX4 at 33Mhz */ + ich_pata_33, /* ICH up to UDMA 33 only */ + ich_pata_66, /* ICH up to 66 Mhz */ + ich_pata_100, /* ICH up to UDMA 100 */ + ich5_sata, + ich6_sata, + ich6_sata_ahci, + ich6m_sata_ahci, + ich8_sata_ahci, + ich8_2port_sata, + ich8m_apple_sata_ahci, /* locks up on second port enable */ + tolapai_sata_ahci, /* constants for mapping table */ P0 = 0, /* port 0 */ @@ -239,19 +240,21 @@ static const struct pci_device_id piix_pci_tbl[] = { /* SATA Controller 1 IDE (ICH8) */ { 0x8086, 0x2820, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_ahci }, /* SATA Controller 2 IDE (ICH8) */ - { 0x8086, 0x2825, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich9_2port_sata }, + { 0x8086, 0x2825, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata }, /* Mobile SATA Controller IDE (ICH8M) */ { 0x8086, 0x2828, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_ahci }, + /* Mobile SATA Controller IDE (ICH8M), Apple */ + { 0x8086, 0x2828, 0x106b, 0x00a0, 0, 0, ich8m_apple_sata_ahci }, /* SATA Controller IDE (ICH9) */ { 0x8086, 0x2920, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_ahci }, /* SATA Controller IDE (ICH9) */ - { 0x8086, 0x2921, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich9_2port_sata }, + { 0x8086, 0x2921, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata }, /* SATA Controller IDE (ICH9) */ - { 0x8086, 0x2926, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich9_2port_sata }, + { 0x8086, 0x2926, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata }, /* SATA Controller IDE (ICH9M) */ - { 0x8086, 0x2928, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich9_2port_sata }, + { 0x8086, 0x2928, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata }, /* SATA Controller IDE (ICH9M) */ - { 0x8086, 0x292d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich9_2port_sata }, + { 0x8086, 0x292d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata }, /* SATA Controller IDE (ICH9M) */ { 0x8086, 0x292e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_ahci }, /* SATA Controller IDE (Tolapai) */ @@ -427,7 +430,7 @@ static const struct piix_map_db ich6m_map_db = { static const struct piix_map_db ich8_map_db = { .mask = 0x3, - .port_enable = 0x3, + .port_enable = 0xf, .map = { /* PM PS SM SS MAP */ { P0, P2, P1, P3 }, /* 00b (hardwired when in AHCI) */ @@ -437,7 +440,7 @@ static const struct piix_map_db ich8_map_db = { }, }; -static const struct piix_map_db tolapai_map_db = { +static const struct piix_map_db ich8_2port_map_db = { .mask = 0x3, .port_enable = 0x3, .map = { @@ -449,7 +452,19 @@ static const struct piix_map_db tolapai_map_db = { }, }; -static const struct piix_map_db ich9_2port_map_db = { +static const struct piix_map_db ich8m_apple_map_db = { + .mask = 0x3, + .port_enable = 0x1, + .map = { + /* PM PS SM SS MAP */ + { P0, NA, NA, NA }, /* 00b */ + { RV, RV, RV, RV }, + { P0, P2, IDE, IDE }, /* 10b */ + { RV, RV, RV, RV }, + }, +}; + +static const struct piix_map_db tolapai_map_db = { .mask = 0x3, .port_enable = 0x3, .map = { @@ -467,11 +482,21 @@ static const struct piix_map_db *piix_map_db_table[] = { [ich6_sata_ahci] = &ich6_map_db, [ich6m_sata_ahci] = &ich6m_map_db, [ich8_sata_ahci] = &ich8_map_db, + [ich8_2port_sata] = &ich8_2port_map_db, + [ich8m_apple_sata_ahci] = &ich8m_apple_map_db, [tolapai_sata_ahci] = &tolapai_map_db, - [ich9_2port_sata] = &ich9_2port_map_db, }; static struct ata_port_info piix_port_info[] = { + [piix_pata_mwdma] = /* PIIX3 MWDMA only */ + { + .sht = &piix_sht, + .flags = PIIX_PATA_FLAGS, + .pio_mask = 0x1f, /* pio0-4 */ + .mwdma_mask = 0x06, /* mwdma1-2 ?? CHECK 0 should be ok but slow */ + .port_ops = &piix_pata_ops, + }, + [piix_pata_33] = /* PIIX4 at 33MHz */ { .sht = &piix_sht, @@ -565,13 +590,15 @@ static struct ata_port_info piix_port_info[] = { .port_ops = &piix_sata_ops, }, - [piix_pata_mwdma] = /* PIIX3 MWDMA only */ + [ich8_2port_sata] = { .sht = &piix_sht, - .flags = PIIX_PATA_FLAGS, + .flags = PIIX_SATA_FLAGS | PIIX_FLAG_SCR | + PIIX_FLAG_AHCI, .pio_mask = 0x1f, /* pio0-4 */ - .mwdma_mask = 0x06, /* mwdma1-2 ?? CHECK 0 should be ok but slow */ - .port_ops = &piix_pata_ops, + .mwdma_mask = 0x07, /* mwdma0-2 */ + .udma_mask = ATA_UDMA6, + .port_ops = &piix_sata_ops, }, [tolapai_sata_ahci] = @@ -585,7 +612,7 @@ static struct ata_port_info piix_port_info[] = { .port_ops = &piix_sata_ops, }, - [ich9_2port_sata] = + [ich8m_apple_sata_ahci] = { .sht = &piix_sht, .flags = PIIX_SATA_FLAGS | PIIX_FLAG_SCR | @@ -595,6 +622,7 @@ static struct ata_port_info piix_port_info[] = { .udma_mask = ATA_UDMA6, .port_ops = &piix_sata_ops, }, + }; static struct pci_bits piix_enable_bits[] = { @@ -939,6 +967,13 @@ static int piix_broken_suspend(void) }, }, { + .ident = "TECRA M3", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), + DMI_MATCH(DMI_PRODUCT_NAME, "Tecra M3"), + }, + }, + { .ident = "TECRA M5", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), @@ -953,6 +988,20 @@ static int piix_broken_suspend(void) }, }, { + .ident = "TECRA A8", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), + DMI_MATCH(DMI_PRODUCT_NAME, "TECRA A8"), + }, + }, + { + .ident = "Satellite R25", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), + DMI_MATCH(DMI_PRODUCT_NAME, "Satellite R25"), + }, + }, + { .ident = "Satellite U200", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), @@ -960,6 +1009,20 @@ static int piix_broken_suspend(void) }, }, { + .ident = "Satellite U200", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), + DMI_MATCH(DMI_PRODUCT_NAME, "SATELLITE U200"), + }, + }, + { + .ident = "Satellite Pro U200", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), + DMI_MATCH(DMI_PRODUCT_NAME, "SATELLITE PRO U200"), + }, + }, + { .ident = "Satellite U205", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), @@ -967,6 +1030,13 @@ static int piix_broken_suspend(void) }, }, { + .ident = "SATELLITE U205", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), + DMI_MATCH(DMI_PRODUCT_NAME, "SATELLITE U205"), + }, + }, + { .ident = "Portege M500", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), @@ -1079,12 +1149,12 @@ static int piix_disable_ahci(struct pci_dev *pdev) if (!mmio) return -ENOMEM; - tmp = readl(mmio + AHCI_GLOBAL_CTL); + tmp = ioread32(mmio + AHCI_GLOBAL_CTL); if (tmp & AHCI_ENABLE) { tmp &= ~AHCI_ENABLE; - writel(tmp, mmio + AHCI_GLOBAL_CTL); + iowrite32(tmp, mmio + AHCI_GLOBAL_CTL); - tmp = readl(mmio + AHCI_GLOBAL_CTL); + tmp = ioread32(mmio + AHCI_GLOBAL_CTL); if (tmp & AHCI_ENABLE) rc = -EIO; } diff --git a/drivers/ata/libata-acpi.c b/drivers/ata/libata-acpi.c index 08a52dd..545ea86 100644 --- a/drivers/ata/libata-acpi.c +++ b/drivers/ata/libata-acpi.c @@ -312,7 +312,7 @@ EXPORT_SYMBOL_GPL(ata_acpi_stm); * * RETURNS: * Number of taskfiles on success, 0 if _GTF doesn't exist or doesn't - * contain valid data. -errno on other errors. + * contain valid data. */ static int ata_dev_get_GTF(struct ata_device *dev, struct ata_acpi_gtf **gtf, void **ptr_to_free) @@ -339,7 +339,6 @@ static int ata_dev_get_GTF(struct ata_device *dev, struct ata_acpi_gtf **gtf, ata_dev_printk(dev, KERN_WARNING, "_GTF evaluation failed (AE 0x%x)\n", status); - rc = -EIO; } goto out_free; } @@ -359,7 +358,6 @@ static int ata_dev_get_GTF(struct ata_device *dev, struct ata_acpi_gtf **gtf, ata_dev_printk(dev, KERN_WARNING, "_GTF unexpected object type 0x%x\n", out_obj->type); - rc = -EINVAL; goto out_free; } @@ -367,7 +365,6 @@ static int ata_dev_get_GTF(struct ata_device *dev, struct ata_acpi_gtf **gtf, ata_dev_printk(dev, KERN_WARNING, "unexpected _GTF length (%d)\n", out_obj->buffer.length); - rc = -EINVAL; goto out_free; } @@ -511,10 +508,7 @@ static int ata_acpi_exec_tfs(struct ata_device *dev) int gtf_count, i, rc; /* get taskfiles */ - rc = ata_dev_get_GTF(dev, >f, &ptr_to_free); - if (rc < 0) - return rc; - gtf_count = rc; + gtf_count = ata_dev_get_GTF(dev, >f, &ptr_to_free); /* execute them */ for (i = 0, rc = 0; i < gtf_count; i++) { diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index ec3ce12..b514a80 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -30,6 +30,14 @@ * Hardware documentation available from http://www.t13.org/ and * http://www.sata-io.org/ * + * Standards documents from: + * http://www.t13.org (ATA standards, PCI DMA IDE spec) + * http://www.t10.org (SCSI MMC - for ATAPI MMC) + * http://www.sata-io.org (SATA) + * http://www.compactflash.org (CF) + * http://www.qic.org (QIC157 - Tape and DSC) + * http://www.ce-ata.org (CE-ATA: not supported) + * */ #include <linux/kernel.h> @@ -2307,8 +2315,10 @@ int ata_dev_configure(struct ata_device *dev) } if ((dev->class == ATA_DEV_ATAPI) && - (atapi_command_packet_set(id) == TYPE_TAPE)) + (atapi_command_packet_set(id) == TYPE_TAPE)) { dev->max_sectors = ATA_MAX_SECTORS_TAPE; + dev->horkage |= ATA_HORKAGE_STUCK_ERR; + } if (dev->horkage & ATA_HORKAGE_MAX_SEC_128) dev->max_sectors = min_t(unsigned int, ATA_MAX_SECTORS_128, @@ -2581,81 +2591,6 @@ void sata_print_link_status(struct ata_link *link) } /** - * __sata_phy_reset - Wake/reset a low-level SATA PHY - * @ap: SATA port associated with target SATA PHY. - * - * This function issues commands to standard SATA Sxxx - * PHY registers, to wake up the phy (and device), and - * clear any reset condition. - * - * LOCKING: - * PCI/etc. bus probe sem. - * - */ -void __sata_phy_reset(struct ata_port *ap) -{ - struct ata_link *link = &ap->link; - unsigned long timeout = jiffies + (HZ * 5); - u32 sstatus; - - if (ap->flags & ATA_FLAG_SATA_RESET) { - /* issue phy wake/reset */ - sata_scr_write_flush(link, SCR_CONTROL, 0x301); - /* Couldn't find anything in SATA I/II specs, but - * AHCI-1.1 10.4.2 says at least 1 ms. */ - mdelay(1); - } - /* phy wake/clear reset */ - sata_scr_write_flush(link, SCR_CONTROL, 0x300); - - /* wait for phy to become ready, if necessary */ - do { - msleep(200); - sata_scr_read(link, SCR_STATUS, &sstatus); - if ((sstatus & 0xf) != 1) - break; - } while (time_before(jiffies, timeout)); - - /* print link status */ - sata_print_link_status(link); - - /* TODO: phy layer with polling, timeouts, etc. */ - if (!ata_link_offline(link)) - ata_port_probe(ap); - else - ata_port_disable(ap); - - if (ap->flags & ATA_FLAG_DISABLED) - return; - - if (ata_busy_sleep(ap, ATA_TMOUT_BOOT_QUICK, ATA_TMOUT_BOOT)) { - ata_port_disable(ap); - return; - } - - ap->cbl = ATA_CBL_SATA; -} - -/** - * sata_phy_reset - Reset SATA bus. - * @ap: SATA port associated with target SATA PHY. - * - * This function resets the SATA bus, and then probes - * the bus for devices. - * - * LOCKING: - * PCI/etc. bus probe sem. - * - */ -void sata_phy_reset(struct ata_port *ap) -{ - __sata_phy_reset(ap); - if (ap->flags & ATA_FLAG_DISABLED) - return; - ata_bus_reset(ap); -} - -/** * ata_dev_pair - return other device on cable * @adev: device * @@ -3373,14 +3308,20 @@ void ata_wait_after_reset(struct ata_port *ap, unsigned long deadline) * to clear 0xff after reset. For example, HHD424020F7SV00 * iVDR needs >= 800ms while. Quantum GoVault needs even more * than that. + * + * Note that some PATA controllers (pata_ali) explode if + * status register is read more than once when there's no + * device attached. */ - while (1) { - u8 status = ata_chk_status(ap); + if (ap->flags & ATA_FLAG_SATA) { + while (1) { + u8 status = ata_chk_status(ap); - if (status != 0xff || time_after(jiffies, deadline)) - return; + if (status != 0xff || time_after(jiffies, deadline)) + return; - msleep(50); + msleep(50); + } } } @@ -4244,6 +4185,9 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = { /* Devices which get the IVB wrong */ { "QUANTUM FIREBALLlct10 05", "A03.0900", ATA_HORKAGE_IVB, }, { "TSSTcorp CDDVDW SH-S202J", "SB00", ATA_HORKAGE_IVB, }, + { "TSSTcorp CDDVDW SH-S202J", "SB01", ATA_HORKAGE_IVB, }, + { "TSSTcorp CDDVDW SH-S202N", "SB00", ATA_HORKAGE_IVB, }, + { "TSSTcorp CDDVDW SH-S202N", "SB01", ATA_HORKAGE_IVB, }, /* End Marker */ { } @@ -5484,11 +5428,19 @@ fsm_start: * let the EH abort the command or reset the device. */ if (unlikely(status & (ATA_ERR | ATA_DF))) { - ata_port_printk(ap, KERN_WARNING, "DRQ=1 with device " - "error, dev_stat 0x%X\n", status); - qc->err_mask |= AC_ERR_HSM; - ap->hsm_task_state = HSM_ST_ERR; - goto fsm_start; + /* Some ATAPI tape drives forget to clear the ERR bit + * when doing the next command (mostly request sense). + * We ignore ERR here to workaround and proceed sending + * the CDB. + */ + if (!(qc->dev->horkage & ATA_HORKAGE_STUCK_ERR)) { + ata_port_printk(ap, KERN_WARNING, + "DRQ=1 with device error, " + "dev_stat 0x%X\n", status); + qc->err_mask |= AC_ERR_HSM; + ap->hsm_task_state = HSM_ST_ERR; + goto fsm_start; + } } /* Send the CDB (atapi) or the first data block (ata pio out). @@ -6821,19 +6773,6 @@ static void ata_host_release(struct device *gendev, void *res) if (!ap) continue; - if ((host->flags & ATA_HOST_STARTED) && ap->ops->port_stop) - ap->ops->port_stop(ap); - } - - if ((host->flags & ATA_HOST_STARTED) && host->ops->host_stop) - host->ops->host_stop(host); - - for (i = 0; i < host->n_ports; i++) { - struct ata_port *ap = host->ports[i]; - - if (!ap) - continue; - if (ap->scsi_host) scsi_host_put(ap->scsi_host); @@ -6960,6 +6899,24 @@ struct ata_host *ata_host_alloc_pinfo(struct device *dev, return host; } +static void ata_host_stop(struct device *gendev, void *res) +{ + struct ata_host *host = dev_get_drvdata(gendev); + int i; + + WARN_ON(!(host->flags & ATA_HOST_STARTED)); + + for (i = 0; i < host->n_ports; i++) { + struct ata_port *ap = host->ports[i]; + + if (ap->ops->port_stop) + ap->ops->port_stop(ap); + } + + if (host->ops->host_stop) + host->ops->host_stop(host); +} + /** * ata_host_start - start and freeze ports of an ATA host * @host: ATA host to start ports for @@ -6978,6 +6935,8 @@ struct ata_host *ata_host_alloc_pinfo(struct device *dev, */ int ata_host_start(struct ata_host *host) { + int have_stop = 0; + void *start_dr = NULL; int i, rc; if (host->flags & ATA_HOST_STARTED) @@ -6989,18 +6948,35 @@ int ata_host_start(struct ata_host *host) if (!host->ops && !ata_port_is_dummy(ap)) host->ops = ap->ops; + if (ap->ops->port_stop) + have_stop = 1; + } + + if (host->ops->host_stop) + have_stop = 1; + + if (have_stop) { + start_dr = devres_alloc(ata_host_stop, 0, GFP_KERNEL); + if (!start_dr) + return -ENOMEM; + } + + for (i = 0; i < host->n_ports; i++) { + struct ata_port *ap = host->ports[i]; + if (ap->ops->port_start) { rc = ap->ops->port_start(ap); if (rc) { - ata_port_printk(ap, KERN_ERR, "failed to " - "start port (errno=%d)\n", rc); + if (rc != -ENODEV) + dev_printk(KERN_ERR, host->dev, "failed to start port %d (errno=%d)\n", i, rc); goto err_out; } } - ata_eh_freeze_port(ap); } + if (start_dr) + devres_add(host->dev, start_dr); host->flags |= ATA_HOST_STARTED; return 0; @@ -7011,6 +6987,7 @@ int ata_host_start(struct ata_host *host) if (ap->ops->port_stop) ap->ops->port_stop(ap); } + devres_free(start_dr); return rc; } @@ -7178,6 +7155,10 @@ int ata_host_register(struct ata_host *host, struct scsi_host_template *sht) * request IRQ and register it. This helper takes necessasry * arguments and performs the three steps in one go. * + * An invalid IRQ skips the IRQ registration and expects the host to + * have set polling mode on the port. In this case, @irq_handler + * should be NULL. + * * LOCKING: * Inherited from calling layer (may sleep). * @@ -7194,6 +7175,12 @@ int ata_host_activate(struct ata_host *host, int irq, if (rc) return rc; + /* Special case for polling mode */ + if (!irq) { + WARN_ON(irq_handler); + return ata_host_register(host, sht); + } + rc = devm_request_irq(host->dev, irq, irq_handler, irq_flags, dev_driver_string(host->dev), host); if (rc) @@ -7611,8 +7598,6 @@ EXPORT_SYMBOL_GPL(ata_dev_disable); EXPORT_SYMBOL_GPL(sata_set_spd); EXPORT_SYMBOL_GPL(sata_link_debounce); EXPORT_SYMBOL_GPL(sata_link_resume); -EXPORT_SYMBOL_GPL(sata_phy_reset); -EXPORT_SYMBOL_GPL(__sata_phy_reset); EXPORT_SYMBOL_GPL(ata_bus_reset); EXPORT_SYMBOL_GPL(ata_std_prereset); EXPORT_SYMBOL_GPL(ata_std_softreset); @@ -7683,7 +7668,6 @@ EXPORT_SYMBOL_GPL(ata_port_desc); #ifdef CONFIG_PCI EXPORT_SYMBOL_GPL(ata_port_pbar_desc); #endif /* CONFIG_PCI */ -EXPORT_SYMBOL_GPL(ata_eng_timeout); EXPORT_SYMBOL_GPL(ata_port_schedule_eh); EXPORT_SYMBOL_GPL(ata_link_abort); EXPORT_SYMBOL_GPL(ata_port_abort); diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c index ed8813b..e6605f0 100644 --- a/drivers/ata/libata-eh.c +++ b/drivers/ata/libata-eh.c @@ -559,101 +559,6 @@ void ata_port_wait_eh(struct ata_port *ap) } } -/** - * ata_qc_timeout - Handle timeout of queued command - * @qc: Command that timed out - * - * Some part of the kernel (currently, only the SCSI layer) - * has noticed that the active command on port @ap has not - * completed after a specified length of time. Handle this - * condition by disabling DMA (if necessary) and completing - * transactions, with error if necessary. - * - * This also handles the case of the "lost interrupt", where - * for some reason (possibly hardware bug, possibly driver bug) - * an interrupt was not delivered to the driver, even though the - * transaction completed successfully. - * - * TODO: kill this function once old EH is gone. - * - * LOCKING: - * Inherited from SCSI layer (none, can sleep) - */ -static void ata_qc_timeout(struct ata_queued_cmd *qc) -{ - struct ata_port *ap = qc->ap; - u8 host_stat = 0, drv_stat; - unsigned long flags; - - DPRINTK("ENTER\n"); - - ap->hsm_task_state = HSM_ST_IDLE; - - spin_lock_irqsave(ap->lock, flags); - - switch (qc->tf.protocol) { - - case ATA_PROT_DMA: - case ATA_PROT_ATAPI_DMA: - host_stat = ap->ops->bmdma_status(ap); - - /* before we do anything else, clear DMA-Start bit */ - ap->ops->bmdma_stop(qc); - - /* fall through */ - - default: - ata_altstatus(ap); - drv_stat = ata_chk_status(ap); - - /* ack bmdma irq events */ - ap->ops->irq_clear(ap); - - ata_dev_printk(qc->dev, KERN_ERR, "command 0x%x timeout, " - "stat 0x%x host_stat 0x%x\n", - qc->tf.command, drv_stat, host_stat); - - /* complete taskfile transaction */ - qc->err_mask |= AC_ERR_TIMEOUT; - break; - } - - spin_unlock_irqrestore(ap->lock, flags); - - ata_eh_qc_complete(qc); - - DPRINTK("EXIT\n"); -} - -/** - * ata_eng_timeout - Handle timeout of queued command - * @ap: Port on which timed-out command is active - * - * Some part of the kernel (currently, only the SCSI layer) - * has noticed that the active command on port @ap has not - * completed after a specified length of time. Handle this - * condition by disabling DMA (if necessary) and completing - * transactions, with error if necessary. - * - * This also handles the case of the "lost interrupt", where - * for some reason (possibly hardware bug, possibly driver bug) - * an interrupt was not delivered to the driver, even though the - * transaction completed successfully. - * - * TODO: kill this function once old EH is gone. - * - * LOCKING: - * Inherited from SCSI layer (none, can sleep) - */ -void ata_eng_timeout(struct ata_port *ap) -{ - DPRINTK("ENTER\n"); - - ata_qc_timeout(ata_qc_from_tag(ap, ap->link.active_tag)); - - DPRINTK("EXIT\n"); -} - static int ata_eh_nr_in_flight(struct ata_port *ap) { unsigned int tag; @@ -1945,30 +1850,54 @@ static void ata_eh_link_report(struct ata_link *link) ehc->i.serror & SERR_DEV_XCHG ? "DevExch " : ""); for (tag = 0; tag < ATA_MAX_QUEUE; tag++) { - static const char *dma_str[] = { - [DMA_BIDIRECTIONAL] = "bidi", - [DMA_TO_DEVICE] = "out", - [DMA_FROM_DEVICE] = "in", - [DMA_NONE] = "", - }; struct ata_queued_cmd *qc = __ata_qc_from_tag(ap, tag); struct ata_taskfile *cmd = &qc->tf, *res = &qc->result_tf; + const u8 *cdb = qc->cdb; + char data_buf[20] = ""; + char cdb_buf[70] = ""; if (!(qc->flags & ATA_QCFLAG_FAILED) || qc->dev->link != link || !qc->err_mask) continue; + if (qc->dma_dir != DMA_NONE) { + static const char *dma_str[] = { + [DMA_BIDIRECTIONAL] = "bidi", + [DMA_TO_DEVICE] = "out", + [DMA_FROM_DEVICE] = "in", + }; + static const char *prot_str[] = { + [ATA_PROT_PIO] = "pio", + [ATA_PROT_DMA] = "dma", + [ATA_PROT_NCQ] = "ncq", + [ATA_PROT_ATAPI] = "pio", + [ATA_PROT_ATAPI_DMA] = "dma", + }; + + snprintf(data_buf, sizeof(data_buf), " %s %u %s", + prot_str[qc->tf.protocol], qc->nbytes, + dma_str[qc->dma_dir]); + } + + if (is_atapi_taskfile(&qc->tf)) + snprintf(cdb_buf, sizeof(cdb_buf), + "cdb %02x %02x %02x %02x %02x %02x %02x %02x " + "%02x %02x %02x %02x %02x %02x %02x %02x\n ", + cdb[0], cdb[1], cdb[2], cdb[3], + cdb[4], cdb[5], cdb[6], cdb[7], + cdb[8], cdb[9], cdb[10], cdb[11], + cdb[12], cdb[13], cdb[14], cdb[15]); + ata_dev_printk(qc->dev, KERN_ERR, "cmd %02x/%02x:%02x:%02x:%02x:%02x/%02x:%02x:%02x:%02x:%02x/%02x " - "tag %d cdb 0x%x data %u %s\n " + "tag %d%s\n %s" "res %02x/%02x:%02x:%02x:%02x:%02x/%02x:%02x:%02x:%02x:%02x/%02x " "Emask 0x%x (%s)%s\n", cmd->command, cmd->feature, cmd->nsect, cmd->lbal, cmd->lbam, cmd->lbah, cmd->hob_feature, cmd->hob_nsect, cmd->hob_lbal, cmd->hob_lbam, cmd->hob_lbah, - cmd->device, qc->tag, qc->cdb[0], qc->nbytes, - dma_str[qc->dma_dir], + cmd->device, qc->tag, data_buf, cdb_buf, res->command, res->feature, res->nsect, res->lbal, res->lbam, res->lbah, res->hob_feature, res->hob_nsect, diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index 94144ed..a883bb0 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c @@ -2485,11 +2485,40 @@ static unsigned int atapi_xlat(struct ata_queued_cmd *qc) if (!using_pio && ata_check_atapi_dma(qc)) using_pio = 1; - /* Some controller variants snoop this value for Packet transfers - to do state machine and FIFO management. Thus we want to set it - properly, and for DMA where it is effectively meaningless */ + /* Some controller variants snoop this value for Packet + * transfers to do state machine and FIFO management. Thus we + * want to set it properly, and for DMA where it is + * effectively meaningless. + */ nbytes = min(qc->nbytes, (unsigned int)63 * 1024); + /* Most ATAPI devices which honor transfer chunk size don't + * behave according to the spec when odd chunk size which + * matches the transfer length is specified. If the number of + * bytes to transfer is 2n+1. According to the spec, what + * should happen is to indicate that 2n+1 is going to be + * transferred and transfer 2n+2 bytes where the last byte is + * padding. + * + * In practice, this doesn't happen. ATAPI devices first + * indicate and transfer 2n bytes and then indicate and + * transfer 2 bytes where the last byte is padding. + * + * This inconsistency confuses several controllers which + * perform PIO using DMA such as Intel AHCIs and sil3124/32. + * These controllers use actual number of transferred bytes to + * update DMA poitner and transfer of 4n+2 bytes make those + * controller push DMA pointer by 4n+4 bytes because SATA data + * FISes are aligned to 4 bytes. This causes data corruption + * and buffer overrun. + * + * Always setting nbytes to even number solves this problem + * because then ATAPI devices don't have to split data at 2n + * boundaries. + */ + if (nbytes & 0x1) + nbytes++; + qc->tf.lbam = (nbytes & 0xFF); qc->tf.lbah = (nbytes >> 8); @@ -2869,7 +2898,8 @@ static inline int __ata_scsi_queuecmd(struct scsi_cmnd *scmd, xlat_func = NULL; if (likely((scsi_op != ATA_16) || !atapi_passthru16)) { /* relay SCSI command to ATAPI device */ - if (unlikely(scmd->cmd_len > dev->cdb_len)) + int len = COMMAND_SIZE(scsi_op); + if (unlikely(len > scmd->cmd_len || len > dev->cdb_len)) goto bad_cdb_len; xlat_func = atapi_xlat; diff --git a/drivers/ata/pata_ali.c b/drivers/ata/pata_ali.c index 364534e..8caf9af 100644 --- a/drivers/ata/pata_ali.c +++ b/drivers/ata/pata_ali.c @@ -63,6 +63,9 @@ static int ali_cable_override(struct pci_dev *pdev) /* Fujitsu P2000 */ if (pdev->subsystem_vendor == 0x10CF && pdev->subsystem_device == 0x10AF) return 1; + /* Mitac 8317 (Winbook-A) and relatives */ + if (pdev->subsystem_vendor == 0x1071 && pdev->subsystem_device == 0x8317) + return 1; /* Systems by DMI */ if (dmi_check_system(cable_dmi_table)) return 1; @@ -282,6 +285,21 @@ static void ali_lock_sectors(struct ata_device *adev) adev->max_sectors = 255; } +/** + * ali_check_atapi_dma - DMA check for most ALi controllers + * @adev: Device + * + * Called to decide whether commands should be sent by DMA or PIO + */ + +static int ali_check_atapi_dma(struct ata_queued_cmd *qc) +{ + /* If its not a media command, its not worth it */ + if (qc->nbytes < 2048) + return -EOPNOTSUPP; + return 0; +} + static struct scsi_host_template ali_sht = { .module = THIS_MODULE, .name = DRV_NAME, @@ -378,6 +396,7 @@ static struct ata_port_operations ali_c2_port_ops = { .mode_filter = ata_pci_default_filter, .tf_load = ata_tf_load, .tf_read = ata_tf_read, + .check_atapi_dma = ali_check_atapi_dma, .check_status = ata_check_status, .exec_command = ata_exec_command, .dev_select = ata_std_dev_select, @@ -415,6 +434,7 @@ static struct ata_port_operations ali_c5_port_ops = { .mode_filter = ata_pci_default_filter, .tf_load = ata_tf_load, .tf_read = ata_tf_read, + .check_atapi_dma = ali_check_atapi_dma, .check_status = ata_check_status, .exec_command = ata_exec_command, .dev_select = ata_std_dev_select, diff --git a/drivers/ata/pata_at32.c b/drivers/ata/pata_at32.c index bb250a4..67e574d 100644 --- a/drivers/ata/pata_at32.c +++ b/drivers/ata/pata_at32.c @@ -28,7 +28,7 @@ #include <asm/arch/smc.h> #define DRV_NAME "pata_at32" -#define DRV_VERSION "0.0.2" +#define DRV_VERSION "0.0.3" /* * CompactFlash controller memory layout relative to the base address: @@ -64,6 +64,8 @@ * Mode 2 | 8.3 | 240 ns | 0x07 * Mode 3 | 11.1 | 180 ns | 0x0f * Mode 4 | 16.7 | 120 ns | 0x1f + * + * Alter PIO_MASK below according to table to set maximal PIO mode. */ #define PIO_MASK (0x1f) @@ -85,36 +87,40 @@ struct at32_ide_info { */ static int pata_at32_setup_timing(struct device *dev, struct at32_ide_info *info, - const struct ata_timing *timing) + const struct ata_timing *ata) { - /* These two values are found through testing */ - const int min_recover = 25; - const int ncs_hold = 15; - struct smc_config *smc = &info->smc; + struct smc_timing timing; int active; int recover; + memset(&timing, 0, sizeof(struct smc_timing)); + /* Total cycle time */ - smc->read_cycle = timing->cyc8b; + timing.read_cycle = ata->cyc8b; /* DIOR <= CFIOR timings */ - smc->nrd_setup = timing->setup; - smc->nrd_pulse = timing->act8b; + timing.nrd_setup = ata->setup; + timing.nrd_pulse = ata->act8b; + timing.nrd_recover = ata->rec8b; + + /* Convert nanosecond timing to clock cycles */ + smc_set_timing(smc, &timing); - /* Compute recover, extend total cycle if needed */ - active = smc->nrd_setup + smc->nrd_pulse; + /* Add one extra cycle setup due to signal ring */ + smc->nrd_setup = smc->nrd_setup + 1; + + active = smc->nrd_setup + smc->nrd_pulse; recover = smc->read_cycle - active; - if (recover < min_recover) { - smc->read_cycle = active + min_recover; - recover = min_recover; - } + /* Need at least two cycles recovery */ + if (recover < 2) + smc->read_cycle = active + 2; /* (CS0, CS1, DIR, OE) <= (CFCE1, CFCE2, CFRNW, NCSX) timings */ - smc->ncs_read_setup = 0; - smc->ncs_read_pulse = active + ncs_hold; + smc->ncs_read_setup = 1; + smc->ncs_read_pulse = smc->read_cycle - 2; /* Write timings same as read timings */ smc->write_cycle = smc->read_cycle; @@ -123,11 +129,13 @@ static int pata_at32_setup_timing(struct device *dev, smc->ncs_write_setup = smc->ncs_read_setup; smc->ncs_write_pulse = smc->ncs_read_pulse; - /* Do some debugging output */ - dev_dbg(dev, "SMC: C=%d S=%d P=%d R=%d NCSS=%d NCSP=%d NCSR=%d\n", + /* Do some debugging output of ATA and SMC timings */ + dev_dbg(dev, "ATA: C=%d S=%d P=%d R=%d\n", + ata->cyc8b, ata->setup, ata->act8b, ata->rec8b); + + dev_dbg(dev, "SMC: C=%d S=%d P=%d NS=%d NP=%d\n", smc->read_cycle, smc->nrd_setup, smc->nrd_pulse, - recover, smc->ncs_read_setup, smc->ncs_read_pulse, - smc->read_cycle - smc->ncs_read_pulse); + smc->ncs_read_setup, smc->ncs_read_pulse); /* Finally, configure the SMC */ return smc_set_configuration(info->cs, smc); @@ -182,7 +190,6 @@ static struct scsi_host_template at32_sht = { }; static struct ata_port_operations at32_port_ops = { - .port_disable = ata_port_disable, .set_piomode = pata_at32_set_piomode, .tf_load = ata_tf_load, .tf_read = ata_tf_read, @@ -203,7 +210,6 @@ static struct ata_port_operations at32_port_ops = { .irq_clear = pata_at32_irq_clear, .irq_on = ata_irq_on, - .irq_ack = ata_irq_ack, .port_start = ata_sff_port_start, }; @@ -223,8 +229,7 @@ static int __init pata_at32_init_one(struct device *dev, /* Setup ATA bindings */ ap->ops = &at32_port_ops; ap->pio_mask = PIO_MASK; - ap->flags = ATA_FLAG_MMIO | ATA_FLAG_SLAVE_POSS - | ATA_FLAG_PIO_POLLING; + ap->flags |= ATA_FLAG_MMIO | ATA_FLAG_SLAVE_POSS; /* * Since all 8-bit taskfile transfers has to go on the lower @@ -357,12 +362,12 @@ static int __init pata_at32_probe(struct platform_device *pdev) info->smc.tdf_mode = 0; /* TDF optimization disabled */ info->smc.tdf_cycles = 0; /* No TDF wait cycles */ - /* Setup ATA timing */ + /* Setup SMC to ATA timing */ ret = pata_at32_setup_timing(dev, info, &initial_timing); if (ret) goto err_setup_timing; - /* Setup ATA addresses */ + /* Map ATA address space */ ret = -ENOMEM; info->ide_addr = devm_ioremap(dev, info->res_ide.start, 16); info->alt_addr = devm_ioremap(dev, info->res_alt.start, 16); @@ -373,7 +378,7 @@ static int __init pata_at32_probe(struct platform_device *pdev) pata_at32_debug_bus(dev, info); #endif - /* Register ATA device */ + /* Setup and register ATA device */ ret = pata_at32_init_one(dev, info); if (ret) goto err_ata_device; diff --git a/drivers/ata/pata_bf54x.c b/drivers/ata/pata_bf54x.c index b5e3842..088a41f 100644 --- a/drivers/ata/pata_bf54x.c +++ b/drivers/ata/pata_bf54x.c @@ -1145,13 +1145,13 @@ static unsigned char bfin_bmdma_status(struct ata_port *ap) unsigned short int_status = ATAPI_GET_INT_STATUS(base); if (ATAPI_GET_STATUS(base) & (MULTI_XFER_ON|ULTRA_XFER_ON)) { - host_stat = ATA_DMA_ACTIVE; + host_stat |= ATA_DMA_ACTIVE; } if (int_status & (MULTI_DONE_INT|UDMAIN_DONE_INT|UDMAOUT_DONE_INT)) { - host_stat = ATA_DMA_INTR; + host_stat |= ATA_DMA_INTR; } if (int_status & (MULTI_TERM_INT|UDMAIN_TERM_INT|UDMAOUT_TERM_INT)) { - host_stat = ATA_DMA_ERR; + host_stat |= ATA_DMA_ERR; } return host_stat; @@ -1489,6 +1489,8 @@ static int __devinit bfin_atapi_probe(struct platform_device *pdev) int board_idx = 0; struct resource *res; struct ata_host *host; + unsigned int fsclk = get_sclk(); + int udma_mode = 5; const struct ata_port_info *ppi[] = { &bfin_port_info[board_idx], NULL }; @@ -1507,6 +1509,11 @@ static int __devinit bfin_atapi_probe(struct platform_device *pdev) if (res == NULL) return -EINVAL; + while (bfin_port_info[board_idx].udma_mask>0 && udma_fsclk[udma_mode] > fsclk) { + udma_mode--; + bfin_port_info[board_idx].udma_mask >>= 1; + } + /* * Now that that's out of the way, wire up the port.. */ diff --git a/drivers/ata/pata_hpt37x.c b/drivers/ata/pata_hpt37x.c index 3816b86..46dc70e 100644 --- a/drivers/ata/pata_hpt37x.c +++ b/drivers/ata/pata_hpt37x.c @@ -329,7 +329,7 @@ static int hpt37x_pre_reset(struct ata_link *link, unsigned long deadline) /* Restore state */ pci_write_config_byte(pdev, 0x5B, scr2); - if (ata66 & (1 << ap->port_no)) + if (ata66 & (2 >> ap->port_no)) ap->cbl = ATA_CBL_PATA40; else ap->cbl = ATA_CBL_PATA80; diff --git a/drivers/ata/pata_isapnp.c b/drivers/ata/pata_isapnp.c index 88ab0e1..4320e79 100644 --- a/drivers/ata/pata_isapnp.c +++ b/drivers/ata/pata_isapnp.c @@ -75,13 +75,16 @@ static int isapnp_init_one(struct pnp_dev *idev, const struct pnp_device_id *dev struct ata_host *host; struct ata_port *ap; void __iomem *cmd_addr, *ctl_addr; + int irq = 0; + irq_handler_t handler = NULL; if (pnp_port_valid(idev, 0) == 0) return -ENODEV; - /* FIXME: Should selected polled PIO here not fail */ - if (pnp_irq_valid(idev, 0) == 0) - return -ENODEV; + if (pnp_irq_valid(idev, 0)) { + irq = pnp_irq(idev, 0); + handler = ata_interrupt; + } /* allocate host */ host = ata_host_alloc(&idev->dev, 1); @@ -115,7 +118,7 @@ static int isapnp_init_one(struct pnp_dev *idev, const struct pnp_device_id *dev (unsigned long long)pnp_port_start(idev, 1)); /* activate */ - return ata_host_activate(host, pnp_irq(idev, 0), ata_interrupt, 0, + return ata_host_activate(host, irq, handler, 0, &isapnp_sht); } diff --git a/drivers/ata/pata_jmicron.c b/drivers/ata/pata_jmicron.c index 225a722..5b8174d 100644 --- a/drivers/ata/pata_jmicron.c +++ b/drivers/ata/pata_jmicron.c @@ -80,11 +80,10 @@ static int jmicron_pre_reset(struct ata_link *link, unsigned long deadline) * actually do our cable checking etc. Thankfully we don't need * to do the plumbing for other cases. */ - switch (port_map[port]) - { + switch (port_map[port]) { case PORT_PATA0: - if (control & (1 << 5)) - return 0; + if ((control & (1 << 5)) == 0) + return -ENOENT; if (control & (1 << 3)) /* 40/80 pin primary */ ap->cbl = ATA_CBL_PATA40; else @@ -93,7 +92,7 @@ static int jmicron_pre_reset(struct ata_link *link, unsigned long deadline) case PORT_PATA1: /* Bit 21 is set if the port is enabled */ if ((control5 & (1 << 21)) == 0) - return 0; + return -ENOENT; if (control5 & (1 << 19)) /* 40/80 pin secondary */ ap->cbl = ATA_CBL_PATA40; else diff --git a/drivers/ata/pata_platform.c b/drivers/ata/pata_platform.c index fc72a96..ac03a90 100644 --- a/drivers/ata/pata_platform.c +++ b/drivers/ata/pata_platform.c @@ -1,7 +1,7 @@ /* * Generic platform device PATA driver * - * Copyright (C) 2006 Paul Mundt + * Copyright (C) 2006 - 2007 Paul Mundt * * Based on pata_pcmcia: * @@ -22,7 +22,7 @@ #include <linux/pata_platform.h> #define DRV_NAME "pata_platform" -#define DRV_VERSION "1.1" +#define DRV_VERSION "1.2" static int pio_mask = 1; @@ -120,15 +120,20 @@ static void pata_platform_setup_port(struct ata_ioports *ioaddr, * Register a platform bus IDE interface. Such interfaces are PIO and we * assume do not support IRQ sharing. * - * Platform devices are expected to contain 3 resources per port: + * Platform devices are expected to contain at least 2 resources per port: * * - I/O Base (IORESOURCE_IO or IORESOURCE_MEM) * - CTL Base (IORESOURCE_IO or IORESOURCE_MEM) + * + * and optionally: + * * - IRQ (IORESOURCE_IRQ) * * If the base resources are both mem types, the ioremap() is handled * here. For IORESOURCE_IO, it's assumed that there's no remapping * necessary. + * + * If no IRQ resource is present, PIO polling mode is used instead. */ static int __devinit pata_platform_probe(struct platform_device *pdev) { @@ -137,11 +142,12 @@ static int __devinit pata_platform_probe(struct platform_device *pdev) struct ata_port *ap; struct pata_platform_info *pp_info; unsigned int mmio; + int irq; /* * Simple resource validation .. */ - if (unlikely(pdev->num_resources != 3)) { + if ((pdev->num_resources != 3) && (pdev->num_resources != 2)) { dev_err(&pdev->dev, "invalid number of resources\n"); return -EINVAL; } @@ -173,6 +179,13 @@ static int __devinit pata_platform_probe(struct platform_device *pdev) (ctl_res->flags == IORESOURCE_MEM)); /* + * And the IRQ + */ + irq = platform_get_irq(pdev, 0); + if (irq < 0) + irq = 0; /* no irq */ + + /* * Now that that's out of the way, wire up the port.. */ host = ata_host_alloc(&pdev->dev, 1); @@ -185,6 +198,14 @@ static int __devinit pata_platform_probe(struct platform_device *pdev) ap->flags |= ATA_FLAG_SLAVE_POSS; /* + * Use polling mode if there's no IRQ + */ + if (!irq) { + ap->flags |= ATA_FLAG_PIO_POLLING; + ata_port_desc(ap, "no IRQ, using PIO polling"); + } + + /* * Handle the MMIO case */ if (mmio) { @@ -213,9 +234,9 @@ static int __devinit pata_platform_probe(struct platform_device *pdev) (unsigned long long)ctl_res->start); /* activate */ - return ata_host_activate(host, platform_get_irq(pdev, 0), - ata_interrupt, pp_info ? pp_info->irq_flags - : 0, &pata_platform_sht); + return ata_host_activate(host, irq, irq ? ata_interrupt : NULL, + pp_info ? pp_info->irq_flags : 0, + &pata_platform_sht); } /** diff --git a/drivers/ata/pata_sil680.c b/drivers/ata/pata_sil680.c index 5c1e9cb..503245a 100644 --- a/drivers/ata/pata_sil680.c +++ b/drivers/ata/pata_sil680.c @@ -33,7 +33,7 @@ #include <linux/libata.h> #define DRV_NAME "pata_sil680" -#define DRV_VERSION "0.4.7" +#define DRV_VERSION "0.4.8" #define SIL680_MMIO_BAR 5 @@ -94,34 +94,6 @@ static int sil680_cable_detect(struct ata_port *ap) { } /** - * sil680_bus_reset - reset the SIL680 bus - * @link: ATA link to reset - * @deadline: deadline jiffies for the operation - * - * Perform the SIL680 housekeeping when doing an ATA bus reset - */ - -static int sil680_bus_reset(struct ata_link *link, unsigned int *classes, - unsigned long deadline) -{ - struct ata_port *ap = link->ap; - struct pci_dev *pdev = to_pci_dev(ap->host->dev); - unsigned long addr = sil680_selreg(ap, 0); - u8 reset; - - pci_read_config_byte(pdev, addr, &reset); - pci_write_config_byte(pdev, addr, reset | 0x03); - udelay(25); - pci_write_config_byte(pdev, addr, reset); - return ata_std_softreset(link, classes, deadline); -} - -static void sil680_error_handler(struct ata_port *ap) -{ - ata_bmdma_drive_eh(ap, ata_std_prereset, sil680_bus_reset, NULL, ata_std_postreset); -} - -/** * sil680_set_piomode - set initial PIO mode data * @ap: ATA interface * @adev: ATA device @@ -249,7 +221,7 @@ static struct ata_port_operations sil680_port_ops = { .freeze = ata_bmdma_freeze, .thaw = ata_bmdma_thaw, - .error_handler = sil680_error_handler, + .error_handler = ata_bmdma_error_handler, .post_internal_cmd = ata_bmdma_post_internal_cmd, .cable_detect = sil680_cable_detect, diff --git a/drivers/ata/pata_sis.c b/drivers/ata/pata_sis.c index 3b5be77..87546d9 100644 --- a/drivers/ata/pata_sis.c +++ b/drivers/ata/pata_sis.c @@ -55,6 +55,7 @@ static const struct sis_laptop sis_laptop[] = { /* devid, subvendor, subdev */ { 0x5513, 0x1043, 0x1107 }, /* ASUS A6K */ { 0x5513, 0x1734, 0x105F }, /* FSC Amilo A1630 */ + { 0x5513, 0x1071, 0x8640 }, /* EasyNote K5305 */ /* end marker */ { 0, } }; diff --git a/drivers/ata/sata_mv.c b/drivers/ata/sata_mv.c index a43f64d..8d864e5 100644 --- a/drivers/ata/sata_mv.c +++ b/drivers/ata/sata_mv.c @@ -164,10 +164,14 @@ enum { MV_PCI_ERR_ATTRIBUTE = 0x1d48, MV_PCI_ERR_COMMAND = 0x1d50, - PCI_IRQ_CAUSE_OFS = 0x1d58, - PCI_IRQ_MASK_OFS = 0x1d5c, + PCI_IRQ_CAUSE_OFS = 0x1d58, + PCI_IRQ_MASK_OFS = 0x1d5c, PCI_UNMASK_ALL_IRQS = 0x7fffff, /* bits 22-0 */ + PCIE_IRQ_CAUSE_OFS = 0x1900, + PCIE_IRQ_MASK_OFS = 0x1910, + PCIE_UNMASK_ALL_IRQS = 0x70a, /* assorted bits */ + HC_MAIN_IRQ_CAUSE_OFS = 0x1d60, HC_MAIN_IRQ_MASK_OFS = 0x1d64, PORT0_ERR = (1 << 0), /* shift by port # */ @@ -303,6 +307,7 @@ enum { MV_HP_GEN_I = (1 << 6), /* Generation I: 50xx */ MV_HP_GEN_II = (1 << 7), /* Generation II: 60xx */ MV_HP_GEN_IIE = (1 << 8), /* Generation IIE: 6042/7042 */ + MV_HP_PCIE = (1 << 9), /* PCIe bus/regs: 7042 */ /* Port private flags (pp_flags) */ MV_PP_FLAG_EDMA_EN = (1 << 0), /* is EDMA engine enabled? */ @@ -388,7 +393,15 @@ struct mv_port_signal { u32 pre; }; -struct mv_host_priv; +struct mv_host_priv { + u32 hp_flags; + struct mv_port_signal signal[8]; + const struct mv_hw_ops *ops; + u32 irq_cause_ofs; + u32 irq_mask_ofs; + u32 unmask_all_irqs; +}; + struct mv_hw_ops { void (*phy_errata)(struct mv_host_priv *hpriv, void __iomem *mmio, unsigned int port); @@ -401,12 +414,6 @@ struct mv_hw_ops { void (*reset_bus)(struct pci_dev *pdev, void __iomem *mmio); }; -struct mv_host_priv { - u32 hp_flags; - struct mv_port_signal signal[8]; - const struct mv_hw_ops *ops; -}; - static void mv_irq_clear(struct ata_port *ap); static int mv_scr_read(struct ata_port *ap, unsigned int sc_reg_in, u32 *val); static int mv_scr_write(struct ata_port *ap, unsigned int sc_reg_in, u32 val); @@ -631,11 +638,13 @@ static const struct pci_device_id mv_pci_tbl[] = { /* Adaptec 1430SA */ { PCI_VDEVICE(ADAPTEC2, 0x0243), chip_7042 }, - { PCI_VDEVICE(TTI, 0x2310), chip_7042 }, - - /* add Marvell 7042 support */ + /* Marvell 7042 support */ { PCI_VDEVICE(MARVELL, 0x7042), chip_7042 }, + /* Highpoint RocketRAID PCIe series */ + { PCI_VDEVICE(TTI, 0x2300), chip_7042 }, + { PCI_VDEVICE(TTI, 0x2310), chip_7042 }, + { } /* terminate list */ }; @@ -1648,13 +1657,14 @@ static void mv_host_intr(struct ata_host *host, u32 relevant, unsigned int hc) static void mv_pci_error(struct ata_host *host, void __iomem *mmio) { + struct mv_host_priv *hpriv = host->private_data; struct ata_port *ap; struct ata_queued_cmd *qc; struct ata_eh_info *ehi; unsigned int i, err_mask, printed = 0; u32 err_cause; - err_cause = readl(mmio + PCI_IRQ_CAUSE_OFS); + err_cause = readl(mmio + hpriv->irq_cause_ofs); dev_printk(KERN_ERR, host->dev, "PCI ERROR; PCI IRQ cause=0x%08x\n", err_cause); @@ -1662,7 +1672,7 @@ static void mv_pci_error(struct ata_host *host, void __iomem *mmio) DPRINTK("All regs @ PCI error\n"); mv_dump_all_regs(mmio, -1, to_pci_dev(host->dev)); - writelfl(0, mmio + PCI_IRQ_CAUSE_OFS); + writelfl(0, mmio + hpriv->irq_cause_ofs); for (i = 0; i < host->n_ports; i++) { ap = host->ports[i]; @@ -1926,6 +1936,8 @@ static int mv5_reset_hc(struct mv_host_priv *hpriv, void __iomem *mmio, #define ZERO(reg) writel(0, mmio + (reg)) static void mv_reset_pci_bus(struct pci_dev *pdev, void __iomem *mmio) { + struct ata_host *host = dev_get_drvdata(&pdev->dev); + struct mv_host_priv *hpriv = host->private_data; u32 tmp; tmp = readl(mmio + MV_PCI_MODE); @@ -1937,8 +1949,8 @@ static void mv_reset_pci_bus(struct pci_dev *pdev, void __iomem *mmio) writel(0x000100ff, mmio + MV_PCI_XBAR_TMOUT); ZERO(HC_MAIN_IRQ_MASK_OFS); ZERO(MV_PCI_SERR_MASK); - ZERO(PCI_IRQ_CAUSE_OFS); - ZERO(PCI_IRQ_MASK_OFS); + ZERO(hpriv->irq_cause_ofs); + ZERO(hpriv->irq_mask_ofs); ZERO(MV_PCI_ERR_LOW_ADDRESS); ZERO(MV_PCI_ERR_HIGH_ADDRESS); ZERO(MV_PCI_ERR_ATTRIBUTE); @@ -2170,7 +2182,7 @@ static void mv_phy_reset(struct ata_port *ap, unsigned int *class, mv_scr_read(ap, SCR_ERROR, &serror); mv_scr_read(ap, SCR_CONTROL, &scontrol); DPRINTK("S-regs after ATA_RST: SStat 0x%08x SErr 0x%08x " - "SCtrl 0x%08x\n", status, serror, scontrol); + "SCtrl 0x%08x\n", sstatus, serror, scontrol); } #endif @@ -2490,6 +2502,7 @@ static int mv_chip_id(struct ata_host *host, unsigned int board_idx) break; case chip_7042: + hp_flags |= MV_HP_PCIE; case chip_6042: hpriv->ops = &mv6xxx_ops; hp_flags |= MV_HP_GEN_IIE; @@ -2516,6 +2529,15 @@ static int mv_chip_id(struct ata_host *host, unsigned int board_idx) } hpriv->hp_flags = hp_flags; + if (hp_flags & MV_HP_PCIE) { + hpriv->irq_cause_ofs = PCIE_IRQ_CAUSE_OFS; + hpriv->irq_mask_ofs = PCIE_IRQ_MASK_OFS; + hpriv->unmask_all_irqs = PCIE_UNMASK_ALL_IRQS; + } else { + hpriv->irq_cause_ofs = PCI_IRQ_CAUSE_OFS; + hpriv->irq_mask_ofs = PCI_IRQ_MASK_OFS; + hpriv->unmask_all_irqs = PCI_UNMASK_ALL_IRQS; + } return 0; } @@ -2595,10 +2617,10 @@ static int mv_init_host(struct ata_host *host, unsigned int board_idx) } /* Clear any currently outstanding host interrupt conditions */ - writelfl(0, mmio + PCI_IRQ_CAUSE_OFS); + writelfl(0, mmio + hpriv->irq_cause_ofs); /* and unmask interrupt generation for host regs */ - writelfl(PCI_UNMASK_ALL_IRQS, mmio + PCI_IRQ_MASK_OFS); + writelfl(hpriv->unmask_all_irqs, mmio + hpriv->irq_mask_ofs); if (IS_GEN_I(hpriv)) writelfl(~HC_MAIN_MASKED_IRQS_5, mmio + HC_MAIN_IRQ_MASK_OFS); @@ -2609,8 +2631,8 @@ static int mv_init_host(struct ata_host *host, unsigned int board_idx) "PCI int cause/mask=0x%08x/0x%08x\n", readl(mmio + HC_MAIN_IRQ_CAUSE_OFS), readl(mmio + HC_MAIN_IRQ_MASK_OFS), - readl(mmio + PCI_IRQ_CAUSE_OFS), - readl(mmio + PCI_IRQ_MASK_OFS)); + readl(mmio + hpriv->irq_cause_ofs), + readl(mmio + hpriv->irq_mask_ofs)); done: return rc; diff --git a/drivers/ata/sata_nv.c b/drivers/ata/sata_nv.c index 35b2df2..44f9e5d 100644 --- a/drivers/ata/sata_nv.c +++ b/drivers/ata/sata_nv.c @@ -1629,7 +1629,7 @@ static int nv_hardreset(struct ata_link *link, unsigned int *class, /* SATA hardreset fails to retrieve proper device signature on * some controllers. Don't classify on hardreset. For more - * info, see http://bugme.osdl.org/show_bug.cgi?id=3352 + * info, see http://bugzilla.kernel.org/show_bug.cgi?id=3352 */ return sata_std_hardreset(link, &dummy, deadline); } diff --git a/drivers/ata/sata_qstor.c b/drivers/ata/sata_qstor.c index 6d43ba7..2f1de6e 100644 --- a/drivers/ata/sata_qstor.c +++ b/drivers/ata/sata_qstor.c @@ -103,7 +103,7 @@ enum { QS_DMA_BOUNDARY = ~0UL }; -typedef enum { qs_state_idle, qs_state_pkt, qs_state_mmio } qs_state_t; +typedef enum { qs_state_mmio, qs_state_pkt } qs_state_t; struct qs_port_priv { u8 *pkt; @@ -116,14 +116,15 @@ static int qs_scr_write(struct ata_port *ap, unsigned int sc_reg, u32 val); static int qs_ata_init_one(struct pci_dev *pdev, const struct pci_device_id *ent); static int qs_port_start(struct ata_port *ap); static void qs_host_stop(struct ata_host *host); -static void qs_phy_reset(struct ata_port *ap); static void qs_qc_prep(struct ata_queued_cmd *qc); static unsigned int qs_qc_issue(struct ata_queued_cmd *qc); static int qs_check_atapi_dma(struct ata_queued_cmd *qc); static void qs_bmdma_stop(struct ata_queued_cmd *qc); static u8 qs_bmdma_status(struct ata_port *ap); static void qs_irq_clear(struct ata_port *ap); -static void qs_eng_timeout(struct ata_port *ap); +static void qs_freeze(struct ata_port *ap); +static void qs_thaw(struct ata_port *ap); +static void qs_error_handler(struct ata_port *ap); static struct scsi_host_template qs_ata_sht = { .module = THIS_MODULE, @@ -150,11 +151,12 @@ static const struct ata_port_operations qs_ata_ops = { .check_atapi_dma = qs_check_atapi_dma, .exec_command = ata_exec_command, .dev_select = ata_std_dev_select, - .phy_reset = qs_phy_reset, .qc_prep = qs_qc_prep, .qc_issue = qs_qc_issue, .data_xfer = ata_data_xfer, - .eng_timeout = qs_eng_timeout, + .freeze = qs_freeze, + .thaw = qs_thaw, + .error_handler = qs_error_handler, .irq_clear = qs_irq_clear, .irq_on = ata_irq_on, .scr_read = qs_scr_read, @@ -169,8 +171,6 @@ static const struct ata_port_info qs_port_info[] = { /* board_2068_idx */ { .flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | - ATA_FLAG_SATA_RESET | - //FIXME ATA_FLAG_SRST | ATA_FLAG_MMIO | ATA_FLAG_PIO_POLLING, .pio_mask = 0x10, /* pio4 */ .udma_mask = ATA_UDMA6, @@ -219,7 +219,9 @@ static void qs_irq_clear(struct ata_port *ap) static inline void qs_enter_reg_mode(struct ata_port *ap) { u8 __iomem *chan = qs_mmio_base(ap->host) + (ap->port_no * 0x4000); + struct qs_port_priv *pp = ap->private_data; + pp->state = qs_state_mmio; writeb(QS_CTR0_REG, chan + QS_CCT_CTR0); readb(chan + QS_CCT_CTR0); /* flush */ } @@ -233,23 +235,28 @@ static inline void qs_reset_channel_logic(struct ata_port *ap) qs_enter_reg_mode(ap); } -static void qs_phy_reset(struct ata_port *ap) +static void qs_freeze(struct ata_port *ap) { - struct qs_port_priv *pp = ap->private_data; + u8 __iomem *mmio_base = qs_mmio_base(ap->host); - pp->state = qs_state_idle; - qs_reset_channel_logic(ap); - sata_phy_reset(ap); + writeb(0, mmio_base + QS_HCT_CTRL); /* disable host interrupts */ + qs_enter_reg_mode(ap); } -static void qs_eng_timeout(struct ata_port *ap) +static void qs_thaw(struct ata_port *ap) { - struct qs_port_priv *pp = ap->private_data; + u8 __iomem *mmio_base = qs_mmio_base(ap->host); + + qs_enter_reg_mode(ap); + writeb(1, mmio_base + QS_HCT_CTRL); /* enable host interrupts */ +} + +static int qs_prereset(struct ata_link *link, unsigned long deadline) +{ + struct ata_port *ap = link->ap; - if (pp->state != qs_state_idle) /* healthy paranoia */ - pp->state = qs_state_mmio; qs_reset_channel_logic(ap); - ata_eng_timeout(ap); + return ata_std_prereset(link, deadline); } static int qs_scr_read(struct ata_port *ap, unsigned int sc_reg, u32 *val) @@ -260,6 +267,13 @@ static int qs_scr_read(struct ata_port *ap, unsigned int sc_reg, u32 *val) return 0; } +static void qs_error_handler(struct ata_port *ap) +{ + qs_enter_reg_mode(ap); + ata_do_eh(ap, qs_prereset, ata_std_softreset, NULL, + ata_std_postreset); +} + static int qs_scr_write(struct ata_port *ap, unsigned int sc_reg, u32 val) { if (sc_reg > SCR_CONTROL) @@ -358,7 +372,6 @@ static unsigned int qs_qc_issue(struct ata_queued_cmd *qc) switch (qc->tf.protocol) { case ATA_PROT_DMA: - pp->state = qs_state_pkt; qs_packet_start(qc); return 0; @@ -375,6 +388,26 @@ static unsigned int qs_qc_issue(struct ata_queued_cmd *qc) return ata_qc_issue_prot(qc); } +static void qs_do_or_die(struct ata_queued_cmd *qc, u8 status) +{ + qc->err_mask |= ac_err_mask(status); + + if (!qc->err_mask) { + ata_qc_complete(qc); + } else { + struct ata_port *ap = qc->ap; + struct ata_eh_info *ehi = &ap->link.eh_info; + + ata_ehi_clear_desc(ehi); + ata_ehi_push_desc(ehi, "status 0x%02X", status); + + if (qc->err_mask == AC_ERR_DEV) + ata_port_abort(ap); + else + ata_port_freeze(ap); + } +} + static inline unsigned int qs_intr_pkt(struct ata_host *host) { unsigned int handled = 0; @@ -406,10 +439,8 @@ static inline unsigned int qs_intr_pkt(struct ata_host *host) switch (sHST) { case 0: /* successful CPB */ case 3: /* device error */ - pp->state = qs_state_idle; qs_enter_reg_mode(qc->ap); - qc->err_mask |= ac_err_mask(sDST); - ata_qc_complete(qc); + qs_do_or_die(qc, sDST); break; default: break; @@ -431,25 +462,27 @@ static inline unsigned int qs_intr_mmio(struct ata_host *host) if (ap && !(ap->flags & ATA_FLAG_DISABLED)) { struct ata_queued_cmd *qc; - struct qs_port_priv *pp = ap->private_data; - if (!pp || pp->state != qs_state_mmio) - continue; + struct qs_port_priv *pp; qc = ata_qc_from_tag(ap, ap->link.active_tag); - if (qc && (!(qc->tf.flags & ATA_TFLAG_POLLING))) { - - /* check main status, clearing INTRQ */ - u8 status = ata_check_status(ap); - if ((status & ATA_BUSY)) - continue; - DPRINTK("ata%u: protocol %d (dev_stat 0x%X)\n", - ap->print_id, qc->tf.protocol, status); - - /* complete taskfile transaction */ - pp->state = qs_state_idle; - qc->err_mask |= ac_err_mask(status); - ata_qc_complete(qc); + if (!qc || !(qc->flags & ATA_QCFLAG_ACTIVE)) { + /* + * The qstor hardware generates spurious + * interrupts from time to time when switching + * in and out of packet mode. + * There's no obvious way to know if we're + * here now due to that, so just ack the irq + * and pretend we knew it was ours.. (ugh). + * This does not affect packet mode. + */ + ata_check_status(ap); handled = 1; + continue; } + pp = ap->private_data; + if (!pp || pp->state != qs_state_mmio) + continue; + if (!(qc->tf.flags & ATA_TFLAG_POLLING)) + handled |= ata_host_intr(ap, qc); } } return handled; @@ -459,12 +492,13 @@ static irqreturn_t qs_intr(int irq, void *dev_instance) { struct ata_host *host = dev_instance; unsigned int handled = 0; + unsigned long flags; VPRINTK("ENTER\n"); - spin_lock(&host->lock); + spin_lock_irqsave(&host->lock, flags); handled = qs_intr_pkt(host) | qs_intr_mmio(host); - spin_unlock(&host->lock); + spin_unlock_irqrestore(&host->lock, flags); VPRINTK("EXIT\n"); @@ -501,7 +535,6 @@ static int qs_port_start(struct ata_port *ap) rc = ata_port_start(ap); if (rc) return rc; - qs_enter_reg_mode(ap); pp = devm_kzalloc(dev, sizeof(*pp), GFP_KERNEL); if (!pp) return -ENOMEM; @@ -512,6 +545,7 @@ static int qs_port_start(struct ata_port *ap) memset(pp->pkt, 0, QS_PKT_BYTES); ap->private_data = pp; + qs_enter_reg_mode(ap); addr = (u64)pp->pkt_dma; writel((u32) addr, chan + QS_CCF_CPBA); writel((u32)(addr >> 32), chan + QS_CCF_CPBA + 4); diff --git a/drivers/ata/sata_sil24.c b/drivers/ata/sata_sil24.c index 187dcb0..96fd526 100644 --- a/drivers/ata/sata_sil24.c +++ b/drivers/ata/sata_sil24.c @@ -63,6 +63,21 @@ enum { SIL24_HOST_BAR = 0, SIL24_PORT_BAR = 2, + /* sil24 fetches in chunks of 64bytes. The first block + * contains the PRB and two SGEs. From the second block, it's + * consisted of four SGEs and called SGT. Calculate the + * number of SGTs that fit into one page. + */ + SIL24_PRB_SZ = sizeof(struct sil24_prb) + + 2 * sizeof(struct sil24_sge), + SIL24_MAX_SGT = (PAGE_SIZE - SIL24_PRB_SZ) + / (4 * sizeof(struct sil24_sge)), + + /* This will give us one unused SGEs for ATA. This extra SGE + * will be used to store CDB for ATAPI devices. + */ + SIL24_MAX_SGE = 4 * SIL24_MAX_SGT + 1, + /* * Global controller registers (128 bytes @ BAR0) */ @@ -247,13 +262,13 @@ enum { struct sil24_ata_block { struct sil24_prb prb; - struct sil24_sge sge[LIBATA_MAX_PRD]; + struct sil24_sge sge[SIL24_MAX_SGE]; }; struct sil24_atapi_block { struct sil24_prb prb; u8 cdb[16]; - struct sil24_sge sge[LIBATA_MAX_PRD - 1]; + struct sil24_sge sge[SIL24_MAX_SGE]; }; union sil24_cmd_block { @@ -378,7 +393,7 @@ static struct scsi_host_template sil24_sht = { .change_queue_depth = ata_scsi_change_queue_depth, .can_queue = SIL24_MAX_CMDS, .this_id = ATA_SHT_THIS_ID, - .sg_tablesize = LIBATA_MAX_PRD, + .sg_tablesize = SIL24_MAX_SGE, .cmd_per_lun = ATA_SHT_CMD_PER_LUN, .emulated = ATA_SHT_EMULATED, .use_clustering = ATA_SHT_USE_CLUSTERING, @@ -1284,6 +1299,7 @@ static void sil24_init_controller(struct ata_host *host) static int sil24_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) { + extern int __MARKER__sil24_cmd_block_is_sized_wrongly; static int printed_version; struct ata_port_info pi = sil24_port_info[ent->driver_data]; const struct ata_port_info *ppi[] = { &pi, NULL }; @@ -1292,6 +1308,10 @@ static int sil24_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) int i, rc; u32 tmp; + /* cause link error if sil24_cmd_block is sized wrongly */ + if (sizeof(union sil24_cmd_block) != PAGE_SIZE) + __MARKER__sil24_cmd_block_is_sized_wrongly = 1; + if (!printed_version++) dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n"); diff --git a/drivers/atm/he.c b/drivers/atm/he.c index d33aba6..3b64a99 100644 --- a/drivers/atm/he.c +++ b/drivers/atm/he.c @@ -394,6 +394,11 @@ he_init_one(struct pci_dev *pci_dev, const struct pci_device_id *pci_ent) he_dev->atm_dev->dev_data = he_dev; atm_dev->dev_data = he_dev; he_dev->number = atm_dev->number; +#ifdef USE_TASKLET + tasklet_init(&he_dev->tasklet, he_tasklet, (unsigned long) he_dev); +#endif + spin_lock_init(&he_dev->global_lock); + if (he_start(atm_dev)) { he_stop(he_dev); err = -ENODEV; @@ -1173,11 +1178,6 @@ he_start(struct atm_dev *dev) if ((err = he_init_irq(he_dev)) != 0) return err; -#ifdef USE_TASKLET - tasklet_init(&he_dev->tasklet, he_tasklet, (unsigned long) he_dev); -#endif - spin_lock_init(&he_dev->global_lock); - /* 4.11 enable pci bus controller state machines */ host_cntl |= (OUTFF_ENB | CMDFF_ENB | QUICK_RD_RETRY | QUICK_WR_RETRY | PERR_INT_ENB); diff --git a/drivers/base/core.c b/drivers/base/core.c index 3f4d6aa..2683eac 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -770,9 +770,10 @@ int device_add(struct device *dev) error = device_add_attrs(dev); if (error) goto AttrsError; - error = device_pm_add(dev); + error = dpm_sysfs_add(dev); if (error) goto PMError; + device_pm_add(dev); error = bus_add_device(dev); if (error) goto BusError; @@ -797,6 +798,7 @@ int device_add(struct device *dev) return error; BusError: device_pm_remove(dev); + dpm_sysfs_remove(dev); PMError: if (dev->bus) blocking_notifier_call_chain(&dev->bus->bus_notifier, diff --git a/drivers/base/power/Makefile b/drivers/base/power/Makefile index a803733..44504e6 100644 --- a/drivers/base/power/Makefile +++ b/drivers/base/power/Makefile @@ -1,5 +1,6 @@ obj-y := shutdown.o -obj-$(CONFIG_PM_SLEEP) += main.o sysfs.o +obj-$(CONFIG_PM) += sysfs.o +obj-$(CONFIG_PM_SLEEP) += main.o obj-$(CONFIG_PM_TRACE) += trace.o ifeq ($(CONFIG_DEBUG_DRIVER),y) diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c index 0ab4ab2..691ffb6 100644 --- a/drivers/base/power/main.c +++ b/drivers/base/power/main.c @@ -38,20 +38,14 @@ static DEFINE_MUTEX(dpm_list_mtx); int (*platform_enable_wakeup)(struct device *dev, int is_on); -int device_pm_add(struct device *dev) +void device_pm_add(struct device *dev) { - int error; - pr_debug("PM: Adding info for %s:%s\n", dev->bus ? dev->bus->name : "No Bus", kobject_name(&dev->kobj)); mutex_lock(&dpm_list_mtx); list_add_tail(&dev->power.entry, &dpm_active); - error = dpm_sysfs_add(dev); - if (error) - list_del(&dev->power.entry); mutex_unlock(&dpm_list_mtx); - return error; } void device_pm_remove(struct device *dev) diff --git a/drivers/base/power/power.h b/drivers/base/power/power.h index 5c4efd4..379da4e 100644 --- a/drivers/base/power/power.h +++ b/drivers/base/power/power.h @@ -13,14 +13,29 @@ extern void device_shutdown(void); extern struct list_head dpm_active; /* The active device list */ -static inline struct device * to_device(struct list_head * entry) +static inline struct device *to_device(struct list_head *entry) { return container_of(entry, struct device, power.entry); } -extern int device_pm_add(struct device *); +extern void device_pm_add(struct device *); extern void device_pm_remove(struct device *); +#else /* CONFIG_PM_SLEEP */ + + +static inline void device_pm_add(struct device *dev) +{ +} + +static inline void device_pm_remove(struct device *dev) +{ +} + +#endif + +#ifdef CONFIG_PM + /* * sysfs.c */ @@ -28,16 +43,15 @@ extern void device_pm_remove(struct device *); extern int dpm_sysfs_add(struct device *); extern void dpm_sysfs_remove(struct device *); -#else /* CONFIG_PM_SLEEP */ - +#else /* CONFIG_PM */ -static inline int device_pm_add(struct device * dev) +static inline int dpm_sysfs_add(struct device *dev) { return 0; } -static inline void device_pm_remove(struct device * dev) -{ +static inline void dpm_sysfs_remove(struct device *dev) +{ } #endif diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c index 6332aca..b4c0888 100644 --- a/drivers/block/nbd.c +++ b/drivers/block/nbd.c @@ -28,6 +28,7 @@ #include <linux/err.h> #include <linux/kernel.h> #include <net/sock.h> +#include <linux/net.h> #include <asm/uaccess.h> #include <asm/system.h> @@ -126,7 +127,7 @@ static void sock_shutdown(struct nbd_device *lo, int lock) if (lo->sock) { printk(KERN_WARNING "%s: shutting down socket\n", lo->disk->disk_name); - lo->sock->ops->shutdown(lo->sock, SEND_SHUTDOWN|RCV_SHUTDOWN); + kernel_sock_shutdown(lo->sock, SHUT_RDWR); lo->sock = NULL; } if (lock) diff --git a/drivers/block/paride/pf.c b/drivers/block/paride/pf.c index ceffa60..e7fe6ca 100644 --- a/drivers/block/paride/pf.c +++ b/drivers/block/paride/pf.c @@ -488,13 +488,11 @@ static int pf_atapi(struct pf_unit *pf, char *cmd, int dlen, char *buf, char *fu return r; } -#define DBMSG(msg) ((verbose>1)?(msg):NULL) - static void pf_lock(struct pf_unit *pf, int func) { char lo_cmd[12] = { ATAPI_LOCK, pf->lun << 5, 0, 0, func, 0, 0, 0, 0, 0, 0, 0 }; - pf_atapi(pf, lo_cmd, 0, pf_scratch, func ? "unlock" : "lock"); + pf_atapi(pf, lo_cmd, 0, pf_scratch, func ? "lock" : "unlock"); } static void pf_eject(struct pf_unit *pf) @@ -555,7 +553,7 @@ static void pf_mode_sense(struct pf_unit *pf) { ATAPI_MODE_SENSE, pf->lun << 5, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0 }; char buf[8]; - pf_atapi(pf, ms_cmd, 8, buf, DBMSG("mode sense")); + pf_atapi(pf, ms_cmd, 8, buf, "mode sense"); pf->media_status = PF_RW; if (buf[3] & 0x80) pf->media_status = PF_RO; @@ -591,7 +589,7 @@ static void pf_get_capacity(struct pf_unit *pf) char buf[8]; int bs; - if (pf_atapi(pf, rc_cmd, 8, buf, DBMSG("get capacity"))) { + if (pf_atapi(pf, rc_cmd, 8, buf, "get capacity")) { pf->media_status = PF_NM; return; } @@ -804,13 +802,18 @@ static int pf_next_buf(void) pf_buf += 512; pf_block++; if (!pf_run) - return 0; - if (!pf_count) return 1; - spin_lock_irqsave(&pf_spin_lock, saved_flags); - pf_end_request(1); - spin_unlock_irqrestore(&pf_spin_lock, saved_flags); - return 1; + if (!pf_count) { + spin_lock_irqsave(&pf_spin_lock, saved_flags); + pf_end_request(1); + pf_req = elv_next_request(pf_queue); + spin_unlock_irqrestore(&pf_spin_lock, saved_flags); + if (!pf_req) + return 1; + pf_count = pf_req->current_nr_sectors; + pf_buf = pf_req->buffer; + } + return 0; } static inline void next_request(int success) diff --git a/drivers/block/pktcdvd.c b/drivers/block/pktcdvd.c index a8130a4..a5ee213 100644 --- a/drivers/block/pktcdvd.c +++ b/drivers/block/pktcdvd.c @@ -358,10 +358,19 @@ static ssize_t class_pktcdvd_store_add(struct class *c, const char *buf, size_t count) { unsigned int major, minor; + if (sscanf(buf, "%u:%u", &major, &minor) == 2) { + /* pkt_setup_dev() expects caller to hold reference to self */ + if (!try_module_get(THIS_MODULE)) + return -ENODEV; + pkt_setup_dev(MKDEV(major, minor), NULL); + + module_put(THIS_MODULE); + return count; } + return -EINVAL; } diff --git a/drivers/block/rd.c b/drivers/block/rd.c index 47f8ac6..82f4eec 100644 --- a/drivers/block/rd.c +++ b/drivers/block/rd.c @@ -189,6 +189,18 @@ static int ramdisk_set_page_dirty(struct page *page) return 0; } +/* + * releasepage is called by pagevec_strip/try_to_release_page if + * buffers_heads_over_limit is true. Without a releasepage function + * try_to_free_buffers is called instead. That can unset the dirty + * bit of our ram disk pages, which will be eventually freed, even + * if the page is still in use. + */ +static int ramdisk_releasepage(struct page *page, gfp_t dummy) +{ + return 0; +} + static const struct address_space_operations ramdisk_aops = { .readpage = ramdisk_readpage, .prepare_write = ramdisk_prepare_write, @@ -196,6 +208,7 @@ static const struct address_space_operations ramdisk_aops = { .writepage = ramdisk_writepage, .set_page_dirty = ramdisk_set_page_dirty, .writepages = ramdisk_writepages, + .releasepage = ramdisk_releasepage, }; static int rd_blkdev_pagecache_IO(int rw, struct bio_vec *vec, sector_t sector, diff --git a/drivers/block/virtio_blk.c b/drivers/block/virtio_blk.c index 3cf7129..924ddd8 100644 --- a/drivers/block/virtio_blk.c +++ b/drivers/block/virtio_blk.c @@ -223,7 +223,7 @@ static int virtblk_probe(struct virtio_device *vdev) err = virtio_config_val(vdev, VIRTIO_CONFIG_BLK_F_CAPACITY, &cap); if (err) { dev_err(&vdev->dev, "Bad/missing capacity in config\n"); - goto out_put_disk; + goto out_cleanup_queue; } /* If capacity is too big, truncate with warning. */ @@ -239,7 +239,7 @@ static int virtblk_probe(struct virtio_device *vdev) blk_queue_max_segment_size(vblk->disk->queue, v); else if (err != -ENOENT) { dev_err(&vdev->dev, "Bad SIZE_MAX in config\n"); - goto out_put_disk; + goto out_cleanup_queue; } err = virtio_config_val(vdev, VIRTIO_CONFIG_BLK_F_SEG_MAX, &v); @@ -247,12 +247,14 @@ static int virtblk_probe(struct virtio_device *vdev) blk_queue_max_hw_segments(vblk->disk->queue, v); else if (err != -ENOENT) { dev_err(&vdev->dev, "Bad SEG_MAX in config\n"); - goto out_put_disk; + goto out_cleanup_queue; } add_disk(vblk->disk); return 0; +out_cleanup_queue: + blk_cleanup_queue(vblk->disk->queue); out_put_disk: put_disk(vblk->disk); out_unregister_blkdev: @@ -277,6 +279,8 @@ static void virtblk_remove(struct virtio_device *vdev) put_disk(vblk->disk); unregister_blkdev(major, "virtblk"); mempool_destroy(vblk->pool); + /* There should be nothing in the queue now, so no need to shutdown */ + vdev->config->del_vq(vblk->vq); kfree(vblk); } diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig index bf18d75..a509b8d 100644 --- a/drivers/char/Kconfig +++ b/drivers/char/Kconfig @@ -457,7 +457,7 @@ config LEGACY_PTYS config LEGACY_PTY_COUNT int "Maximum number of legacy PTY in use" depends on LEGACY_PTYS - range 1 256 + range 0 256 default "256" ---help--- The maximum number of legacy PTYs that can be used at any one time. diff --git a/drivers/char/pcmcia/cm4000_cs.c b/drivers/char/pcmcia/cm4000_cs.c index cc5d777..02518da 100644 --- a/drivers/char/pcmcia/cm4000_cs.c +++ b/drivers/char/pcmcia/cm4000_cs.c @@ -47,7 +47,7 @@ /* #define ATR_CSUM */ #ifdef PCMCIA_DEBUG -#define reader_to_dev(x) (&handle_to_dev(x->p_dev->handle)) +#define reader_to_dev(x) (&handle_to_dev(x->p_dev)) static int pc_debug = PCMCIA_DEBUG; module_param(pc_debug, int, 0600); #define DEBUGP(n, rdr, x, args...) do { \ diff --git a/drivers/char/pcmcia/cm4040_cs.c b/drivers/char/pcmcia/cm4040_cs.c index a0b9c87..5f291bf 100644 --- a/drivers/char/pcmcia/cm4040_cs.c +++ b/drivers/char/pcmcia/cm4040_cs.c @@ -41,7 +41,7 @@ #ifdef PCMCIA_DEBUG -#define reader_to_dev(x) (&handle_to_dev(x->p_dev->handle)) +#define reader_to_dev(x) (&handle_to_dev(x->p_dev)) static int pc_debug = PCMCIA_DEBUG; module_param(pc_debug, int, 0600); #define DEBUGP(n, rdr, x, args...) do { \ diff --git a/drivers/char/random.c b/drivers/char/random.c index 1756b1f..5fee056 100644 --- a/drivers/char/random.c +++ b/drivers/char/random.c @@ -1494,7 +1494,7 @@ __u32 secure_tcpv6_sequence_number(__be32 *saddr, __be32 *daddr, seq = twothirdsMD4Transform((const __u32 *)daddr, hash) & HASH_MASK; seq += keyptr->count; - seq += ktime_get_real().tv64; + seq += ktime_to_ns(ktime_get_real()); return seq; } @@ -1556,7 +1556,7 @@ __u32 secure_tcp_sequence_number(__be32 saddr, __be32 daddr, * overlaps less than one time per MSL (2 minutes). * Choosing a clock of 64 ns period is OK. (period of 274 s) */ - seq += ktime_get_real().tv64 >> 6; + seq += ktime_to_ns(ktime_get_real()) >> 6; #if 0 printk("init_seq(%lx, %lx, %d, %d) = %d\n", saddr, daddr, sport, dport, seq); @@ -1616,7 +1616,7 @@ u64 secure_dccp_sequence_number(__be32 saddr, __be32 daddr, seq = half_md4_transform(hash, keyptr->secret); seq |= ((u64)keyptr->count) << (32 - HASH_BITS); - seq += ktime_get_real().tv64; + seq += ktime_to_ns(ktime_get_real()); seq &= (1ull << 48) - 1; #if 0 printk("dccp init_seq(%lx, %lx, %d, %d) = %d\n", diff --git a/drivers/char/rtc.c b/drivers/char/rtc.c index ec6b65e..0c66b80 100644 --- a/drivers/char/rtc.c +++ b/drivers/char/rtc.c @@ -918,6 +918,31 @@ static const struct file_operations rtc_proc_fops = { }; #endif +static resource_size_t rtc_size; + +static struct resource * __init rtc_request_region(resource_size_t size) +{ + struct resource *r; + + if (RTC_IOMAPPED) + r = request_region(RTC_PORT(0), size, "rtc"); + else + r = request_mem_region(RTC_PORT(0), size, "rtc"); + + if (r) + rtc_size = size; + + return r; +} + +static void rtc_release_region(void) +{ + if (RTC_IOMAPPED) + release_region(RTC_PORT(0), rtc_size); + else + release_mem_region(RTC_PORT(0), rtc_size); +} + static int __init rtc_init(void) { #ifdef CONFIG_PROC_FS @@ -968,10 +993,17 @@ found: } no_irq: #else - if (RTC_IOMAPPED) - r = request_region(RTC_PORT(0), RTC_IO_EXTENT, "rtc"); - else - r = request_mem_region(RTC_PORT(0), RTC_IO_EXTENT, "rtc"); + r = rtc_request_region(RTC_IO_EXTENT); + + /* + * If we've already requested a smaller range (for example, because + * PNPBIOS or ACPI told us how the device is configured), the request + * above might fail because it's too big. + * + * If so, request just the range we actually use. + */ + if (!r) + r = rtc_request_region(RTC_IO_EXTENT_USED); if (!r) { #ifdef RTC_IRQ rtc_has_irq = 0; @@ -992,10 +1024,7 @@ no_irq: /* Yeah right, seeing as irq 8 doesn't even hit the bus. */ rtc_has_irq = 0; printk(KERN_ERR "rtc: IRQ %d is not free.\n", RTC_IRQ); - if (RTC_IOMAPPED) - release_region(RTC_PORT(0), RTC_IO_EXTENT); - else - release_mem_region(RTC_PORT(0), RTC_IO_EXTENT); + rtc_release_region(); return -EIO; } hpet_rtc_timer_init(); @@ -1009,7 +1038,7 @@ no_irq: free_irq(RTC_IRQ, NULL); rtc_has_irq = 0; #endif - release_region(RTC_PORT(0), RTC_IO_EXTENT); + rtc_release_region(); return -ENODEV; } @@ -1091,10 +1120,7 @@ static void __exit rtc_exit (void) if (rtc_has_irq) free_irq (rtc_irq, &rtc_port); #else - if (RTC_IOMAPPED) - release_region(RTC_PORT(0), RTC_IO_EXTENT); - else - release_mem_region(RTC_PORT(0), RTC_IO_EXTENT); + rtc_release_region(); #ifdef RTC_IRQ if (rtc_has_irq) free_irq (RTC_IRQ, NULL); diff --git a/drivers/char/sonypi.c b/drivers/char/sonypi.c index 877e53d..921c6d2 100644 --- a/drivers/char/sonypi.c +++ b/drivers/char/sonypi.c @@ -1163,7 +1163,7 @@ static struct acpi_driver sonypi_acpi_driver = { }; #endif -static int __devinit sonypi_create_input_devices(void) +static int __devinit sonypi_create_input_devices(struct platform_device *pdev) { struct input_dev *jog_dev; struct input_dev *key_dev; @@ -1177,6 +1177,7 @@ static int __devinit sonypi_create_input_devices(void) jog_dev->name = "Sony Vaio Jogdial"; jog_dev->id.bustype = BUS_ISA; jog_dev->id.vendor = PCI_VENDOR_ID_SONY; + jog_dev->dev.parent = &pdev->dev; jog_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REL); jog_dev->keybit[BIT_WORD(BTN_MOUSE)] = BIT_MASK(BTN_MIDDLE); @@ -1191,6 +1192,7 @@ static int __devinit sonypi_create_input_devices(void) key_dev->name = "Sony Vaio Keys"; key_dev->id.bustype = BUS_ISA; key_dev->id.vendor = PCI_VENDOR_ID_SONY; + key_dev->dev.parent = &pdev->dev; /* Initialize the Input Drivers: special keys */ key_dev->evbit[0] = BIT_MASK(EV_KEY); @@ -1385,7 +1387,7 @@ static int __devinit sonypi_probe(struct platform_device *dev) if (useinput) { - error = sonypi_create_input_devices(); + error = sonypi_create_input_devices(dev); if (error) { printk(KERN_ERR "sonypi: failed to create input devices\n"); @@ -1432,7 +1434,7 @@ static int __devexit sonypi_remove(struct platform_device *dev) { sonypi_disable(); - synchronize_sched(); /* Allow sonypi interrupt to complete. */ + synchronize_irq(sonypi_device.irq); flush_scheduled_work(); if (useinput) { diff --git a/drivers/char/tpm/tpm_tis.c b/drivers/char/tpm/tpm_tis.c index fd771a4..81503d9 100644 --- a/drivers/char/tpm/tpm_tis.c +++ b/drivers/char/tpm/tpm_tis.c @@ -450,6 +450,11 @@ static int tpm_tis_init(struct device *dev, resource_size_t start, goto out_err; } + if (request_locality(chip, 0) != 0) { + rc = -ENODEV; + goto out_err; + } + vendor = ioread32(chip->vendor.iobase + TPM_DID_VID(0)); /* Default timeouts */ @@ -487,11 +492,6 @@ static int tpm_tis_init(struct device *dev, resource_size_t start, if (intfcaps & TPM_INTF_DATA_AVAIL_INT) dev_dbg(dev, "\tData Avail Int Support\n"); - if (request_locality(chip, 0) != 0) { - rc = -ENODEV; - goto out_err; - } - /* INTERRUPT Setup */ init_waitqueue_head(&chip->vendor.read_queue); init_waitqueue_head(&chip->vendor.int_queue); diff --git a/drivers/char/tty_ioctl.c b/drivers/char/tty_ioctl.c index 7a00350..1bdd2bf 100644 --- a/drivers/char/tty_ioctl.c +++ b/drivers/char/tty_ioctl.c @@ -730,13 +730,23 @@ static int send_prio_char(struct tty_struct *tty, char ch) return 0; } -int n_tty_ioctl(struct tty_struct * tty, struct file * file, - unsigned int cmd, unsigned long arg) +/** + * tty_mode_ioctl - mode related ioctls + * @tty: tty for the ioctl + * @file: file pointer for the tty + * @cmd: command + * @arg: ioctl argument + * + * Perform non line discipline specific mode control ioctls. This + * is designed to be called by line disciplines to ensure they provide + * consistent mode setting. + */ + +int tty_mode_ioctl(struct tty_struct * tty, struct file *file, + unsigned int cmd, unsigned long arg) { struct tty_struct * real_tty; void __user *p = (void __user *)arg; - int retval; - struct tty_ldisc *ld; if (tty->driver->type == TTY_DRIVER_TYPE_PTY && tty->driver->subtype == PTY_TYPE_MASTER) @@ -799,6 +809,93 @@ int n_tty_ioctl(struct tty_struct * tty, struct file * file, return set_termios(real_tty, p, TERMIOS_WAIT | TERMIOS_TERMIO); case TCSETA: return set_termios(real_tty, p, TERMIOS_TERMIO); +#ifndef TCGETS2 + case TIOCGLCKTRMIOS: + if (kernel_termios_to_user_termios((struct termios __user *)arg, real_tty->termios_locked)) + return -EFAULT; + return 0; + + case TIOCSLCKTRMIOS: + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + if (user_termios_to_kernel_termios(real_tty->termios_locked, (struct termios __user *) arg)) + return -EFAULT; + return 0; +#else + case TIOCGLCKTRMIOS: + if (kernel_termios_to_user_termios_1((struct termios __user *)arg, real_tty->termios_locked)) + return -EFAULT; + return 0; + + case TIOCSLCKTRMIOS: + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + if (user_termios_to_kernel_termios_1(real_tty->termios_locked, (struct termios __user *) arg)) + return -EFAULT; + return 0; +#endif + case TIOCGSOFTCAR: + return put_user(C_CLOCAL(tty) ? 1 : 0, (int __user *)arg); + case TIOCSSOFTCAR: + if (get_user(arg, (unsigned int __user *) arg)) + return -EFAULT; + mutex_lock(&tty->termios_mutex); + tty->termios->c_cflag = + ((tty->termios->c_cflag & ~CLOCAL) | + (arg ? CLOCAL : 0)); + mutex_unlock(&tty->termios_mutex); + return 0; + default: + return -ENOIOCTLCMD; + } +} + +EXPORT_SYMBOL_GPL(tty_mode_ioctl); + +int tty_perform_flush(struct tty_struct *tty, unsigned long arg) +{ + struct tty_ldisc *ld; + int retval = tty_check_change(tty); + if (retval) + return retval; + + ld = tty_ldisc_ref(tty); + switch (arg) { + case TCIFLUSH: + if (ld && ld->flush_buffer) + ld->flush_buffer(tty); + break; + case TCIOFLUSH: + if (ld && ld->flush_buffer) + ld->flush_buffer(tty); + /* fall through */ + case TCOFLUSH: + if (tty->driver->flush_buffer) + tty->driver->flush_buffer(tty); + break; + default: + tty_ldisc_deref(ld); + return -EINVAL; + } + tty_ldisc_deref(ld); + return 0; +} + +EXPORT_SYMBOL_GPL(tty_perform_flush); + +int n_tty_ioctl(struct tty_struct * tty, struct file * file, + unsigned int cmd, unsigned long arg) +{ + struct tty_struct * real_tty; + int retval; + + if (tty->driver->type == TTY_DRIVER_TYPE_PTY && + tty->driver->subtype == PTY_TYPE_MASTER) + real_tty = tty->link; + else + real_tty = tty; + + switch (cmd) { case TCXONC: retval = tty_check_change(tty); if (retval) @@ -829,30 +926,7 @@ int n_tty_ioctl(struct tty_struct * tty, struct file * file, } return 0; case TCFLSH: - retval = tty_check_change(tty); - if (retval) - return retval; - - ld = tty_ldisc_ref(tty); - switch (arg) { - case TCIFLUSH: - if (ld && ld->flush_buffer) - ld->flush_buffer(tty); - break; - case TCIOFLUSH: - if (ld && ld->flush_buffer) - ld->flush_buffer(tty); - /* fall through */ - case TCOFLUSH: - if (tty->driver->flush_buffer) - tty->driver->flush_buffer(tty); - break; - default: - tty_ldisc_deref(ld); - return -EINVAL; - } - tty_ldisc_deref(ld); - return 0; + return tty_perform_flush(tty, arg); case TIOCOUTQ: return put_user(tty->driver->chars_in_buffer ? tty->driver->chars_in_buffer(tty) : 0, @@ -862,32 +936,6 @@ int n_tty_ioctl(struct tty_struct * tty, struct file * file, if (L_ICANON(tty)) retval = inq_canon(tty); return put_user(retval, (unsigned int __user *) arg); -#ifndef TCGETS2 - case TIOCGLCKTRMIOS: - if (kernel_termios_to_user_termios((struct termios __user *)arg, real_tty->termios_locked)) - return -EFAULT; - return 0; - - case TIOCSLCKTRMIOS: - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; - if (user_termios_to_kernel_termios(real_tty->termios_locked, (struct termios __user *) arg)) - return -EFAULT; - return 0; -#else - case TIOCGLCKTRMIOS: - if (kernel_termios_to_user_termios_1((struct termios __user *)arg, real_tty->termios_locked)) - return -EFAULT; - return 0; - - case TIOCSLCKTRMIOS: - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; - if (user_termios_to_kernel_termios_1(real_tty->termios_locked, (struct termios __user *) arg)) - return -EFAULT; - return 0; -#endif - case TIOCPKT: { int pktmode; @@ -906,19 +954,9 @@ int n_tty_ioctl(struct tty_struct * tty, struct file * file, tty->packet = 0; return 0; } - case TIOCGSOFTCAR: - return put_user(C_CLOCAL(tty) ? 1 : 0, (int __user *)arg); - case TIOCSSOFTCAR: - if (get_user(arg, (unsigned int __user *) arg)) - return -EFAULT; - mutex_lock(&tty->termios_mutex); - tty->termios->c_cflag = - ((tty->termios->c_cflag & ~CLOCAL) | - (arg ? CLOCAL : 0)); - mutex_unlock(&tty->termios_mutex); - return 0; default: - return -ENOIOCTLCMD; + /* Try the mode commands */ + return tty_mode_ioctl(tty, file, cmd, arg); } } diff --git a/drivers/cpufreq/cpufreq_conservative.c b/drivers/cpufreq/cpufreq_conservative.c index 4bd33ce..1bba997 100644 --- a/drivers/cpufreq/cpufreq_conservative.c +++ b/drivers/cpufreq/cpufreq_conservative.c @@ -37,17 +37,17 @@ #define DEF_FREQUENCY_UP_THRESHOLD (80) #define DEF_FREQUENCY_DOWN_THRESHOLD (20) -/* - * The polling frequency of this governor depends on the capability of +/* + * The polling frequency of this governor depends on the capability of * the processor. Default polling frequency is 1000 times the transition - * latency of the processor. The governor will work on any processor with - * transition latency <= 10mS, using appropriate sampling + * latency of the processor. The governor will work on any processor with + * transition latency <= 10mS, using appropriate sampling * rate. * For CPUs with transition latency > 10mS (mostly drivers * with CPUFREQ_ETERNAL), this governor will not work. * All times here are in uS. */ -static unsigned int def_sampling_rate; +static unsigned int def_sampling_rate; #define MIN_SAMPLING_RATE_RATIO (2) /* for correct statistics, we need at least 10 ticks between each measure */ #define MIN_STAT_SAMPLING_RATE \ @@ -63,12 +63,12 @@ static unsigned int def_sampling_rate; static void do_dbs_timer(struct work_struct *work); struct cpu_dbs_info_s { - struct cpufreq_policy *cur_policy; - unsigned int prev_cpu_idle_up; - unsigned int prev_cpu_idle_down; - unsigned int enable; - unsigned int down_skip; - unsigned int requested_freq; + struct cpufreq_policy *cur_policy; + unsigned int prev_cpu_idle_up; + unsigned int prev_cpu_idle_down; + unsigned int enable; + unsigned int down_skip; + unsigned int requested_freq; }; static DEFINE_PER_CPU(struct cpu_dbs_info_s, cpu_dbs_info); @@ -82,24 +82,24 @@ static unsigned int dbs_enable; /* number of CPUs using this policy */ * cpu_hotplug lock should be taken before that. Note that cpu_hotplug lock * is recursive for the same process. -Venki */ -static DEFINE_MUTEX (dbs_mutex); +static DEFINE_MUTEX (dbs_mutex); static DECLARE_DELAYED_WORK(dbs_work, do_dbs_timer); struct dbs_tuners { - unsigned int sampling_rate; - unsigned int sampling_down_factor; - unsigned int up_threshold; - unsigned int down_threshold; - unsigned int ignore_nice; - unsigned int freq_step; + unsigned int sampling_rate; + unsigned int sampling_down_factor; + unsigned int up_threshold; + unsigned int down_threshold; + unsigned int ignore_nice; + unsigned int freq_step; }; static struct dbs_tuners dbs_tuners_ins = { - .up_threshold = DEF_FREQUENCY_UP_THRESHOLD, - .down_threshold = DEF_FREQUENCY_DOWN_THRESHOLD, - .sampling_down_factor = DEF_SAMPLING_DOWN_FACTOR, - .ignore_nice = 0, - .freq_step = 5, + .up_threshold = DEF_FREQUENCY_UP_THRESHOLD, + .down_threshold = DEF_FREQUENCY_DOWN_THRESHOLD, + .sampling_down_factor = DEF_SAMPLING_DOWN_FACTOR, + .ignore_nice = 0, + .freq_step = 5, }; static inline unsigned int get_cpu_idle_time(unsigned int cpu) @@ -109,13 +109,34 @@ static inline unsigned int get_cpu_idle_time(unsigned int cpu) if (dbs_tuners_ins.ignore_nice) add_nice = kstat_cpu(cpu).cpustat.nice; - ret = kstat_cpu(cpu).cpustat.idle + + ret = kstat_cpu(cpu).cpustat.idle + kstat_cpu(cpu).cpustat.iowait + add_nice; return ret; } +/* keep track of frequency transitions */ +static int +dbs_cpufreq_notifier(struct notifier_block *nb, unsigned long val, + void *data) +{ + struct cpufreq_freqs *freq = data; + struct cpu_dbs_info_s *this_dbs_info = &per_cpu(cpu_dbs_info, + freq->cpu); + + if (!this_dbs_info->enable) + return 0; + + this_dbs_info->requested_freq = freq->new; + + return 0; +} + +static struct notifier_block dbs_cpufreq_notifier_block = { + .notifier_call = dbs_cpufreq_notifier +}; + /************************** sysfs interface ************************/ static ssize_t show_sampling_rate_max(struct cpufreq_policy *policy, char *buf) { @@ -127,8 +148,8 @@ static ssize_t show_sampling_rate_min(struct cpufreq_policy *policy, char *buf) return sprintf (buf, "%u\n", MIN_SAMPLING_RATE); } -#define define_one_ro(_name) \ -static struct freq_attr _name = \ +#define define_one_ro(_name) \ +static struct freq_attr _name = \ __ATTR(_name, 0444, show_##_name, NULL) define_one_ro(sampling_rate_max); @@ -148,7 +169,7 @@ show_one(down_threshold, down_threshold); show_one(ignore_nice_load, ignore_nice); show_one(freq_step, freq_step); -static ssize_t store_sampling_down_factor(struct cpufreq_policy *unused, +static ssize_t store_sampling_down_factor(struct cpufreq_policy *unused, const char *buf, size_t count) { unsigned int input; @@ -164,7 +185,7 @@ static ssize_t store_sampling_down_factor(struct cpufreq_policy *unused, return count; } -static ssize_t store_sampling_rate(struct cpufreq_policy *unused, +static ssize_t store_sampling_rate(struct cpufreq_policy *unused, const char *buf, size_t count) { unsigned int input; @@ -183,7 +204,7 @@ static ssize_t store_sampling_rate(struct cpufreq_policy *unused, return count; } -static ssize_t store_up_threshold(struct cpufreq_policy *unused, +static ssize_t store_up_threshold(struct cpufreq_policy *unused, const char *buf, size_t count) { unsigned int input; @@ -202,7 +223,7 @@ static ssize_t store_up_threshold(struct cpufreq_policy *unused, return count; } -static ssize_t store_down_threshold(struct cpufreq_policy *unused, +static ssize_t store_down_threshold(struct cpufreq_policy *unused, const char *buf, size_t count) { unsigned int input; @@ -228,16 +249,16 @@ static ssize_t store_ignore_nice_load(struct cpufreq_policy *policy, int ret; unsigned int j; - - ret = sscanf (buf, "%u", &input); - if ( ret != 1 ) + + ret = sscanf(buf, "%u", &input); + if (ret != 1) return -EINVAL; - if ( input > 1 ) + if (input > 1) input = 1; - + mutex_lock(&dbs_mutex); - if ( input == dbs_tuners_ins.ignore_nice ) { /* nothing to do */ + if (input == dbs_tuners_ins.ignore_nice) { /* nothing to do */ mutex_unlock(&dbs_mutex); return count; } @@ -261,14 +282,14 @@ static ssize_t store_freq_step(struct cpufreq_policy *policy, unsigned int input; int ret; - ret = sscanf (buf, "%u", &input); + ret = sscanf(buf, "%u", &input); - if ( ret != 1 ) + if (ret != 1) return -EINVAL; - if ( input > 100 ) + if (input > 100) input = 100; - + /* no need to test here if freq_step is zero as the user might actually * want this, they would be crazy though :) */ mutex_lock(&dbs_mutex); @@ -322,18 +343,18 @@ static void dbs_check_cpu(int cpu) policy = this_dbs_info->cur_policy; - /* - * The default safe range is 20% to 80% + /* + * The default safe range is 20% to 80% * Every sampling_rate, we check - * - If current idle time is less than 20%, then we try to - * increase frequency + * - If current idle time is less than 20%, then we try to + * increase frequency * Every sampling_rate*sampling_down_factor, we check - * - If current idle time is more than 80%, then we try to - * decrease frequency + * - If current idle time is more than 80%, then we try to + * decrease frequency * - * Any frequency increase takes it to the maximum frequency. - * Frequency reduction happens at minimum steps of - * 5% (default) of max_frequency + * Any frequency increase takes it to the maximum frequency. + * Frequency reduction happens at minimum steps of + * 5% (default) of max_frequency */ /* Check for frequency increase */ @@ -361,13 +382,13 @@ static void dbs_check_cpu(int cpu) /* if we are already at full speed then break out early */ if (this_dbs_info->requested_freq == policy->max) return; - + freq_step = (dbs_tuners_ins.freq_step * policy->max) / 100; /* max freq cannot be less than 100. But who knows.... */ if (unlikely(freq_step == 0)) freq_step = 5; - + this_dbs_info->requested_freq += freq_step; if (this_dbs_info->requested_freq > policy->max) this_dbs_info->requested_freq = policy->max; @@ -427,15 +448,15 @@ static void dbs_check_cpu(int cpu) } static void do_dbs_timer(struct work_struct *work) -{ +{ int i; mutex_lock(&dbs_mutex); for_each_online_cpu(i) dbs_check_cpu(i); - schedule_delayed_work(&dbs_work, + schedule_delayed_work(&dbs_work, usecs_to_jiffies(dbs_tuners_ins.sampling_rate)); mutex_unlock(&dbs_mutex); -} +} static inline void dbs_timer_init(void) { @@ -462,13 +483,12 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy, switch (event) { case CPUFREQ_GOV_START: - if ((!cpu_online(cpu)) || - (!policy->cur)) + if ((!cpu_online(cpu)) || (!policy->cur)) return -EINVAL; if (this_dbs_info->enable) /* Already enabled */ break; - + mutex_lock(&dbs_mutex); rc = sysfs_create_group(&policy->kobj, &dbs_attr_group); @@ -481,7 +501,7 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy, struct cpu_dbs_info_s *j_dbs_info; j_dbs_info = &per_cpu(cpu_dbs_info, j); j_dbs_info->cur_policy = policy; - + j_dbs_info->prev_cpu_idle_up = get_cpu_idle_time(cpu); j_dbs_info->prev_cpu_idle_down = j_dbs_info->prev_cpu_idle_up; @@ -511,8 +531,11 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy, dbs_tuners_ins.sampling_rate = def_sampling_rate; dbs_timer_init(); + cpufreq_register_notifier( + &dbs_cpufreq_notifier_block, + CPUFREQ_TRANSITION_NOTIFIER); } - + mutex_unlock(&dbs_mutex); break; @@ -525,9 +548,13 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy, * Stop the timerschedule work, when this governor * is used for first time */ - if (dbs_enable == 0) + if (dbs_enable == 0) { dbs_timer_exit(); - + cpufreq_unregister_notifier( + &dbs_cpufreq_notifier_block, + CPUFREQ_TRANSITION_NOTIFIER); + } + mutex_unlock(&dbs_mutex); break; @@ -537,11 +564,11 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy, if (policy->max < this_dbs_info->cur_policy->cur) __cpufreq_driver_target( this_dbs_info->cur_policy, - policy->max, CPUFREQ_RELATION_H); + policy->max, CPUFREQ_RELATION_H); else if (policy->min > this_dbs_info->cur_policy->cur) __cpufreq_driver_target( this_dbs_info->cur_policy, - policy->min, CPUFREQ_RELATION_L); + policy->min, CPUFREQ_RELATION_L); mutex_unlock(&dbs_mutex); break; } diff --git a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig index 5fd6688..ddd3a25 100644 --- a/drivers/crypto/Kconfig +++ b/drivers/crypto/Kconfig @@ -12,7 +12,7 @@ if CRYPTO_HW config CRYPTO_DEV_PADLOCK tristate "Support for VIA PadLock ACE" - depends on X86_32 + depends on X86_32 && !UML select CRYPTO_ALGAPI help Some VIA processors come with an integrated crypto engine diff --git a/drivers/crypto/geode-aes.c b/drivers/crypto/geode-aes.c index f9a34ab..711e246 100644 --- a/drivers/crypto/geode-aes.c +++ b/drivers/crypto/geode-aes.c @@ -110,8 +110,7 @@ geode_aes_crypt(struct geode_aes_op *op) * we don't need to worry */ - if (op->src == op->dst) - flags |= (AES_CTRL_DCA | AES_CTRL_SCA); + flags |= (AES_CTRL_DCA | AES_CTRL_SCA); if (op->dir == AES_DIR_ENCRYPT) flags |= AES_CTRL_ENCRYPT; diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig index 6a7d25f..c46b7c2 100644 --- a/drivers/dma/Kconfig +++ b/drivers/dma/Kconfig @@ -3,11 +3,13 @@ # menuconfig DMADEVICES - bool "DMA Offload Engine support" + bool "DMA Engine support" depends on (PCI && X86) || ARCH_IOP32X || ARCH_IOP33X || ARCH_IOP13XX help - Intel(R) offload engines enable offloading memory copies in the - network stack and RAID operations in the MD driver. + DMA engines can do asynchronous data transfers without + involving the host CPU. Currently, this framework can be + used to offload memory copies in the network stack and + RAID operations in the MD driver. if DMADEVICES diff --git a/drivers/dma/dmaengine.c b/drivers/dma/dmaengine.c index 8248992..d59b2f4 100644 --- a/drivers/dma/dmaengine.c +++ b/drivers/dma/dmaengine.c @@ -182,10 +182,9 @@ static void dma_client_chan_alloc(struct dma_client *client) /* we are done once this client rejects * an available resource */ - if (ack == DMA_ACK) { + if (ack == DMA_ACK) dma_chan_get(chan); - kref_get(&device->refcount); - } else if (ack == DMA_NAK) + else if (ack == DMA_NAK) return; } } @@ -272,11 +271,8 @@ static void dma_clients_notify_removed(struct dma_chan *chan) /* client was holding resources for this channel so * free it */ - if (ack == DMA_ACK) { + if (ack == DMA_ACK) dma_chan_put(chan); - kref_put(&chan->device->refcount, - dma_async_device_cleanup); - } } mutex_unlock(&dma_list_mutex); @@ -316,11 +312,8 @@ void dma_async_client_unregister(struct dma_client *client) ack = client->event_callback(client, chan, DMA_RESOURCE_REMOVED); - if (ack == DMA_ACK) { + if (ack == DMA_ACK) dma_chan_put(chan); - kref_put(&chan->device->refcount, - dma_async_device_cleanup); - } } list_del(&client->global_node); @@ -397,6 +390,8 @@ int dma_async_device_register(struct dma_device *device) goto err_out; } + /* One for the channel, one of the class device */ + kref_get(&device->refcount); kref_get(&device->refcount); kref_init(&chan->refcount); chan->slow_ref = 0; diff --git a/drivers/dma/ioat.c b/drivers/dma/ioat.c index f204c39..16e0fd8 100644 --- a/drivers/dma/ioat.c +++ b/drivers/dma/ioat.c @@ -39,10 +39,14 @@ MODULE_LICENSE("GPL"); MODULE_AUTHOR("Intel Corporation"); static struct pci_device_id ioat_pci_tbl[] = { + /* I/OAT v1 platforms */ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_IOAT) }, { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_IOAT_CNB) }, { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_IOAT_SCNB) }, { PCI_DEVICE(PCI_VENDOR_ID_UNISYS, PCI_DEVICE_ID_UNISYS_DMA_DIRECTOR) }, + + /* I/OAT v2 platforms */ + { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_IOAT_SNB) }, { 0, } }; @@ -74,10 +78,17 @@ static int ioat_setup_functionality(struct pci_dev *pdev, void __iomem *iobase) if (device->dma && ioat_dca_enabled) device->dca = ioat_dca_init(pdev, iobase); break; + case IOAT_VER_2_0: + device->dma = ioat_dma_probe(pdev, iobase); + if (device->dma && ioat_dca_enabled) + device->dca = ioat2_dca_init(pdev, iobase); + break; default: err = -ENODEV; break; } + if (!device->dma) + err = -ENODEV; return err; } diff --git a/drivers/dma/ioat_dca.c b/drivers/dma/ioat_dca.c index ba98571..0fa8a98 100644 --- a/drivers/dma/ioat_dca.c +++ b/drivers/dma/ioat_dca.c @@ -261,3 +261,167 @@ struct dca_provider *ioat_dca_init(struct pci_dev *pdev, void __iomem *iobase) return dca; } + +static int ioat2_dca_add_requester(struct dca_provider *dca, struct device *dev) +{ + struct ioat_dca_priv *ioatdca = dca_priv(dca); + struct pci_dev *pdev; + int i; + u16 id; + u16 global_req_table; + + /* This implementation only supports PCI-Express */ + if (dev->bus != &pci_bus_type) + return -ENODEV; + pdev = to_pci_dev(dev); + id = dcaid_from_pcidev(pdev); + + if (ioatdca->requester_count == ioatdca->max_requesters) + return -ENODEV; + + for (i = 0; i < ioatdca->max_requesters; i++) { + if (ioatdca->req_slots[i].pdev == NULL) { + /* found an empty slot */ + ioatdca->requester_count++; + ioatdca->req_slots[i].pdev = pdev; + ioatdca->req_slots[i].rid = id; + global_req_table = + readw(ioatdca->dca_base + IOAT_DCA_GREQID_OFFSET); + writel(id | IOAT_DCA_GREQID_VALID, + ioatdca->iobase + global_req_table + (i * 4)); + return i; + } + } + /* Error, ioatdma->requester_count is out of whack */ + return -EFAULT; +} + +static int ioat2_dca_remove_requester(struct dca_provider *dca, + struct device *dev) +{ + struct ioat_dca_priv *ioatdca = dca_priv(dca); + struct pci_dev *pdev; + int i; + u16 global_req_table; + + /* This implementation only supports PCI-Express */ + if (dev->bus != &pci_bus_type) + return -ENODEV; + pdev = to_pci_dev(dev); + + for (i = 0; i < ioatdca->max_requesters; i++) { + if (ioatdca->req_slots[i].pdev == pdev) { + global_req_table = + readw(ioatdca->dca_base + IOAT_DCA_GREQID_OFFSET); + writel(0, ioatdca->iobase + global_req_table + (i * 4)); + ioatdca->req_slots[i].pdev = NULL; + ioatdca->req_slots[i].rid = 0; + ioatdca->requester_count--; + return i; + } + } + return -ENODEV; +} + +static u8 ioat2_dca_get_tag(struct dca_provider *dca, int cpu) +{ + u8 tag; + + tag = ioat_dca_get_tag(dca, cpu); + tag = (~tag) & 0x1F; + return tag; +} + +static struct dca_ops ioat2_dca_ops = { + .add_requester = ioat2_dca_add_requester, + .remove_requester = ioat2_dca_remove_requester, + .get_tag = ioat2_dca_get_tag, +}; + +static int ioat2_dca_count_dca_slots(void *iobase, u16 dca_offset) +{ + int slots = 0; + u32 req; + u16 global_req_table; + + global_req_table = readw(iobase + dca_offset + IOAT_DCA_GREQID_OFFSET); + if (global_req_table == 0) + return 0; + do { + req = readl(iobase + global_req_table + (slots * sizeof(u32))); + slots++; + } while ((req & IOAT_DCA_GREQID_LASTID) == 0); + + return slots; +} + +struct dca_provider *ioat2_dca_init(struct pci_dev *pdev, void __iomem *iobase) +{ + struct dca_provider *dca; + struct ioat_dca_priv *ioatdca; + int slots; + int i; + int err; + u32 tag_map; + u16 dca_offset; + u16 csi_fsb_control; + u16 pcie_control; + u8 bit; + + if (!system_has_dca_enabled(pdev)) + return NULL; + + dca_offset = readw(iobase + IOAT_DCAOFFSET_OFFSET); + if (dca_offset == 0) + return NULL; + + slots = ioat2_dca_count_dca_slots(iobase, dca_offset); + if (slots == 0) + return NULL; + + dca = alloc_dca_provider(&ioat2_dca_ops, + sizeof(*ioatdca) + + (sizeof(struct ioat_dca_slot) * slots)); + if (!dca) + return NULL; + + ioatdca = dca_priv(dca); + ioatdca->iobase = iobase; + ioatdca->dca_base = iobase + dca_offset; + ioatdca->max_requesters = slots; + + /* some bios might not know to turn these on */ + csi_fsb_control = readw(ioatdca->dca_base + IOAT_FSB_CAP_ENABLE_OFFSET); + if ((csi_fsb_control & IOAT_FSB_CAP_ENABLE_PREFETCH) == 0) { + csi_fsb_control |= IOAT_FSB_CAP_ENABLE_PREFETCH; + writew(csi_fsb_control, + ioatdca->dca_base + IOAT_FSB_CAP_ENABLE_OFFSET); + } + pcie_control = readw(ioatdca->dca_base + IOAT_PCI_CAP_ENABLE_OFFSET); + if ((pcie_control & IOAT_PCI_CAP_ENABLE_MEMWR) == 0) { + pcie_control |= IOAT_PCI_CAP_ENABLE_MEMWR; + writew(pcie_control, + ioatdca->dca_base + IOAT_PCI_CAP_ENABLE_OFFSET); + } + + + /* TODO version, compatibility and configuration checks */ + + /* copy out the APIC to DCA tag map */ + tag_map = readl(ioatdca->dca_base + IOAT_APICID_TAG_MAP_OFFSET); + for (i = 0; i < 5; i++) { + bit = (tag_map >> (4 * i)) & 0x0f; + if (bit < 8) + ioatdca->tag_map[i] = bit | DCA_TAG_MAP_VALID; + else + ioatdca->tag_map[i] = 0; + } + + err = register_dca_provider(dca, &pdev->dev); + if (err) { + free_dca_provider(dca); + return NULL; + } + + return dca; +} diff --git a/drivers/dma/ioat_dma.c b/drivers/dma/ioat_dma.c index 7e4a785..c1c2dcc 100644 --- a/drivers/dma/ioat_dma.c +++ b/drivers/dma/ioat_dma.c @@ -36,18 +36,24 @@ #include "ioatdma_registers.h" #include "ioatdma_hw.h" -#define INITIAL_IOAT_DESC_COUNT 128 - #define to_ioat_chan(chan) container_of(chan, struct ioat_dma_chan, common) #define to_ioatdma_device(dev) container_of(dev, struct ioatdma_device, common) #define to_ioat_desc(lh) container_of(lh, struct ioat_desc_sw, node) #define tx_to_ioat_desc(tx) container_of(tx, struct ioat_desc_sw, async_tx) +static int ioat_pending_level = 4; +module_param(ioat_pending_level, int, 0644); +MODULE_PARM_DESC(ioat_pending_level, + "high-water mark for pushing ioat descriptors (default: 4)"); + /* internal functions */ static void ioat_dma_start_null_desc(struct ioat_dma_chan *ioat_chan); static void ioat_dma_memcpy_cleanup(struct ioat_dma_chan *ioat_chan); + +static struct ioat_desc_sw * +ioat1_dma_get_next_descriptor(struct ioat_dma_chan *ioat_chan); static struct ioat_desc_sw * -ioat_dma_get_next_descriptor(struct ioat_dma_chan *ioat_chan); +ioat2_dma_get_next_descriptor(struct ioat_dma_chan *ioat_chan); static inline struct ioat_dma_chan *ioat_lookup_chan_by_index( struct ioatdma_device *device, @@ -130,6 +136,12 @@ static int ioat_dma_enumerate_channels(struct ioatdma_device *device) ioat_chan->device = device; ioat_chan->reg_base = device->reg_base + (0x80 * (i + 1)); ioat_chan->xfercap = xfercap; + ioat_chan->desccount = 0; + if (ioat_chan->device->version != IOAT_VER_1_2) { + writel(IOAT_DCACTRL_CMPL_WRITE_ENABLE + | IOAT_DMA_DCA_ANY_CPU, + ioat_chan->reg_base + IOAT_DCACTRL_OFFSET); + } spin_lock_init(&ioat_chan->cleanup_lock); spin_lock_init(&ioat_chan->desc_lock); INIT_LIST_HEAD(&ioat_chan->free_desc); @@ -161,13 +173,17 @@ static void ioat_set_dest(dma_addr_t addr, tx_to_ioat_desc(tx)->dst = addr; } -static dma_cookie_t ioat_tx_submit(struct dma_async_tx_descriptor *tx) +static inline void __ioat1_dma_memcpy_issue_pending( + struct ioat_dma_chan *ioat_chan); +static inline void __ioat2_dma_memcpy_issue_pending( + struct ioat_dma_chan *ioat_chan); + +static dma_cookie_t ioat1_tx_submit(struct dma_async_tx_descriptor *tx) { struct ioat_dma_chan *ioat_chan = to_ioat_chan(tx->chan); struct ioat_desc_sw *first = tx_to_ioat_desc(tx); struct ioat_desc_sw *prev, *new; struct ioat_dma_descriptor *hw; - int append = 0; dma_cookie_t cookie; LIST_HEAD(new_chain); u32 copy; @@ -209,7 +225,7 @@ static dma_cookie_t ioat_tx_submit(struct dma_async_tx_descriptor *tx) list_add_tail(&new->node, &new_chain); desc_count++; prev = new; - } while (len && (new = ioat_dma_get_next_descriptor(ioat_chan))); + } while (len && (new = ioat1_dma_get_next_descriptor(ioat_chan))); hw->ctl = IOAT_DMA_DESCRIPTOR_CTL_CP_STS; if (new->async_tx.callback) { @@ -246,20 +262,98 @@ static dma_cookie_t ioat_tx_submit(struct dma_async_tx_descriptor *tx) first->async_tx.phys; __list_splice(&new_chain, ioat_chan->used_desc.prev); + ioat_chan->dmacount += desc_count; ioat_chan->pending += desc_count; - if (ioat_chan->pending >= 4) { - append = 1; - ioat_chan->pending = 0; - } + if (ioat_chan->pending >= ioat_pending_level) + __ioat1_dma_memcpy_issue_pending(ioat_chan); spin_unlock_bh(&ioat_chan->desc_lock); - if (append) - writeb(IOAT_CHANCMD_APPEND, - ioat_chan->reg_base + IOAT_CHANCMD_OFFSET); + return cookie; +} + +static dma_cookie_t ioat2_tx_submit(struct dma_async_tx_descriptor *tx) +{ + struct ioat_dma_chan *ioat_chan = to_ioat_chan(tx->chan); + struct ioat_desc_sw *first = tx_to_ioat_desc(tx); + struct ioat_desc_sw *new; + struct ioat_dma_descriptor *hw; + dma_cookie_t cookie; + u32 copy; + size_t len; + dma_addr_t src, dst; + int orig_ack; + unsigned int desc_count = 0; + + /* src and dest and len are stored in the initial descriptor */ + len = first->len; + src = first->src; + dst = first->dst; + orig_ack = first->async_tx.ack; + new = first; + + /* ioat_chan->desc_lock is still in force in version 2 path */ + + do { + copy = min((u32) len, ioat_chan->xfercap); + + new->async_tx.ack = 1; + + hw = new->hw; + hw->size = copy; + hw->ctl = 0; + hw->src_addr = src; + hw->dst_addr = dst; + + len -= copy; + dst += copy; + src += copy; + desc_count++; + } while (len && (new = ioat2_dma_get_next_descriptor(ioat_chan))); + + hw->ctl = IOAT_DMA_DESCRIPTOR_CTL_CP_STS; + if (new->async_tx.callback) { + hw->ctl |= IOAT_DMA_DESCRIPTOR_CTL_INT_GN; + if (first != new) { + /* move callback into to last desc */ + new->async_tx.callback = first->async_tx.callback; + new->async_tx.callback_param + = first->async_tx.callback_param; + first->async_tx.callback = NULL; + first->async_tx.callback_param = NULL; + } + } + + new->tx_cnt = desc_count; + new->async_tx.ack = orig_ack; /* client is in control of this ack */ + + /* store the original values for use in later cleanup */ + if (new != first) { + new->src = first->src; + new->dst = first->dst; + new->len = first->len; + } + + /* cookie incr and addition to used_list must be atomic */ + cookie = ioat_chan->common.cookie; + cookie++; + if (cookie < 0) + cookie = 1; + ioat_chan->common.cookie = new->async_tx.cookie = cookie; + + ioat_chan->dmacount += desc_count; + ioat_chan->pending += desc_count; + if (ioat_chan->pending >= ioat_pending_level) + __ioat2_dma_memcpy_issue_pending(ioat_chan); + spin_unlock_bh(&ioat_chan->desc_lock); return cookie; } +/** + * ioat_dma_alloc_descriptor - allocate and return a sw and hw descriptor pair + * @ioat_chan: the channel supplying the memory pool for the descriptors + * @flags: allocation flags + */ static struct ioat_desc_sw *ioat_dma_alloc_descriptor( struct ioat_dma_chan *ioat_chan, gfp_t flags) @@ -284,15 +378,57 @@ static struct ioat_desc_sw *ioat_dma_alloc_descriptor( dma_async_tx_descriptor_init(&desc_sw->async_tx, &ioat_chan->common); desc_sw->async_tx.tx_set_src = ioat_set_src; desc_sw->async_tx.tx_set_dest = ioat_set_dest; - desc_sw->async_tx.tx_submit = ioat_tx_submit; + switch (ioat_chan->device->version) { + case IOAT_VER_1_2: + desc_sw->async_tx.tx_submit = ioat1_tx_submit; + break; + case IOAT_VER_2_0: + desc_sw->async_tx.tx_submit = ioat2_tx_submit; + break; + } INIT_LIST_HEAD(&desc_sw->async_tx.tx_list); + desc_sw->hw = desc; desc_sw->async_tx.phys = phys; return desc_sw; } -/* returns the actual number of allocated descriptors */ +static int ioat_initial_desc_count = 256; +module_param(ioat_initial_desc_count, int, 0644); +MODULE_PARM_DESC(ioat_initial_desc_count, + "initial descriptors per channel (default: 256)"); + +/** + * ioat2_dma_massage_chan_desc - link the descriptors into a circle + * @ioat_chan: the channel to be massaged + */ +static void ioat2_dma_massage_chan_desc(struct ioat_dma_chan *ioat_chan) +{ + struct ioat_desc_sw *desc, *_desc; + + /* setup used_desc */ + ioat_chan->used_desc.next = ioat_chan->free_desc.next; + ioat_chan->used_desc.prev = NULL; + + /* pull free_desc out of the circle so that every node is a hw + * descriptor, but leave it pointing to the list + */ + ioat_chan->free_desc.prev->next = ioat_chan->free_desc.next; + ioat_chan->free_desc.next->prev = ioat_chan->free_desc.prev; + + /* circle link the hw descriptors */ + desc = to_ioat_desc(ioat_chan->free_desc.next); + desc->hw->next = to_ioat_desc(desc->node.next)->async_tx.phys; + list_for_each_entry_safe(desc, _desc, ioat_chan->free_desc.next, node) { + desc->hw->next = to_ioat_desc(desc->node.next)->async_tx.phys; + } +} + +/** + * ioat_dma_alloc_chan_resources - returns the number of allocated descriptors + * @chan: the channel to be filled out + */ static int ioat_dma_alloc_chan_resources(struct dma_chan *chan) { struct ioat_dma_chan *ioat_chan = to_ioat_chan(chan); @@ -304,7 +440,7 @@ static int ioat_dma_alloc_chan_resources(struct dma_chan *chan) /* have we already been set up? */ if (!list_empty(&ioat_chan->free_desc)) - return INITIAL_IOAT_DESC_COUNT; + return ioat_chan->desccount; /* Setup register to interrupt and write completion status on error */ chanctrl = IOAT_CHANCTRL_ERR_INT_EN | @@ -320,7 +456,7 @@ static int ioat_dma_alloc_chan_resources(struct dma_chan *chan) } /* Allocate descriptors */ - for (i = 0; i < INITIAL_IOAT_DESC_COUNT; i++) { + for (i = 0; i < ioat_initial_desc_count; i++) { desc = ioat_dma_alloc_descriptor(ioat_chan, GFP_KERNEL); if (!desc) { dev_err(&ioat_chan->device->pdev->dev, @@ -330,7 +466,10 @@ static int ioat_dma_alloc_chan_resources(struct dma_chan *chan) list_add_tail(&desc->node, &tmp_list); } spin_lock_bh(&ioat_chan->desc_lock); + ioat_chan->desccount = i; list_splice(&tmp_list, &ioat_chan->free_desc); + if (ioat_chan->device->version != IOAT_VER_1_2) + ioat2_dma_massage_chan_desc(ioat_chan); spin_unlock_bh(&ioat_chan->desc_lock); /* allocate a completion writeback area */ @@ -347,10 +486,14 @@ static int ioat_dma_alloc_chan_resources(struct dma_chan *chan) ioat_chan->reg_base + IOAT_CHANCMP_OFFSET_HIGH); tasklet_enable(&ioat_chan->cleanup_task); - ioat_dma_start_null_desc(ioat_chan); - return i; + ioat_dma_start_null_desc(ioat_chan); /* give chain to dma device */ + return ioat_chan->desccount; } +/** + * ioat_dma_free_chan_resources - release all the descriptors + * @chan: the channel to be cleaned + */ static void ioat_dma_free_chan_resources(struct dma_chan *chan) { struct ioat_dma_chan *ioat_chan = to_ioat_chan(chan); @@ -364,22 +507,45 @@ static void ioat_dma_free_chan_resources(struct dma_chan *chan) /* Delay 100ms after reset to allow internal DMA logic to quiesce * before removing DMA descriptor resources. */ - writeb(IOAT_CHANCMD_RESET, ioat_chan->reg_base + IOAT_CHANCMD_OFFSET); + writeb(IOAT_CHANCMD_RESET, + ioat_chan->reg_base + + IOAT_CHANCMD_OFFSET(ioat_chan->device->version)); mdelay(100); spin_lock_bh(&ioat_chan->desc_lock); - list_for_each_entry_safe(desc, _desc, &ioat_chan->used_desc, node) { - in_use_descs++; - list_del(&desc->node); - pci_pool_free(ioatdma_device->dma_pool, desc->hw, - desc->async_tx.phys); - kfree(desc); - } - list_for_each_entry_safe(desc, _desc, &ioat_chan->free_desc, node) { - list_del(&desc->node); + switch (ioat_chan->device->version) { + case IOAT_VER_1_2: + list_for_each_entry_safe(desc, _desc, + &ioat_chan->used_desc, node) { + in_use_descs++; + list_del(&desc->node); + pci_pool_free(ioatdma_device->dma_pool, desc->hw, + desc->async_tx.phys); + kfree(desc); + } + list_for_each_entry_safe(desc, _desc, + &ioat_chan->free_desc, node) { + list_del(&desc->node); + pci_pool_free(ioatdma_device->dma_pool, desc->hw, + desc->async_tx.phys); + kfree(desc); + } + break; + case IOAT_VER_2_0: + list_for_each_entry_safe(desc, _desc, + ioat_chan->free_desc.next, node) { + list_del(&desc->node); + pci_pool_free(ioatdma_device->dma_pool, desc->hw, + desc->async_tx.phys); + kfree(desc); + } + desc = to_ioat_desc(ioat_chan->free_desc.next); pci_pool_free(ioatdma_device->dma_pool, desc->hw, desc->async_tx.phys); kfree(desc); + INIT_LIST_HEAD(&ioat_chan->free_desc); + INIT_LIST_HEAD(&ioat_chan->used_desc); + break; } spin_unlock_bh(&ioat_chan->desc_lock); @@ -395,6 +561,7 @@ static void ioat_dma_free_chan_resources(struct dma_chan *chan) ioat_chan->last_completion = ioat_chan->completion_addr = 0; ioat_chan->pending = 0; + ioat_chan->dmacount = 0; } /** @@ -406,7 +573,7 @@ static void ioat_dma_free_chan_resources(struct dma_chan *chan) * has run out. */ static struct ioat_desc_sw * -ioat_dma_get_next_descriptor(struct ioat_dma_chan *ioat_chan) +ioat1_dma_get_next_descriptor(struct ioat_dma_chan *ioat_chan) { struct ioat_desc_sw *new = NULL; @@ -425,7 +592,82 @@ ioat_dma_get_next_descriptor(struct ioat_dma_chan *ioat_chan) return new; } -static struct dma_async_tx_descriptor *ioat_dma_prep_memcpy( +static struct ioat_desc_sw * +ioat2_dma_get_next_descriptor(struct ioat_dma_chan *ioat_chan) +{ + struct ioat_desc_sw *new = NULL; + + /* + * used.prev points to where to start processing + * used.next points to next free descriptor + * if used.prev == NULL, there are none waiting to be processed + * if used.next == used.prev.prev, there is only one free descriptor, + * and we need to use it to as a noop descriptor before + * linking in a new set of descriptors, since the device + * has probably already read the pointer to it + */ + if (ioat_chan->used_desc.prev && + ioat_chan->used_desc.next == ioat_chan->used_desc.prev->prev) { + + struct ioat_desc_sw *desc = NULL; + struct ioat_desc_sw *noop_desc = NULL; + int i; + + /* set up the noop descriptor */ + noop_desc = to_ioat_desc(ioat_chan->used_desc.next); + noop_desc->hw->size = 0; + noop_desc->hw->ctl = IOAT_DMA_DESCRIPTOR_NUL; + noop_desc->hw->src_addr = 0; + noop_desc->hw->dst_addr = 0; + + ioat_chan->used_desc.next = ioat_chan->used_desc.next->next; + ioat_chan->pending++; + ioat_chan->dmacount++; + + /* get a few more descriptors */ + for (i = 16; i; i--) { + desc = ioat_dma_alloc_descriptor(ioat_chan, GFP_ATOMIC); + BUG_ON(!desc); + list_add_tail(&desc->node, ioat_chan->used_desc.next); + + desc->hw->next + = to_ioat_desc(desc->node.next)->async_tx.phys; + to_ioat_desc(desc->node.prev)->hw->next + = desc->async_tx.phys; + ioat_chan->desccount++; + } + + ioat_chan->used_desc.next = noop_desc->node.next; + } + new = to_ioat_desc(ioat_chan->used_desc.next); + prefetch(new); + ioat_chan->used_desc.next = new->node.next; + + if (ioat_chan->used_desc.prev == NULL) + ioat_chan->used_desc.prev = &new->node; + + prefetch(new->hw); + return new; +} + +static struct ioat_desc_sw *ioat_dma_get_next_descriptor( + struct ioat_dma_chan *ioat_chan) +{ + if (!ioat_chan) + return NULL; + + switch (ioat_chan->device->version) { + case IOAT_VER_1_2: + return ioat1_dma_get_next_descriptor(ioat_chan); + break; + case IOAT_VER_2_0: + return ioat2_dma_get_next_descriptor(ioat_chan); + break; + } + return NULL; +} + +static struct dma_async_tx_descriptor *ioat1_dma_prep_memcpy( struct dma_chan *chan, size_t len, int int_en) @@ -441,19 +683,62 @@ static struct dma_async_tx_descriptor *ioat_dma_prep_memcpy( return new ? &new->async_tx : NULL; } +static struct dma_async_tx_descriptor *ioat2_dma_prep_memcpy( + struct dma_chan *chan, + size_t len, + int int_en) +{ + struct ioat_dma_chan *ioat_chan = to_ioat_chan(chan); + struct ioat_desc_sw *new; + + spin_lock_bh(&ioat_chan->desc_lock); + new = ioat2_dma_get_next_descriptor(ioat_chan); + new->len = len; + + /* leave ioat_chan->desc_lock set in version 2 path */ + return new ? &new->async_tx : NULL; +} + + /** * ioat_dma_memcpy_issue_pending - push potentially unrecognized appended * descriptors to hw * @chan: DMA channel handle */ -static void ioat_dma_memcpy_issue_pending(struct dma_chan *chan) +static inline void __ioat1_dma_memcpy_issue_pending( + struct ioat_dma_chan *ioat_chan) +{ + ioat_chan->pending = 0; + writeb(IOAT_CHANCMD_APPEND, ioat_chan->reg_base + IOAT1_CHANCMD_OFFSET); +} + +static void ioat1_dma_memcpy_issue_pending(struct dma_chan *chan) { struct ioat_dma_chan *ioat_chan = to_ioat_chan(chan); if (ioat_chan->pending != 0) { - ioat_chan->pending = 0; - writeb(IOAT_CHANCMD_APPEND, - ioat_chan->reg_base + IOAT_CHANCMD_OFFSET); + spin_lock_bh(&ioat_chan->desc_lock); + __ioat1_dma_memcpy_issue_pending(ioat_chan); + spin_unlock_bh(&ioat_chan->desc_lock); + } +} + +static inline void __ioat2_dma_memcpy_issue_pending( + struct ioat_dma_chan *ioat_chan) +{ + ioat_chan->pending = 0; + writew(ioat_chan->dmacount, + ioat_chan->reg_base + IOAT_CHAN_DMACOUNT_OFFSET); +} + +static void ioat2_dma_memcpy_issue_pending(struct dma_chan *chan) +{ + struct ioat_dma_chan *ioat_chan = to_ioat_chan(chan); + + if (ioat_chan->pending != 0) { + spin_lock_bh(&ioat_chan->desc_lock); + __ioat2_dma_memcpy_issue_pending(ioat_chan); + spin_unlock_bh(&ioat_chan->desc_lock); } } @@ -465,11 +750,17 @@ static void ioat_dma_cleanup_tasklet(unsigned long data) chan->reg_base + IOAT_CHANCTRL_OFFSET); } +/** + * ioat_dma_memcpy_cleanup - cleanup up finished descriptors + * @chan: ioat channel to be cleaned up + */ static void ioat_dma_memcpy_cleanup(struct ioat_dma_chan *ioat_chan) { unsigned long phys_complete; struct ioat_desc_sw *desc, *_desc; dma_cookie_t cookie = 0; + unsigned long desc_phys; + struct ioat_desc_sw *latest_desc; prefetch(ioat_chan->completion_virt); @@ -507,56 +798,115 @@ static void ioat_dma_memcpy_cleanup(struct ioat_dma_chan *ioat_chan) cookie = 0; spin_lock_bh(&ioat_chan->desc_lock); - list_for_each_entry_safe(desc, _desc, &ioat_chan->used_desc, node) { - - /* - * Incoming DMA requests may use multiple descriptors, due to - * exceeding xfercap, perhaps. If so, only the last one will - * have a cookie, and require unmapping. - */ - if (desc->async_tx.cookie) { - cookie = desc->async_tx.cookie; + switch (ioat_chan->device->version) { + case IOAT_VER_1_2: + list_for_each_entry_safe(desc, _desc, + &ioat_chan->used_desc, node) { /* - * yes we are unmapping both _page and _single alloc'd - * regions with unmap_page. Is this *really* that bad? + * Incoming DMA requests may use multiple descriptors, + * due to exceeding xfercap, perhaps. If so, only the + * last one will have a cookie, and require unmapping. */ - pci_unmap_page(ioat_chan->device->pdev, - pci_unmap_addr(desc, dst), - pci_unmap_len(desc, len), - PCI_DMA_FROMDEVICE); - pci_unmap_page(ioat_chan->device->pdev, - pci_unmap_addr(desc, src), - pci_unmap_len(desc, len), - PCI_DMA_TODEVICE); - if (desc->async_tx.callback) { - desc->async_tx.callback( - desc->async_tx.callback_param); - desc->async_tx.callback = NULL; + if (desc->async_tx.cookie) { + cookie = desc->async_tx.cookie; + + /* + * yes we are unmapping both _page and _single + * alloc'd regions with unmap_page. Is this + * *really* that bad? + */ + pci_unmap_page(ioat_chan->device->pdev, + pci_unmap_addr(desc, dst), + pci_unmap_len(desc, len), + PCI_DMA_FROMDEVICE); + pci_unmap_page(ioat_chan->device->pdev, + pci_unmap_addr(desc, src), + pci_unmap_len(desc, len), + PCI_DMA_TODEVICE); + + if (desc->async_tx.callback) { + desc->async_tx.callback(desc->async_tx.callback_param); + desc->async_tx.callback = NULL; + } } - } - if (desc->async_tx.phys != phys_complete) { - /* - * a completed entry, but not the last, so cleanup - * if the client is done with the descriptor - */ - if (desc->async_tx.ack) { - list_del(&desc->node); - list_add_tail(&desc->node, - &ioat_chan->free_desc); - } else + if (desc->async_tx.phys != phys_complete) { + /* + * a completed entry, but not the last, so clean + * up if the client is done with the descriptor + */ + if (desc->async_tx.ack) { + list_del(&desc->node); + list_add_tail(&desc->node, + &ioat_chan->free_desc); + } else + desc->async_tx.cookie = 0; + } else { + /* + * last used desc. Do not remove, so we can + * append from it, but don't look at it next + * time, either + */ desc->async_tx.cookie = 0; - } else { - /* - * last used desc. Do not remove, so we can append from - * it, but don't look at it next time, either - */ - desc->async_tx.cookie = 0; - /* TODO check status bits? */ + /* TODO check status bits? */ + break; + } + } + break; + case IOAT_VER_2_0: + /* has some other thread has already cleaned up? */ + if (ioat_chan->used_desc.prev == NULL) break; + + /* work backwards to find latest finished desc */ + desc = to_ioat_desc(ioat_chan->used_desc.next); + latest_desc = NULL; + do { + desc = to_ioat_desc(desc->node.prev); + desc_phys = (unsigned long)desc->async_tx.phys + & IOAT_CHANSTS_COMPLETED_DESCRIPTOR_ADDR; + if (desc_phys == phys_complete) { + latest_desc = desc; + break; + } + } while (&desc->node != ioat_chan->used_desc.prev); + + if (latest_desc != NULL) { + + /* work forwards to clear finished descriptors */ + for (desc = to_ioat_desc(ioat_chan->used_desc.prev); + &desc->node != latest_desc->node.next && + &desc->node != ioat_chan->used_desc.next; + desc = to_ioat_desc(desc->node.next)) { + if (desc->async_tx.cookie) { + cookie = desc->async_tx.cookie; + desc->async_tx.cookie = 0; + + pci_unmap_page(ioat_chan->device->pdev, + pci_unmap_addr(desc, dst), + pci_unmap_len(desc, len), + PCI_DMA_FROMDEVICE); + pci_unmap_page(ioat_chan->device->pdev, + pci_unmap_addr(desc, src), + pci_unmap_len(desc, len), + PCI_DMA_TODEVICE); + + if (desc->async_tx.callback) { + desc->async_tx.callback(desc->async_tx.callback_param); + desc->async_tx.callback = NULL; + } + } + } + + /* move used.prev up beyond those that are finished */ + if (&desc->node == ioat_chan->used_desc.next) + ioat_chan->used_desc.prev = NULL; + else + ioat_chan->used_desc.prev = &desc->node; } + break; } spin_unlock_bh(&ioat_chan->desc_lock); @@ -621,8 +971,6 @@ static enum dma_status ioat_dma_is_complete(struct dma_chan *chan, return dma_async_is_complete(cookie, last_complete, last_used); } -/* PCI API */ - static void ioat_dma_start_null_desc(struct ioat_dma_chan *ioat_chan) { struct ioat_desc_sw *desc; @@ -633,21 +981,34 @@ static void ioat_dma_start_null_desc(struct ioat_dma_chan *ioat_chan) desc->hw->ctl = IOAT_DMA_DESCRIPTOR_NUL | IOAT_DMA_DESCRIPTOR_CTL_INT_GN | IOAT_DMA_DESCRIPTOR_CTL_CP_STS; - desc->hw->next = 0; desc->hw->size = 0; desc->hw->src_addr = 0; desc->hw->dst_addr = 0; desc->async_tx.ack = 1; - - list_add_tail(&desc->node, &ioat_chan->used_desc); + switch (ioat_chan->device->version) { + case IOAT_VER_1_2: + desc->hw->next = 0; + list_add_tail(&desc->node, &ioat_chan->used_desc); + + writel(((u64) desc->async_tx.phys) & 0x00000000FFFFFFFF, + ioat_chan->reg_base + IOAT1_CHAINADDR_OFFSET_LOW); + writel(((u64) desc->async_tx.phys) >> 32, + ioat_chan->reg_base + IOAT1_CHAINADDR_OFFSET_HIGH); + + writeb(IOAT_CHANCMD_START, ioat_chan->reg_base + + IOAT_CHANCMD_OFFSET(ioat_chan->device->version)); + break; + case IOAT_VER_2_0: + writel(((u64) desc->async_tx.phys) & 0x00000000FFFFFFFF, + ioat_chan->reg_base + IOAT2_CHAINADDR_OFFSET_LOW); + writel(((u64) desc->async_tx.phys) >> 32, + ioat_chan->reg_base + IOAT2_CHAINADDR_OFFSET_HIGH); + + ioat_chan->dmacount++; + __ioat2_dma_memcpy_issue_pending(ioat_chan); + break; + } spin_unlock_bh(&ioat_chan->desc_lock); - - writel(((u64) desc->async_tx.phys) & 0x00000000FFFFFFFF, - ioat_chan->reg_base + IOAT_CHAINADDR_OFFSET_LOW); - writel(((u64) desc->async_tx.phys) >> 32, - ioat_chan->reg_base + IOAT_CHAINADDR_OFFSET_HIGH); - - writeb(IOAT_CHANCMD_START, ioat_chan->reg_base + IOAT_CHANCMD_OFFSET); } /* @@ -693,14 +1054,14 @@ static int ioat_dma_self_test(struct ioatdma_device *device) dma_chan = container_of(device->common.channels.next, struct dma_chan, device_node); - if (ioat_dma_alloc_chan_resources(dma_chan) < 1) { + if (device->common.device_alloc_chan_resources(dma_chan) < 1) { dev_err(&device->pdev->dev, "selftest cannot allocate chan resource\n"); err = -ENODEV; goto out; } - tx = ioat_dma_prep_memcpy(dma_chan, IOAT_TEST_SIZE, 0); + tx = device->common.device_prep_dma_memcpy(dma_chan, IOAT_TEST_SIZE, 0); if (!tx) { dev_err(&device->pdev->dev, "Self-test prep failed, disabling\n"); @@ -710,24 +1071,25 @@ static int ioat_dma_self_test(struct ioatdma_device *device) async_tx_ack(tx); addr = dma_map_single(dma_chan->device->dev, src, IOAT_TEST_SIZE, - DMA_TO_DEVICE); - ioat_set_src(addr, tx, 0); + DMA_TO_DEVICE); + tx->tx_set_src(addr, tx, 0); addr = dma_map_single(dma_chan->device->dev, dest, IOAT_TEST_SIZE, - DMA_FROM_DEVICE); - ioat_set_dest(addr, tx, 0); + DMA_FROM_DEVICE); + tx->tx_set_dest(addr, tx, 0); tx->callback = ioat_dma_test_callback; tx->callback_param = (void *)0x8086; - cookie = ioat_tx_submit(tx); + cookie = tx->tx_submit(tx); if (cookie < 0) { dev_err(&device->pdev->dev, "Self-test setup failed, disabling\n"); err = -ENODEV; goto free_resources; } - ioat_dma_memcpy_issue_pending(dma_chan); + device->common.device_issue_pending(dma_chan); msleep(1); - if (ioat_dma_is_complete(dma_chan, cookie, NULL, NULL) != DMA_SUCCESS) { + if (device->common.device_is_tx_complete(dma_chan, cookie, NULL, NULL) + != DMA_SUCCESS) { dev_err(&device->pdev->dev, "Self-test copy timed out, disabling\n"); err = -ENODEV; @@ -741,7 +1103,7 @@ static int ioat_dma_self_test(struct ioatdma_device *device) } free_resources: - ioat_dma_free_chan_resources(dma_chan); + device->common.device_free_chan_resources(dma_chan); out: kfree(src); kfree(dest); @@ -941,16 +1303,28 @@ struct ioatdma_device *ioat_dma_probe(struct pci_dev *pdev, INIT_LIST_HEAD(&device->common.channels); ioat_dma_enumerate_channels(device); - dma_cap_set(DMA_MEMCPY, device->common.cap_mask); device->common.device_alloc_chan_resources = ioat_dma_alloc_chan_resources; device->common.device_free_chan_resources = ioat_dma_free_chan_resources; - device->common.device_prep_dma_memcpy = ioat_dma_prep_memcpy; + device->common.dev = &pdev->dev; + + dma_cap_set(DMA_MEMCPY, device->common.cap_mask); device->common.device_is_tx_complete = ioat_dma_is_complete; - device->common.device_issue_pending = ioat_dma_memcpy_issue_pending; device->common.device_dependency_added = ioat_dma_dependency_added; - device->common.dev = &pdev->dev; + switch (device->version) { + case IOAT_VER_1_2: + device->common.device_prep_dma_memcpy = ioat1_dma_prep_memcpy; + device->common.device_issue_pending = + ioat1_dma_memcpy_issue_pending; + break; + case IOAT_VER_2_0: + device->common.device_prep_dma_memcpy = ioat2_dma_prep_memcpy; + device->common.device_issue_pending = + ioat2_dma_memcpy_issue_pending; + break; + } + dev_err(&device->pdev->dev, "Intel(R) I/OAT DMA Engine found," " %d channels, device version 0x%02x, driver version %s\n", diff --git a/drivers/dma/ioatdma.h b/drivers/dma/ioatdma.h index 5f9881e7..b668234 100644 --- a/drivers/dma/ioatdma.h +++ b/drivers/dma/ioatdma.h @@ -1,5 +1,5 @@ /* - * Copyright(c) 2004 - 2006 Intel Corporation. All rights reserved. + * Copyright(c) 2004 - 2007 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free @@ -28,7 +28,7 @@ #include <linux/cache.h> #include <linux/pci_ids.h> -#define IOAT_DMA_VERSION "1.26" +#define IOAT_DMA_VERSION "2.04" enum ioat_interrupt { none = 0, @@ -39,6 +39,8 @@ enum ioat_interrupt { }; #define IOAT_LOW_COMPLETION_MASK 0xffffffc0 +#define IOAT_DMA_DCA_ANY_CPU ~0 + /** * struct ioatdma_device - internal representation of a IOAT device @@ -47,6 +49,9 @@ enum ioat_interrupt { * @dma_pool: for allocating DMA descriptors * @common: embedded struct dma_device * @version: version of ioatdma device + * @irq_mode: which style irq to use + * @msix_entries: irq handlers + * @idx: per channel data */ struct ioatdma_device { @@ -63,23 +68,7 @@ struct ioatdma_device { /** * struct ioat_dma_chan - internal representation of a DMA channel - * @device: - * @reg_base: - * @sw_in_use: - * @completion: - * @completion_low: - * @completion_high: - * @completed_cookie: last cookie seen completed on cleanup - * @cookie: value of last cookie given to client - * @last_completion: - * @xfercap: - * @desc_lock: - * @free_desc: - * @used_desc: - * @resource: - * @device_node: */ - struct ioat_dma_chan { void __iomem *reg_base; @@ -95,6 +84,8 @@ struct ioat_dma_chan { struct list_head used_desc; int pending; + int dmacount; + int desccount; struct ioatdma_device *device; struct dma_chan common; @@ -134,12 +125,13 @@ struct ioat_desc_sw { struct ioatdma_device *ioat_dma_probe(struct pci_dev *pdev, void __iomem *iobase); void ioat_dma_remove(struct ioatdma_device *device); -struct dca_provider *ioat_dca_init(struct pci_dev *pdev, - void __iomem *iobase); +struct dca_provider *ioat_dca_init(struct pci_dev *pdev, void __iomem *iobase); +struct dca_provider *ioat2_dca_init(struct pci_dev *pdev, void __iomem *iobase); #else #define ioat_dma_probe(pdev, iobase) NULL #define ioat_dma_remove(device) do { } while (0) #define ioat_dca_init(pdev, iobase) NULL +#define ioat2_dca_init(pdev, iobase) NULL #endif #endif /* IOATDMA_H */ diff --git a/drivers/dma/ioatdma_hw.h b/drivers/dma/ioatdma_hw.h index 9e7434e..dd470fa 100644 --- a/drivers/dma/ioatdma_hw.h +++ b/drivers/dma/ioatdma_hw.h @@ -1,5 +1,5 @@ /* - * Copyright(c) 2004 - 2006 Intel Corporation. All rights reserved. + * Copyright(c) 2004 - 2007 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free @@ -22,12 +22,19 @@ #define _IOAT_HW_H_ /* PCI Configuration Space Values */ -#define IOAT_PCI_VID 0x8086 -#define IOAT_PCI_DID 0x1A38 -#define IOAT_PCI_RID 0x00 -#define IOAT_PCI_SVID 0x8086 -#define IOAT_PCI_SID 0x8086 -#define IOAT_VER_1_2 0x12 /* Version 1.2 */ +#define IOAT_PCI_VID 0x8086 + +/* CB device ID's */ +#define IOAT_PCI_DID_5000 0x1A38 +#define IOAT_PCI_DID_CNB 0x360B +#define IOAT_PCI_DID_SCNB 0x65FF +#define IOAT_PCI_DID_SNB 0x402F + +#define IOAT_PCI_RID 0x00 +#define IOAT_PCI_SVID 0x8086 +#define IOAT_PCI_SID 0x8086 +#define IOAT_VER_1_2 0x12 /* Version 1.2 */ +#define IOAT_VER_2_0 0x20 /* Version 2.0 */ struct ioat_dma_descriptor { uint32_t size; @@ -47,6 +54,16 @@ struct ioat_dma_descriptor { #define IOAT_DMA_DESCRIPTOR_CTL_CP_STS 0x00000008 #define IOAT_DMA_DESCRIPTOR_CTL_FRAME 0x00000010 #define IOAT_DMA_DESCRIPTOR_NUL 0x00000020 -#define IOAT_DMA_DESCRIPTOR_OPCODE 0xFF000000 +#define IOAT_DMA_DESCRIPTOR_CTL_SP_BRK 0x00000040 +#define IOAT_DMA_DESCRIPTOR_CTL_DP_BRK 0x00000080 +#define IOAT_DMA_DESCRIPTOR_CTL_BNDL 0x00000100 +#define IOAT_DMA_DESCRIPTOR_CTL_DCA 0x00000200 +#define IOAT_DMA_DESCRIPTOR_CTL_BUFHINT 0x00000400 + +#define IOAT_DMA_DESCRIPTOR_CTL_OPCODE_CONTEXT 0xFF000000 +#define IOAT_DMA_DESCRIPTOR_CTL_OPCODE_DMA 0x00000000 + +#define IOAT_DMA_DESCRIPTOR_CTL_CONTEXT_DCA 0x00000001 +#define IOAT_DMA_DESCRIPTOR_CTL_OPCODE_MASK 0xFF000000 #endif diff --git a/drivers/dma/ioatdma_registers.h b/drivers/dma/ioatdma_registers.h index baaab5e..9832d7e 100644 --- a/drivers/dma/ioatdma_registers.h +++ b/drivers/dma/ioatdma_registers.h @@ -42,26 +42,25 @@ #define IOAT_INTRCTRL_MASTER_INT_EN 0x01 /* Master Interrupt Enable */ #define IOAT_INTRCTRL_INT_STATUS 0x02 /* ATTNSTATUS -or- Channel Int */ #define IOAT_INTRCTRL_INT 0x04 /* INT_STATUS -and- MASTER_INT_EN */ -#define IOAT_INTRCTRL_MSIX_VECTOR_CONTROL 0x08 /* Enable all MSI-X vectors */ +#define IOAT_INTRCTRL_MSIX_VECTOR_CONTROL 0x08 /* Enable all MSI-X vectors */ #define IOAT_ATTNSTATUS_OFFSET 0x04 /* Each bit is a channel */ #define IOAT_VER_OFFSET 0x08 /* 8-bit */ #define IOAT_VER_MAJOR_MASK 0xF0 #define IOAT_VER_MINOR_MASK 0x0F -#define GET_IOAT_VER_MAJOR(x) ((x) & IOAT_VER_MAJOR_MASK) +#define GET_IOAT_VER_MAJOR(x) (((x) & IOAT_VER_MAJOR_MASK) >> 4) #define GET_IOAT_VER_MINOR(x) ((x) & IOAT_VER_MINOR_MASK) #define IOAT_PERPORTOFFSET_OFFSET 0x0A /* 16-bit */ #define IOAT_INTRDELAY_OFFSET 0x0C /* 16-bit */ #define IOAT_INTRDELAY_INT_DELAY_MASK 0x3FFF /* Interrupt Delay Time */ -#define IOAT_INTRDELAY_COALESE_SUPPORT 0x8000 /* Interrupt Coalesing Supported */ +#define IOAT_INTRDELAY_COALESE_SUPPORT 0x8000 /* Interrupt Coalescing Supported */ #define IOAT_DEVICE_STATUS_OFFSET 0x0E /* 16-bit */ #define IOAT_DEVICE_STATUS_DEGRADED_MODE 0x0001 - #define IOAT_CHANNEL_MMIO_SIZE 0x80 /* Each Channel MMIO space is this size */ /* DMA Channel Registers */ @@ -74,25 +73,101 @@ #define IOAT_CHANCTRL_ERR_COMPLETION_EN 0x0004 #define IOAT_CHANCTRL_INT_DISABLE 0x0001 -#define IOAT_DMA_COMP_OFFSET 0x02 /* 16-bit DMA channel compatability */ -#define IOAT_DMA_COMP_V1 0x0001 /* Compatability with DMA version 1 */ - -#define IOAT_CHANSTS_OFFSET 0x04 /* 64-bit Channel Status Register */ -#define IOAT_CHANSTS_OFFSET_LOW 0x04 -#define IOAT_CHANSTS_OFFSET_HIGH 0x08 -#define IOAT_CHANSTS_COMPLETED_DESCRIPTOR_ADDR 0xFFFFFFFFFFFFFFC0UL +#define IOAT_DMA_COMP_OFFSET 0x02 /* 16-bit DMA channel compatibility */ +#define IOAT_DMA_COMP_V1 0x0001 /* Compatibility with DMA version 1 */ +#define IOAT_DMA_COMP_V2 0x0002 /* Compatibility with DMA version 2 */ + + +#define IOAT1_CHANSTS_OFFSET 0x04 /* 64-bit Channel Status Register */ +#define IOAT2_CHANSTS_OFFSET 0x08 /* 64-bit Channel Status Register */ +#define IOAT_CHANSTS_OFFSET(ver) ((ver) < IOAT_VER_2_0 \ + ? IOAT1_CHANSTS_OFFSET : IOAT2_CHANSTS_OFFSET) +#define IOAT1_CHANSTS_OFFSET_LOW 0x04 +#define IOAT2_CHANSTS_OFFSET_LOW 0x08 +#define IOAT_CHANSTS_OFFSET_LOW(ver) ((ver) < IOAT_VER_2_0 \ + ? IOAT1_CHANSTS_OFFSET_LOW : IOAT2_CHANSTS_OFFSET_LOW) +#define IOAT1_CHANSTS_OFFSET_HIGH 0x08 +#define IOAT2_CHANSTS_OFFSET_HIGH 0x0C +#define IOAT_CHANSTS_OFFSET_HIGH(ver) ((ver) < IOAT_VER_2_0 \ + ? IOAT1_CHANSTS_OFFSET_HIGH : IOAT2_CHANSTS_OFFSET_HIGH) +#define IOAT_CHANSTS_COMPLETED_DESCRIPTOR_ADDR ~0x3F #define IOAT_CHANSTS_SOFT_ERR 0x0000000000000010 +#define IOAT_CHANSTS_UNAFFILIATED_ERR 0x0000000000000008 #define IOAT_CHANSTS_DMA_TRANSFER_STATUS 0x0000000000000007 #define IOAT_CHANSTS_DMA_TRANSFER_STATUS_ACTIVE 0x0 #define IOAT_CHANSTS_DMA_TRANSFER_STATUS_DONE 0x1 #define IOAT_CHANSTS_DMA_TRANSFER_STATUS_SUSPENDED 0x2 #define IOAT_CHANSTS_DMA_TRANSFER_STATUS_HALTED 0x3 -#define IOAT_CHAINADDR_OFFSET 0x0C /* 64-bit Descriptor Chain Address Register */ -#define IOAT_CHAINADDR_OFFSET_LOW 0x0C -#define IOAT_CHAINADDR_OFFSET_HIGH 0x10 -#define IOAT_CHANCMD_OFFSET 0x14 /* 8-bit DMA Channel Command Register */ + +#define IOAT_CHAN_DMACOUNT_OFFSET 0x06 /* 16-bit DMA Count register */ + +#define IOAT_DCACTRL_OFFSET 0x30 /* 32 bit Direct Cache Access Control Register */ +#define IOAT_DCACTRL_CMPL_WRITE_ENABLE 0x10000 +#define IOAT_DCACTRL_TARGET_CPU_MASK 0xFFFF /* APIC ID */ + +/* CB DCA Memory Space Registers */ +#define IOAT_DCAOFFSET_OFFSET 0x14 +/* CB_BAR + IOAT_DCAOFFSET value */ +#define IOAT_DCA_VER_OFFSET 0x00 +#define IOAT_DCA_VER_MAJOR_MASK 0xF0 +#define IOAT_DCA_VER_MINOR_MASK 0x0F + +#define IOAT_DCA_COMP_OFFSET 0x02 +#define IOAT_DCA_COMP_V1 0x1 + +#define IOAT_FSB_CAPABILITY_OFFSET 0x04 +#define IOAT_FSB_CAPABILITY_PREFETCH 0x1 + +#define IOAT_PCI_CAPABILITY_OFFSET 0x06 +#define IOAT_PCI_CAPABILITY_MEMWR 0x1 + +#define IOAT_FSB_CAP_ENABLE_OFFSET 0x08 +#define IOAT_FSB_CAP_ENABLE_PREFETCH 0x1 + +#define IOAT_PCI_CAP_ENABLE_OFFSET 0x0A +#define IOAT_PCI_CAP_ENABLE_MEMWR 0x1 + +#define IOAT_APICID_TAG_MAP_OFFSET 0x0C +#define IOAT_APICID_TAG_MAP_TAG0 0x0000000F +#define IOAT_APICID_TAG_MAP_TAG0_SHIFT 0 +#define IOAT_APICID_TAG_MAP_TAG1 0x000000F0 +#define IOAT_APICID_TAG_MAP_TAG1_SHIFT 4 +#define IOAT_APICID_TAG_MAP_TAG2 0x00000F00 +#define IOAT_APICID_TAG_MAP_TAG2_SHIFT 8 +#define IOAT_APICID_TAG_MAP_TAG3 0x0000F000 +#define IOAT_APICID_TAG_MAP_TAG3_SHIFT 12 +#define IOAT_APICID_TAG_MAP_TAG4 0x000F0000 +#define IOAT_APICID_TAG_MAP_TAG4_SHIFT 16 +#define IOAT_APICID_TAG_CB2_VALID 0x8080808080 + +#define IOAT_DCA_GREQID_OFFSET 0x10 +#define IOAT_DCA_GREQID_SIZE 0x04 +#define IOAT_DCA_GREQID_MASK 0xFFFF +#define IOAT_DCA_GREQID_IGNOREFUN 0x10000000 +#define IOAT_DCA_GREQID_VALID 0x20000000 +#define IOAT_DCA_GREQID_LASTID 0x80000000 + + + +#define IOAT1_CHAINADDR_OFFSET 0x0C /* 64-bit Descriptor Chain Address Register */ +#define IOAT2_CHAINADDR_OFFSET 0x10 /* 64-bit Descriptor Chain Address Register */ +#define IOAT_CHAINADDR_OFFSET(ver) ((ver) < IOAT_VER_2_0 \ + ? IOAT1_CHAINADDR_OFFSET : IOAT2_CHAINADDR_OFFSET) +#define IOAT1_CHAINADDR_OFFSET_LOW 0x0C +#define IOAT2_CHAINADDR_OFFSET_LOW 0x10 +#define IOAT_CHAINADDR_OFFSET_LOW(ver) ((ver) < IOAT_VER_2_0 \ + ? IOAT1_CHAINADDR_OFFSET_LOW : IOAT2_CHAINADDR_OFFSET_LOW) +#define IOAT1_CHAINADDR_OFFSET_HIGH 0x10 +#define IOAT2_CHAINADDR_OFFSET_HIGH 0x14 +#define IOAT_CHAINADDR_OFFSET_HIGH(ver) ((ver) < IOAT_VER_2_0 \ + ? IOAT1_CHAINADDR_OFFSET_HIGH : IOAT2_CHAINADDR_OFFSET_HIGH) + +#define IOAT1_CHANCMD_OFFSET 0x14 /* 8-bit DMA Channel Command Register */ +#define IOAT2_CHANCMD_OFFSET 0x04 /* 8-bit DMA Channel Command Register */ +#define IOAT_CHANCMD_OFFSET(ver) ((ver) < IOAT_VER_2_0 \ + ? IOAT1_CHANCMD_OFFSET : IOAT2_CHANCMD_OFFSET) #define IOAT_CHANCMD_RESET 0x20 #define IOAT_CHANCMD_RESUME 0x10 #define IOAT_CHANCMD_ABORT 0x08 @@ -124,6 +199,7 @@ #define IOAT_CHANERR_COMPLETION_ADDR_ERR 0x1000 #define IOAT_CHANERR_INT_CONFIGURATION_ERR 0x2000 #define IOAT_CHANERR_SOFT_ERR 0x4000 +#define IOAT_CHANERR_UNAFFILIATED_ERR 0x8000 #define IOAT_CHANERR_MASK_OFFSET 0x2C /* 32-bit Channel Error Register */ diff --git a/drivers/edac/i5000_edac.c b/drivers/edac/i5000_edac.c index 96f7e63..a1f24c4 100644 --- a/drivers/edac/i5000_edac.c +++ b/drivers/edac/i5000_edac.c @@ -1462,7 +1462,7 @@ MODULE_DEVICE_TABLE(pci, i5000_pci_tbl); * */ static struct pci_driver i5000_driver = { - .name = __stringify(KBUILD_BASENAME), + .name = KBUILD_BASENAME, .probe = i5000_init_one, .remove = __devexit_p(i5000_remove_one), .id_table = i5000_pci_tbl, diff --git a/drivers/firewire/fw-sbp2.c b/drivers/firewire/fw-sbp2.c index 5596df6..624ff3e 100644 --- a/drivers/firewire/fw-sbp2.c +++ b/drivers/firewire/fw-sbp2.c @@ -650,13 +650,14 @@ static void sbp2_login(struct work_struct *work) if (sbp2_send_management_orb(lu, node_id, generation, SBP2_LOGIN_REQUEST, lu->lun, &response) < 0) { if (lu->retries++ < 5) { - queue_delayed_work(sbp2_wq, &lu->work, - DIV_ROUND_UP(HZ, 5)); + if (queue_delayed_work(sbp2_wq, &lu->work, + DIV_ROUND_UP(HZ, 5))) + kref_get(&lu->tgt->kref); } else { fw_error("failed to login to %s LUN %04x\n", unit->device.bus_id, lu->lun); - kref_put(&lu->tgt->kref, sbp2_release_target); } + kref_put(&lu->tgt->kref, sbp2_release_target); return; } @@ -914,7 +915,9 @@ static void sbp2_reconnect(struct work_struct *work) lu->retries = 0; PREPARE_DELAYED_WORK(&lu->work, sbp2_login); } - queue_delayed_work(sbp2_wq, &lu->work, DIV_ROUND_UP(HZ, 5)); + if (queue_delayed_work(sbp2_wq, &lu->work, DIV_ROUND_UP(HZ, 5))) + kref_get(&lu->tgt->kref); + kref_put(&lu->tgt->kref, sbp2_release_target); return; } diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig index 700a165..a0445be 100644 --- a/drivers/hwmon/Kconfig +++ b/drivers/hwmon/Kconfig @@ -216,6 +216,16 @@ config SENSORS_DS1621 This driver can also be built as a module. If so, the module will be called ds1621. +config SENSORS_I5K_AMB + tristate "FB-DIMM AMB temperature sensor on Intel 5000 series chipsets" + depends on PCI && EXPERIMENTAL + help + If you say yes here you get support for FB-DIMM AMB temperature + monitoring chips on systems with the Intel 5000 series chipset. + + This driver can also be built as a module. If so, the module + will be called i5k_amb. + config SENSORS_F71805F tristate "Fintek F71805F/FG, F71806F/FG and F71872F/FG" depends on EXPERIMENTAL diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile index 6da3eef..55595f6 100644 --- a/drivers/hwmon/Makefile +++ b/drivers/hwmon/Makefile @@ -38,6 +38,7 @@ obj-$(CONFIG_SENSORS_FSCPOS) += fscpos.o obj-$(CONFIG_SENSORS_GL518SM) += gl518sm.o obj-$(CONFIG_SENSORS_GL520SM) += gl520sm.o obj-$(CONFIG_SENSORS_HDAPS) += hdaps.o +obj-$(CONFIG_SENSORS_I5K_AMB) += i5k_amb.o obj-$(CONFIG_SENSORS_IBMPEX) += ibmpex.o obj-$(CONFIG_SENSORS_IT87) += it87.o obj-$(CONFIG_SENSORS_K8TEMP) += k8temp.o diff --git a/drivers/hwmon/abituguru3.c b/drivers/hwmon/abituguru3.c index cb2331b..d9f04ce 100644 --- a/drivers/hwmon/abituguru3.c +++ b/drivers/hwmon/abituguru3.c @@ -503,7 +503,7 @@ static const struct abituguru3_motherboard_info abituguru3_motherboards[] = { { "AUX3 FAN", 36, 2, 60, 1, 0 }, { NULL, 0, 0, 0, 0, 0 } } }, - { 0x001A, "unknown", { + { 0x001A, "Abit IP35 Pro", { { "CPU Core", 0, 0, 10, 1, 0 }, { "DDR2", 1, 0, 20, 1, 0 }, { "DDR2 VTT", 2, 0, 10, 1, 0 }, @@ -530,6 +530,60 @@ static const struct abituguru3_motherboard_info abituguru3_motherboards[] = { { "AUX3 Fan", 36, 2, 60, 1, 0 }, { NULL, 0, 0, 0, 0, 0 } } }, + { 0x001B, "unknown", { + { "CPU Core", 0, 0, 10, 1, 0 }, + { "DDR3", 1, 0, 20, 1, 0 }, + { "DDR3 VTT", 2, 0, 10, 1, 0 }, + { "CPU VTT", 3, 0, 10, 1, 0 }, + { "MCH 1.25V", 4, 0, 10, 1, 0 }, + { "ICHIO 1.5V", 5, 0, 10, 1, 0 }, + { "ICH 1.05V", 6, 0, 10, 1, 0 }, + { "ATX +12V (24-Pin)", 7, 0, 60, 1, 0 }, + { "ATX +12V (8-pin)", 8, 0, 60, 1, 0 }, + { "ATX +5V", 9, 0, 30, 1, 0 }, + { "+3.3V", 10, 0, 20, 1, 0 }, + { "5VSB", 11, 0, 30, 1, 0 }, + { "CPU", 24, 1, 1, 1, 0 }, + { "System", 25, 1, 1, 1, 0 }, + { "PWM Phase1", 26, 1, 1, 1, 0 }, + { "PWM Phase2", 27, 1, 1, 1, 0 }, + { "PWM Phase3", 28, 1, 1, 1, 0 }, + { "PWM Phase4", 29, 1, 1, 1, 0 }, + { "PWM Phase5", 30, 1, 1, 1, 0 }, + { "CPU Fan", 32, 2, 60, 1, 0 }, + { "SYS Fan", 34, 2, 60, 1, 0 }, + { "AUX1 Fan", 33, 2, 60, 1, 0 }, + { "AUX2 Fan", 35, 2, 60, 1, 0 }, + { "AUX3 Fan", 36, 2, 60, 1, 0 }, + { NULL, 0, 0, 0, 0, 0 } } + }, + { 0x001C, "unknown", { + { "CPU Core", 0, 0, 10, 1, 0 }, + { "DDR2", 1, 0, 20, 1, 0 }, + { "DDR2 VTT", 2, 0, 10, 1, 0 }, + { "CPU VTT", 3, 0, 10, 1, 0 }, + { "MCH 1.25V", 4, 0, 10, 1, 0 }, + { "ICHIO 1.5V", 5, 0, 10, 1, 0 }, + { "ICH 1.05V", 6, 0, 10, 1, 0 }, + { "ATX +12V (24-Pin)", 7, 0, 60, 1, 0 }, + { "ATX +12V (8-pin)", 8, 0, 60, 1, 0 }, + { "ATX +5V", 9, 0, 30, 1, 0 }, + { "+3.3V", 10, 0, 20, 1, 0 }, + { "5VSB", 11, 0, 30, 1, 0 }, + { "CPU", 24, 1, 1, 1, 0 }, + { "System", 25, 1, 1, 1, 0 }, + { "PWM Phase1", 26, 1, 1, 1, 0 }, + { "PWM Phase2", 27, 1, 1, 1, 0 }, + { "PWM Phase3", 28, 1, 1, 1, 0 }, + { "PWM Phase4", 29, 1, 1, 1, 0 }, + { "PWM Phase5", 30, 1, 1, 1, 0 }, + { "CPU Fan", 32, 2, 60, 1, 0 }, + { "SYS Fan", 34, 2, 60, 1, 0 }, + { "AUX1 Fan", 33, 2, 60, 1, 0 }, + { "AUX2 Fan", 35, 2, 60, 1, 0 }, + { "AUX3 Fan", 36, 2, 60, 1, 0 }, + { NULL, 0, 0, 0, 0, 0 } } + }, { 0x0000, NULL, { { NULL, 0, 0, 0, 0, 0 } } } }; diff --git a/drivers/hwmon/applesmc.c b/drivers/hwmon/applesmc.c index 1001d2e..86c66c3 100644 --- a/drivers/hwmon/applesmc.c +++ b/drivers/hwmon/applesmc.c @@ -80,7 +80,7 @@ /* * Temperature sensors keys (sp78 - 2 bytes). */ -static const char* temperature_sensors_sets[][13] = { +static const char* temperature_sensors_sets[][36] = { /* Set 0: Macbook Pro */ { "TA0P", "TB0T", "TC0D", "TC0P", "TG0H", "TG0P", "TG0T", "Th0H", "Th1H", "Tm0P", "Ts0P", "Ts1P", NULL }, @@ -88,7 +88,13 @@ static const char* temperature_sensors_sets[][13] = { { "TB0T", "TC0D", "TC0P", "TM0P", "TN0P", "TN1P", "Th0H", "Th0S", "Th1H", "Ts0P", NULL }, /* Set 2: Macmini set */ - { "TC0D", "TC0P", NULL } + { "TC0D", "TC0P", NULL }, +/* Set 3: Mac Pro (2 x Quad-Core) */ + { "TA0P", "TCAG", "TCAH", "TCBG", "TCBH", "TC0C", "TC0D", "TC0P", + "TC1C", "TC1D", "TC2C", "TC2D", "TC3C", "TC3D", "THTG", "TH0P", + "TH1P", "TH2P", "TH3P", "TMAP", "TMAS", "TMBS", "TM0P", "TM0S", + "TM1P", "TM1S", "TM2P", "TM2S", "TM3S", "TM8P", "TM8S", "TM9P", + "TM9S", "TN0H", "TS0C", NULL }, }; /* List of keys used to read/write fan speeds */ @@ -990,14 +996,18 @@ static struct attribute *fan##offset##_attributes[] = { \ /* * Create the needed functions for each fan using the macro defined above - * (2 fans are supported) + * (4 fans are supported) */ sysfs_fan_speeds_offset(1); sysfs_fan_speeds_offset(2); +sysfs_fan_speeds_offset(3); +sysfs_fan_speeds_offset(4); static const struct attribute_group fan_attribute_groups[] = { { .attrs = fan1_attributes }, - { .attrs = fan2_attributes } + { .attrs = fan2_attributes }, + { .attrs = fan3_attributes }, + { .attrs = fan4_attributes }, }; /* @@ -1027,6 +1037,52 @@ static SENSOR_DEVICE_ATTR(temp11_input, S_IRUGO, applesmc_show_temperature, NULL, 10); static SENSOR_DEVICE_ATTR(temp12_input, S_IRUGO, applesmc_show_temperature, NULL, 11); +static SENSOR_DEVICE_ATTR(temp13_input, S_IRUGO, + applesmc_show_temperature, NULL, 12); +static SENSOR_DEVICE_ATTR(temp14_input, S_IRUGO, + applesmc_show_temperature, NULL, 13); +static SENSOR_DEVICE_ATTR(temp15_input, S_IRUGO, + applesmc_show_temperature, NULL, 14); +static SENSOR_DEVICE_ATTR(temp16_input, S_IRUGO, + applesmc_show_temperature, NULL, 15); +static SENSOR_DEVICE_ATTR(temp17_input, S_IRUGO, + applesmc_show_temperature, NULL, 16); +static SENSOR_DEVICE_ATTR(temp18_input, S_IRUGO, + applesmc_show_temperature, NULL, 17); +static SENSOR_DEVICE_ATTR(temp19_input, S_IRUGO, + applesmc_show_temperature, NULL, 18); +static SENSOR_DEVICE_ATTR(temp20_input, S_IRUGO, + applesmc_show_temperature, NULL, 19); +static SENSOR_DEVICE_ATTR(temp21_input, S_IRUGO, + applesmc_show_temperature, NULL, 20); +static SENSOR_DEVICE_ATTR(temp22_input, S_IRUGO, + applesmc_show_temperature, NULL, 21); +static SENSOR_DEVICE_ATTR(temp23_input, S_IRUGO, + applesmc_show_temperature, NULL, 22); +static SENSOR_DEVICE_ATTR(temp24_input, S_IRUGO, + applesmc_show_temperature, NULL, 23); +static SENSOR_DEVICE_ATTR(temp25_input, S_IRUGO, + applesmc_show_temperature, NULL, 24); +static SENSOR_DEVICE_ATTR(temp26_input, S_IRUGO, + applesmc_show_temperature, NULL, 25); +static SENSOR_DEVICE_ATTR(temp27_input, S_IRUGO, + applesmc_show_temperature, NULL, 26); +static SENSOR_DEVICE_ATTR(temp28_input, S_IRUGO, + applesmc_show_temperature, NULL, 27); +static SENSOR_DEVICE_ATTR(temp29_input, S_IRUGO, + applesmc_show_temperature, NULL, 28); +static SENSOR_DEVICE_ATTR(temp30_input, S_IRUGO, + applesmc_show_temperature, NULL, 29); +static SENSOR_DEVICE_ATTR(temp31_input, S_IRUGO, + applesmc_show_temperature, NULL, 30); +static SENSOR_DEVICE_ATTR(temp32_input, S_IRUGO, + applesmc_show_temperature, NULL, 31); +static SENSOR_DEVICE_ATTR(temp33_input, S_IRUGO, + applesmc_show_temperature, NULL, 32); +static SENSOR_DEVICE_ATTR(temp34_input, S_IRUGO, + applesmc_show_temperature, NULL, 33); +static SENSOR_DEVICE_ATTR(temp35_input, S_IRUGO, + applesmc_show_temperature, NULL, 34); static struct attribute *temperature_attributes[] = { &sensor_dev_attr_temp1_input.dev_attr.attr, @@ -1041,6 +1097,29 @@ static struct attribute *temperature_attributes[] = { &sensor_dev_attr_temp10_input.dev_attr.attr, &sensor_dev_attr_temp11_input.dev_attr.attr, &sensor_dev_attr_temp12_input.dev_attr.attr, + &sensor_dev_attr_temp13_input.dev_attr.attr, + &sensor_dev_attr_temp14_input.dev_attr.attr, + &sensor_dev_attr_temp15_input.dev_attr.attr, + &sensor_dev_attr_temp16_input.dev_attr.attr, + &sensor_dev_attr_temp17_input.dev_attr.attr, + &sensor_dev_attr_temp18_input.dev_attr.attr, + &sensor_dev_attr_temp19_input.dev_attr.attr, + &sensor_dev_attr_temp20_input.dev_attr.attr, + &sensor_dev_attr_temp21_input.dev_attr.attr, + &sensor_dev_attr_temp22_input.dev_attr.attr, + &sensor_dev_attr_temp23_input.dev_attr.attr, + &sensor_dev_attr_temp24_input.dev_attr.attr, + &sensor_dev_attr_temp25_input.dev_attr.attr, + &sensor_dev_attr_temp26_input.dev_attr.attr, + &sensor_dev_attr_temp27_input.dev_attr.attr, + &sensor_dev_attr_temp28_input.dev_attr.attr, + &sensor_dev_attr_temp29_input.dev_attr.attr, + &sensor_dev_attr_temp30_input.dev_attr.attr, + &sensor_dev_attr_temp31_input.dev_attr.attr, + &sensor_dev_attr_temp32_input.dev_attr.attr, + &sensor_dev_attr_temp33_input.dev_attr.attr, + &sensor_dev_attr_temp34_input.dev_attr.attr, + &sensor_dev_attr_temp35_input.dev_attr.attr, NULL }; @@ -1137,6 +1216,8 @@ static __initdata struct dmi_match_data applesmc_dmi_data[] = { { .accelerometer = 1, .light = 0, .temperature_set = 1 }, /* MacMini: temperature set 2 */ { .accelerometer = 0, .light = 0, .temperature_set = 2 }, +/* MacPro: temperature set 3 */ + { .accelerometer = 0, .light = 0, .temperature_set = 3 }, }; /* Note that DMI_MATCH(...,"MacBook") will match "MacBookPro1,1". @@ -1154,6 +1235,10 @@ static __initdata struct dmi_system_id applesmc_whitelist[] = { DMI_MATCH(DMI_BOARD_VENDOR,"Apple"), DMI_MATCH(DMI_PRODUCT_NAME,"Macmini") }, (void*)&applesmc_dmi_data[2]}, + { applesmc_dmi_match, "Apple MacPro2", { + DMI_MATCH(DMI_BOARD_VENDOR,"Apple"), + DMI_MATCH(DMI_PRODUCT_NAME,"MacPro2") }, + (void*)&applesmc_dmi_data[3]}, { .ident = NULL } }; @@ -1204,9 +1289,19 @@ static int __init applesmc_init(void) switch (count) { default: - printk(KERN_WARNING "applesmc: More than 2 fans found," - " but at most 2 fans are supported" + printk(KERN_WARNING "applesmc: More than 4 fans found," + " but at most 4 fans are supported" " by the driver.\n"); + case 4: + ret = sysfs_create_group(&pdev->dev.kobj, + &fan_attribute_groups[3]); + if (ret) + goto out_key_enumeration; + case 3: + ret = sysfs_create_group(&pdev->dev.kobj, + &fan_attribute_groups[2]); + if (ret) + goto out_key_enumeration; case 2: ret = sysfs_create_group(&pdev->dev.kobj, &fan_attribute_groups[1]); diff --git a/drivers/hwmon/f75375s.c b/drivers/hwmon/f75375s.c index 13a0413..6892f76 100644 --- a/drivers/hwmon/f75375s.c +++ b/drivers/hwmon/f75375s.c @@ -34,6 +34,7 @@ #include <linux/i2c.h> #include <linux/err.h> #include <linux/mutex.h> +#include <linux/f75375s.h> /* Addresses to scan */ static unsigned short normal_i2c[] = { 0x2d, 0x2e, I2C_CLIENT_END }; @@ -86,7 +87,7 @@ I2C_CLIENT_INSMOD_2(f75373, f75375); struct f75375_data { unsigned short addr; - struct i2c_client client; + struct i2c_client *client; struct device *hwmon_dev; const char *name; @@ -116,15 +117,25 @@ struct f75375_data { static int f75375_attach_adapter(struct i2c_adapter *adapter); static int f75375_detect(struct i2c_adapter *adapter, int address, int kind); static int f75375_detach_client(struct i2c_client *client); +static int f75375_probe(struct i2c_client *client); +static int f75375_remove(struct i2c_client *client); -static struct i2c_driver f75375_driver = { +static struct i2c_driver f75375_legacy_driver = { .driver = { - .name = "f75375", + .name = "f75375_legacy", }, .attach_adapter = f75375_attach_adapter, .detach_client = f75375_detach_client, }; +static struct i2c_driver f75375_driver = { + .driver = { + .name = "f75375", + }, + .probe = f75375_probe, + .remove = f75375_remove, +}; + static inline int f75375_read8(struct i2c_client *client, u8 reg) { return i2c_smbus_read_byte_data(client, reg); @@ -276,19 +287,14 @@ static ssize_t show_pwm_enable(struct device *dev, struct device_attribute return sprintf(buf, "%d\n", data->pwm_enable[nr]); } -static ssize_t set_pwm_enable(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) +static int set_pwm_enable_direct(struct i2c_client *client, int nr, int val) { - int nr = to_sensor_dev_attr(attr)->index; - struct i2c_client *client = to_i2c_client(dev); struct f75375_data *data = i2c_get_clientdata(client); - int val = simple_strtoul(buf, NULL, 10); u8 fanmode; if (val < 0 || val > 4) return -EINVAL; - mutex_lock(&data->update_lock); fanmode = f75375_read8(client, F75375_REG_FAN_TIMER); fanmode = ~(3 << FAN_CTRL_MODE(nr)); @@ -310,8 +316,22 @@ static ssize_t set_pwm_enable(struct device *dev, struct device_attribute *attr, } f75375_write8(client, F75375_REG_FAN_TIMER, fanmode); data->pwm_enable[nr] = val; + return 0; +} + +static ssize_t set_pwm_enable(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + int nr = to_sensor_dev_attr(attr)->index; + struct i2c_client *client = to_i2c_client(dev); + struct f75375_data *data = i2c_get_clientdata(client); + int val = simple_strtoul(buf, NULL, 10); + int err = 0; + + mutex_lock(&data->update_lock); + err = set_pwm_enable_direct(client, nr, val); mutex_unlock(&data->update_lock); - return count; + return err ? err : count; } static ssize_t set_pwm_mode(struct device *dev, struct device_attribute *attr, @@ -323,7 +343,7 @@ static ssize_t set_pwm_mode(struct device *dev, struct device_attribute *attr, int val = simple_strtoul(buf, NULL, 10); u8 conf = 0; - if (val != 0 || val != 1 || data->kind == f75373) + if (!(val == 0 || val == 1)) return -EINVAL; mutex_lock(&data->update_lock); @@ -529,13 +549,13 @@ static SENSOR_DEVICE_ATTR(pwm1, S_IRUGO|S_IWUSR, show_pwm, set_pwm, 0); static SENSOR_DEVICE_ATTR(pwm1_enable, S_IRUGO|S_IWUSR, show_pwm_enable, set_pwm_enable, 0); -static SENSOR_DEVICE_ATTR(pwm1_mode, S_IRUGO|S_IWUSR, +static SENSOR_DEVICE_ATTR(pwm1_mode, S_IRUGO, show_pwm_mode, set_pwm_mode, 0); static SENSOR_DEVICE_ATTR(pwm2, S_IRUGO | S_IWUSR, show_pwm, set_pwm, 1); static SENSOR_DEVICE_ATTR(pwm2_enable, S_IRUGO|S_IWUSR, show_pwm_enable, set_pwm_enable, 1); -static SENSOR_DEVICE_ATTR(pwm2_mode, S_IRUGO|S_IWUSR, +static SENSOR_DEVICE_ATTR(pwm2_mode, S_IRUGO, show_pwm_mode, set_pwm_mode, 1); static struct attribute *f75375_attributes[] = { @@ -580,12 +600,9 @@ static const struct attribute_group f75375_group = { static int f75375_detach_client(struct i2c_client *client) { - struct f75375_data *data = i2c_get_clientdata(client); int err; - hwmon_device_unregister(data->hwmon_dev); - sysfs_remove_group(&client->dev.kobj, &f75375_group); - + f75375_remove(client); err = i2c_detach_client(client); if (err) { dev_err(&client->dev, @@ -593,7 +610,91 @@ static int f75375_detach_client(struct i2c_client *client) "client not detached.\n"); return err; } + kfree(client); + return 0; +} + +static void f75375_init(struct i2c_client *client, struct f75375_data *data, + struct f75375s_platform_data *f75375s_pdata) +{ + int nr; + set_pwm_enable_direct(client, 0, f75375s_pdata->pwm_enable[0]); + set_pwm_enable_direct(client, 1, f75375s_pdata->pwm_enable[1]); + for (nr = 0; nr < 2; nr++) { + data->pwm[nr] = SENSORS_LIMIT(f75375s_pdata->pwm[nr], 0, 255); + f75375_write8(client, F75375_REG_FAN_PWM_DUTY(nr), + data->pwm[nr]); + } + +} + +static int f75375_probe(struct i2c_client *client) +{ + struct f75375_data *data = i2c_get_clientdata(client); + struct f75375s_platform_data *f75375s_pdata = client->dev.platform_data; + int err; + + if (!i2c_check_functionality(client->adapter, + I2C_FUNC_SMBUS_BYTE_DATA)) + return -EIO; + if (!(data = kzalloc(sizeof(struct f75375_data), GFP_KERNEL))) + return -ENOMEM; + + i2c_set_clientdata(client, data); + data->client = client; + mutex_init(&data->update_lock); + + if (strcmp(client->name, "f75375") == 0) + data->kind = f75375; + else if (strcmp(client->name, "f75373") == 0) + data->kind = f75373; + else { + dev_err(&client->dev, "Unsupported device: %s\n", client->name); + return -ENODEV; + } + + if ((err = sysfs_create_group(&client->dev.kobj, &f75375_group))) + goto exit_free; + + if (data->kind == f75375) { + err = sysfs_chmod_file(&client->dev.kobj, + &sensor_dev_attr_pwm1_mode.dev_attr.attr, + S_IRUGO | S_IWUSR); + if (err) + goto exit_remove; + err = sysfs_chmod_file(&client->dev.kobj, + &sensor_dev_attr_pwm2_mode.dev_attr.attr, + S_IRUGO | S_IWUSR); + if (err) + goto exit_remove; + } + + data->hwmon_dev = hwmon_device_register(&client->dev); + if (IS_ERR(data->hwmon_dev)) { + err = PTR_ERR(data->hwmon_dev); + goto exit_remove; + } + + if (f75375s_pdata != NULL) + f75375_init(client, data, f75375s_pdata); + + return 0; + +exit_remove: + sysfs_remove_group(&client->dev.kobj, &f75375_group); +exit_free: kfree(data); + i2c_set_clientdata(client, NULL); + return err; +} + +static int f75375_remove(struct i2c_client *client) +{ + struct f75375_data *data = i2c_get_clientdata(client); + hwmon_device_unregister(data->hwmon_dev); + sysfs_remove_group(&client->dev.kobj, &f75375_group); + kfree(data); + i2c_set_clientdata(client, NULL); return 0; } @@ -608,20 +709,17 @@ static int f75375_attach_adapter(struct i2c_adapter *adapter) static int f75375_detect(struct i2c_adapter *adapter, int address, int kind) { struct i2c_client *client; - struct f75375_data *data; u8 version = 0; int err = 0; const char *name = ""; - if (!(data = kzalloc(sizeof(struct f75375_data), GFP_KERNEL))) { + if (!(client = kzalloc(sizeof(*client), GFP_KERNEL))) { err = -ENOMEM; goto exit; } - client = &data->client; - i2c_set_clientdata(client, data); client->addr = address; client->adapter = adapter; - client->driver = &f75375_driver; + client->driver = &f75375_legacy_driver; if (kind < 0) { u16 vendid = f75375_read16(client, F75375_REG_VENDOR); @@ -644,42 +742,42 @@ static int f75375_detect(struct i2c_adapter *adapter, int address, int kind) } else if (kind == f75373) { name = "f75373"; } - dev_info(&adapter->dev, "found %s version: %02X\n", name, version); strlcpy(client->name, name, I2C_NAME_SIZE); - data->kind = kind; - mutex_init(&data->update_lock); + if ((err = i2c_attach_client(client))) goto exit_free; - if ((err = sysfs_create_group(&client->dev.kobj, &f75375_group))) + if ((err = f75375_probe(client)) < 0) goto exit_detach; - data->hwmon_dev = hwmon_device_register(&client->dev); - if (IS_ERR(data->hwmon_dev)) { - err = PTR_ERR(data->hwmon_dev); - goto exit_remove; - } - return 0; -exit_remove: - sysfs_remove_group(&client->dev.kobj, &f75375_group); exit_detach: i2c_detach_client(client); exit_free: - kfree(data); + kfree(client); exit: return err; } static int __init sensors_f75375_init(void) { - return i2c_add_driver(&f75375_driver); + int status; + status = i2c_add_driver(&f75375_driver); + if (status) + return status; + + status = i2c_add_driver(&f75375_legacy_driver); + if (status) + i2c_del_driver(&f75375_driver); + + return status; } static void __exit sensors_f75375_exit(void) { + i2c_del_driver(&f75375_legacy_driver); i2c_del_driver(&f75375_driver); } diff --git a/drivers/hwmon/i5k_amb.c b/drivers/hwmon/i5k_amb.c new file mode 100644 index 0000000..6ac5c6f --- /dev/null +++ b/drivers/hwmon/i5k_amb.c @@ -0,0 +1,552 @@ +/* + * A hwmon driver for the Intel 5000 series chipset FB-DIMM AMB + * temperature sensors + * Copyright (C) 2007 IBM + * + * Author: Darrick J. Wong <djwong@us.ibm.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include <linux/module.h> +#include <linux/jiffies.h> +#include <linux/hwmon.h> +#include <linux/hwmon-sysfs.h> +#include <linux/err.h> +#include <linux/mutex.h> +#include <linux/delay.h> +#include <linux/log2.h> +#include <linux/pci.h> +#include <linux/platform_device.h> + +#define DRVNAME "i5k_amb" + +#define I5K_REG_AMB_BASE_ADDR 0x48 +#define I5K_REG_AMB_LEN_ADDR 0x50 +#define I5K_REG_CHAN0_PRESENCE_ADDR 0x64 +#define I5K_REG_CHAN1_PRESENCE_ADDR 0x66 + +#define AMB_REG_TEMP_MIN_ADDR 0x80 +#define AMB_REG_TEMP_MID_ADDR 0x81 +#define AMB_REG_TEMP_MAX_ADDR 0x82 +#define AMB_REG_TEMP_STATUS_ADDR 0x84 +#define AMB_REG_TEMP_ADDR 0x85 + +#define AMB_CONFIG_SIZE 2048 +#define AMB_FUNC_3_OFFSET 768 + +static unsigned long amb_reg_temp_status(unsigned int amb) +{ + return AMB_FUNC_3_OFFSET + AMB_REG_TEMP_STATUS_ADDR + + AMB_CONFIG_SIZE * amb; +} + +static unsigned long amb_reg_temp_min(unsigned int amb) +{ + return AMB_FUNC_3_OFFSET + AMB_REG_TEMP_MIN_ADDR + + AMB_CONFIG_SIZE * amb; +} + +static unsigned long amb_reg_temp_mid(unsigned int amb) +{ + return AMB_FUNC_3_OFFSET + AMB_REG_TEMP_MID_ADDR + + AMB_CONFIG_SIZE * amb; +} + +static unsigned long amb_reg_temp_max(unsigned int amb) +{ + return AMB_FUNC_3_OFFSET + AMB_REG_TEMP_MAX_ADDR + + AMB_CONFIG_SIZE * amb; +} + +static unsigned long amb_reg_temp(unsigned int amb) +{ + return AMB_FUNC_3_OFFSET + AMB_REG_TEMP_ADDR + + AMB_CONFIG_SIZE * amb; +} + +#define MAX_MEM_CHANNELS 4 +#define MAX_AMBS_PER_CHANNEL 16 +#define MAX_AMBS (MAX_MEM_CHANNELS * \ + MAX_AMBS_PER_CHANNEL) +/* + * Ugly hack: For some reason the highest bit is set if there + * are _any_ DIMMs in the channel. Attempting to read from + * this "high-order" AMB results in a memory bus error, so + * for now we'll just ignore that top bit, even though that + * might prevent us from seeing the 16th DIMM in the channel. + */ +#define REAL_MAX_AMBS_PER_CHANNEL 15 +#define KNOBS_PER_AMB 5 + +static unsigned long amb_num_from_reg(unsigned int byte_num, unsigned int bit) +{ + return byte_num * MAX_AMBS_PER_CHANNEL + bit; +} + +#define AMB_SYSFS_NAME_LEN 16 +struct i5k_device_attribute { + struct sensor_device_attribute s_attr; + char name[AMB_SYSFS_NAME_LEN]; +}; + +struct i5k_amb_data { + struct device *hwmon_dev; + + unsigned long amb_base; + unsigned long amb_len; + u16 amb_present[MAX_MEM_CHANNELS]; + void __iomem *amb_mmio; + struct i5k_device_attribute *attrs; + unsigned int num_attrs; +}; + +static ssize_t show_name(struct device *dev, struct device_attribute *devattr, + char *buf) +{ + return sprintf(buf, "%s\n", DRVNAME); +} + + +static DEVICE_ATTR(name, S_IRUGO, show_name, NULL); + +static struct platform_device *amb_pdev; + +static u8 amb_read_byte(struct i5k_amb_data *data, unsigned long offset) +{ + return ioread8(data->amb_mmio + offset); +} + +static void amb_write_byte(struct i5k_amb_data *data, unsigned long offset, + u8 val) +{ + iowrite8(val, data->amb_mmio + offset); +} + +static ssize_t show_amb_alarm(struct device *dev, + struct device_attribute *devattr, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + struct i5k_amb_data *data = dev_get_drvdata(dev); + + if (!(amb_read_byte(data, amb_reg_temp_status(attr->index)) & 0x20) && + (amb_read_byte(data, amb_reg_temp_status(attr->index)) & 0x8)) + return sprintf(buf, "1\n"); + else + return sprintf(buf, "0\n"); +} + +static ssize_t store_amb_min(struct device *dev, + struct device_attribute *devattr, + const char *buf, + size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + struct i5k_amb_data *data = dev_get_drvdata(dev); + unsigned long temp = simple_strtoul(buf, NULL, 10) / 500; + + if (temp > 255) + temp = 255; + + amb_write_byte(data, amb_reg_temp_min(attr->index), temp); + return count; +} + +static ssize_t store_amb_mid(struct device *dev, + struct device_attribute *devattr, + const char *buf, + size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + struct i5k_amb_data *data = dev_get_drvdata(dev); + unsigned long temp = simple_strtoul(buf, NULL, 10) / 500; + + if (temp > 255) + temp = 255; + + amb_write_byte(data, amb_reg_temp_mid(attr->index), temp); + return count; +} + +static ssize_t store_amb_max(struct device *dev, + struct device_attribute *devattr, + const char *buf, + size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + struct i5k_amb_data *data = dev_get_drvdata(dev); + unsigned long temp = simple_strtoul(buf, NULL, 10) / 500; + + if (temp > 255) + temp = 255; + + amb_write_byte(data, amb_reg_temp_max(attr->index), temp); + return count; +} + +static ssize_t show_amb_min(struct device *dev, + struct device_attribute *devattr, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + struct i5k_amb_data *data = dev_get_drvdata(dev); + return sprintf(buf, "%d\n", + 500 * amb_read_byte(data, amb_reg_temp_min(attr->index))); +} + +static ssize_t show_amb_mid(struct device *dev, + struct device_attribute *devattr, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + struct i5k_amb_data *data = dev_get_drvdata(dev); + return sprintf(buf, "%d\n", + 500 * amb_read_byte(data, amb_reg_temp_mid(attr->index))); +} + +static ssize_t show_amb_max(struct device *dev, + struct device_attribute *devattr, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + struct i5k_amb_data *data = dev_get_drvdata(dev); + return sprintf(buf, "%d\n", + 500 * amb_read_byte(data, amb_reg_temp_max(attr->index))); +} + +static ssize_t show_amb_temp(struct device *dev, + struct device_attribute *devattr, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + struct i5k_amb_data *data = dev_get_drvdata(dev); + return sprintf(buf, "%d\n", + 500 * amb_read_byte(data, amb_reg_temp(attr->index))); +} + +static int __devinit i5k_amb_hwmon_init(struct platform_device *pdev) +{ + int i, j, k, d = 0; + u16 c; + int res = 0; + int num_ambs = 0; + struct i5k_amb_data *data = platform_get_drvdata(pdev); + + /* Count the number of AMBs found */ + /* ignore the high-order bit, see "Ugly hack" comment above */ + for (i = 0; i < MAX_MEM_CHANNELS; i++) + num_ambs += hweight16(data->amb_present[i] & 0x7fff); + + /* Set up sysfs stuff */ + data->attrs = kzalloc(sizeof(*data->attrs) * num_ambs * KNOBS_PER_AMB, + GFP_KERNEL); + if (!data->attrs) + return -ENOMEM; + data->num_attrs = 0; + + for (i = 0; i < MAX_MEM_CHANNELS; i++) { + c = data->amb_present[i]; + for (j = 0; j < REAL_MAX_AMBS_PER_CHANNEL; j++, c >>= 1) { + struct i5k_device_attribute *iattr; + + k = amb_num_from_reg(i, j); + if (!(c & 0x1)) + continue; + d++; + + /* Temperature sysfs knob */ + iattr = data->attrs + data->num_attrs; + snprintf(iattr->name, AMB_SYSFS_NAME_LEN, + "temp%d_input", d); + iattr->s_attr.dev_attr.attr.name = iattr->name; + iattr->s_attr.dev_attr.attr.mode = S_IRUGO; + iattr->s_attr.dev_attr.show = show_amb_temp; + iattr->s_attr.index = k; + res = device_create_file(&pdev->dev, + &iattr->s_attr.dev_attr); + if (res) + goto exit_remove; + data->num_attrs++; + + /* Temperature min sysfs knob */ + iattr = data->attrs + data->num_attrs; + snprintf(iattr->name, AMB_SYSFS_NAME_LEN, + "temp%d_min", d); + iattr->s_attr.dev_attr.attr.name = iattr->name; + iattr->s_attr.dev_attr.attr.mode = S_IWUSR | S_IRUGO; + iattr->s_attr.dev_attr.show = show_amb_min; + iattr->s_attr.dev_attr.store = store_amb_min; + iattr->s_attr.index = k; + res = device_create_file(&pdev->dev, + &iattr->s_attr.dev_attr); + if (res) + goto exit_remove; + data->num_attrs++; + + /* Temperature mid sysfs knob */ + iattr = data->attrs + data->num_attrs; + snprintf(iattr->name, AMB_SYSFS_NAME_LEN, + "temp%d_mid", d); + iattr->s_attr.dev_attr.attr.name = iattr->name; + iattr->s_attr.dev_attr.attr.mode = S_IWUSR | S_IRUGO; + iattr->s_attr.dev_attr.show = show_amb_mid; + iattr->s_attr.dev_attr.store = store_amb_mid; + iattr->s_attr.index = k; + res = device_create_file(&pdev->dev, + &iattr->s_attr.dev_attr); + if (res) + goto exit_remove; + data->num_attrs++; + + /* Temperature max sysfs knob */ + iattr = data->attrs + data->num_attrs; + snprintf(iattr->name, AMB_SYSFS_NAME_LEN, + "temp%d_max", d); + iattr->s_attr.dev_attr.attr.name = iattr->name; + iattr->s_attr.dev_attr.attr.mode = S_IWUSR | S_IRUGO; + iattr->s_attr.dev_attr.show = show_amb_max; + iattr->s_attr.dev_attr.store = store_amb_max; + iattr->s_attr.index = k; + res = device_create_file(&pdev->dev, + &iattr->s_attr.dev_attr); + if (res) + goto exit_remove; + data->num_attrs++; + + /* Temperature alarm sysfs knob */ + iattr = data->attrs + data->num_attrs; + snprintf(iattr->name, AMB_SYSFS_NAME_LEN, + "temp%d_alarm", d); + iattr->s_attr.dev_attr.attr.name = iattr->name; + iattr->s_attr.dev_attr.attr.mode = S_IRUGO; + iattr->s_attr.dev_attr.show = show_amb_alarm; + iattr->s_attr.index = k; + res = device_create_file(&pdev->dev, + &iattr->s_attr.dev_attr); + if (res) + goto exit_remove; + data->num_attrs++; + } + } + + res = device_create_file(&pdev->dev, &dev_attr_name); + if (res) + goto exit_remove; + + data->hwmon_dev = hwmon_device_register(&pdev->dev); + if (IS_ERR(data->hwmon_dev)) { + res = PTR_ERR(data->hwmon_dev); + goto exit_remove; + } + + return res; + +exit_remove: + device_remove_file(&pdev->dev, &dev_attr_name); + for (i = 0; i < data->num_attrs; i++) + device_remove_file(&pdev->dev, &data->attrs[i].s_attr.dev_attr); + kfree(data->attrs); + + return res; +} + +static int __devinit i5k_amb_add(void) +{ + int res = -ENODEV; + + /* only ever going to be one of these */ + amb_pdev = platform_device_alloc(DRVNAME, 0); + if (!amb_pdev) + return -ENOMEM; + + res = platform_device_add(amb_pdev); + if (res) + goto err; + return 0; + +err: + platform_device_put(amb_pdev); + return res; +} + +static int __devinit i5k_find_amb_registers(struct i5k_amb_data *data) +{ + struct pci_dev *pcidev; + u32 val32; + int res = -ENODEV; + + /* Find AMB register memory space */ + pcidev = pci_get_device(PCI_VENDOR_ID_INTEL, + PCI_DEVICE_ID_INTEL_5000_ERR, + NULL); + if (!pcidev) + return -ENODEV; + + if (pci_read_config_dword(pcidev, I5K_REG_AMB_BASE_ADDR, &val32)) + goto out; + data->amb_base = val32; + + if (pci_read_config_dword(pcidev, I5K_REG_AMB_LEN_ADDR, &val32)) + goto out; + data->amb_len = val32; + + /* Is it big enough? */ + if (data->amb_len < AMB_CONFIG_SIZE * MAX_AMBS) { + dev_err(&pcidev->dev, "AMB region too small!\n"); + goto out; + } + + res = 0; +out: + pci_dev_put(pcidev); + return res; +} + +static int __devinit i5k_channel_probe(u16 *amb_present, unsigned long dev_id) +{ + struct pci_dev *pcidev; + u16 val16; + int res = -ENODEV; + + /* Copy the DIMM presence map for these two channels */ + pcidev = pci_get_device(PCI_VENDOR_ID_INTEL, dev_id, NULL); + if (!pcidev) + return -ENODEV; + + if (pci_read_config_word(pcidev, I5K_REG_CHAN0_PRESENCE_ADDR, &val16)) + goto out; + amb_present[0] = val16; + + if (pci_read_config_word(pcidev, I5K_REG_CHAN1_PRESENCE_ADDR, &val16)) + goto out; + amb_present[1] = val16; + + res = 0; + +out: + pci_dev_put(pcidev); + return res; +} + +static int __devinit i5k_amb_probe(struct platform_device *pdev) +{ + struct i5k_amb_data *data; + struct resource *reso; + int res = -ENODEV; + + data = kzalloc(sizeof(*data), GFP_KERNEL); + if (!data) + return -ENOMEM; + + /* Figure out where the AMB registers live */ + res = i5k_find_amb_registers(data); + if (res) + goto err; + + /* Copy the DIMM presence map for the first two channels */ + res = i5k_channel_probe(&data->amb_present[0], + PCI_DEVICE_ID_INTEL_5000_FBD0); + if (res) + goto err; + + /* Copy the DIMM presence map for the optional second two channels */ + i5k_channel_probe(&data->amb_present[2], + PCI_DEVICE_ID_INTEL_5000_FBD1); + + /* Set up resource regions */ + reso = request_mem_region(data->amb_base, data->amb_len, DRVNAME); + if (!reso) { + res = -EBUSY; + goto err; + } + + data->amb_mmio = ioremap_nocache(data->amb_base, data->amb_len); + if (!data->amb_mmio) { + res = -EBUSY; + goto err_map_failed; + } + + platform_set_drvdata(pdev, data); + + res = i5k_amb_hwmon_init(pdev); + if (res) + goto err_init_failed; + + return res; + +err_init_failed: + iounmap(data->amb_mmio); + platform_set_drvdata(pdev, NULL); +err_map_failed: + release_mem_region(data->amb_base, data->amb_len); +err: + kfree(data); + return res; +} + +static int __devexit i5k_amb_remove(struct platform_device *pdev) +{ + int i; + struct i5k_amb_data *data = platform_get_drvdata(pdev); + + hwmon_device_unregister(data->hwmon_dev); + device_remove_file(&pdev->dev, &dev_attr_name); + for (i = 0; i < data->num_attrs; i++) + device_remove_file(&pdev->dev, &data->attrs[i].s_attr.dev_attr); + kfree(data->attrs); + iounmap(data->amb_mmio); + release_mem_region(data->amb_base, data->amb_len); + platform_set_drvdata(pdev, NULL); + kfree(data); + return 0; +} + +static struct platform_driver i5k_amb_driver = { + .driver = { + .owner = THIS_MODULE, + .name = DRVNAME, + }, + .probe = i5k_amb_probe, + .remove = __devexit_p(i5k_amb_remove), +}; + +static int __init i5k_amb_init(void) +{ + int res; + + res = platform_driver_register(&i5k_amb_driver); + if (res) + return res; + + res = i5k_amb_add(); + if (res) + platform_driver_unregister(&i5k_amb_driver); + + return res; +} + +static void __exit i5k_amb_exit(void) +{ + platform_device_unregister(amb_pdev); + platform_driver_unregister(&i5k_amb_driver); +} + +MODULE_AUTHOR("Darrick J. Wong <djwong@us.ibm.com>"); +MODULE_DESCRIPTION("Intel 5000 chipset FB-DIMM AMB temperature sensor"); +MODULE_LICENSE("GPL"); + +module_init(i5k_amb_init); +module_exit(i5k_amb_exit); diff --git a/drivers/hwmon/ibmpex.c b/drivers/hwmon/ibmpex.c index c462824..9c9cdb0 100644 --- a/drivers/hwmon/ibmpex.c +++ b/drivers/hwmon/ibmpex.c @@ -140,10 +140,10 @@ static int ibmpex_send_message(struct ibmpex_bmc_data *data) return 0; out1: - printk(KERN_ERR "%s: request_settime=%x\n", __FUNCTION__, err); + dev_err(data->bmc_device, "request_settime=%x\n", err); return err; out: - printk(KERN_ERR "%s: validate_addr=%x\n", __FUNCTION__, err); + dev_err(data->bmc_device, "validate_addr=%x\n", err); return err; } @@ -161,14 +161,14 @@ static int ibmpex_ver_check(struct ibmpex_bmc_data *data) data->sensor_major = data->rx_msg_data[0]; data->sensor_minor = data->rx_msg_data[1]; - printk(KERN_INFO DRVNAME ": Found BMC with sensor interface " - "v%d.%d %d-%02d-%02d on interface %d\n", - data->sensor_major, - data->sensor_minor, - extract_value(data->rx_msg_data, 2), - data->rx_msg_data[4], - data->rx_msg_data[5], - data->interface); + dev_info(data->bmc_device, "Found BMC with sensor interface " + "v%d.%d %d-%02d-%02d on interface %d\n", + data->sensor_major, + data->sensor_minor, + extract_value(data->rx_msg_data, 2), + data->rx_msg_data[4], + data->rx_msg_data[5], + data->interface); return 0; } @@ -212,8 +212,8 @@ static int ibmpex_query_sensor_data(struct ibmpex_bmc_data *data, int sensor) wait_for_completion(&data->read_complete); if (data->rx_result || data->rx_msg_len < 26) { - printk(KERN_ERR "Error reading sensor %d, please check.\n", - sensor); + dev_err(data->bmc_device, "Error reading sensor %d.\n", + sensor); return -ENOENT; } @@ -456,8 +456,7 @@ static void ibmpex_register_bmc(int iface, struct device *dev) data = kzalloc(sizeof(*data), GFP_KERNEL); if (!data) { - printk(KERN_ERR DRVNAME ": Insufficient memory for BMC " - "interface %d.\n", data->interface); + dev_err(dev, "Insufficient memory for BMC interface.\n"); return; } @@ -471,9 +470,8 @@ static void ibmpex_register_bmc(int iface, struct device *dev) err = ipmi_create_user(data->interface, &driver_data.ipmi_hndlrs, data, &data->user); if (err < 0) { - printk(KERN_ERR DRVNAME ": Error, unable to register user with " - "ipmi interface %d\n", - data->interface); + dev_err(dev, "Unable to register user with IPMI " + "interface %d\n", data->interface); goto out; } @@ -495,9 +493,9 @@ static void ibmpex_register_bmc(int iface, struct device *dev) data->hwmon_dev = hwmon_device_register(data->bmc_device); if (IS_ERR(data->hwmon_dev)) { - printk(KERN_ERR DRVNAME ": Error, unable to register hwmon " - "class device for interface %d\n", - data->interface); + dev_err(data->bmc_device, "Unable to register hwmon " + "device for IPMI interface %d\n", + data->interface); goto out_user; } @@ -508,7 +506,7 @@ static void ibmpex_register_bmc(int iface, struct device *dev) /* Now go find all the sensors */ err = ibmpex_find_sensors(data); if (err) { - printk(KERN_ERR "Error %d allocating memory\n", err); + dev_err(data->bmc_device, "Error %d finding sensors\n", err); goto out_register; } @@ -561,10 +559,10 @@ static void ibmpex_msg_handler(struct ipmi_recv_msg *msg, void *user_msg_data) struct ibmpex_bmc_data *data = (struct ibmpex_bmc_data *)user_msg_data; if (msg->msgid != data->tx_msgid) { - printk(KERN_ERR "Received msgid (%02x) and transmitted " - "msgid (%02x) mismatch!\n", - (int)msg->msgid, - (int)data->tx_msgid); + dev_err(data->bmc_device, "Mismatch between received msgid " + "(%02x) and transmitted msgid (%02x)!\n", + (int)msg->msgid, + (int)data->tx_msgid); ipmi_free_recv_msg(msg); return; } diff --git a/drivers/hwmon/lm70.c b/drivers/hwmon/lm70.c index dd36688..d435f00 100644 --- a/drivers/hwmon/lm70.c +++ b/drivers/hwmon/lm70.c @@ -31,14 +31,15 @@ #include <linux/err.h> #include <linux/sysfs.h> #include <linux/hwmon.h> +#include <linux/mutex.h> #include <linux/spi/spi.h> -#include <asm/semaphore.h> + #define DRVNAME "lm70" struct lm70 { struct device *hwmon_dev; - struct semaphore sem; + struct mutex lock; }; /* sysfs hook function */ @@ -51,7 +52,7 @@ static ssize_t lm70_sense_temp(struct device *dev, s16 raw=0; struct lm70 *p_lm70 = dev_get_drvdata(&spi->dev); - if (down_interruptible(&p_lm70->sem)) + if (mutex_lock_interruptible(&p_lm70->lock)) return -ERESTARTSYS; /* @@ -83,7 +84,7 @@ static ssize_t lm70_sense_temp(struct device *dev, val = ((int)raw/32) * 250; status = sprintf(buf, "%d\n", val); /* millidegrees Celsius */ out: - up(&p_lm70->sem); + mutex_unlock(&p_lm70->lock); return status; } @@ -112,7 +113,7 @@ static int __devinit lm70_probe(struct spi_device *spi) if (!p_lm70) return -ENOMEM; - init_MUTEX(&p_lm70->sem); + mutex_init(&p_lm70->lock); /* sysfs hook */ p_lm70->hwmon_dev = hwmon_device_register(&spi->dev); diff --git a/drivers/hwmon/sis5595.c b/drivers/hwmon/sis5595.c index 7e2d978..a276806 100644 --- a/drivers/hwmon/sis5595.c +++ b/drivers/hwmon/sis5595.c @@ -435,6 +435,22 @@ static ssize_t show_alarms(struct device *dev, struct device_attribute *attr, ch } static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL); +static ssize_t show_alarm(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sis5595_data *data = sis5595_update_device(dev); + int nr = to_sensor_dev_attr(da)->index; + return sprintf(buf, "%u\n", (data->alarms >> nr) & 1); +} +static SENSOR_DEVICE_ATTR(in0_alarm, S_IRUGO, show_alarm, NULL, 0); +static SENSOR_DEVICE_ATTR(in1_alarm, S_IRUGO, show_alarm, NULL, 1); +static SENSOR_DEVICE_ATTR(in2_alarm, S_IRUGO, show_alarm, NULL, 2); +static SENSOR_DEVICE_ATTR(in3_alarm, S_IRUGO, show_alarm, NULL, 3); +static SENSOR_DEVICE_ATTR(in4_alarm, S_IRUGO, show_alarm, NULL, 15); +static SENSOR_DEVICE_ATTR(fan1_alarm, S_IRUGO, show_alarm, NULL, 6); +static SENSOR_DEVICE_ATTR(fan2_alarm, S_IRUGO, show_alarm, NULL, 7); +static SENSOR_DEVICE_ATTR(temp1_alarm, S_IRUGO, show_alarm, NULL, 15); + static ssize_t show_name(struct device *dev, struct device_attribute *attr, char *buf) { @@ -447,22 +463,28 @@ static struct attribute *sis5595_attributes[] = { &sensor_dev_attr_in0_input.dev_attr.attr, &sensor_dev_attr_in0_min.dev_attr.attr, &sensor_dev_attr_in0_max.dev_attr.attr, + &sensor_dev_attr_in0_alarm.dev_attr.attr, &sensor_dev_attr_in1_input.dev_attr.attr, &sensor_dev_attr_in1_min.dev_attr.attr, &sensor_dev_attr_in1_max.dev_attr.attr, + &sensor_dev_attr_in1_alarm.dev_attr.attr, &sensor_dev_attr_in2_input.dev_attr.attr, &sensor_dev_attr_in2_min.dev_attr.attr, &sensor_dev_attr_in2_max.dev_attr.attr, + &sensor_dev_attr_in2_alarm.dev_attr.attr, &sensor_dev_attr_in3_input.dev_attr.attr, &sensor_dev_attr_in3_min.dev_attr.attr, &sensor_dev_attr_in3_max.dev_attr.attr, + &sensor_dev_attr_in3_alarm.dev_attr.attr, &sensor_dev_attr_fan1_input.dev_attr.attr, &sensor_dev_attr_fan1_min.dev_attr.attr, &sensor_dev_attr_fan1_div.dev_attr.attr, + &sensor_dev_attr_fan1_alarm.dev_attr.attr, &sensor_dev_attr_fan2_input.dev_attr.attr, &sensor_dev_attr_fan2_min.dev_attr.attr, &sensor_dev_attr_fan2_div.dev_attr.attr, + &sensor_dev_attr_fan2_alarm.dev_attr.attr, &dev_attr_alarms.attr, &dev_attr_name.attr, @@ -473,19 +495,28 @@ static const struct attribute_group sis5595_group = { .attrs = sis5595_attributes, }; -static struct attribute *sis5595_attributes_opt[] = { +static struct attribute *sis5595_attributes_in4[] = { &sensor_dev_attr_in4_input.dev_attr.attr, &sensor_dev_attr_in4_min.dev_attr.attr, &sensor_dev_attr_in4_max.dev_attr.attr, + &sensor_dev_attr_in4_alarm.dev_attr.attr, + NULL +}; + +static const struct attribute_group sis5595_group_in4 = { + .attrs = sis5595_attributes_in4, +}; +static struct attribute *sis5595_attributes_temp1[] = { &dev_attr_temp1_input.attr, &dev_attr_temp1_max.attr, &dev_attr_temp1_max_hyst.attr, + &sensor_dev_attr_temp1_alarm.dev_attr.attr, NULL }; -static const struct attribute_group sis5595_group_opt = { - .attrs = sis5595_attributes_opt, +static const struct attribute_group sis5595_group_temp1 = { + .attrs = sis5595_attributes_temp1, }; /* This is called when the module is loaded */ @@ -540,20 +571,12 @@ static int __devinit sis5595_probe(struct platform_device *pdev) if ((err = sysfs_create_group(&pdev->dev.kobj, &sis5595_group))) goto exit_free; if (data->maxins == 4) { - if ((err = device_create_file(&pdev->dev, - &sensor_dev_attr_in4_input.dev_attr)) - || (err = device_create_file(&pdev->dev, - &sensor_dev_attr_in4_min.dev_attr)) - || (err = device_create_file(&pdev->dev, - &sensor_dev_attr_in4_max.dev_attr))) + if ((err = sysfs_create_group(&pdev->dev.kobj, + &sis5595_group_in4))) goto exit_remove_files; } else { - if ((err = device_create_file(&pdev->dev, - &dev_attr_temp1_input)) - || (err = device_create_file(&pdev->dev, - &dev_attr_temp1_max)) - || (err = device_create_file(&pdev->dev, - &dev_attr_temp1_max_hyst))) + if ((err = sysfs_create_group(&pdev->dev.kobj, + &sis5595_group_temp1))) goto exit_remove_files; } @@ -567,7 +590,8 @@ static int __devinit sis5595_probe(struct platform_device *pdev) exit_remove_files: sysfs_remove_group(&pdev->dev.kobj, &sis5595_group); - sysfs_remove_group(&pdev->dev.kobj, &sis5595_group_opt); + sysfs_remove_group(&pdev->dev.kobj, &sis5595_group_in4); + sysfs_remove_group(&pdev->dev.kobj, &sis5595_group_temp1); exit_free: kfree(data); exit_release: @@ -582,7 +606,8 @@ static int __devexit sis5595_remove(struct platform_device *pdev) hwmon_device_unregister(data->hwmon_dev); sysfs_remove_group(&pdev->dev.kobj, &sis5595_group); - sysfs_remove_group(&pdev->dev.kobj, &sis5595_group_opt); + sysfs_remove_group(&pdev->dev.kobj, &sis5595_group_in4); + sysfs_remove_group(&pdev->dev.kobj, &sis5595_group_temp1); release_region(data->addr, SIS5595_EXTENT); platform_set_drvdata(pdev, NULL); diff --git a/drivers/hwmon/w83627hf.c b/drivers/hwmon/w83627hf.c index 20ae425..879d0a6 100644 --- a/drivers/hwmon/w83627hf.c +++ b/drivers/hwmon/w83627hf.c @@ -170,20 +170,16 @@ superio_exit(void) #define W83781D_REG_IN(nr) ((nr < 7) ? (0x20 + (nr)) : \ (0x550 + (nr) - 7)) -#define W83781D_REG_FAN_MIN(nr) (0x3a + (nr)) -#define W83781D_REG_FAN(nr) (0x27 + (nr)) - -#define W83781D_REG_TEMP2_CONFIG 0x152 -#define W83781D_REG_TEMP3_CONFIG 0x252 -#define W83781D_REG_TEMP(nr) ((nr == 3) ? (0x0250) : \ - ((nr == 2) ? (0x0150) : \ - (0x27))) -#define W83781D_REG_TEMP_HYST(nr) ((nr == 3) ? (0x253) : \ - ((nr == 2) ? (0x153) : \ - (0x3A))) -#define W83781D_REG_TEMP_OVER(nr) ((nr == 3) ? (0x255) : \ - ((nr == 2) ? (0x155) : \ - (0x39))) +/* nr:0-2 for fans:1-3 */ +#define W83627HF_REG_FAN_MIN(nr) (0x3b + (nr)) +#define W83627HF_REG_FAN(nr) (0x28 + (nr)) + +#define W83627HF_REG_TEMP2_CONFIG 0x152 +#define W83627HF_REG_TEMP3_CONFIG 0x252 +/* these are zero-based, unlike config constants above */ +static const u16 w83627hf_reg_temp[] = { 0x27, 0x150, 0x250 }; +static const u16 w83627hf_reg_temp_hyst[] = { 0x3A, 0x153, 0x253 }; +static const u16 w83627hf_reg_temp_over[] = { 0x39, 0x155, 0x255 }; #define W83781D_REG_BANK 0x4E @@ -360,12 +356,9 @@ struct w83627hf_data { u8 in_min[9]; /* Register value */ u8 fan[3]; /* Register value */ u8 fan_min[3]; /* Register value */ - u8 temp; - u8 temp_max; /* Register value */ - u8 temp_max_hyst; /* Register value */ - u16 temp_add[2]; /* Register value */ - u16 temp_max_add[2]; /* Register value */ - u16 temp_max_hyst_add[2]; /* Register value */ + u16 temp[3]; /* Register value */ + u16 temp_max[3]; /* Register value */ + u16 temp_max_hyst[3]; /* Register value */ u8 fan_div[3]; /* Register encoding, shifted right */ u8 vid; /* Register encoding, combined */ u32 alarms; /* Register encoding, combined */ @@ -590,7 +583,7 @@ store_fan_min(struct device *dev, struct device_attribute *devattr, mutex_lock(&data->update_lock); data->fan_min[nr] = FAN_TO_REG(val, DIV_FROM_REG(data->fan_div[nr])); - w83627hf_write_value(data, W83781D_REG_FAN_MIN(nr+1), + w83627hf_write_value(data, W83627HF_REG_FAN_MIN(nr), data->fan_min[nr]); mutex_unlock(&data->update_lock); @@ -611,12 +604,10 @@ show_temp(struct device *dev, struct device_attribute *devattr, char *buf) { int nr = to_sensor_dev_attr(devattr)->index; struct w83627hf_data *data = w83627hf_update_device(dev); - if (nr >= 2) { /* TEMP2 and TEMP3 */ - return sprintf(buf, "%ld\n", - (long)LM75_TEMP_FROM_REG(data->temp_add[nr-2])); - } else { /* TEMP1 */ - return sprintf(buf, "%ld\n", (long)TEMP_FROM_REG(data->temp)); - } + + u16 tmp = data->temp[nr]; + return sprintf(buf, "%ld\n", (nr) ? (long) LM75_TEMP_FROM_REG(tmp) + : (long) TEMP_FROM_REG(tmp)); } static ssize_t @@ -625,13 +616,10 @@ show_temp_max(struct device *dev, struct device_attribute *devattr, { int nr = to_sensor_dev_attr(devattr)->index; struct w83627hf_data *data = w83627hf_update_device(dev); - if (nr >= 2) { /* TEMP2 and TEMP3 */ - return sprintf(buf, "%ld\n", - (long)LM75_TEMP_FROM_REG(data->temp_max_add[nr-2])); - } else { /* TEMP1 */ - return sprintf(buf, "%ld\n", - (long)TEMP_FROM_REG(data->temp_max)); - } + + u16 tmp = data->temp_max[nr]; + return sprintf(buf, "%ld\n", (nr) ? (long) LM75_TEMP_FROM_REG(tmp) + : (long) TEMP_FROM_REG(tmp)); } static ssize_t @@ -640,13 +628,10 @@ show_temp_max_hyst(struct device *dev, struct device_attribute *devattr, { int nr = to_sensor_dev_attr(devattr)->index; struct w83627hf_data *data = w83627hf_update_device(dev); - if (nr >= 2) { /* TEMP2 and TEMP3 */ - return sprintf(buf, "%ld\n", - (long)LM75_TEMP_FROM_REG(data->temp_max_hyst_add[nr-2])); - } else { /* TEMP1 */ - return sprintf(buf, "%ld\n", - (long)TEMP_FROM_REG(data->temp_max_hyst)); - } + + u16 tmp = data->temp_max_hyst[nr]; + return sprintf(buf, "%ld\n", (nr) ? (long) LM75_TEMP_FROM_REG(tmp) + : (long) TEMP_FROM_REG(tmp)); } static ssize_t @@ -656,18 +641,11 @@ store_temp_max(struct device *dev, struct device_attribute *devattr, int nr = to_sensor_dev_attr(devattr)->index; struct w83627hf_data *data = dev_get_drvdata(dev); long val = simple_strtol(buf, NULL, 10); + u16 tmp = (nr) ? LM75_TEMP_TO_REG(val) : TEMP_TO_REG(val); mutex_lock(&data->update_lock); - - if (nr >= 2) { /* TEMP2 and TEMP3 */ - data->temp_max_add[nr-2] = LM75_TEMP_TO_REG(val); - w83627hf_write_value(data, W83781D_REG_TEMP_OVER(nr), - data->temp_max_add[nr-2]); - } else { /* TEMP1 */ - data->temp_max = TEMP_TO_REG(val); - w83627hf_write_value(data, W83781D_REG_TEMP_OVER(nr), - data->temp_max); - } + data->temp_max[nr] = tmp; + w83627hf_write_value(data, w83627hf_reg_temp_over[nr], tmp); mutex_unlock(&data->update_lock); return count; } @@ -679,29 +657,22 @@ store_temp_max_hyst(struct device *dev, struct device_attribute *devattr, int nr = to_sensor_dev_attr(devattr)->index; struct w83627hf_data *data = dev_get_drvdata(dev); long val = simple_strtol(buf, NULL, 10); + u16 tmp = (nr) ? LM75_TEMP_TO_REG(val) : TEMP_TO_REG(val); mutex_lock(&data->update_lock); - - if (nr >= 2) { /* TEMP2 and TEMP3 */ - data->temp_max_hyst_add[nr-2] = LM75_TEMP_TO_REG(val); - w83627hf_write_value(data, W83781D_REG_TEMP_HYST(nr), - data->temp_max_hyst_add[nr-2]); - } else { /* TEMP1 */ - data->temp_max_hyst = TEMP_TO_REG(val); - w83627hf_write_value(data, W83781D_REG_TEMP_HYST(nr), - data->temp_max_hyst); - } + data->temp_max_hyst[nr] = tmp; + w83627hf_write_value(data, w83627hf_reg_temp_hyst[nr], tmp); mutex_unlock(&data->update_lock); return count; } #define sysfs_temp_decl(offset) \ static SENSOR_DEVICE_ATTR(temp##offset##_input, S_IRUGO, \ - show_temp, NULL, offset); \ + show_temp, NULL, offset - 1); \ static SENSOR_DEVICE_ATTR(temp##offset##_max, S_IRUGO|S_IWUSR, \ - show_temp_max, store_temp_max, offset); \ + show_temp_max, store_temp_max, offset - 1); \ static SENSOR_DEVICE_ATTR(temp##offset##_max_hyst, S_IRUGO|S_IWUSR, \ - show_temp_max_hyst, store_temp_max_hyst, offset); + show_temp_max_hyst, store_temp_max_hyst, offset - 1); sysfs_temp_decl(1); sysfs_temp_decl(2); @@ -844,7 +815,7 @@ store_fan_div(struct device *dev, struct device_attribute *devattr, /* Restore fan_min */ data->fan_min[nr] = FAN_TO_REG(min, DIV_FROM_REG(data->fan_div[nr])); - w83627hf_write_value(data, W83781D_REG_FAN_MIN(nr+1), data->fan_min[nr]); + w83627hf_write_value(data, W83627HF_REG_FAN_MIN(nr), data->fan_min[nr]); mutex_unlock(&data->update_lock); return count; @@ -1170,7 +1141,7 @@ static int __devinit w83627hf_probe(struct platform_device *pdev) struct w83627hf_sio_data *sio_data = dev->platform_data; struct w83627hf_data *data; struct resource *res; - int err; + int err, i; static const char *names[] = { "w83627hf", @@ -1204,9 +1175,9 @@ static int __devinit w83627hf_probe(struct platform_device *pdev) w83627hf_init_device(pdev); /* A few vars need to be filled upon startup */ - data->fan_min[0] = w83627hf_read_value(data, W83781D_REG_FAN_MIN(1)); - data->fan_min[1] = w83627hf_read_value(data, W83781D_REG_FAN_MIN(2)); - data->fan_min[2] = w83627hf_read_value(data, W83781D_REG_FAN_MIN(3)); + for (i = 0; i <= 2; i++) + data->fan_min[i] = w83627hf_read_value( + data, W83627HF_REG_FAN_MIN(i)); w83627hf_update_fan_div(data); /* Register common device attributes */ @@ -1514,23 +1485,23 @@ static void __devinit w83627hf_init_device(struct platform_device *pdev) if(init) { /* Enable temp2 */ - tmp = w83627hf_read_value(data, W83781D_REG_TEMP2_CONFIG); + tmp = w83627hf_read_value(data, W83627HF_REG_TEMP2_CONFIG); if (tmp & 0x01) { dev_warn(&pdev->dev, "Enabling temp2, readings " "might not make sense\n"); - w83627hf_write_value(data, W83781D_REG_TEMP2_CONFIG, + w83627hf_write_value(data, W83627HF_REG_TEMP2_CONFIG, tmp & 0xfe); } /* Enable temp3 */ if (type != w83697hf) { tmp = w83627hf_read_value(data, - W83781D_REG_TEMP3_CONFIG); + W83627HF_REG_TEMP3_CONFIG); if (tmp & 0x01) { dev_warn(&pdev->dev, "Enabling temp3, " "readings might not make sense\n"); w83627hf_write_value(data, - W83781D_REG_TEMP3_CONFIG, tmp & 0xfe); + W83627HF_REG_TEMP3_CONFIG, tmp & 0xfe); } } } @@ -1563,7 +1534,7 @@ static void w83627hf_update_fan_div(struct w83627hf_data *data) static struct w83627hf_data *w83627hf_update_device(struct device *dev) { struct w83627hf_data *data = dev_get_drvdata(dev); - int i; + int i, num_temps = (data->type == w83697hf) ? 2 : 3; mutex_lock(&data->update_lock); @@ -1584,12 +1555,12 @@ static struct w83627hf_data *w83627hf_update_device(struct device *dev) w83627hf_read_value(data, W83781D_REG_IN_MAX(i)); } - for (i = 1; i <= 3; i++) { - data->fan[i - 1] = - w83627hf_read_value(data, W83781D_REG_FAN(i)); - data->fan_min[i - 1] = + for (i = 0; i <= 2; i++) { + data->fan[i] = + w83627hf_read_value(data, W83627HF_REG_FAN(i)); + data->fan_min[i] = w83627hf_read_value(data, - W83781D_REG_FAN_MIN(i)); + W83627HF_REG_FAN_MIN(i)); } for (i = 0; i <= 2; i++) { u8 tmp = w83627hf_read_value(data, @@ -1616,25 +1587,13 @@ static struct w83627hf_data *w83627hf_update_device(struct device *dev) break; } } - - data->temp = w83627hf_read_value(data, W83781D_REG_TEMP(1)); - data->temp_max = - w83627hf_read_value(data, W83781D_REG_TEMP_OVER(1)); - data->temp_max_hyst = - w83627hf_read_value(data, W83781D_REG_TEMP_HYST(1)); - data->temp_add[0] = - w83627hf_read_value(data, W83781D_REG_TEMP(2)); - data->temp_max_add[0] = - w83627hf_read_value(data, W83781D_REG_TEMP_OVER(2)); - data->temp_max_hyst_add[0] = - w83627hf_read_value(data, W83781D_REG_TEMP_HYST(2)); - if (data->type != w83697hf) { - data->temp_add[1] = - w83627hf_read_value(data, W83781D_REG_TEMP(3)); - data->temp_max_add[1] = - w83627hf_read_value(data, W83781D_REG_TEMP_OVER(3)); - data->temp_max_hyst_add[1] = - w83627hf_read_value(data, W83781D_REG_TEMP_HYST(3)); + for (i = 0; i < num_temps; i++) { + data->temp[i] = w83627hf_read_value( + data, w83627hf_reg_temp[i]); + data->temp_max[i] = w83627hf_read_value( + data, w83627hf_reg_temp_over[i]); + data->temp_max_hyst[i] = w83627hf_read_value( + data, w83627hf_reg_temp_hyst[i]); } w83627hf_update_fan_div(data); diff --git a/drivers/hwmon/w83781d.c b/drivers/hwmon/w83781d.c index a6a1edf..e0fa752 100644 --- a/drivers/hwmon/w83781d.c +++ b/drivers/hwmon/w83781d.c @@ -1122,12 +1122,13 @@ w83781d_create_files(struct device *dev, int kind, int is_isa) &sensor_dev_attr_temp3_beep.dev_attr))) return err; - if (kind != w83781d) + if (kind != w83781d) { err = sysfs_chmod_file(&dev->kobj, &sensor_dev_attr_temp3_alarm.dev_attr.attr, S_IRUGO | S_IWUSR); if (err) return err; + } } if (kind != w83781d && kind != as99127f) { diff --git a/drivers/i2c/busses/i2c-pasemi.c b/drivers/i2c/busses/i2c-pasemi.c index 58e3271..ca18e0b 100644 --- a/drivers/i2c/busses/i2c-pasemi.c +++ b/drivers/i2c/busses/i2c-pasemi.c @@ -51,6 +51,7 @@ struct pasemi_smbus { #define MRXFIFO_DATA_M 0x000000ff #define SMSTA_XEN 0x08000000 +#define SMSTA_MTN 0x00200000 #define CTL_MRR 0x00000400 #define CTL_MTR 0x00000200 @@ -98,6 +99,10 @@ static unsigned int pasemi_smb_waitready(struct pasemi_smbus *smbus) status = reg_read(smbus, REG_SMSTA); } + /* Got NACK? */ + if (status & SMSTA_MTN) + return -ENXIO; + if (timeout < 0) { dev_warn(&smbus->dev->dev, "Timeout, status 0x%08x\n", status); reg_write(smbus, REG_SMSTA, status); @@ -364,7 +369,7 @@ static int __devinit pasemi_smb_probe(struct pci_dev *dev, smbus->adapter.algo = &smbus_algorithm; smbus->adapter.algo_data = smbus; - /* set up the driverfs linkage to our parent device */ + /* set up the sysfs linkage to our parent device */ smbus->adapter.dev.parent = &dev->dev; reg_write(smbus, REG_CTL, (CTL_MTR | CTL_MRR | diff --git a/drivers/i2c/chips/eeprom.c b/drivers/i2c/chips/eeprom.c index d3da1fb..1a7eeeb 100644 --- a/drivers/i2c/chips/eeprom.c +++ b/drivers/i2c/chips/eeprom.c @@ -128,13 +128,20 @@ static ssize_t eeprom_read(struct kobject *kobj, struct bin_attribute *bin_attr, for (slice = off >> 5; slice <= (off + count - 1) >> 5; slice++) eeprom_update_client(client, slice); - /* Hide Vaio security settings to regular users (16 first bytes) */ - if (data->nature == VAIO && off < 16 && !capable(CAP_SYS_ADMIN)) { - size_t in_row1 = 16 - off; - in_row1 = min(in_row1, count); - memset(buf, 0, in_row1); - if (count - in_row1 > 0) - memcpy(buf + in_row1, &data->data[16], count - in_row1); + /* Hide Vaio private settings to regular users: + - BIOS passwords: bytes 0x00 to 0x0f + - UUID: bytes 0x10 to 0x1f + - Serial number: 0xc0 to 0xdf */ + if (data->nature == VAIO && !capable(CAP_SYS_ADMIN)) { + int i; + + for (i = 0; i < count; i++) { + if ((off + i <= 0x1f) || + (off + i >= 0xc0 && off + i <= 0xdf)) + buf[i] = 0; + else + buf[i] = data->data[off + i]; + } } else { memcpy(buf, &data->data[off], count); } @@ -197,14 +204,18 @@ static int eeprom_detect(struct i2c_adapter *adapter, int address, int kind) goto exit_kfree; /* Detect the Vaio nature of EEPROMs. - We use the "PCG-" prefix as the signature. */ + We use the "PCG-" or "VGN-" prefix as the signature. */ if (address == 0x57) { - if (i2c_smbus_read_byte_data(new_client, 0x80) == 'P' - && i2c_smbus_read_byte(new_client) == 'C' - && i2c_smbus_read_byte(new_client) == 'G' - && i2c_smbus_read_byte(new_client) == '-') { + char name[4]; + + name[0] = i2c_smbus_read_byte_data(new_client, 0x80); + name[1] = i2c_smbus_read_byte(new_client); + name[2] = i2c_smbus_read_byte(new_client); + name[3] = i2c_smbus_read_byte(new_client); + + if (!memcmp(name, "PCG-", 4) || !memcmp(name, "VGN-", 4)) { dev_info(&new_client->dev, "Vaio EEPROM detected, " - "enabling password protection\n"); + "enabling privacy protection\n"); data->nature = VAIO; } } diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c index 1a4e8dc..b5e13e4 100644 --- a/drivers/i2c/i2c-core.c +++ b/drivers/i2c/i2c-core.c @@ -673,7 +673,7 @@ static int __i2c_check_addr(struct i2c_adapter *adapter, unsigned int addr) return 0; } -int i2c_check_addr(struct i2c_adapter *adapter, int addr) +static int i2c_check_addr(struct i2c_adapter *adapter, int addr) { int rval; @@ -683,7 +683,6 @@ int i2c_check_addr(struct i2c_adapter *adapter, int addr) return rval; } -EXPORT_SYMBOL(i2c_check_addr); int i2c_attach_client(struct i2c_client *client) { diff --git a/drivers/i2c/i2c-dev.c b/drivers/i2c/i2c-dev.c index 5a15e50..c21ae20 100644 --- a/drivers/i2c/i2c-dev.c +++ b/drivers/i2c/i2c-dev.c @@ -38,6 +38,15 @@ static struct i2c_driver i2cdev_driver; +/* + * An i2c_dev represents an i2c_adapter ... an I2C or SMBus master, not a + * slave (i2c_client) with which messages will be exchanged. It's coupled + * with a character special file which is accessed by user mode drivers. + * + * The list of i2c_dev structures is parallel to the i2c_adapter lists + * maintained by the driver model, and is updated using notifications + * delivered to the i2cdev_driver. + */ struct i2c_dev { struct list_head list; struct i2c_adapter *adap; @@ -103,6 +112,25 @@ static ssize_t show_adapter_name(struct device *dev, } static DEVICE_ATTR(name, S_IRUGO, show_adapter_name, NULL); +/* ------------------------------------------------------------------------- */ + +/* + * After opening an instance of this character special file, a file + * descriptor starts out associated only with an i2c_adapter (and bus). + * + * Using the I2C_RDWR ioctl(), you can then *immediately* issue i2c_msg + * traffic to any devices on the bus used by that adapter. That's because + * the i2c_msg vectors embed all the addressing information they need, and + * are submitted directly to an i2c_adapter. However, SMBus-only adapters + * don't support that interface. + * + * To use read()/write() system calls on that file descriptor, or to use + * SMBus interfaces (and work with SMBus-only hosts!), you must first issue + * an I2C_SLAVE (or I2C_SLAVE_FORCE) ioctl. That configures an anonymous + * (never registered) i2c_client so it holds the addressing information + * needed by those system calls and by this SMBus interface. + */ + static ssize_t i2cdev_read (struct file *file, char __user *buf, size_t count, loff_t *offset) { @@ -154,6 +182,29 @@ static ssize_t i2cdev_write (struct file *file, const char __user *buf, size_t c return ret; } +/* This address checking function differs from the one in i2c-core + in that it considers an address with a registered device, but no + bounded driver, as NOT busy. */ +static int i2cdev_check_addr(struct i2c_adapter *adapter, unsigned int addr) +{ + struct list_head *item; + struct i2c_client *client; + int res = 0; + + mutex_lock(&adapter->clist_lock); + list_for_each(item, &adapter->clients) { + client = list_entry(item, struct i2c_client, list); + if (client->addr == addr) { + if (client->driver) + res = -EBUSY; + break; + } + } + mutex_unlock(&adapter->clist_lock); + + return res; +} + static int i2cdev_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { @@ -172,11 +223,22 @@ static int i2cdev_ioctl(struct inode *inode, struct file *file, switch ( cmd ) { case I2C_SLAVE: case I2C_SLAVE_FORCE: + /* NOTE: devices set up to work with "new style" drivers + * can't use I2C_SLAVE, even when the device node is not + * bound to a driver. Only I2C_SLAVE_FORCE will work. + * + * Setting the PEC flag here won't affect kernel drivers, + * which will be using the i2c_client node registered with + * the driver model core. Likewise, when that client has + * the PEC flag already set, the i2c-dev driver won't see + * (or use) this setting. + */ if ((arg > 0x3ff) || (((client->flags & I2C_M_TEN) == 0) && arg > 0x7f)) return -EINVAL; - if ((cmd == I2C_SLAVE) && i2c_check_addr(client->adapter,arg)) + if (cmd == I2C_SLAVE && i2cdev_check_addr(client->adapter, arg)) return -EBUSY; + /* REVISIT: address could become busy later */ client->addr = arg; return 0; case I2C_TENBIT: @@ -386,6 +448,13 @@ static int i2cdev_open(struct inode *inode, struct file *file) if (!adap) return -ENODEV; + /* This creates an anonymous i2c_client, which may later be + * pointed to some address using I2C_SLAVE or I2C_SLAVE_FORCE. + * + * This client is ** NEVER REGISTERED ** with the driver model + * or I2C core code!! It just holds private copies of addressing + * information and maybe a PEC flag. + */ client = kzalloc(sizeof(*client), GFP_KERNEL); if (!client) { i2c_put_adapter(adap); @@ -394,7 +463,6 @@ static int i2cdev_open(struct inode *inode, struct file *file) snprintf(client->name, I2C_NAME_SIZE, "i2c-dev %d", adap->nr); client->driver = &i2cdev_driver; - /* registered with adapter, passed as client to user */ client->adapter = adap; file->private_data = client; @@ -422,6 +490,14 @@ static const struct file_operations i2cdev_fops = { .release = i2cdev_release, }; +/* ------------------------------------------------------------------------- */ + +/* + * The legacy "i2cdev_driver" is used primarily to get notifications when + * I2C adapters are added or removed, so that each one gets an i2c_dev + * and is thus made available to userspace driver code. + */ + static struct class *i2c_dev_class; static int i2cdev_attach_adapter(struct i2c_adapter *adap) @@ -486,6 +562,12 @@ static struct i2c_driver i2cdev_driver = { .detach_client = i2cdev_detach_client, }; +/* ------------------------------------------------------------------------- */ + +/* + * module load/unload record keeping + */ + static int __init i2c_dev_init(void) { int res; diff --git a/drivers/ide/Kconfig b/drivers/ide/Kconfig index d1e8df1..45b2228 100644 --- a/drivers/ide/Kconfig +++ b/drivers/ide/Kconfig @@ -203,10 +203,6 @@ config BLK_DEV_IDECD CD-ROM drive, you can say N to all other CD-ROM options, but be sure to say Y or M to "ISO 9660 CD-ROM file system support". - Note that older versions of LILO (LInux LOader) cannot properly deal - with IDE/ATAPI CD-ROMs, so install LILO 16 or higher, available from - <http://lilo.go.dyndns.org/>. - To compile this driver as a module, choose M here: the module will be called ide-cd. @@ -317,7 +313,6 @@ comment "IDE chipset support/bugfixes" config IDE_GENERIC tristate "generic/default IDE chipset support" - default H8300 help If unsure, say N. @@ -488,6 +483,7 @@ config WDC_ALI15X3 config BLK_DEV_AMD74XX tristate "AMD and nVidia IDE support" + depends on !ARM select BLK_DEV_IDEDMA_PCI help This driver adds explicit support for AMD-7xx and AMD-8111 chips @@ -887,6 +883,49 @@ config BLK_DEV_IDE_BAST Say Y here if you want to support the onboard IDE channels on the Simtec BAST or the Thorcom VR1000 +config ETRAX_IDE + bool "ETRAX IDE support" + depends on CRIS && BROKEN + select BLK_DEV_IDEDMA + select IDE_GENERIC + help + Enables the ETRAX IDE driver. + + You can't use parallel ports or SCSI ports at the same time. + +config ETRAX_IDE_DELAY + int "Delay for drives to regain consciousness" + depends on ETRAX_IDE && ETRAX_ARCH_V10 + default 15 + help + Number of seconds to wait for IDE drives to spin up after an IDE + reset. + +choice + prompt "IDE reset pin" + depends on ETRAX_IDE && ETRAX_ARCH_V10 + default ETRAX_IDE_PB7_RESET + +config ETRAX_IDE_PB7_RESET + bool "Port_PB_Bit_7" + help + IDE reset on pin 7 on port B + +config ETRAX_IDE_G27_RESET + bool "Port_G_Bit_27" + help + IDE reset on pin 27 on port G + +endchoice + +config IDE_H8300 + bool "H8300 IDE support" + depends on H8300 + select IDE_GENERIC + default y + help + Enables the H8300 IDE driver. + config BLK_DEV_GAYLE bool "Amiga Gayle IDE interface support" depends on AMIGA @@ -967,7 +1006,7 @@ config BLK_DEV_Q40IDE config BLK_DEV_MPC8xx_IDE bool "MPC8xx IDE support" - depends on 8xx && IDE=y && BLK_DEV_IDE=y && !PPC_MERGE + depends on 8xx && (LWMON || IVMS8 || IVML24 || TQM8xxL) && IDE=y && BLK_DEV_IDE=y && !PPC_MERGE select IDE_GENERIC help This option provides support for IDE on Motorola MPC8xx Systems. diff --git a/drivers/ide/Makefile b/drivers/ide/Makefile index 75dc696..b181fc6 100644 --- a/drivers/ide/Makefile +++ b/drivers/ide/Makefile @@ -39,7 +39,7 @@ ide-core-$(CONFIG_BLK_DEV_MPC8xx_IDE) += ppc/mpc8xx.o ide-core-$(CONFIG_BLK_DEV_IDE_PMAC) += ppc/pmac.o # built-in only drivers from h8300/ -ide-core-$(CONFIG_H8300) += h8300/ide-h8300.o +ide-core-$(CONFIG_IDE_H8300) += h8300/ide-h8300.o obj-$(CONFIG_BLK_DEV_IDE) += ide-core.o obj-$(CONFIG_IDE_GENERIC) += ide-generic.o diff --git a/drivers/ide/cris/ide-cris.c b/drivers/ide/cris/ide-cris.c index e196aef..476e0d6 100644 --- a/drivers/ide/cris/ide-cris.c +++ b/drivers/ide/cris/ide-cris.c @@ -748,8 +748,7 @@ static void cris_set_dma_mode(ide_drive_t *drive, const u8 speed) hold = ATA_DMA2_HOLD; break; default: - BUG(); - break; + return; } if (speed >= XFER_UDMA_0) @@ -774,15 +773,16 @@ init_e100_ide (void) /* the IDE control register is at ATA address 6, with CS1 active instead of CS0 */ ide_offsets[IDE_CONTROL_OFFSET] = cris_ide_reg_addr(6, 1, 0); - /* first fill in some stuff in the ide_hwifs fields */ + for (h = 0; h < 4; h++) { + ide_hwif_t *hwif = NULL; - for(h = 0; h < MAX_HWIFS; h++) { - ide_hwif_t *hwif = &ide_hwifs[h]; ide_setup_ports(&hw, cris_ide_base_address(h), ide_offsets, 0, 0, cris_ide_ack_intr, ide_default_irq(0)); ide_register_hw(&hw, NULL, 1, &hwif); + if (hwif == NULL) + continue; hwif->mmio = 1; hwif->chipset = ide_etrax100; hwif->set_pio_mode = &cris_set_pio_mode; diff --git a/drivers/ide/ide-dma.c b/drivers/ide/ide-dma.c index e3add70..0d795a1 100644 --- a/drivers/ide/ide-dma.c +++ b/drivers/ide/ide-dma.c @@ -130,6 +130,7 @@ static const struct drive_list_entry drive_blacklist [] = { { "_NEC DV5800A", NULL }, { "SAMSUNG CD-ROM SN-124", "N001" }, { "Seagate STT20000A", NULL }, + { "CD-ROM CDR_U200", "1.09" }, { NULL , NULL } }; diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c index 7550118..db22d1f 100644 --- a/drivers/ide/ide-io.c +++ b/drivers/ide/ide-io.c @@ -885,7 +885,6 @@ static ide_startstop_t execute_drive_cmd (ide_drive_t *drive, return do_rw_taskfile(drive, args); } else if (rq->cmd_type == REQ_TYPE_ATA_TASK) { u8 *args = rq->buffer; - u8 sel; if (!args) goto done; @@ -903,10 +902,7 @@ static ide_startstop_t execute_drive_cmd (ide_drive_t *drive, hwif->OUTB(args[3], IDE_SECTOR_REG); hwif->OUTB(args[4], IDE_LCYL_REG); hwif->OUTB(args[5], IDE_HCYL_REG); - sel = (args[6] & ~0x10); - if (drive->select.b.unit) - sel |= 0x10; - hwif->OUTB(sel, IDE_SELECT_REG); + hwif->OUTB((args[6] & 0xEF)|drive->select.all, IDE_SELECT_REG); ide_cmd(drive, args[0], args[2], &drive_cmd_intr); return ide_started; } else if (rq->cmd_type == REQ_TYPE_ATA_CMD) { diff --git a/drivers/ide/ide-iops.c b/drivers/ide/ide-iops.c index e17a9ee..5c32561 100644 --- a/drivers/ide/ide-iops.c +++ b/drivers/ide/ide-iops.c @@ -303,9 +303,6 @@ void default_hwif_transport(ide_hwif_t *hwif) hwif->atapi_output_bytes = atapi_output_bytes; } -/* - * Beginning of Taskfile OPCODE Library and feature sets. - */ void ide_fix_driveid (struct hd_driveid *id) { #ifndef __LITTLE_ENDIAN @@ -592,6 +589,9 @@ EXPORT_SYMBOL_GPL(ide_in_drive_list); static const struct drive_list_entry ivb_list[] = { { "QUANTUM FIREBALLlct10 05" , "A03.0900" }, { "TSSTcorp CDDVDW SH-S202J" , "SB00" }, + { "TSSTcorp CDDVDW SH-S202J" , "SB01" }, + { "TSSTcorp CDDVDW SH-S202N" , "SB00" }, + { "TSSTcorp CDDVDW SH-S202N" , "SB01" }, { NULL , NULL } }; @@ -756,7 +756,7 @@ int ide_driveid_update(ide_drive_t *drive) int ide_config_drive_speed(ide_drive_t *drive, u8 speed) { ide_hwif_t *hwif = drive->hwif; - int error; + int error = 0; u8 stat; // while (HWGROUP(drive)->busy) @@ -767,6 +767,10 @@ int ide_config_drive_speed(ide_drive_t *drive, u8 speed) hwif->dma_host_off(drive); #endif + /* Skip setting PIO flow-control modes on pre-EIDE drives */ + if ((speed & 0xf8) == XFER_PIO_0 && !(drive->id->capability & 0x08)) + goto skip; + /* * Don't use ide_wait_cmd here - it will * attempt to set_geometry and recalibrate, @@ -814,6 +818,7 @@ int ide_config_drive_speed(ide_drive_t *drive, u8 speed) drive->id->dma_mword &= ~0x0F00; drive->id->dma_1word &= ~0x0F00; + skip: #ifdef CONFIG_BLK_DEV_IDEDMA if (speed >= XFER_SW_DMA_0) hwif->dma_host_on(drive); diff --git a/drivers/ide/ide-lib.c b/drivers/ide/ide-lib.c index af86433..1609b86 100644 --- a/drivers/ide/ide-lib.c +++ b/drivers/ide/ide-lib.c @@ -514,6 +514,7 @@ static u8 ide_dump_ata_status(ide_drive_t *drive, const char *msg, u8 stat) if (drive->addressing == 1) { __u64 sectors = 0; u32 low = 0, high = 0; + hwif->OUTB(drive->ctl&~0x80, IDE_CONTROL_REG); low = ide_read_24(drive); hwif->OUTB(drive->ctl|0x80, IDE_CONTROL_REG); high = ide_read_24(drive); diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c index 56fb0b8..ee848c7 100644 --- a/drivers/ide/ide-probe.c +++ b/drivers/ide/ide-probe.c @@ -644,7 +644,7 @@ static void hwif_register (ide_hwif_t *hwif) static int wait_hwif_ready(ide_hwif_t *hwif) { - int rc; + int unit, rc; printk(KERN_DEBUG "Probing IDE interface %s...\n", hwif->name); @@ -661,20 +661,26 @@ static int wait_hwif_ready(ide_hwif_t *hwif) return rc; /* Now make sure both master & slave are ready */ - SELECT_DRIVE(&hwif->drives[0]); - hwif->OUTB(8, hwif->io_ports[IDE_CONTROL_OFFSET]); - mdelay(2); - rc = ide_wait_not_busy(hwif, 35000); - if (rc) - return rc; - SELECT_DRIVE(&hwif->drives[1]); - hwif->OUTB(8, hwif->io_ports[IDE_CONTROL_OFFSET]); - mdelay(2); - rc = ide_wait_not_busy(hwif, 35000); + for (unit = 0; unit < MAX_DRIVES; unit++) { + ide_drive_t *drive = &hwif->drives[unit]; + /* Ignore disks that we will not probe for later. */ + if (!drive->noprobe || drive->present) { + SELECT_DRIVE(drive); + hwif->OUTB(8, hwif->io_ports[IDE_CONTROL_OFFSET]); + mdelay(2); + rc = ide_wait_not_busy(hwif, 35000); + if (rc) + goto out; + } else + printk(KERN_DEBUG "%s: ide_wait_not_busy() skipped\n", + drive->name); + } +out: /* Exit function with master reselected (let's be sane) */ - SELECT_DRIVE(&hwif->drives[0]); - + if (unit) + SELECT_DRIVE(&hwif->drives[0]); + return rc; } diff --git a/drivers/ide/legacy/ali14xx.c b/drivers/ide/legacy/ali14xx.c index 10311ec..38c3a6d 100644 --- a/drivers/ide/legacy/ali14xx.c +++ b/drivers/ide/legacy/ali14xx.c @@ -53,12 +53,13 @@ /* port addresses for auto-detection */ #define ALI_NUM_PORTS 4 -static int ports[ALI_NUM_PORTS] __initdata = {0x074, 0x0f4, 0x034, 0x0e4}; +static const int ports[ALI_NUM_PORTS] __initdata = + { 0x074, 0x0f4, 0x034, 0x0e4 }; /* register initialization data */ typedef struct { u8 reg, data; } RegInitializer; -static RegInitializer initData[] __initdata = { +static const RegInitializer initData[] __initdata = { {0x01, 0x0f}, {0x02, 0x00}, {0x03, 0x00}, {0x04, 0x00}, {0x05, 0x00}, {0x06, 0x00}, {0x07, 0x2b}, {0x0a, 0x0f}, {0x25, 0x00}, {0x26, 0x00}, {0x27, 0x00}, {0x28, 0x00}, @@ -177,7 +178,7 @@ static int __init findPort (void) * Initialize controller registers with default values. */ static int __init initRegisters (void) { - RegInitializer *p; + const RegInitializer *p; u8 t; unsigned long flags; diff --git a/drivers/ide/legacy/macide.c b/drivers/ide/legacy/macide.c index e87cd2f..5c6aa77 100644 --- a/drivers/ide/legacy/macide.c +++ b/drivers/ide/legacy/macide.c @@ -81,7 +81,7 @@ int macide_ack_intr(ide_hwif_t* hwif) * Probe for a Macintosh IDE interface */ -void macide_init(void) +void __init macide_init(void) { hw_regs_t hw; ide_hwif_t *hwif; diff --git a/drivers/ide/legacy/q40ide.c b/drivers/ide/legacy/q40ide.c index a73db1b..6ea46a6 100644 --- a/drivers/ide/legacy/q40ide.c +++ b/drivers/ide/legacy/q40ide.c @@ -111,7 +111,7 @@ static const char *q40_ide_names[Q40IDE_NUM_HWIFS]={ * Probe for Q40 IDE interfaces */ -void q40ide_init(void) +void __init q40ide_init(void) { int i; ide_hwif_t *hwif; diff --git a/drivers/ide/pci/aec62xx.c b/drivers/ide/pci/aec62xx.c index 19ec421..4426850 100644 --- a/drivers/ide/pci/aec62xx.c +++ b/drivers/ide/pci/aec62xx.c @@ -260,6 +260,11 @@ static int __devinit aec62xx_init_one(struct pci_dev *dev, const struct pci_devi { struct ide_port_info d; u8 idx = id->driver_data; + int err; + + err = pci_enable_device(dev); + if (err) + return err; d = aec62xx_chipsets[idx]; @@ -272,7 +277,11 @@ static int __devinit aec62xx_init_one(struct pci_dev *dev, const struct pci_devi } } - return ide_setup_pci_device(dev, &d); + err = ide_setup_pci_device(dev, &d); + if (err) + pci_disable_device(dev); + + return err; } static const struct pci_device_id aec62xx_pci_tbl[] = { diff --git a/drivers/ide/pci/alim15x3.c b/drivers/ide/pci/alim15x3.c index a607dd3..ce29393 100644 --- a/drivers/ide/pci/alim15x3.c +++ b/drivers/ide/pci/alim15x3.c @@ -603,6 +603,11 @@ static int ali_cable_override(struct pci_dev *pdev) pdev->subsystem_device == 0x10AF) return 1; + /* Mitac 8317 (Winbook-A) and relatives */ + if (pdev->subsystem_vendor == 0x1071 && + pdev->subsystem_device == 0x8317) + return 1; + /* Systems by DMI */ if (dmi_check_system(cable_dmi_table)) return 1; diff --git a/drivers/ide/pci/cmd64x.c b/drivers/ide/pci/cmd64x.c index ea0143e..51fca44 100644 --- a/drivers/ide/pci/cmd64x.c +++ b/drivers/ide/pci/cmd64x.c @@ -1,5 +1,5 @@ /* - * linux/drivers/ide/pci/cmd64x.c Version 1.50 May 10, 2007 + * linux/drivers/ide/pci/cmd64x.c Version 1.51 Nov 8, 2007 * * cmd64x.c: Enable interrupts at initialization time on Ultra/PCI machines. * Due to massive hardware bugs, UltraDMA is only supported @@ -339,7 +339,8 @@ static int cmd648_ide_dma_end (ide_drive_t *drive) u8 mrdmode = inb(hwif->dma_master + 0x01); /* clear the interrupt bit */ - outb(mrdmode | irq_mask, hwif->dma_master + 0x01); + outb((mrdmode & ~(MRDMODE_INTR_CH0 | MRDMODE_INTR_CH1)) | irq_mask, + hwif->dma_master + 0x01); return err; } diff --git a/drivers/ide/pci/cs5530.c b/drivers/ide/pci/cs5530.c index 5994089..5476903 100644 --- a/drivers/ide/pci/cs5530.c +++ b/drivers/ide/pci/cs5530.c @@ -117,8 +117,7 @@ static void cs5530_set_dma_mode(ide_drive_t *drive, const u8 mode) case XFER_MW_DMA_1: timings = 0x00012121; break; case XFER_MW_DMA_2: timings = 0x00002020; break; default: - BUG(); - break; + return; } basereg = CS5530_BASEREG(drive->hwif); reg = inl(basereg + 4); /* get drive0 config register */ diff --git a/drivers/ide/pci/it821x.c b/drivers/ide/pci/it821x.c index 5c99754..99b7d76 100644 --- a/drivers/ide/pci/it821x.c +++ b/drivers/ide/pci/it821x.c @@ -653,8 +653,7 @@ static const struct ide_port_info it821x_chipsets[] __devinitdata = { static int __devinit it821x_init_one(struct pci_dev *dev, const struct pci_device_id *id) { - ide_setup_pci_device(dev, &it821x_chipsets[id->driver_data]); - return 0; + return ide_setup_pci_device(dev, &it821x_chipsets[id->driver_data]); } static const struct pci_device_id it821x_pci_tbl[] = { diff --git a/drivers/ide/pci/jmicron.c b/drivers/ide/pci/jmicron.c index bdf64d9..0083eaf 100644 --- a/drivers/ide/pci/jmicron.c +++ b/drivers/ide/pci/jmicron.c @@ -139,8 +139,7 @@ static const struct ide_port_info jmicron_chipset __devinitdata = { static int __devinit jmicron_init_one(struct pci_dev *dev, const struct pci_device_id *id) { - ide_setup_pci_device(dev, &jmicron_chipset); - return 0; + return ide_setup_pci_device(dev, &jmicron_chipset); } /* All JMB PATA controllers have and will continue to have the same diff --git a/drivers/ide/pci/piix.c b/drivers/ide/pci/piix.c index 63625a0..27781d2 100644 --- a/drivers/ide/pci/piix.c +++ b/drivers/ide/pci/piix.c @@ -306,6 +306,7 @@ static const struct ich_laptop ich_laptop[] = { { 0x27DF, 0x0005, 0x0280 }, /* ICH7 on Acer 5602WLMi */ { 0x27DF, 0x1025, 0x0110 }, /* ICH7 on Acer 3682WLMi */ { 0x27DF, 0x1043, 0x1267 }, /* ICH7 on Asus W5F */ + { 0x27DF, 0x103C, 0x30A1 }, /* ICH7 on HP Compaq nc2400 */ { 0x24CA, 0x1025, 0x0061 }, /* ICH4 on Acer Aspire 2023WLMi */ /* end marker */ { 0, } diff --git a/drivers/ide/pci/sc1200.c b/drivers/ide/pci/sc1200.c index 0a7b320..707d5ff 100644 --- a/drivers/ide/pci/sc1200.c +++ b/drivers/ide/pci/sc1200.c @@ -186,8 +186,7 @@ static void sc1200_set_dma_mode(ide_drive_t *drive, const u8 mode) } break; default: - BUG(); - break; + return; } if (unit == 0) { /* are we configuring drive0? */ diff --git a/drivers/ide/pci/siimage.c b/drivers/ide/pci/siimage.c index 6d99441..5709c25 100644 --- a/drivers/ide/pci/siimage.c +++ b/drivers/ide/pci/siimage.c @@ -1,5 +1,5 @@ /* - * linux/drivers/ide/pci/siimage.c Version 1.18 Oct 18 2007 + * linux/drivers/ide/pci/siimage.c Version 1.19 Nov 16 2007 * * Copyright (C) 2001-2002 Andre Hedrick <andre@linux-ide.org> * Copyright (C) 2003 Red Hat <alan@redhat.com> @@ -460,48 +460,6 @@ static void sil_sata_pre_reset(ide_drive_t *drive) } /** - * siimage_reset - reset a device on an siimage controller - * @drive: drive to reset - * - * Perform a controller level reset fo the device. For - * SATA we must also check the PHY. - */ - -static void siimage_reset (ide_drive_t *drive) -{ - ide_hwif_t *hwif = HWIF(drive); - u8 reset = 0; - unsigned long addr = siimage_selreg(hwif, 0); - - if (hwif->mmio) { - reset = hwif->INB(addr); - hwif->OUTB((reset|0x03), addr); - /* FIXME:posting */ - udelay(25); - hwif->OUTB(reset, addr); - (void) hwif->INB(addr); - } else { - pci_read_config_byte(hwif->pci_dev, addr, &reset); - pci_write_config_byte(hwif->pci_dev, addr, reset|0x03); - udelay(25); - pci_write_config_byte(hwif->pci_dev, addr, reset); - pci_read_config_byte(hwif->pci_dev, addr, &reset); - } - - if (SATA_STATUS_REG) { - /* SATA_STATUS_REG is valid only when in MMIO mode */ - u32 sata_stat = readl((void __iomem *)SATA_STATUS_REG); - printk(KERN_WARNING "%s: reset phy, status=0x%08x, %s\n", - hwif->name, sata_stat, __FUNCTION__); - if (!(sata_stat)) { - printk(KERN_WARNING "%s: reset phy dead, status=0x%08x\n", - hwif->name, sata_stat); - drive->failures++; - } - } -} - -/** * proc_reports_siimage - add siimage controller to proc * @dev: PCI device * @clocking: SCSC value @@ -857,7 +815,6 @@ static void __devinit init_hwif_siimage(ide_hwif_t *hwif) { u8 sata = is_sata(hwif); - hwif->resetproc = &siimage_reset; hwif->set_pio_mode = &sil_set_pio_mode; hwif->set_dma_mode = &sil_set_dma_mode; diff --git a/drivers/ide/pci/sis5513.c b/drivers/ide/pci/sis5513.c index 6b7bb53..d90b429 100644 --- a/drivers/ide/pci/sis5513.c +++ b/drivers/ide/pci/sis5513.c @@ -356,7 +356,6 @@ static void sis_set_dma_mode(ide_drive_t *drive, const u8 speed) sis_program_timings(drive, speed); break; default: - BUG(); break; } } @@ -527,6 +526,7 @@ static const struct sis_laptop sis_laptop[] = { /* devid, subvendor, subdev */ { 0x5513, 0x1043, 0x1107 }, /* ASUS A6K */ { 0x5513, 0x1734, 0x105f }, /* FSC Amilo A1630 */ + { 0x5513, 0x1071, 0x8640 }, /* EasyNote K5305 */ /* end marker */ { 0, } }; diff --git a/drivers/ide/pci/trm290.c b/drivers/ide/pci/trm290.c index 5011ba2..0895e75 100644 --- a/drivers/ide/pci/trm290.c +++ b/drivers/ide/pci/trm290.c @@ -240,9 +240,6 @@ static int trm290_ide_dma_test_irq (ide_drive_t *drive) return (status == 0x00ff); } -/* - * Invoked from ide-dma.c at boot time. - */ static void __devinit init_hwif_trm290(ide_hwif_t *hwif) { unsigned int cfgbase = 0; diff --git a/drivers/ide/ppc/pmac.c b/drivers/ide/ppc/pmac.c index 816b531..7f7a598 100644 --- a/drivers/ide/ppc/pmac.c +++ b/drivers/ide/ppc/pmac.c @@ -1138,6 +1138,7 @@ pmac_ide_setup_device(pmac_ide_hwif_t *pmif, ide_hwif_t *hwif) hwif->drives[0].autotune = IDE_TUNE_AUTO; hwif->drives[1].autotune = IDE_TUNE_AUTO; hwif->host_flags = IDE_HFLAG_SET_PIO_MODE_KEEP_DMA | + IDE_HFLAG_PIO_NO_DOWNGRADE | IDE_HFLAG_POST_SET_MODE; hwif->pio_mask = ATA_PIO4; hwif->set_pio_mode = pmac_ide_set_pio_mode; @@ -1512,7 +1513,7 @@ pmac_ide_build_dmatable(ide_drive_t *drive, struct request *rq) if (pmif->broken_dma && cur_addr & (L1_CACHE_BYTES - 1)) { if (pmif->broken_dma_warn == 0) { - printk(KERN_WARNING "%s: DMA on non aligned address," + printk(KERN_WARNING "%s: DMA on non aligned address, " "switching to PIO on Ohare chipset\n", drive->name); pmif->broken_dma_warn = 1; } diff --git a/drivers/ide/setup-pci.c b/drivers/ide/setup-pci.c index 02d14bf..25fd090 100644 --- a/drivers/ide/setup-pci.c +++ b/drivers/ide/setup-pci.c @@ -7,11 +7,6 @@ * May be copied or modified under the terms of the GNU General Public License */ -/* - * This module provides support for automatic detection and - * configuration of all PCI IDE interfaces present in a system. - */ - #include <linux/module.h> #include <linux/types.h> #include <linux/kernel.h> diff --git a/drivers/infiniband/hw/cxgb3/iwch_provider.c b/drivers/infiniband/hw/cxgb3/iwch_provider.c index f0c7775..b5436ca 100644 --- a/drivers/infiniband/hw/cxgb3/iwch_provider.c +++ b/drivers/infiniband/hw/cxgb3/iwch_provider.c @@ -1000,6 +1000,7 @@ static int iwch_query_device(struct ib_device *ibdev, props->max_sge = dev->attr.max_sge_per_wr; props->max_sge_rd = 1; props->max_qp_rd_atom = dev->attr.max_rdma_reads_per_qp; + props->max_qp_init_rd_atom = dev->attr.max_rdma_reads_per_qp; props->max_cq = dev->attr.max_cqs; props->max_cqe = dev->attr.max_cqes_per_cq; props->max_mr = dev->attr.max_mem_regs; diff --git a/drivers/infiniband/hw/ehca/ehca_av.c b/drivers/infiniband/hw/ehca/ehca_av.c index 97d1086..f7782c8 100644 --- a/drivers/infiniband/hw/ehca/ehca_av.c +++ b/drivers/infiniband/hw/ehca/ehca_av.c @@ -50,6 +50,42 @@ static struct kmem_cache *av_cache; +int ehca_calc_ipd(struct ehca_shca *shca, int port, + enum ib_rate path_rate, u32 *ipd) +{ + int path = ib_rate_to_mult(path_rate); + int link, ret; + struct ib_port_attr pa; + + if (path_rate == IB_RATE_PORT_CURRENT) { + *ipd = 0; + return 0; + } + + if (unlikely(path < 0)) { + ehca_err(&shca->ib_device, "Invalid static rate! path_rate=%x", + path_rate); + return -EINVAL; + } + + ret = ehca_query_port(&shca->ib_device, port, &pa); + if (unlikely(ret < 0)) { + ehca_err(&shca->ib_device, "Failed to query port ret=%i", ret); + return ret; + } + + link = ib_width_enum_to_int(pa.active_width) * pa.active_speed; + + if (path >= link) + /* no need to throttle if path faster than link */ + *ipd = 0; + else + /* IPD = round((link / path) - 1) */ + *ipd = ((link + (path >> 1)) / path) - 1; + + return 0; +} + struct ib_ah *ehca_create_ah(struct ib_pd *pd, struct ib_ah_attr *ah_attr) { int ret; @@ -69,15 +105,13 @@ struct ib_ah *ehca_create_ah(struct ib_pd *pd, struct ib_ah_attr *ah_attr) av->av.slid_path_bits = ah_attr->src_path_bits; if (ehca_static_rate < 0) { - int ah_mult = ib_rate_to_mult(ah_attr->static_rate); - int ehca_mult = - ib_rate_to_mult(shca->sport[ah_attr->port_num].rate ); - - if (ah_mult >= ehca_mult) - av->av.ipd = 0; - else - av->av.ipd = (ah_mult > 0) ? - ((ehca_mult - 1) / ah_mult) : 0; + u32 ipd; + if (ehca_calc_ipd(shca, ah_attr->port_num, + ah_attr->static_rate, &ipd)) { + ret = -EINVAL; + goto create_ah_exit1; + } + av->av.ipd = ipd; } else av->av.ipd = ehca_static_rate; diff --git a/drivers/infiniband/hw/ehca/ehca_classes.h b/drivers/infiniband/hw/ehca/ehca_classes.h index 2d660ae..87f12d4 100644 --- a/drivers/infiniband/hw/ehca/ehca_classes.h +++ b/drivers/infiniband/hw/ehca/ehca_classes.h @@ -95,7 +95,6 @@ struct ehca_sma_attr { struct ehca_sport { struct ib_cq *ibcq_aqp1; struct ib_qp *ibqp_aqp1; - enum ib_rate rate; enum ib_port_state port_state; struct ehca_sma_attr saved_attr; }; diff --git a/drivers/infiniband/hw/ehca/ehca_hca.c b/drivers/infiniband/hw/ehca/ehca_hca.c index 15806d1..5bd7b59 100644 --- a/drivers/infiniband/hw/ehca/ehca_hca.c +++ b/drivers/infiniband/hw/ehca/ehca_hca.c @@ -151,7 +151,6 @@ int ehca_query_port(struct ib_device *ibdev, } memset(props, 0, sizeof(struct ib_port_attr)); - props->state = rblock->state; switch (rblock->max_mtu) { case 0x1: @@ -188,11 +187,20 @@ int ehca_query_port(struct ib_device *ibdev, props->subnet_timeout = rblock->subnet_timeout; props->init_type_reply = rblock->init_type_reply; - props->active_width = IB_WIDTH_12X; - props->active_speed = 0x1; - - /* at the moment (logical) link state is always LINK_UP */ - props->phys_state = 0x5; + if (rblock->state && rblock->phys_width) { + props->phys_state = rblock->phys_pstate; + props->state = rblock->phys_state; + props->active_width = rblock->phys_width; + props->active_speed = rblock->phys_speed; + } else { + /* old firmware releases don't report physical + * port info, so use default values + */ + props->phys_state = 5; + props->state = rblock->state; + props->active_width = IB_WIDTH_12X; + props->active_speed = 0x1; + } query_port1: ehca_free_fw_ctrlblock(rblock); diff --git a/drivers/infiniband/hw/ehca/ehca_iverbs.h b/drivers/infiniband/hw/ehca/ehca_iverbs.h index dce503b..5485799 100644 --- a/drivers/infiniband/hw/ehca/ehca_iverbs.h +++ b/drivers/infiniband/hw/ehca/ehca_iverbs.h @@ -189,6 +189,9 @@ int ehca_mmap(struct ib_ucontext *context, struct vm_area_struct *vma); void ehca_poll_eqs(unsigned long data); +int ehca_calc_ipd(struct ehca_shca *shca, int port, + enum ib_rate path_rate, u32 *ipd); + #ifdef CONFIG_PPC_64K_PAGES void *ehca_alloc_fw_ctrlblock(gfp_t flags); void ehca_free_fw_ctrlblock(void *ptr); diff --git a/drivers/infiniband/hw/ehca/ehca_main.c b/drivers/infiniband/hw/ehca/ehca_main.c index c6cd38c..90d4334 100644 --- a/drivers/infiniband/hw/ehca/ehca_main.c +++ b/drivers/infiniband/hw/ehca/ehca_main.c @@ -327,9 +327,6 @@ static int ehca_sense_attributes(struct ehca_shca *shca) shca->hw_level = ehca_hw_level; ehca_gen_dbg(" ... hardware level=%x", shca->hw_level); - shca->sport[0].rate = IB_RATE_30_GBPS; - shca->sport[1].rate = IB_RATE_30_GBPS; - shca->hca_cap = rblock->hca_cap_indicators; ehca_gen_dbg(" ... HCA capabilities:"); for (i = 0; i < ARRAY_SIZE(hca_cap_descr); i++) diff --git a/drivers/infiniband/hw/ehca/ehca_qp.c b/drivers/infiniband/hw/ehca/ehca_qp.c index de18264..dd12668 100644 --- a/drivers/infiniband/hw/ehca/ehca_qp.c +++ b/drivers/infiniband/hw/ehca/ehca_qp.c @@ -1196,10 +1196,6 @@ static int internal_modify_qp(struct ib_qp *ibqp, update_mask |= EHCA_BMASK_SET(MQPCB_MASK_QKEY, 1); } if (attr_mask & IB_QP_AV) { - int ah_mult = ib_rate_to_mult(attr->ah_attr.static_rate); - int ehca_mult = ib_rate_to_mult(shca->sport[my_qp-> - init_attr.port_num].rate); - mqpcb->dlid = attr->ah_attr.dlid; update_mask |= EHCA_BMASK_SET(MQPCB_MASK_DLID, 1); mqpcb->source_path_bits = attr->ah_attr.src_path_bits; @@ -1207,11 +1203,12 @@ static int internal_modify_qp(struct ib_qp *ibqp, mqpcb->service_level = attr->ah_attr.sl; update_mask |= EHCA_BMASK_SET(MQPCB_MASK_SERVICE_LEVEL, 1); - if (ah_mult < ehca_mult) - mqpcb->max_static_rate = (ah_mult > 0) ? - ((ehca_mult - 1) / ah_mult) : 0; - else - mqpcb->max_static_rate = 0; + if (ehca_calc_ipd(shca, mqpcb->prim_phys_port, + attr->ah_attr.static_rate, + &mqpcb->max_static_rate)) { + ret = -EINVAL; + goto modify_qp_exit2; + } update_mask |= EHCA_BMASK_SET(MQPCB_MASK_MAX_STATIC_RATE, 1); /* @@ -1280,10 +1277,6 @@ static int internal_modify_qp(struct ib_qp *ibqp, (MQPCB_MASK_RDMA_ATOMIC_OUTST_DEST_QP, 1); } if (attr_mask & IB_QP_ALT_PATH) { - int ah_mult = ib_rate_to_mult(attr->alt_ah_attr.static_rate); - int ehca_mult = ib_rate_to_mult( - shca->sport[my_qp->init_attr.port_num].rate); - if (attr->alt_port_num < 1 || attr->alt_port_num > shca->num_ports) { ret = -EINVAL; @@ -1309,10 +1302,12 @@ static int internal_modify_qp(struct ib_qp *ibqp, mqpcb->source_path_bits_al = attr->alt_ah_attr.src_path_bits; mqpcb->service_level_al = attr->alt_ah_attr.sl; - if (ah_mult > 0 && ah_mult < ehca_mult) - mqpcb->max_static_rate_al = (ehca_mult - 1) / ah_mult; - else - mqpcb->max_static_rate_al = 0; + if (ehca_calc_ipd(shca, mqpcb->alt_phys_port, + attr->alt_ah_attr.static_rate, + &mqpcb->max_static_rate_al)) { + ret = -EINVAL; + goto modify_qp_exit2; + } /* OpenIB doesn't support alternate retry counts - copy them */ mqpcb->retry_count_al = mqpcb->retry_count; diff --git a/drivers/infiniband/hw/ehca/hipz_hw.h b/drivers/infiniband/hw/ehca/hipz_hw.h index d9739e5..485b840 100644 --- a/drivers/infiniband/hw/ehca/hipz_hw.h +++ b/drivers/infiniband/hw/ehca/hipz_hw.h @@ -402,7 +402,11 @@ struct hipz_query_port { u64 max_msg_sz; u32 max_mtu; u32 vl_cap; - u8 reserved2[1900]; + u32 phys_pstate; + u32 phys_state; + u32 phys_speed; + u32 phys_width; + u8 reserved2[1884]; u64 guid_entries[255]; } __attribute__ ((packed)); diff --git a/drivers/infiniband/hw/ipath/ipath_cq.c b/drivers/infiniband/hw/ipath/ipath_cq.c index 645ed71..d1380c7 100644 --- a/drivers/infiniband/hw/ipath/ipath_cq.c +++ b/drivers/infiniband/hw/ipath/ipath_cq.c @@ -395,16 +395,13 @@ int ipath_resize_cq(struct ib_cq *ibcq, int cqe, struct ib_udata *udata) goto bail; } - /* - * Return the address of the WC as the offset to mmap. - * See ipath_mmap() for details. - */ + /* Check that we can write the offset to mmap. */ if (udata && udata->outlen >= sizeof(__u64)) { - __u64 offset = (__u64) wc; + __u64 offset = 0; ret = ib_copy_to_udata(udata, &offset, sizeof(offset)); if (ret) - goto bail; + goto bail_free; } spin_lock_irq(&cq->lock); @@ -424,10 +421,8 @@ int ipath_resize_cq(struct ib_cq *ibcq, int cqe, struct ib_udata *udata) else n = head - tail; if (unlikely((u32)cqe < n)) { - spin_unlock_irq(&cq->lock); - vfree(wc); ret = -EOVERFLOW; - goto bail; + goto bail_unlock; } for (n = 0; tail != head; n++) { if (cq->ip) @@ -452,6 +447,18 @@ int ipath_resize_cq(struct ib_cq *ibcq, int cqe, struct ib_udata *udata) struct ipath_mmap_info *ip = cq->ip; ipath_update_mmap_info(dev, ip, sz, wc); + + /* + * Return the offset to mmap. + * See ipath_mmap() for details. + */ + if (udata && udata->outlen >= sizeof(__u64)) { + ret = ib_copy_to_udata(udata, &ip->offset, + sizeof(ip->offset)); + if (ret) + goto bail; + } + spin_lock_irq(&dev->pending_lock); if (list_empty(&ip->pending_mmaps)) list_add(&ip->pending_mmaps, &dev->pending_mmaps); @@ -459,7 +466,12 @@ int ipath_resize_cq(struct ib_cq *ibcq, int cqe, struct ib_udata *udata) } ret = 0; + goto bail; +bail_unlock: + spin_unlock_irq(&cq->lock); +bail_free: + vfree(wc); bail: return ret; } diff --git a/drivers/infiniband/hw/ipath/ipath_qp.c b/drivers/infiniband/hw/ipath/ipath_qp.c index 6a41fdb..b997ff8 100644 --- a/drivers/infiniband/hw/ipath/ipath_qp.c +++ b/drivers/infiniband/hw/ipath/ipath_qp.c @@ -835,7 +835,8 @@ struct ib_qp *ipath_create_qp(struct ib_pd *ibpd, init_attr->qp_type); if (err) { ret = ERR_PTR(err); - goto bail_rwq; + vfree(qp->r_rq.wq); + goto bail_qp; } qp->ip = NULL; ipath_reset_qp(qp); @@ -863,7 +864,7 @@ struct ib_qp *ipath_create_qp(struct ib_pd *ibpd, sizeof(offset)); if (err) { ret = ERR_PTR(err); - goto bail_rwq; + goto bail_ip; } } else { u32 s = sizeof(struct ipath_rwq) + @@ -875,7 +876,7 @@ struct ib_qp *ipath_create_qp(struct ib_pd *ibpd, qp->r_rq.wq); if (!qp->ip) { ret = ERR_PTR(-ENOMEM); - goto bail_rwq; + goto bail_ip; } err = ib_copy_to_udata(udata, &(qp->ip->offset), @@ -907,9 +908,11 @@ struct ib_qp *ipath_create_qp(struct ib_pd *ibpd, goto bail; bail_ip: - kfree(qp->ip); -bail_rwq: - vfree(qp->r_rq.wq); + if (qp->ip) + kref_put(&qp->ip->ref, ipath_release_mmap_info); + else + vfree(qp->r_rq.wq); + ipath_free_qp(&dev->qp_table, qp); bail_qp: kfree(qp); bail_swq: diff --git a/drivers/infiniband/hw/ipath/ipath_rc.c b/drivers/infiniband/hw/ipath/ipath_rc.c index 5c29b2b..120a61b 100644 --- a/drivers/infiniband/hw/ipath/ipath_rc.c +++ b/drivers/infiniband/hw/ipath/ipath_rc.c @@ -959,8 +959,9 @@ static int do_rc_ack(struct ipath_qp *qp, u32 aeth, u32 psn, int opcode, /* If this is a partial ACK, reset the retransmit timer. */ if (qp->s_last != qp->s_tail) { spin_lock(&dev->pending_lock); - list_add_tail(&qp->timerwait, - &dev->pending[dev->pending_index]); + if (list_empty(&qp->timerwait)) + list_add_tail(&qp->timerwait, + &dev->pending[dev->pending_index]); spin_unlock(&dev->pending_lock); /* * If we get a partial ACK for a resent operation, diff --git a/drivers/infiniband/hw/ipath/ipath_srq.c b/drivers/infiniband/hw/ipath/ipath_srq.c index 40c36ec..2fef36f4 100644 --- a/drivers/infiniband/hw/ipath/ipath_srq.c +++ b/drivers/infiniband/hw/ipath/ipath_srq.c @@ -59,7 +59,7 @@ int ipath_post_srq_receive(struct ib_srq *ibsrq, struct ib_recv_wr *wr, if ((unsigned) wr->num_sge > srq->rq.max_sge) { *bad_wr = wr; - ret = -ENOMEM; + ret = -EINVAL; goto bail; } @@ -211,11 +211,11 @@ int ipath_modify_srq(struct ib_srq *ibsrq, struct ib_srq_attr *attr, struct ib_udata *udata) { struct ipath_srq *srq = to_isrq(ibsrq); + struct ipath_rwq *wq; int ret = 0; if (attr_mask & IB_SRQ_MAX_WR) { struct ipath_rwq *owq; - struct ipath_rwq *wq; struct ipath_rwqe *p; u32 sz, size, n, head, tail; @@ -236,27 +236,20 @@ int ipath_modify_srq(struct ib_srq *ibsrq, struct ib_srq_attr *attr, goto bail; } - /* - * Return the address of the RWQ as the offset to mmap. - * See ipath_mmap() for details. - */ + /* Check that we can write the offset to mmap. */ if (udata && udata->inlen >= sizeof(__u64)) { __u64 offset_addr; - __u64 offset = (__u64) wq; + __u64 offset = 0; ret = ib_copy_from_udata(&offset_addr, udata, sizeof(offset_addr)); - if (ret) { - vfree(wq); - goto bail; - } + if (ret) + goto bail_free; udata->outbuf = (void __user *) offset_addr; ret = ib_copy_to_udata(udata, &offset, sizeof(offset)); - if (ret) { - vfree(wq); - goto bail; - } + if (ret) + goto bail_free; } spin_lock_irq(&srq->rq.lock); @@ -277,10 +270,8 @@ int ipath_modify_srq(struct ib_srq *ibsrq, struct ib_srq_attr *attr, else n -= tail; if (size <= n) { - spin_unlock_irq(&srq->rq.lock); - vfree(wq); ret = -EINVAL; - goto bail; + goto bail_unlock; } n = 0; p = wq->wq; @@ -314,6 +305,18 @@ int ipath_modify_srq(struct ib_srq *ibsrq, struct ib_srq_attr *attr, u32 s = sizeof(struct ipath_rwq) + size * sz; ipath_update_mmap_info(dev, ip, s, wq); + + /* + * Return the offset to mmap. + * See ipath_mmap() for details. + */ + if (udata && udata->inlen >= sizeof(__u64)) { + ret = ib_copy_to_udata(udata, &ip->offset, + sizeof(ip->offset)); + if (ret) + goto bail; + } + spin_lock_irq(&dev->pending_lock); if (list_empty(&ip->pending_mmaps)) list_add(&ip->pending_mmaps, @@ -328,7 +331,12 @@ int ipath_modify_srq(struct ib_srq *ibsrq, struct ib_srq_attr *attr, srq->limit = attr->srq_limit; spin_unlock_irq(&srq->rq.lock); } + goto bail; +bail_unlock: + spin_unlock_irq(&srq->rq.lock); +bail_free: + vfree(wq); bail: return ret; } diff --git a/drivers/infiniband/hw/ipath/ipath_verbs.c b/drivers/infiniband/hw/ipath/ipath_verbs.c index 74f77e7..c4c9984 100644 --- a/drivers/infiniband/hw/ipath/ipath_verbs.c +++ b/drivers/infiniband/hw/ipath/ipath_verbs.c @@ -302,8 +302,10 @@ static int ipath_post_one_send(struct ipath_qp *qp, struct ib_send_wr *wr) next = qp->s_head + 1; if (next >= qp->s_size) next = 0; - if (next == qp->s_last) - goto bail_inval; + if (next == qp->s_last) { + ret = -ENOMEM; + goto bail; + } wqe = get_swqe_ptr(qp, qp->s_head); wqe->wr = *wr; @@ -404,7 +406,7 @@ static int ipath_post_receive(struct ib_qp *ibqp, struct ib_recv_wr *wr, if ((unsigned) wr->num_sge > qp->r_rq.max_sge) { *bad_wr = wr; - ret = -ENOMEM; + ret = -EINVAL; goto bail; } diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c index a03a65e..c9f6077 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_main.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c @@ -460,6 +460,9 @@ static struct ipoib_path *path_rec_create(struct net_device *dev, void *gid) struct ipoib_dev_priv *priv = netdev_priv(dev); struct ipoib_path *path; + if (!priv->broadcast) + return NULL; + path = kzalloc(sizeof *path, GFP_ATOMIC); if (!path) return NULL; diff --git a/drivers/infiniband/ulp/iser/iser_memory.c b/drivers/infiniband/ulp/iser/iser_memory.c index d687980..4a17743 100644 --- a/drivers/infiniband/ulp/iser/iser_memory.c +++ b/drivers/infiniband/ulp/iser/iser_memory.c @@ -310,13 +310,15 @@ static unsigned int iser_data_buf_aligned_len(struct iser_data_buf *data, if (i + 1 < data->dma_nents) { next_addr = ib_sg_dma_address(ibdev, sg_next(sg)); /* are i, i+1 fragments of the same page? */ - if (end_addr == next_addr) + if (end_addr == next_addr) { + cnt++; continue; - else if (!IS_4K_ALIGNED(end_addr)) { + } else if (!IS_4K_ALIGNED(end_addr)) { ret_len = cnt + 1; break; } } + cnt++; } if (i == data->dma_nents) ret_len = cnt; /* loop ended */ diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig index 2316a01..dfa6592 100644 --- a/drivers/input/keyboard/Kconfig +++ b/drivers/input/keyboard/Kconfig @@ -286,7 +286,7 @@ config KEYBOARD_MAPLE config KEYBOARD_BFIN tristate "Blackfin BF54x keypad support" - depends on BF54x + depends on (BF54x && !BF544) help Say Y here if you want to use the BF54x keypad. diff --git a/drivers/input/keyboard/gpio_keys.c b/drivers/input/keyboard/gpio_keys.c index 3eddf52..6a9ca4b 100644 --- a/drivers/input/keyboard/gpio_keys.c +++ b/drivers/input/keyboard/gpio_keys.c @@ -75,16 +75,32 @@ static int __devinit gpio_keys_probe(struct platform_device *pdev) for (i = 0; i < pdata->nbuttons; i++) { struct gpio_keys_button *button = &pdata->buttons[i]; - int irq = gpio_to_irq(button->gpio); + int irq; unsigned int type = button->type ?: EV_KEY; + error = gpio_request(button->gpio, button->desc ?: "gpio_keys"); + if (error < 0) { + pr_err("gpio-keys: failed to request GPIO %d," + " error %d\n", button->gpio, error); + goto fail; + } + + error = gpio_direction_input(button->gpio); + if (error < 0) { + pr_err("gpio-keys: failed to configure input" + " direction for GPIO %d, error %d\n", + button->gpio, error); + gpio_free(button->gpio); + goto fail; + } + + irq = gpio_to_irq(button->gpio); if (irq < 0) { error = irq; - printk(KERN_ERR - "gpio-keys: " - "Unable to get irq number for GPIO %d," - "error %d\n", + pr_err("gpio-keys: Unable to get irq number" + " for GPIO %d, error %d\n", button->gpio, error); + gpio_free(button->gpio); goto fail; } @@ -94,9 +110,9 @@ static int __devinit gpio_keys_probe(struct platform_device *pdev) button->desc ? button->desc : "gpio_keys", pdev); if (error) { - printk(KERN_ERR - "gpio-keys: Unable to claim irq %d; error %d\n", + pr_err("gpio-keys: Unable to claim irq %d; error %d\n", irq, error); + gpio_free(button->gpio); goto fail; } @@ -108,8 +124,7 @@ static int __devinit gpio_keys_probe(struct platform_device *pdev) error = input_register_device(input); if (error) { - printk(KERN_ERR - "gpio-keys: Unable to register input device, " + pr_err("gpio-keys: Unable to register input device, " "error: %d\n", error); goto fail; } @@ -119,8 +134,10 @@ static int __devinit gpio_keys_probe(struct platform_device *pdev) return 0; fail: - while (--i >= 0) + while (--i >= 0) { free_irq(gpio_to_irq(pdata->buttons[i].gpio), pdev); + gpio_free(pdata->buttons[i].gpio); + } platform_set_drvdata(pdev, NULL); input_free_device(input); @@ -139,6 +156,7 @@ static int __devexit gpio_keys_remove(struct platform_device *pdev) for (i = 0; i < pdata->nbuttons; i++) { int irq = gpio_to_irq(pdata->buttons[i].gpio); free_irq(irq, pdev); + gpio_free(pdata->buttons[i].gpio); } input_unregister_device(input); diff --git a/drivers/input/serio/Kconfig b/drivers/input/serio/Kconfig index 5ce632c..b88569e 100644 --- a/drivers/input/serio/Kconfig +++ b/drivers/input/serio/Kconfig @@ -21,7 +21,7 @@ if SERIO config SERIO_I8042 tristate "i8042 PC Keyboard controller" if EMBEDDED || !X86 default y - depends on !PARISC && (!ARM || ARCH_SHARK || FOOTBRIDGE_HOST) && !M68K && !BFIN + depends on !PARISC && (!ARM || ARCH_SHARK || FOOTBRIDGE_HOST) && !M68K && !BLACKFIN ---help--- i8042 is the chip over which the standard AT keyboard and PS/2 mouse are connected to the computer. If you use these devices, diff --git a/drivers/input/serio/i8042-x86ia64io.h b/drivers/input/serio/i8042-x86ia64io.h index f8fe421..c5e68dc 100644 --- a/drivers/input/serio/i8042-x86ia64io.h +++ b/drivers/input/serio/i8042-x86ia64io.h @@ -110,6 +110,14 @@ static struct dmi_system_id __initdata i8042_dmi_noloop_table[] = { DMI_MATCH(DMI_PRODUCT_VERSION, "5a"), }, }, + { + .ident = "Microsoft Virtual Machine", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Microsoft Corporation"), + DMI_MATCH(DMI_PRODUCT_NAME, "Virtual Machine"), + DMI_MATCH(DMI_PRODUCT_VERSION, "VS2005R2"), + }, + }, { } }; diff --git a/drivers/isdn/hisax/hfcscard.c b/drivers/isdn/hisax/hfcscard.c index 57670dc..909d670 100644 --- a/drivers/isdn/hisax/hfcscard.c +++ b/drivers/isdn/hisax/hfcscard.c @@ -118,8 +118,7 @@ hfcs_card_msg(struct IsdnCardState *cs, int mt, void *arg) return(0); case CARD_INIT: delay = (75*HZ)/100 +1; - cs->hw.hfcD.timer.expires = jiffies + delay; - add_timer(&cs->hw.hfcD.timer); + mod_timer(&cs->hw.hfcD.timer, jiffies + delay); spin_lock_irqsave(&cs->lock, flags); reset_hfcs(cs); init2bds0(cs); diff --git a/drivers/isdn/i4l/isdn_common.c b/drivers/isdn/i4l/isdn_common.c index c6df292..d695295 100644 --- a/drivers/isdn/i4l/isdn_common.c +++ b/drivers/isdn/i4l/isdn_common.c @@ -1515,6 +1515,7 @@ isdn_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg) if (copy_from_user(&iocts, argp, sizeof(isdn_ioctl_struct))) return -EFAULT; + iocts.drvid[sizeof(iocts.drvid)-1] = 0; if (strlen(iocts.drvid)) { if ((p = strchr(iocts.drvid, ','))) *p = 0; @@ -1599,6 +1600,7 @@ isdn_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg) if (copy_from_user(&iocts, argp, sizeof(isdn_ioctl_struct))) return -EFAULT; + iocts.drvid[sizeof(iocts.drvid)-1] = 0; if (strlen(iocts.drvid)) { drvidx = -1; for (i = 0; i < ISDN_MAX_DRIVERS; i++) @@ -1643,7 +1645,7 @@ isdn_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg) } else { p = (char __user *) iocts.arg; for (i = 0; i < 10; i++) { - sprintf(bname, "%s%s", + snprintf(bname, sizeof(bname), "%s%s", strlen(dev->drv[drvidx]->msn2eaz[i]) ? dev->drv[drvidx]->msn2eaz[i] : "_", (i < 9) ? "," : "\0"); @@ -1673,6 +1675,7 @@ isdn_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg) char *p; if (copy_from_user(&iocts, argp, sizeof(isdn_ioctl_struct))) return -EFAULT; + iocts.drvid[sizeof(iocts.drvid)-1] = 0; if (strlen(iocts.drvid)) { if ((p = strchr(iocts.drvid, ','))) *p = 0; diff --git a/drivers/isdn/i4l/isdn_net.c b/drivers/isdn/i4l/isdn_net.c index b39d1f5..ced83c2 100644 --- a/drivers/isdn/i4l/isdn_net.c +++ b/drivers/isdn/i4l/isdn_net.c @@ -2104,7 +2104,7 @@ isdn_net_find_icall(int di, int ch, int idx, setup_parm *setup) u_long flags; isdn_net_dev *p; isdn_net_phone *n; - char nr[32]; + char nr[ISDN_MSNLEN]; char *my_eaz; /* Search name in netdev-chain */ @@ -2113,7 +2113,7 @@ isdn_net_find_icall(int di, int ch, int idx, setup_parm *setup) nr[1] = '\0'; printk(KERN_INFO "isdn_net: Incoming call without OAD, assuming '0'\n"); } else - strcpy(nr, setup->phone); + strlcpy(nr, setup->phone, ISDN_MSNLEN); si1 = (int) setup->si1; si2 = (int) setup->si2; if (!setup->eazmsn[0]) { @@ -2789,7 +2789,7 @@ isdn_net_setcfg(isdn_net_ioctl_cfg * cfg) chidx = -1; } } - strcpy(lp->msn, cfg->eaz); + strlcpy(lp->msn, cfg->eaz, sizeof(lp->msn)); lp->pre_device = drvidx; lp->pre_channel = chidx; lp->onhtime = cfg->onhtime; @@ -2936,7 +2936,7 @@ isdn_net_addphone(isdn_net_ioctl_phone * phone) if (p) { if (!(n = kmalloc(sizeof(isdn_net_phone), GFP_KERNEL))) return -ENOMEM; - strcpy(n->num, phone->phone); + strlcpy(n->num, phone->phone, sizeof(n->num)); n->next = p->local->phone[phone->outgoing & 1]; p->local->phone[phone->outgoing & 1] = n; return 0; diff --git a/drivers/isdn/sc/card.h b/drivers/isdn/sc/card.h index 5992f63..0120bcf 100644 --- a/drivers/isdn/sc/card.h +++ b/drivers/isdn/sc/card.h @@ -109,7 +109,7 @@ void memcpy_fromshmem(int card, void *dest, const void *src, size_t n); int get_card_from_id(int driver); int indicate_status(int card, int event, ulong Channel, char *Data); irqreturn_t interrupt_handler(int interrupt, void *cardptr); -int sndpkt(int devId, int channel, struct sk_buff *data); +int sndpkt(int devId, int channel, int ack, struct sk_buff *data); void rcvpkt(int card, RspMessage *rcvmsg); int command(isdn_ctrl *cmd); int reset(int card); diff --git a/drivers/isdn/sc/packet.c b/drivers/isdn/sc/packet.c index 92016a2..5ff6ae8 100644 --- a/drivers/isdn/sc/packet.c +++ b/drivers/isdn/sc/packet.c @@ -20,7 +20,7 @@ #include "message.h" #include "card.h" -int sndpkt(int devId, int channel, struct sk_buff *data) +int sndpkt(int devId, int channel, int ack, struct sk_buff *data) { LLData ReqLnkWrite; int status; diff --git a/drivers/isdn/sc/shmem.c b/drivers/isdn/sc/shmem.c index e0331e0..712220c 100644 --- a/drivers/isdn/sc/shmem.c +++ b/drivers/isdn/sc/shmem.c @@ -50,7 +50,7 @@ void memcpy_toshmem(int card, void *dest, const void *src, size_t n) outb(((sc_adapter[card]->shmem_magic + ch * SRAM_PAGESIZE) >> 14) | 0x80, sc_adapter[card]->ioport[sc_adapter[card]->shmem_pgport]); - memcpy_toio(sc_adapter[card]->rambase + dest_rem, src, n); + memcpy_toio((void __iomem *)(sc_adapter[card]->rambase + dest_rem), src, n); spin_unlock_irqrestore(&sc_adapter[card]->lock, flags); pr_debug("%s: set page to %#x\n",sc_adapter[card]->devicename, ((sc_adapter[card]->shmem_magic + ch * SRAM_PAGESIZE)>>14)|0x80); diff --git a/drivers/kvm/kvm_main.c b/drivers/kvm/kvm_main.c index 07ae280..47c10b8 100644 --- a/drivers/kvm/kvm_main.c +++ b/drivers/kvm/kvm_main.c @@ -1188,8 +1188,7 @@ int emulate_invlpg(struct kvm_vcpu *vcpu, gva_t address) int emulate_clts(struct kvm_vcpu *vcpu) { - vcpu->cr0 &= ~X86_CR0_TS; - kvm_x86_ops->set_cr0(vcpu, vcpu->cr0); + kvm_x86_ops->set_cr0(vcpu, vcpu->cr0 & ~X86_CR0_TS); return X86EMUL_CONTINUE; } diff --git a/drivers/kvm/svm.c b/drivers/kvm/svm.c index 729f1cd..4e04e49 100644 --- a/drivers/kvm/svm.c +++ b/drivers/kvm/svm.c @@ -494,6 +494,7 @@ static void init_vmcb(struct vmcb *vmcb) */ /* (1ULL << INTERCEPT_SELECTIVE_CR0) | */ (1ULL << INTERCEPT_CPUID) | + (1ULL << INTERCEPT_INVD) | (1ULL << INTERCEPT_HLT) | (1ULL << INTERCEPT_INVLPGA) | (1ULL << INTERCEPT_IOIO_PROT) | @@ -507,6 +508,7 @@ static void init_vmcb(struct vmcb *vmcb) (1ULL << INTERCEPT_STGI) | (1ULL << INTERCEPT_CLGI) | (1ULL << INTERCEPT_SKINIT) | + (1ULL << INTERCEPT_WBINVD) | (1ULL << INTERCEPT_MONITOR) | (1ULL << INTERCEPT_MWAIT); @@ -561,6 +563,12 @@ static void svm_vcpu_reset(struct kvm_vcpu *vcpu) struct vcpu_svm *svm = to_svm(vcpu); init_vmcb(svm->vmcb); + + if (vcpu->vcpu_id != 0) { + svm->vmcb->save.rip = 0; + svm->vmcb->save.cs.base = svm->vcpu.sipi_vector << 12; + svm->vmcb->save.cs.selector = svm->vcpu.sipi_vector << 8; + } } static struct kvm_vcpu *svm_create_vcpu(struct kvm *kvm, unsigned int id) @@ -655,6 +663,7 @@ static void svm_vcpu_put(struct kvm_vcpu *vcpu) wrmsrl(host_save_user_msrs[i], svm->host_user_msrs[i]); rdtscll(vcpu->host_tsc); + kvm_put_guest_fpu(vcpu); } static void svm_vcpu_decache(struct kvm_vcpu *vcpu) @@ -1241,6 +1250,7 @@ static int (*svm_exit_handlers[])(struct vcpu_svm *svm, [SVM_EXIT_VINTR] = interrupt_window_interception, /* [SVM_EXIT_CR0_SEL_WRITE] = emulate_on_interception, */ [SVM_EXIT_CPUID] = cpuid_interception, + [SVM_EXIT_INVD] = emulate_on_interception, [SVM_EXIT_HLT] = halt_interception, [SVM_EXIT_INVLPG] = emulate_on_interception, [SVM_EXIT_INVLPGA] = invalid_op_interception, @@ -1255,6 +1265,7 @@ static int (*svm_exit_handlers[])(struct vcpu_svm *svm, [SVM_EXIT_STGI] = invalid_op_interception, [SVM_EXIT_CLGI] = invalid_op_interception, [SVM_EXIT_SKINIT] = invalid_op_interception, + [SVM_EXIT_WBINVD] = emulate_on_interception, [SVM_EXIT_MONITOR] = invalid_op_interception, [SVM_EXIT_MWAIT] = invalid_op_interception, }; @@ -1579,10 +1590,6 @@ static void svm_vcpu_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) #endif : "cc", "memory" ); - local_irq_disable(); - - stgi(); - if ((svm->vmcb->save.dr7 & 0xff)) load_db_regs(svm->host_db_regs); @@ -1599,6 +1606,10 @@ static void svm_vcpu_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) reload_tss(vcpu); + local_irq_disable(); + + stgi(); + svm->next_rip = 0; } diff --git a/drivers/kvm/x86_emulate.c b/drivers/kvm/x86_emulate.c index a6ace30..bd46de6 100644 --- a/drivers/kvm/x86_emulate.c +++ b/drivers/kvm/x86_emulate.c @@ -167,7 +167,7 @@ static u8 opcode_table[256] = { static u16 twobyte_table[256] = { /* 0x00 - 0x0F */ 0, SrcMem | ModRM | DstReg, 0, 0, 0, 0, ImplicitOps, 0, - 0, ImplicitOps, 0, 0, 0, ImplicitOps | ModRM, 0, 0, + ImplicitOps, ImplicitOps, 0, 0, 0, ImplicitOps | ModRM, 0, 0, /* 0x10 - 0x1F */ 0, 0, 0, 0, 0, 0, 0, 0, ImplicitOps | ModRM, 0, 0, 0, 0, 0, 0, 0, /* 0x20 - 0x2F */ @@ -448,8 +448,7 @@ struct operand { #define JMP_REL(rel) \ do { \ - _eip += (int)(rel); \ - _eip = ((op_bytes == 2) ? (uint16_t)_eip : (uint32_t)_eip); \ + register_address_increment(_eip, rel); \ } while (0) /* @@ -980,17 +979,6 @@ done_prefixes: goto cannot_emulate; dst.val = (s32) src.val; break; - case 0x6a: /* push imm8 */ - src.val = 0L; - src.val = insn_fetch(s8, 1, _eip); -push: - dst.type = OP_MEM; - dst.bytes = op_bytes; - dst.val = src.val; - register_address_increment(_regs[VCPU_REGS_RSP], -op_bytes); - dst.ptr = (void *) register_address(ctxt->ss_base, - _regs[VCPU_REGS_RSP]); - break; case 0x80 ... 0x83: /* Grp1 */ switch (modrm_reg) { case 0: @@ -1158,7 +1146,7 @@ push: } register_address_increment(_regs[VCPU_REGS_RSP], -dst.bytes); - if ((rc = ops->write_std( + if ((rc = ops->write_emulated( register_address(ctxt->ss_base, _regs[VCPU_REGS_RSP]), &dst.val, dst.bytes, ctxt->vcpu)) != 0) @@ -1243,6 +1231,17 @@ special_insn: register_address_increment(_regs[VCPU_REGS_RSP], op_bytes); no_wb = 1; /* Disable writeback. */ break; + case 0x6a: /* push imm8 */ + src.val = 0L; + src.val = insn_fetch(s8, 1, _eip); + push: + dst.type = OP_MEM; + dst.bytes = op_bytes; + dst.val = src.val; + register_address_increment(_regs[VCPU_REGS_RSP], -op_bytes); + dst.ptr = (void *) register_address(ctxt->ss_base, + _regs[VCPU_REGS_RSP]); + break; case 0x6c: /* insb */ case 0x6d: /* insw/insd */ if (kvm_emulate_pio_string(ctxt->vcpu, NULL, @@ -1359,6 +1358,7 @@ special_insn: } src.val = (unsigned long) _eip; JMP_REL(rel); + op_bytes = ad_bytes; goto push; } case 0xe9: /* jmp rel */ @@ -1532,6 +1532,8 @@ twobyte_special_insn: case 0x06: emulate_clts(ctxt->vcpu); break; + case 0x08: /* invd */ + break; case 0x09: /* wbinvd */ break; case 0x0d: /* GrpP (prefetch) */ diff --git a/drivers/lguest/lguest_device.c b/drivers/lguest/lguest_device.c index 8904f72..e2eec38 100644 --- a/drivers/lguest/lguest_device.c +++ b/drivers/lguest/lguest_device.c @@ -200,7 +200,8 @@ static struct virtqueue *lg_find_vq(struct virtio_device *vdev, /* Figure out how many pages the ring will take, and map that memory */ lvq->pages = lguest_map((unsigned long)lvq->config.pfn << PAGE_SHIFT, - DIV_ROUND_UP(vring_size(lvq->config.num), + DIV_ROUND_UP(vring_size(lvq->config.num, + PAGE_SIZE), PAGE_SIZE)); if (!lvq->pages) { err = -ENOMEM; @@ -246,6 +247,8 @@ static void lg_del_vq(struct virtqueue *vq) { struct lguest_vq_info *lvq = vq->priv; + /* Release the interrupt */ + free_irq(lvq->config.irq, vq); /* Tell virtio_ring.c to free the virtqueue. */ vring_del_virtqueue(vq); /* Unmap the pages containing the ring. */ diff --git a/drivers/lguest/lguest_user.c b/drivers/lguest/lguest_user.c index 9d716fa..3b92a61 100644 --- a/drivers/lguest/lguest_user.c +++ b/drivers/lguest/lguest_user.c @@ -184,7 +184,7 @@ static int initialize(struct file *file, const unsigned long __user *input) free_regs: free_page(lg->regs_page); release_guest: - memset(lg, 0, sizeof(*lg)); + kfree(lg); unlock: mutex_unlock(&lguest_lock); return err; diff --git a/drivers/macintosh/windfarm_core.c b/drivers/macintosh/windfarm_core.c index 516d943..075b4d9 100644 --- a/drivers/macintosh/windfarm_core.c +++ b/drivers/macintosh/windfarm_core.c @@ -94,7 +94,9 @@ static int wf_thread_func(void *data) DBG("wf: thread started\n"); set_freezable(); - while(!kthread_should_stop()) { + while (!kthread_should_stop()) { + try_to_freeze(); + if (time_after_eq(jiffies, next)) { wf_notify(WF_EVENT_TICK, NULL); if (wf_overtemp) { @@ -116,12 +118,6 @@ static int wf_thread_func(void *data) delay = next - jiffies; if (delay <= HZ) schedule_timeout_interruptible(delay); - - /* there should be no non-suspend signal, but oh well */ - if (signal_pending(current) && !try_to_freeze()) { - printk(KERN_WARNING "windfarm: thread got sigl !\n"); - break; - } } DBG("wf: thread stopped\n"); diff --git a/drivers/md/bitmap.c b/drivers/md/bitmap.c index 7c426d0..1b1ef31 100644 --- a/drivers/md/bitmap.c +++ b/drivers/md/bitmap.c @@ -1207,8 +1207,7 @@ int bitmap_startwrite(struct bitmap *bitmap, sector_t offset, unsigned long sect prepare_to_wait(&bitmap->overflow_wait, &__wait, TASK_UNINTERRUPTIBLE); spin_unlock_irq(&bitmap->lock); - bitmap->mddev->queue - ->unplug_fn(bitmap->mddev->queue); + blk_unplug(bitmap->mddev->queue); schedule(); finish_wait(&bitmap->overflow_wait, &__wait); continue; diff --git a/drivers/md/dm-table.c b/drivers/md/dm-table.c index 5a7eb65..e298d8d 100644 --- a/drivers/md/dm-table.c +++ b/drivers/md/dm-table.c @@ -1000,8 +1000,7 @@ void dm_table_unplug_all(struct dm_table *t) struct dm_dev *dd = list_entry(d, struct dm_dev, list); struct request_queue *q = bdev_get_queue(dd->bdev); - if (q->unplug_fn) - q->unplug_fn(q); + blk_unplug(q); } } diff --git a/drivers/md/linear.c b/drivers/md/linear.c index 56a11f6..3dac1cf 100644 --- a/drivers/md/linear.c +++ b/drivers/md/linear.c @@ -87,8 +87,7 @@ static void linear_unplug(struct request_queue *q) for (i=0; i < mddev->raid_disks; i++) { struct request_queue *r_queue = bdev_get_queue(conf->disks[i].rdev->bdev); - if (r_queue->unplug_fn) - r_queue->unplug_fn(r_queue); + blk_unplug(r_queue); } } diff --git a/drivers/md/md.c b/drivers/md/md.c index 808cd95..cef9ebd 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -5445,7 +5445,7 @@ void md_do_sync(mddev_t *mddev) * about not overloading the IO subsystem. (things like an * e2fsck being done on the RAID array should execute fast) */ - mddev->queue->unplug_fn(mddev->queue); + blk_unplug(mddev->queue); cond_resched(); currspeed = ((unsigned long)(io_sectors-mddev->resync_mark_cnt))/2 @@ -5464,7 +5464,7 @@ void md_do_sync(mddev_t *mddev) * this also signals 'finished resyncing' to md_stop */ out: - mddev->queue->unplug_fn(mddev->queue); + blk_unplug(mddev->queue); wait_event(mddev->recovery_wait, !atomic_read(&mddev->recovery_active)); diff --git a/drivers/md/multipath.c b/drivers/md/multipath.c index b35731c..eb631eb 100644 --- a/drivers/md/multipath.c +++ b/drivers/md/multipath.c @@ -125,8 +125,7 @@ static void unplug_slaves(mddev_t *mddev) atomic_inc(&rdev->nr_pending); rcu_read_unlock(); - if (r_queue->unplug_fn) - r_queue->unplug_fn(r_queue); + blk_unplug(r_queue); rdev_dec_pending(rdev, mddev); rcu_read_lock(); diff --git a/drivers/md/raid0.c b/drivers/md/raid0.c index c111105..f8e5917 100644 --- a/drivers/md/raid0.c +++ b/drivers/md/raid0.c @@ -35,8 +35,7 @@ static void raid0_unplug(struct request_queue *q) for (i=0; i<mddev->raid_disks; i++) { struct request_queue *r_queue = bdev_get_queue(devlist[i]->bdev); - if (r_queue->unplug_fn) - r_queue->unplug_fn(r_queue); + blk_unplug(r_queue); } } diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c index 85478d6..4a69c41 100644 --- a/drivers/md/raid1.c +++ b/drivers/md/raid1.c @@ -549,8 +549,7 @@ static void unplug_slaves(mddev_t *mddev) atomic_inc(&rdev->nr_pending); rcu_read_unlock(); - if (r_queue->unplug_fn) - r_queue->unplug_fn(r_queue); + blk_unplug(r_queue); rdev_dec_pending(rdev, mddev); rcu_read_lock(); diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c index fc6607a..5cdcc93 100644 --- a/drivers/md/raid10.c +++ b/drivers/md/raid10.c @@ -593,8 +593,7 @@ static void unplug_slaves(mddev_t *mddev) atomic_inc(&rdev->nr_pending); rcu_read_unlock(); - if (r_queue->unplug_fn) - r_queue->unplug_fn(r_queue); + blk_unplug(r_queue); rdev_dec_pending(rdev, mddev); rcu_read_lock(); diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index 82af346..a5aad8c 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c @@ -688,7 +688,8 @@ ops_run_prexor(struct stripe_head *sh, struct dma_async_tx_descriptor *tx) } static struct dma_async_tx_descriptor * -ops_run_biodrain(struct stripe_head *sh, struct dma_async_tx_descriptor *tx) +ops_run_biodrain(struct stripe_head *sh, struct dma_async_tx_descriptor *tx, + unsigned long pending) { int disks = sh->disks; int pd_idx = sh->pd_idx, i; @@ -696,7 +697,7 @@ ops_run_biodrain(struct stripe_head *sh, struct dma_async_tx_descriptor *tx) /* check if prexor is active which means only process blocks * that are part of a read-modify-write (Wantprexor) */ - int prexor = test_bit(STRIPE_OP_PREXOR, &sh->ops.pending); + int prexor = test_bit(STRIPE_OP_PREXOR, &pending); pr_debug("%s: stripe %llu\n", __FUNCTION__, (unsigned long long)sh->sector); @@ -773,7 +774,8 @@ static void ops_complete_write(void *stripe_head_ref) } static void -ops_run_postxor(struct stripe_head *sh, struct dma_async_tx_descriptor *tx) +ops_run_postxor(struct stripe_head *sh, struct dma_async_tx_descriptor *tx, + unsigned long pending) { /* kernel stack size limits the total number of disks */ int disks = sh->disks; @@ -781,7 +783,7 @@ ops_run_postxor(struct stripe_head *sh, struct dma_async_tx_descriptor *tx) int count = 0, pd_idx = sh->pd_idx, i; struct page *xor_dest; - int prexor = test_bit(STRIPE_OP_PREXOR, &sh->ops.pending); + int prexor = test_bit(STRIPE_OP_PREXOR, &pending); unsigned long flags; dma_async_tx_callback callback; @@ -808,7 +810,7 @@ ops_run_postxor(struct stripe_head *sh, struct dma_async_tx_descriptor *tx) } /* check whether this postxor is part of a write */ - callback = test_bit(STRIPE_OP_BIODRAIN, &sh->ops.pending) ? + callback = test_bit(STRIPE_OP_BIODRAIN, &pending) ? ops_complete_write : ops_complete_postxor; /* 1/ if we prexor'd then the dest is reused as a source @@ -896,12 +898,12 @@ static void raid5_run_ops(struct stripe_head *sh, unsigned long pending) tx = ops_run_prexor(sh, tx); if (test_bit(STRIPE_OP_BIODRAIN, &pending)) { - tx = ops_run_biodrain(sh, tx); + tx = ops_run_biodrain(sh, tx, pending); overlap_clear++; } if (test_bit(STRIPE_OP_POSTXOR, &pending)) - ops_run_postxor(sh, tx); + ops_run_postxor(sh, tx, pending); if (test_bit(STRIPE_OP_CHECK, &pending)) ops_run_check(sh); @@ -3186,8 +3188,7 @@ static void unplug_slaves(mddev_t *mddev) atomic_inc(&rdev->nr_pending); rcu_read_unlock(); - if (r_queue->unplug_fn) - r_queue->unplug_fn(r_queue); + blk_unplug(r_queue); rdev_dec_pending(rdev, mddev); rcu_read_lock(); diff --git a/drivers/mfd/sm501.c b/drivers/mfd/sm501.c index 8135e4c..afd8296 100644 --- a/drivers/mfd/sm501.c +++ b/drivers/mfd/sm501.c @@ -156,7 +156,7 @@ static void sm501_dump_clk(struct sm501_devdata *sm) dev_dbg(sm->dev, "PM0[%c]: " "P2 %ld.%ld MHz (%ld), V2 %ld.%ld (%ld), " -x "M %ld.%ld (%ld), MX1 %ld.%ld (%ld)\n", + "M %ld.%ld (%ld), MX1 %ld.%ld (%ld)\n", (pmc & 3 ) == 0 ? '*' : '-', fmt_freq(decode_div(pll2, pm0, 24, 1<<29, 31, px_div)), fmt_freq(decode_div(pll2, pm0, 16, 1<<20, 15, misc_div)), diff --git a/drivers/misc/ioc4.c b/drivers/misc/ioc4.c index 6a5a05d..05172d2 100644 --- a/drivers/misc/ioc4.c +++ b/drivers/misc/ioc4.c @@ -244,10 +244,11 @@ ioc4_variant(struct ioc4_driver_data *idd) idd->idd_pdev->bus->number == pdev->bus->number && 3 == PCI_SLOT(pdev->devfn)) found = 1; - pci_dev_put(pdev); } while (pdev && !found); - if (NULL != pdev) + if (NULL != pdev) { + pci_dev_put(pdev); return IOC4_VARIANT_IO9; + } /* IO10: Look for a Vitesse VSC 7174 at the same bus and slot 3. */ pdev = NULL; @@ -258,10 +259,11 @@ ioc4_variant(struct ioc4_driver_data *idd) idd->idd_pdev->bus->number == pdev->bus->number && 3 == PCI_SLOT(pdev->devfn)) found = 1; - pci_dev_put(pdev); } while (pdev && !found); - if (NULL != pdev) + if (NULL != pdev) { + pci_dev_put(pdev); return IOC4_VARIANT_IO10; + } /* PCI-RT: No SCSI/SATA controller will be present */ return IOC4_VARIANT_PCI_RT; diff --git a/drivers/misc/sony-laptop.c b/drivers/misc/sony-laptop.c index bb13858..b0f6803 100644 --- a/drivers/misc/sony-laptop.c +++ b/drivers/misc/sony-laptop.c @@ -338,7 +338,7 @@ static void sony_laptop_report_input_event(u8 event) dprintk("unknown input event %.2x\n", event); } -static int sony_laptop_setup_input(void) +static int sony_laptop_setup_input(struct acpi_device *acpi_device) { struct input_dev *jog_dev; struct input_dev *key_dev; @@ -379,6 +379,7 @@ static int sony_laptop_setup_input(void) key_dev->name = "Sony Vaio Keys"; key_dev->id.bustype = BUS_ISA; key_dev->id.vendor = PCI_VENDOR_ID_SONY; + key_dev->dev.parent = &acpi_device->dev; /* Initialize the Input Drivers: special keys */ set_bit(EV_KEY, key_dev->evbit); @@ -410,6 +411,7 @@ static int sony_laptop_setup_input(void) jog_dev->name = "Sony Vaio Jogdial"; jog_dev->id.bustype = BUS_ISA; jog_dev->id.vendor = PCI_VENDOR_ID_SONY; + key_dev->dev.parent = &acpi_device->dev; jog_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REL); jog_dev->keybit[BIT_WORD(BTN_MOUSE)] = BIT_MASK(BTN_MIDDLE); @@ -1006,7 +1008,7 @@ static int sony_nc_add(struct acpi_device *device) } /* setup input devices and helper fifo */ - result = sony_laptop_setup_input(); + result = sony_laptop_setup_input(device); if (result) { printk(KERN_ERR DRV_PFX "Unabe to create input devices.\n"); @@ -1034,7 +1036,7 @@ static int sony_nc_add(struct acpi_device *device) sony_backlight_device->props.brightness = sony_backlight_get_brightness (sony_backlight_device); - sony_backlight_device->props.max_brightness = + sony_backlight_device->props.max_brightness = SONY_MAX_BRIGHTNESS - 1; } @@ -2453,7 +2455,7 @@ static int sony_pic_add(struct acpi_device *device) } /* setup input devices and helper fifo */ - result = sony_laptop_setup_input(); + result = sony_laptop_setup_input(device); if (result) { printk(KERN_ERR DRV_PFX "Unabe to create input devices.\n"); diff --git a/drivers/misc/thinkpad_acpi.c b/drivers/misc/thinkpad_acpi.c index e953276..ab23a32 100644 --- a/drivers/misc/thinkpad_acpi.c +++ b/drivers/misc/thinkpad_acpi.c @@ -21,7 +21,7 @@ * 02110-1301, USA. */ -#define IBM_VERSION "0.16" +#define IBM_VERSION "0.17" #define TPACPI_SYSFS_VERSION 0x020000 /* @@ -964,15 +964,15 @@ static int __init hotkey_init(struct ibm_init_struct *iibm) KEY_UNKNOWN, /* 0x0C: FN+BACKSPACE */ KEY_UNKNOWN, /* 0x0D: FN+INSERT */ KEY_UNKNOWN, /* 0x0E: FN+DELETE */ - KEY_BRIGHTNESSUP, /* 0x0F: FN+HOME (brightness up) */ + KEY_RESERVED, /* 0x0F: FN+HOME (brightness up) */ /* Scan codes 0x10 to 0x1F: Extended ACPI HKEY hot keys */ - KEY_BRIGHTNESSDOWN, /* 0x10: FN+END (brightness down) */ + KEY_RESERVED, /* 0x10: FN+END (brightness down) */ KEY_RESERVED, /* 0x11: FN+PGUP (thinklight toggle) */ KEY_UNKNOWN, /* 0x12: FN+PGDOWN */ KEY_ZOOM, /* 0x13: FN+SPACE (zoom) */ - KEY_VOLUMEUP, /* 0x14: VOLUME UP */ - KEY_VOLUMEDOWN, /* 0x15: VOLUME DOWN */ - KEY_MUTE, /* 0x16: MUTE */ + KEY_RESERVED, /* 0x14: VOLUME UP */ + KEY_RESERVED, /* 0x15: VOLUME DOWN */ + KEY_RESERVED, /* 0x16: MUTE */ KEY_VENDOR, /* 0x17: Thinkpad/AccessIBM/Lenovo */ /* (assignments unknown, please report if found) */ KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, @@ -993,9 +993,9 @@ static int __init hotkey_init(struct ibm_init_struct *iibm) KEY_RESERVED, /* 0x11: FN+PGUP (thinklight toggle) */ KEY_UNKNOWN, /* 0x12: FN+PGDOWN */ KEY_ZOOM, /* 0x13: FN+SPACE (zoom) */ - KEY_VOLUMEUP, /* 0x14: VOLUME UP */ - KEY_VOLUMEDOWN, /* 0x15: VOLUME DOWN */ - KEY_MUTE, /* 0x16: MUTE */ + KEY_RESERVED, /* 0x14: VOLUME UP */ + KEY_RESERVED, /* 0x15: VOLUME DOWN */ + KEY_RESERVED, /* 0x16: MUTE */ KEY_VENDOR, /* 0x17: Thinkpad/AccessIBM/Lenovo */ /* (assignments unknown, please report if found) */ KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, @@ -1342,9 +1342,8 @@ static int hotkey_read(char *p) return len; } - res = mutex_lock_interruptible(&hotkey_mutex); - if (res < 0) - return res; + if (mutex_lock_interruptible(&hotkey_mutex)) + return -ERESTARTSYS; res = hotkey_get(&status, &mask); mutex_unlock(&hotkey_mutex); if (res) @@ -1373,9 +1372,8 @@ static int hotkey_write(char *buf) if (!tp_features.hotkey) return -ENODEV; - res = mutex_lock_interruptible(&hotkey_mutex); - if (res < 0) - return res; + if (mutex_lock_interruptible(&hotkey_mutex)) + return -ERESTARTSYS; res = hotkey_get(&status, &mask); if (res) @@ -3114,6 +3112,99 @@ static struct backlight_ops ibm_backlight_data = { static struct mutex brightness_mutex; +static int __init tpacpi_query_bcll_levels(acpi_handle handle) +{ + struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; + union acpi_object *obj; + int rc; + + if (ACPI_SUCCESS(acpi_evaluate_object(handle, NULL, NULL, &buffer))) { + obj = (union acpi_object *)buffer.pointer; + if (!obj || (obj->type != ACPI_TYPE_PACKAGE)) { + printk(IBM_ERR "Unknown BCLL data, " + "please report this to %s\n", IBM_MAIL); + rc = 0; + } else { + rc = obj->package.count; + } + } else { + return 0; + } + + kfree(buffer.pointer); + return rc; +} + +static acpi_status __init brightness_find_bcll(acpi_handle handle, u32 lvl, + void *context, void **rv) +{ + char name[ACPI_PATH_SEGMENT_LENGTH]; + struct acpi_buffer buffer = { sizeof(name), &name }; + + if (ACPI_SUCCESS(acpi_get_name(handle, ACPI_SINGLE_NAME, &buffer)) && + !strncmp("BCLL", name, sizeof(name) - 1)) { + if (tpacpi_query_bcll_levels(handle) == 16) { + *rv = handle; + return AE_CTRL_TERMINATE; + } else { + return AE_OK; + } + } else { + return AE_OK; + } +} + +static int __init brightness_check_levels(void) +{ + int status; + void *found_node = NULL; + + if (!vid_handle) { + IBM_ACPIHANDLE_INIT(vid); + } + if (!vid_handle) + return 0; + + /* Search for a BCLL package with 16 levels */ + status = acpi_walk_namespace(ACPI_TYPE_PACKAGE, vid_handle, 3, + brightness_find_bcll, NULL, &found_node); + + return (ACPI_SUCCESS(status) && found_node != NULL); +} + +static acpi_status __init brightness_find_bcl(acpi_handle handle, u32 lvl, + void *context, void **rv) +{ + char name[ACPI_PATH_SEGMENT_LENGTH]; + struct acpi_buffer buffer = { sizeof(name), &name }; + + if (ACPI_SUCCESS(acpi_get_name(handle, ACPI_SINGLE_NAME, &buffer)) && + !strncmp("_BCL", name, sizeof(name) - 1)) { + *rv = handle; + return AE_CTRL_TERMINATE; + } else { + return AE_OK; + } +} + +static int __init brightness_check_std_acpi_support(void) +{ + int status; + void *found_node = NULL; + + if (!vid_handle) { + IBM_ACPIHANDLE_INIT(vid); + } + if (!vid_handle) + return 0; + + /* Search for a _BCL method, but don't execute it */ + status = acpi_walk_namespace(ACPI_TYPE_METHOD, vid_handle, 3, + brightness_find_bcl, NULL, &found_node); + + return (ACPI_SUCCESS(status) && found_node != NULL); +} + static int __init brightness_init(struct ibm_init_struct *iibm) { int b; @@ -3122,6 +3213,18 @@ static int __init brightness_init(struct ibm_init_struct *iibm) mutex_init(&brightness_mutex); + if (!brightness_enable) { + dbg_printk(TPACPI_DBG_INIT, + "brightness support disabled by module parameter\n"); + return 1; + } else if (brightness_enable > 1) { + if (brightness_check_std_acpi_support()) { + printk(IBM_NOTICE + "standard ACPI backlight interface available, not loading native one...\n"); + return 1; + } + } + if (!brightness_mode) { if (thinkpad_id.vendor == PCI_VENDOR_ID_LENOVO) brightness_mode = 2; @@ -3135,10 +3238,17 @@ static int __init brightness_init(struct ibm_init_struct *iibm) if (brightness_mode > 3) return -EINVAL; + tp_features.bright_16levels = + thinkpad_id.vendor == PCI_VENDOR_ID_LENOVO && + brightness_check_levels(); + b = brightness_get(NULL); if (b < 0) return 1; + if (tp_features.bright_16levels) + printk(IBM_INFO "detected a 16-level brightness capable ThinkPad\n"); + ibm_backlight_device = backlight_device_register( TPACPI_BACKLIGHT_DEV_NAME, NULL, NULL, &ibm_backlight_data); @@ -3148,7 +3258,8 @@ static int __init brightness_init(struct ibm_init_struct *iibm) } vdbg_printk(TPACPI_DBG_INIT, "brightness is supported\n"); - ibm_backlight_device->props.max_brightness = 7; + ibm_backlight_device->props.max_brightness = + (tp_features.bright_16levels)? 15 : 7; ibm_backlight_device->props.brightness = b; backlight_update_status(ibm_backlight_device); @@ -3167,6 +3278,8 @@ static void brightness_exit(void) static int brightness_update_status(struct backlight_device *bd) { + /* it is the backlight class's job (caller) to handle + * EINTR and other errors properly */ return brightness_set( (bd->props.fb_blank == FB_BLANK_UNBLANK && bd->props.power == FB_BLANK_UNBLANK) ? @@ -3184,13 +3297,14 @@ static int brightness_get(struct backlight_device *bd) if (brightness_mode & 1) { if (!acpi_ec_read(brightness_offset, &lec)) return -EIO; - lec &= 7; + lec &= (tp_features.bright_16levels)? 0x0f : 0x07; level = lec; }; if (brightness_mode & 2) { lcmos = (nvram_read_byte(TP_NVRAM_ADDR_BRIGHTNESS) & TP_NVRAM_MASK_LEVEL_BRIGHTNESS) >> TP_NVRAM_POS_LEVEL_BRIGHTNESS; + lcmos &= (tp_features.bright_16levels)? 0x0f : 0x07; level = lcmos; } @@ -3206,12 +3320,13 @@ static int brightness_get(struct backlight_device *bd) return level; } +/* May return EINTR which can always be mapped to ERESTARTSYS */ static int brightness_set(int value) { int cmos_cmd, inc, i, res; int current_value; - if (value > 7) + if (value > ((tp_features.bright_16levels)? 15 : 7)) return -EINVAL; res = mutex_lock_interruptible(&brightness_mutex); @@ -3227,7 +3342,7 @@ static int brightness_set(int value) cmos_cmd = value > current_value ? TP_CMOS_BRIGHTNESS_UP : TP_CMOS_BRIGHTNESS_DOWN; - inc = value > current_value ? 1 : -1; + inc = (value > current_value)? 1 : -1; res = 0; for (i = current_value; i != value; i += inc) { @@ -3256,10 +3371,11 @@ static int brightness_read(char *p) if ((level = brightness_get(NULL)) < 0) { len += sprintf(p + len, "level:\t\tunreadable\n"); } else { - len += sprintf(p + len, "level:\t\t%d\n", level & 0x7); + len += sprintf(p + len, "level:\t\t%d\n", level); len += sprintf(p + len, "commands:\tup, down\n"); len += sprintf(p + len, "commands:\tlevel <level>" - " (<level> is 0-7)\n"); + " (<level> is 0-%d)\n", + (tp_features.bright_16levels) ? 15 : 7); } return len; @@ -3268,28 +3384,34 @@ static int brightness_read(char *p) static int brightness_write(char *buf) { int level; - int new_level; + int rc; char *cmd; + int max_level = (tp_features.bright_16levels) ? 15 : 7; - while ((cmd = next_cmd(&buf))) { - if ((level = brightness_get(NULL)) < 0) - return level; - level &= 7; + level = brightness_get(NULL); + if (level < 0) + return level; + while ((cmd = next_cmd(&buf))) { if (strlencmp(cmd, "up") == 0) { - new_level = level == 7 ? 7 : level + 1; + if (level < max_level) + level++; } else if (strlencmp(cmd, "down") == 0) { - new_level = level == 0 ? 0 : level - 1; - } else if (sscanf(cmd, "level %d", &new_level) == 1 && - new_level >= 0 && new_level <= 7) { - /* new_level set */ + if (level > 0) + level--; + } else if (sscanf(cmd, "level %d", &level) == 1 && + level >= 0 && level <= max_level) { + /* new level set */ } else return -EINVAL; - - brightness_set(new_level); } - return 0; + /* + * Now we know what the final level should be, so we try to set it. + * Doing it this way makes the syscall restartable in case of EINTR + */ + rc = brightness_set(level); + return (rc == -EINTR)? ERESTARTSYS : rc; } static struct ibm_struct brightness_driver_data = { @@ -3652,9 +3774,8 @@ static ssize_t fan_pwm1_store(struct device *dev, /* scale down from 0-255 to 0-7 */ newlevel = (s >> 5) & 0x07; - rc = mutex_lock_interruptible(&fan_mutex); - if (rc < 0) - return rc; + if (mutex_lock_interruptible(&fan_mutex)) + return -ERESTARTSYS; rc = fan_get_status(&status); if (!rc && (status & @@ -3904,9 +4025,8 @@ static int fan_get_status_safe(u8 *status) int rc; u8 s; - rc = mutex_lock_interruptible(&fan_mutex); - if (rc < 0) - return rc; + if (mutex_lock_interruptible(&fan_mutex)) + return -ERESTARTSYS; rc = fan_get_status(&s); if (!rc) fan_update_desired_level(s); @@ -4040,9 +4160,8 @@ static int fan_set_level_safe(int level) if (!fan_control_allowed) return -EPERM; - rc = mutex_lock_interruptible(&fan_mutex); - if (rc < 0) - return rc; + if (mutex_lock_interruptible(&fan_mutex)) + return -ERESTARTSYS; if (level == TPACPI_FAN_LAST_LEVEL) level = fan_control_desired_level; @@ -4063,9 +4182,8 @@ static int fan_set_enable(void) if (!fan_control_allowed) return -EPERM; - rc = mutex_lock_interruptible(&fan_mutex); - if (rc < 0) - return rc; + if (mutex_lock_interruptible(&fan_mutex)) + return -ERESTARTSYS; switch (fan_control_access_mode) { case TPACPI_FAN_WR_ACPI_FANS: @@ -4119,9 +4237,8 @@ static int fan_set_disable(void) if (!fan_control_allowed) return -EPERM; - rc = mutex_lock_interruptible(&fan_mutex); - if (rc < 0) - return rc; + if (mutex_lock_interruptible(&fan_mutex)) + return -ERESTARTSYS; rc = 0; switch (fan_control_access_mode) { @@ -4158,9 +4275,8 @@ static int fan_set_speed(int speed) if (!fan_control_allowed) return -EPERM; - rc = mutex_lock_interruptible(&fan_mutex); - if (rc < 0) - return rc; + if (mutex_lock_interruptible(&fan_mutex)) + return -ERESTARTSYS; rc = 0; switch (fan_control_access_mode) { @@ -4701,9 +4817,15 @@ static int __init set_ibm_param(const char *val, struct kernel_param *kp) unsigned int i; struct ibm_struct *ibm; + if (!kp || !kp->name || !val) + return -EINVAL; + for (i = 0; i < ARRAY_SIZE(ibms_init); i++) { ibm = ibms_init[i].data; - BUG_ON(ibm == NULL); + WARN_ON(ibm == NULL); + + if (!ibm || !ibm->name) + continue; if (strcmp(ibm->name, kp->name) == 0 && ibm->write) { if (strlen(val) > sizeof(ibms_init[i].param) - 2) @@ -4732,6 +4854,9 @@ module_param_named(fan_control, fan_control_allowed, bool, 0); static int brightness_mode; module_param_named(brightness_mode, brightness_mode, int, 0); +static unsigned int brightness_enable = 2; /* 2 = auto, 0 = no, 1 = yes */ +module_param(brightness_enable, uint, 0); + static unsigned int hotkey_report_mode; module_param(hotkey_report_mode, uint, 0); diff --git a/drivers/misc/thinkpad_acpi.h b/drivers/misc/thinkpad_acpi.h index 3abcc81..8fba2bb 100644 --- a/drivers/misc/thinkpad_acpi.h +++ b/drivers/misc/thinkpad_acpi.h @@ -84,7 +84,7 @@ /* ThinkPad CMOS NVRAM constants */ #define TP_NVRAM_ADDR_BRIGHTNESS 0x5e -#define TP_NVRAM_MASK_LEVEL_BRIGHTNESS 0x07 +#define TP_NVRAM_MASK_LEVEL_BRIGHTNESS 0x0f #define TP_NVRAM_POS_LEVEL_BRIGHTNESS 0 #define onoff(status,bit) ((status) & (1 << (bit)) ? "on" : "off") @@ -246,6 +246,7 @@ static struct { u32 hotkey_wlsw:1; u32 light:1; u32 light_status:1; + u32 bright_16levels:1; u32 wan:1; u32 fan_ctrl_status_undef:1; u32 input_device_registered:1; @@ -338,6 +339,7 @@ static int bluetooth_write(char *buf); static struct backlight_device *ibm_backlight_device; static int brightness_offset = 0x31; static int brightness_mode; +static unsigned int brightness_enable; /* 0 = no, 1 = yes, 2 = auto */ static int brightness_init(struct ibm_init_struct *iibm); static void brightness_exit(void); diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c index e38d5a3..aeb32a9 100644 --- a/drivers/mmc/card/block.c +++ b/drivers/mmc/card/block.c @@ -44,6 +44,9 @@ * max 8 partitions per card */ #define MMC_SHIFT 3 +#define MMC_NUM_MINORS (256 >> MMC_SHIFT) + +static unsigned long dev_use[MMC_NUM_MINORS/(8*sizeof(unsigned long))]; /* * There is one mmc_blk_data per slot. @@ -80,6 +83,9 @@ static void mmc_blk_put(struct mmc_blk_data *md) mutex_lock(&open_lock); md->usage--; if (md->usage == 0) { + int devidx = md->disk->first_minor >> MMC_SHIFT; + __clear_bit(devidx, dev_use); + put_disk(md->disk); kfree(md); } @@ -321,7 +327,13 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req) req->rq_disk->disk_name, err); goto cmd_err; } - } while (!(cmd.resp[0] & R1_READY_FOR_DATA)); + /* + * Some cards mishandle the status bits, + * so make sure to check both the busy + * indication and the card state. + */ + } while (!(cmd.resp[0] & R1_READY_FOR_DATA) || + (R1_CURRENT_STATE(cmd.resp[0]) == 7)); #if 0 if (cmd.resp[0] & ~0x00000900) @@ -400,9 +412,6 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req) return 0; } -#define MMC_NUM_MINORS (256 >> MMC_SHIFT) - -static unsigned long dev_use[MMC_NUM_MINORS/(8*sizeof(unsigned long))]; static inline int mmc_blk_readonly(struct mmc_card *card) { @@ -568,17 +577,12 @@ static void mmc_blk_remove(struct mmc_card *card) struct mmc_blk_data *md = mmc_get_drvdata(card); if (md) { - int devidx; - /* Stop new requests from getting into the queue */ del_gendisk(md->disk); /* Then flush out any already in there */ mmc_cleanup_queue(&md->queue); - devidx = md->disk->first_minor >> MMC_SHIFT; - __clear_bit(devidx, dev_use); - mmc_blk_put(md); } mmc_set_drvdata(card, NULL); diff --git a/drivers/mmc/card/queue.c b/drivers/mmc/card/queue.c index 9203a0b..30cd13b 100644 --- a/drivers/mmc/card/queue.c +++ b/drivers/mmc/card/queue.c @@ -180,12 +180,13 @@ int mmc_init_queue(struct mmc_queue *mq, struct mmc_card *card, spinlock_t *lock blk_queue_max_hw_segments(mq->queue, host->max_hw_segs); blk_queue_max_segment_size(mq->queue, host->max_seg_size); - mq->sg = kzalloc(sizeof(struct scatterlist) * + mq->sg = kmalloc(sizeof(struct scatterlist) * host->max_phys_segs, GFP_KERNEL); if (!mq->sg) { ret = -ENOMEM; goto cleanup_queue; } + sg_init_table(mq->sg, host->max_phys_segs); } init_MUTEX(&mq->thread_sem); @@ -310,7 +311,7 @@ static void copy_sg(struct scatterlist *dst, unsigned int dst_len, } if (src_size == 0) { - src_buf = sg_virt(dst); + src_buf = sg_virt(src); src_size = src->length; } diff --git a/drivers/mmc/card/sdio_uart.c b/drivers/mmc/card/sdio_uart.c index d552de6..eeea84c 100644 --- a/drivers/mmc/card/sdio_uart.c +++ b/drivers/mmc/card/sdio_uart.c @@ -386,7 +386,7 @@ static void sdio_uart_stop_rx(struct sdio_uart_port *port) sdio_out(port, UART_IER, port->ier); } -static void sdio_uart_receive_chars(struct sdio_uart_port *port, int *status) +static void sdio_uart_receive_chars(struct sdio_uart_port *port, unsigned int *status) { struct tty_struct *tty = port->tty; unsigned int ch, flag; diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index 6b80bf7..ff59d2e 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c @@ -1301,7 +1301,7 @@ static int __devinit sdhci_probe_slot(struct pci_dev *pdev, int slot) if ((chip->quirks & SDHCI_QUIRK_BROKEN_DMA) && (host->flags & SDHCI_USE_DMA)) { - DBG("Disabling DMA as it is marked broken"); + DBG("Disabling DMA as it is marked broken\n"); host->flags &= ~SDHCI_USE_DMA; } diff --git a/drivers/mmc/host/tifm_sd.c b/drivers/mmc/host/tifm_sd.c index c11a3d2..20d5c7b 100644 --- a/drivers/mmc/host/tifm_sd.c +++ b/drivers/mmc/host/tifm_sd.c @@ -16,7 +16,6 @@ #include <linux/mmc/host.h> #include <linux/highmem.h> #include <linux/scatterlist.h> -#include <linux/log2.h> #include <asm/io.h> #define DRIVER_NAME "tifm_sd" @@ -638,17 +637,15 @@ static void tifm_sd_request(struct mmc_host *mmc, struct mmc_request *mrq) goto err_out; } - if (mrq->data && !is_power_of_2(mrq->data->blksz)) { - printk(KERN_ERR "%s: Unsupported block size (%d bytes)\n", - sock->dev.bus_id, mrq->data->blksz); - mrq->cmd->error = -EINVAL; - goto err_out; - } - host->cmd_flags = 0; host->block_pos = 0; host->sg_pos = 0; + if (mrq->data && !is_power_of_2(mrq->data->blksz)) + host->no_dma = 1; + else + host->no_dma = no_dma ? 1 : 0; + if (r_data) { tifm_sd_set_data_timeout(host, r_data); @@ -676,7 +673,7 @@ static void tifm_sd_request(struct mmc_host *mmc, struct mmc_request *mrq) : PCI_DMA_FROMDEVICE)) { printk(KERN_ERR "%s : scatterlist map failed\n", sock->dev.bus_id); - spin_unlock_irqrestore(&sock->lock, flags); + mrq->cmd->error = -ENOMEM; goto err_out; } host->sg_len = tifm_map_sg(sock, r_data->sg, @@ -692,7 +689,7 @@ static void tifm_sd_request(struct mmc_host *mmc, struct mmc_request *mrq) r_data->flags & MMC_DATA_WRITE ? PCI_DMA_TODEVICE : PCI_DMA_FROMDEVICE); - spin_unlock_irqrestore(&sock->lock, flags); + mrq->cmd->error = -ENOMEM; goto err_out; } @@ -966,7 +963,6 @@ static int tifm_sd_probe(struct tifm_dev *sock) return -ENOMEM; host = mmc_priv(mmc); - host->no_dma = no_dma; tifm_set_drvdata(sock, mmc); host->dev = sock; host->timeout_jiffies = msecs_to_jiffies(1000); diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index 5f800a6..d9107e5 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -136,10 +136,11 @@ config TUN If you don't know what to use this for, you don't need it. config VETH - tristate "Virtual ethernet device" + tristate "Virtual ethernet pair device" ---help--- - The device is an ethernet tunnel. Devices are created in pairs. When - one end receives the packet it appears on its pair and vice versa. + This device is a local ethernet tunnel. Devices are created in pairs. + When one end receives the packet it appears on its pair and vice + versa. config NET_SB1000 tristate "General Instruments Surfboard 1000" @@ -234,7 +235,7 @@ source "drivers/net/arm/Kconfig" config AX88796 tristate "ASIX AX88796 NE2000 clone support" - depends on ARM || MIPS + depends on ARM || MIPS || SUPERH select CRC32 select MII help @@ -365,8 +366,7 @@ config MAC89x0 read the Ethernet-HOWTO, available from <http://www.tldp.org/docs.html#howto>. - To compile this driver as a module, choose M here and read - <file:Documentation/networking/net-modules.txt>. This module will + To compile this driver as a module, choose M here. This module will be called mac89x0. config MACSONIC @@ -379,8 +379,7 @@ config MACSONIC one of these say Y and read the Ethernet-HOWTO, available from <http://www.tldp.org/docs.html#howto>. - To compile this driver as a module, choose M here and read - <file:Documentation/networking/net-modules.txt>. This module will + To compile this driver as a module, choose M here. This module will be called macsonic. config MACMACE @@ -618,8 +617,7 @@ config EL1 have problems. Some people suggest to ping ("man ping") a nearby machine every minute ("man cron") when using this card. - To compile this driver as a module, choose M here and read - <file:Documentation/networking/net-modules.txt>. The module + To compile this driver as a module, choose M here. The module will be called 3c501. config EL2 @@ -631,8 +629,7 @@ config EL2 the Ethernet-HOWTO, available from <http://www.tldp.org/docs.html#howto>. - To compile this driver as a module, choose M here and read - <file:Documentation/networking/net-modules.txt>. The module + To compile this driver as a module, choose M here. The module will be called 3c503. config ELPLUS @@ -644,8 +641,7 @@ config ELPLUS this type, say Y and read the Ethernet-HOWTO, available from <http://www.tldp.org/docs.html#howto>. - To compile this driver as a module, choose M here and read - <file:Documentation/networking/net-modules.txt>. The module + To compile this driver as a module, choose M here. The module will be called 3c505. config EL16 @@ -656,8 +652,7 @@ config EL16 the Ethernet-HOWTO, available from <http://www.tldp.org/docs.html#howto>. - To compile this driver as a module, choose M here and read - <file:Documentation/networking/net-modules.txt>. The module + To compile this driver as a module, choose M here. The module will be called 3c507. config EL3 @@ -672,8 +667,7 @@ config EL3 setup disk to disable Plug & Play mode, and to select the default media type. - To compile this driver as a module, choose M here and read - <file:Documentation/networking/net-modules.txt>. The module + To compile this driver as a module, choose M here. The module will be called 3c509. config 3C515 @@ -684,8 +678,7 @@ config 3C515 network card, say Y and read the Ethernet-HOWTO, available from <http://www.tldp.org/docs.html#howto>. - To compile this driver as a module, choose M here and read - <file:Documentation/networking/net-modules.txt>. The module + To compile this driver as a module, choose M here. The module will be called 3c515. config ELMC @@ -696,8 +689,7 @@ config ELMC the Ethernet-HOWTO, available from <http://www.tldp.org/docs.html#howto>. - To compile this driver as a module, choose M here and read - <file:Documentation/networking/net-modules.txt>. The module + To compile this driver as a module, choose M here. The module will be called 3c523. config ELMC_II @@ -708,8 +700,7 @@ config ELMC_II the Ethernet-HOWTO, available from <http://www.tldp.org/docs.html#howto>. - To compile this driver as a module, choose M here and read - <file:Documentation/networking/net-modules.txt>. The module + To compile this driver as a module, choose M here. The module will be called 3c527. config VORTEX @@ -732,8 +723,7 @@ config VORTEX <file:Documentation/networking/vortex.txt> and in the comments at the beginning of <file:drivers/net/3c59x.c>. - To compile this support as a module, choose M here and read - <file:Documentation/networking/net-modules.txt>. + To compile this support as a module, choose M here. config TYPHOON tristate "3cr990 series \"Typhoon\" support" @@ -750,8 +740,7 @@ config TYPHOON the Ethernet-HOWTO, available from <http://www.tldp.org/docs.html#howto>. - To compile this driver as a module, choose M here and read - <file:Documentation/networking/net-modules.txt>. The module + To compile this driver as a module, choose M here. The module will be called typhoon. config LANCE @@ -788,8 +777,7 @@ config WD80x3 the Ethernet-HOWTO, available from <http://www.tldp.org/docs.html#howto>. - To compile this driver as a module, choose M here and read - <file:Documentation/networking/net-modules.txt>. The module + To compile this driver as a module, choose M here. The module will be called wd. config ULTRAMCA @@ -801,8 +789,7 @@ config ULTRAMCA an MCA based system (PS/2), say Y and read the Ethernet-HOWTO, available from <http://www.tldp.org/docs.html#howto>. - To compile this driver as a module, choose M here and read - <file:Documentation/networking/net-modules.txt>. The module + To compile this driver as a module, choose M here. The module will be called smc-mca. config ULTRA @@ -821,8 +808,7 @@ config ULTRA this but keep it in mind if you have such a SCSI card and have problems. - To compile this driver as a module, choose M here and read - <file:Documentation/networking/net-modules.txt>. The module + To compile this driver as a module, choose M here. The module will be called smc-ultra. config ULTRA32 @@ -834,8 +820,7 @@ config ULTRA32 the Ethernet-HOWTO, available from <http://www.tldp.org/docs.html#howto>. - To compile this driver as a module, choose M here and read - <file:Documentation/networking/net-modules.txt>. The module + To compile this driver as a module, choose M here. The module will be called smc-ultra32. config BFIN_MAC @@ -896,15 +881,14 @@ config SMC9194 <file:Documentation/networking/smc9.txt> and the Ethernet-HOWTO, available from <http://www.tldp.org/docs.html#howto>. - To compile this driver as a module, choose M here and read - <file:Documentation/networking/net-modules.txt>. The module + To compile this driver as a module, choose M here. The module will be called smc9194. config SMC91X tristate "SMC 91C9x/91C1xxx support" select CRC32 select MII - depends on ARM || REDWOOD_5 || REDWOOD_6 || M32R || SUPERH || SOC_AU1X00 || BFIN + depends on ARM || REDWOOD_5 || REDWOOD_6 || M32R || SUPERH || SOC_AU1X00 || BLACKFIN help This is a driver for SMC's 91x series of Ethernet chipsets, including the SMC91C94 and the SMC91C111. Say Y if you want it @@ -915,8 +899,7 @@ config SMC91X This driver is also available as a module ( = code which can be inserted in and removed from the running kernel whenever you want). The module will be called smc91x. If you want to compile it as a - module, say M here and read <file:Documentation/kbuild/modules.txt> - as well as <file:Documentation/networking/net-modules.txt>. + module, say M here and read <file:Documentation/kbuild/modules.txt>. config NET_NETX tristate "NetX Ethernet support" @@ -925,8 +908,7 @@ config NET_NETX help This is support for the Hilscher netX builtin Ethernet ports - To compile this driver as a module, choose M here and read - <file:Documentation/networking/net-modules.txt>. The module + To compile this driver as a module, choose M here. The module will be called netx-eth. config DM9000 @@ -937,15 +919,14 @@ config DM9000 ---help--- Support for DM9000 chipset. - To compile this driver as a module, choose M here and read - <file:Documentation/networking/net-modules.txt>. The module will be - called dm9000. + To compile this driver as a module, choose M here. The module + will be called dm9000. config SMC911X tristate "SMSC LAN911[5678] support" select CRC32 select MII - depends on ARCH_PXA || SUPERH + depends on ARCH_PXA || SH_MAGIC_PANEL_R2 help This is a driver for SMSC's LAN911x series of Ethernet chipsets including the new LAN9115, LAN9116, LAN9117, and LAN9118. @@ -979,8 +960,7 @@ config NI5010 <http://www.tldp.org/docs.html#howto>. Note that this is still experimental code. - To compile this driver as a module, choose M here and read - <file:Documentation/networking/net-modules.txt>. The module + To compile this driver as a module, choose M here. The module will be called ni5010. config NI52 @@ -991,8 +971,7 @@ config NI52 the Ethernet-HOWTO, available from <http://www.tldp.org/docs.html#howto>. - To compile this driver as a module, choose M here and read - <file:Documentation/networking/net-modules.txt>. The module + To compile this driver as a module, choose M here. The module will be called ni52. config NI65 @@ -1003,8 +982,7 @@ config NI65 the Ethernet-HOWTO, available from <http://www.tldp.org/docs.html#howto>. - To compile this driver as a module, choose M here and read - <file:Documentation/networking/net-modules.txt>. The module + To compile this driver as a module, choose M here. The module will be called ni65. source "drivers/net/tulip/Kconfig" @@ -1018,8 +996,7 @@ config AT1700 the Ethernet-HOWTO, available from <http://www.tldp.org/docs.html#howto>. - To compile this driver as a module, choose M here and read - <file:Documentation/networking/net-modules.txt>. The module + To compile this driver as a module, choose M here. The module will be called at1700. config DEPCA @@ -1032,8 +1009,7 @@ config DEPCA <http://www.tldp.org/docs.html#howto> as well as <file:drivers/net/depca.c>. - To compile this driver as a module, choose M here and read - <file:Documentation/networking/net-modules.txt>. The module + To compile this driver as a module, choose M here. The module will be called depca. config HP100 @@ -1044,8 +1020,7 @@ config HP100 the Ethernet-HOWTO, available from <http://www.tldp.org/docs.html#howto>. - To compile this driver as a module, choose M here and read - <file:Documentation/networking/net-modules.txt>. The module + To compile this driver as a module, choose M here. The module will be called hp100. config NET_ISA @@ -1074,8 +1049,7 @@ config E2100 the Ethernet-HOWTO, available from <http://www.tldp.org/docs.html#howto>. - To compile this driver as a module, choose M here and read - <file:Documentation/networking/net-modules.txt>. The module + To compile this driver as a module, choose M here. The module will be called e2100. config EWRK3 @@ -1089,8 +1063,7 @@ config EWRK3 well as the Ethernet-HOWTO, available from <http://www.tldp.org/docs.html#howto>. - To compile this driver as a module, choose M here and read - <file:Documentation/networking/net-modules.txt>. The module + To compile this driver as a module, choose M here. The module will be called ewrk3. config EEXPRESS @@ -1104,8 +1077,7 @@ config EEXPRESS because the driver was very unreliable. We now have a new driver that should do better. - To compile this driver as a module, choose M here and read - <file:Documentation/networking/net-modules.txt>. The module + To compile this driver as a module, choose M here. The module will be called eexpress. config EEXPRESS_PRO @@ -1118,8 +1090,7 @@ config EEXPRESS_PRO driver. Please read the Ethernet-HOWTO, available from <http://www.tldp.org/docs.html#howto>. - To compile this driver as a module, choose M here and read - <file:Documentation/networking/net-modules.txt>. The module + To compile this driver as a module, choose M here. The module will be called eepro. config HPLAN_PLUS @@ -1131,8 +1102,7 @@ config HPLAN_PLUS the Ethernet-HOWTO, available from <http://www.tldp.org/docs.html#howto>. - To compile this driver as a module, choose M here and read - <file:Documentation/networking/net-modules.txt>. The module + To compile this driver as a module, choose M here. The module will be called hp-plus. config HPLAN @@ -1144,8 +1114,7 @@ config HPLAN the Ethernet-HOWTO, available from <http://www.tldp.org/docs.html#howto>. - To compile this driver as a module, choose M here and read - <file:Documentation/networking/net-modules.txt>. The module + To compile this driver as a module, choose M here. The module will be called hp. config LP486E @@ -1164,8 +1133,7 @@ config ETH16I the Ethernet-HOWTO, available from <http://www.tldp.org/docs.html#howto>. - To compile this driver as a module, choose M here and read - <file:Documentation/networking/net-modules.txt>. The module + To compile this driver as a module, choose M here. The module will be called eth16i. config NE2000 @@ -1185,8 +1153,7 @@ config NE2000 laptops), say N here and Y to "NE/2 (ne2000 MCA version) support", below. - To compile this driver as a module, choose M here and read - <file:Documentation/networking/net-modules.txt>. The module + To compile this driver as a module, choose M here. The module will be called ne. config ZNET @@ -1207,8 +1174,7 @@ config SEEQ8005 is for you, read the Ethernet-HOWTO, available from <http://www.tldp.org/docs.html#howto>. - To compile this driver as a module, choose M here and read - <file:Documentation/networking/net-modules.txt>. The module + To compile this driver as a module, choose M here. The module will be called seeq8005. config NE2_MCA @@ -1220,8 +1186,7 @@ config NE2_MCA the Ethernet-HOWTO, available from <http://www.tldp.org/docs.html#howto>. - To compile this driver as a module, choose M here and read - <file:Documentation/networking/net-modules.txt>. The module + To compile this driver as a module, choose M here. The module will be called ne2. config IBMLANA @@ -1232,8 +1197,7 @@ config IBMLANA CONFIG_MCA to use this driver. It is both available as an in-kernel driver and as a module. - To compile this driver as a module, choose M here and read - <file:Documentation/networking/net-modules.txt>. The only + To compile this driver as a module, choose M here. The only currently supported card is the IBM LAN Adapter/A for Ethernet. It will both support 16K and 32K memory windows, however a 32K window gives a better security against packet losses. Usage of multiple @@ -1247,8 +1211,7 @@ config IBMVETH This driver supports virtual ethernet adapters on newer IBM iSeries and pSeries systems. - To compile this driver as a module, choose M here and read - <file:Documentation/networking/net-modules.txt>. The module will + To compile this driver as a module, choose M here. The module will be called ibmveth. source "drivers/net/ibm_emac/Kconfig" @@ -1278,8 +1241,7 @@ config PCNET32 answer Y here and read the Ethernet-HOWTO, available from <http://www.tldp.org/docs.html#howto>. - To compile this driver as a module, choose M here and read - <file:Documentation/networking/net-modules.txt>. The module + To compile this driver as a module, choose M here. The module will be called pcnet32. config PCNET32_NAPI @@ -1306,8 +1268,7 @@ config AMD8111_ETH answer Y here and read the Ethernet-HOWTO, available from <http://www.tldp.org/docs.html#howto>. - To compile this driver as a module, choose M here and read - <file:Documentation/networking/net-modules.txt>. The module + To compile this driver as a module, choose M here. The module will be called amd8111e. config AMD8111E_NAPI @@ -1361,8 +1322,7 @@ config AC3200 the Ethernet-HOWTO, available from <http://www.tldp.org/docs.html#howto>. - To compile this driver as a module, choose M here and read - <file:Documentation/networking/net-modules.txt>. The module + To compile this driver as a module, choose M here. The module will be called ac3200. config APRICOT @@ -1373,9 +1333,8 @@ config APRICOT read the Ethernet-HOWTO, available from <http://www.tldp.org/docs.html#howto>. - To compile this driver as a module, choose M here and read - <file:Documentation/networking/net-modules.txt>. The module will be - called apricot. + To compile this driver as a module, choose M here. The module + will be called apricot. config B44 tristate "Broadcom 440x/47xx ethernet support" @@ -1387,9 +1346,8 @@ config B44 or M and read the Ethernet-HOWTO, available from <http://www.tldp.org/docs.html#howto>. - To compile this driver as a module, choose M here and read - <file:Documentation/networking/net-modules.txt>. The module will be - called b44. + To compile this driver as a module, choose M here. The module + will be called b44. # Auto-select SSB PCI-HOST support, if possible config B44_PCI_AUTOSELECT @@ -1418,9 +1376,8 @@ config FORCEDETH read the Ethernet-HOWTO, available from <http://www.tldp.org/docs.html#howto>. - To compile this driver as a module, choose M here and read - <file:Documentation/networking/net-modules.txt>. The module will be - called forcedeth. + To compile this driver as a module, choose M here. The module + will be called forcedeth. config FORCEDETH_NAPI bool "Use Rx Polling (NAPI) (EXPERIMENTAL)" @@ -1446,9 +1403,8 @@ config CS89x0 <http://www.tldp.org/docs.html#howto> as well as <file:Documentation/networking/cs89x0.txt>. - To compile this driver as a module, choose M here and read - <file:Documentation/networking/net-modules.txt>. The module will be - called cs89x0. + To compile this driver as a module, choose M here. The module + will be called cs89x0. config TC35815 tristate "TOSHIBA TC35815 Ethernet support" @@ -1464,8 +1420,7 @@ config EEPRO100 card, say Y and read the Ethernet-HOWTO, available from <http://www.tldp.org/docs.html#howto>. - To compile this driver as a module, choose M here and read - <file:Documentation/networking/net-modules.txt>. The module + To compile this driver as a module, choose M here. The module will be called eepro100. @@ -1492,8 +1447,7 @@ config E100 More specific information on configuring the driver is in <file:Documentation/networking/e100.txt>. - To compile this driver as a module, choose M here and read - <file:Documentation/networking/net-modules.txt>. The module + To compile this driver as a module, choose M here. The module will be called e100. config LNE390 @@ -1505,8 +1459,7 @@ config LNE390 the Ethernet-HOWTO, available from <http://www.tldp.org/docs.html#howto>. - To compile this driver as a module, choose M here and read - <file:Documentation/networking/net-modules.txt>. The module + To compile this driver as a module, choose M here. The module will be called lne390. config FEALNX @@ -1546,8 +1499,7 @@ config NE2K_PCI NetVin NV5000SC Via 86C926 SureCom NE34 Winbond Holtek HT80232 Holtek HT80229 - To compile this driver as a module, choose M here and read - <file:Documentation/networking/net-modules.txt>. The module + To compile this driver as a module, choose M here. The module will be called ne2k-pci. config NE3210 @@ -1560,8 +1512,7 @@ config NE3210 <http://www.tldp.org/docs.html#howto>. Note that this driver will NOT WORK for NE3200 cards as they are completely different. - To compile this driver as a module, choose M here and read - <file:Documentation/networking/net-modules.txt>. The module + To compile this driver as a module, choose M here. The module will be called ne3210. config ES3210 @@ -1573,8 +1524,7 @@ config ES3210 the Ethernet-HOWTO, available from <http://www.tldp.org/docs.html#howto>. - To compile this driver as a module, choose M here and read - <file:Documentation/networking/net-modules.txt>. The module + To compile this driver as a module, choose M here. The module will be called es3210. config 8139CP @@ -1704,8 +1654,7 @@ config TLAN Compaq NetFlex and Olicom cards. Please read the file <file:Documentation/networking/tlan.txt> for more details. - To compile this driver as a module, choose M here and read - <file:Documentation/networking/net-modules.txt>. The module + To compile this driver as a module, choose M here. The module will be called tlan. Please email feedback to <torben.mathiasen@compaq.com>. @@ -1995,8 +1944,7 @@ config E1000 More specific information on configuring the driver is in <file:Documentation/networking/e1000.txt>. - To compile this driver as a module, choose M here and read - <file:Documentation/networking/net-modules.txt>. The module + To compile this driver as a module, choose M here. The module will be called e1000. config E1000_NAPI @@ -2041,8 +1989,7 @@ config E1000E More specific information on configuring the driver is in <file:Documentation/networking/e1000e.txt>. - To compile this driver as a module, choose M here and read - <file:Documentation/networking/net-modules.txt>. The module + To compile this driver as a module, choose M here. The module will be called e1000e. source "drivers/net/ixp2000/Kconfig" @@ -2075,8 +2022,7 @@ config HAMACHI the Ethernet-HOWTO, available from <http://www.tldp.org/docs.html#howto>. - To compile this driver as a module, choose M here and read - <file:Documentation/networking/net-modules.txt>. The module will be + To compile this driver as a module, choose M here. The module will be called hamachi. config YELLOWFIN @@ -2525,8 +2471,7 @@ config IXGBE More specific information on configuring the driver is in <file:Documentation/networking/ixgbe.txt>. - To compile this driver as a module, choose M here and read - <file:Documentation/networking/net-modules.txt>. The module + To compile this driver as a module, choose M here. The module will be called ixgbe. config IXGB @@ -2548,8 +2493,7 @@ config IXGB More specific information on configuring the driver is in <file:Documentation/networking/ixgb.txt>. - To compile this driver as a module, choose M here and read - <file:Documentation/networking/net-modules.txt>. The module + To compile this driver as a module, choose M here. The module will be called ixgb. config IXGB_NAPI @@ -2602,8 +2546,7 @@ config MYRI10GE <http://www.myri.com/scs/download-Myri10GE.html> - To compile this driver as a module, choose M here and read - <file:Documentation/networking/net-modules.txt>. The module + To compile this driver as a module, choose M here. The module will be called myri10ge. config NETXEN_NIC @@ -2827,10 +2770,9 @@ config PLIP with the PLIP support in Linux versions 1.0.x. This option enlarges your kernel by about 8 KB. - To compile this driver as a module, choose M here and read - <file:Documentation/networking/net-modules.txt>. The module will be - called plip. If unsure, say Y or M, in case you buy a laptop - later. + To compile this driver as a module, choose M here. The module + will be called plip. If unsure, say Y or M, in case you buy + a laptop later. config PPP tristate "PPP (point-to-point protocol) support" @@ -2860,8 +2802,7 @@ config PPP If you said Y to "Version information on all symbols" above, then you cannot compile the PPP driver into the kernel; you can then only compile it as a module. To compile this driver as a module, choose M - here and read <file:Documentation/networking/net-modules.txt>. - The module will be called ppp_generic. + here. The module will be called ppp_generic. config PPP_MULTILINK bool "PPP multilink support (EXPERIMENTAL)" @@ -3022,9 +2963,8 @@ config SLIP <http://www.bart.nl/~patrickr/term-howto/Term-HOWTO.html>). SLIP support will enlarge your kernel by about 4 KB. If unsure, say N. - To compile this driver as a module, choose M here and read - <file:Documentation/networking/net-modules.txt>. The module will be - called slip. + To compile this driver as a module, choose M here. The module + will be called slip. config SLIP_COMPRESSED bool "CSLIP compressed headers" diff --git a/drivers/net/amd8111e.c b/drivers/net/amd8111e.c index eebf5bb..e7fdd81 100644 --- a/drivers/net/amd8111e.c +++ b/drivers/net/amd8111e.c @@ -1340,7 +1340,9 @@ static int amd8111e_close(struct net_device * dev) struct amd8111e_priv *lp = netdev_priv(dev); netif_stop_queue(dev); +#ifdef CONFIG_AMD8111E_NAPI napi_disable(&lp->napi); +#endif spin_lock_irq(&lp->lock); @@ -1372,7 +1374,9 @@ static int amd8111e_open(struct net_device * dev ) dev->name, dev)) return -EAGAIN; +#ifdef CONFIG_AMD8111E_NAPI napi_enable(&lp->napi); +#endif spin_lock_irq(&lp->lock); @@ -1380,7 +1384,9 @@ static int amd8111e_open(struct net_device * dev ) if(amd8111e_restart(dev)){ spin_unlock_irq(&lp->lock); +#ifdef CONFIG_AMD8111E_NAPI napi_disable(&lp->napi); +#endif if (dev->irq) free_irq(dev->irq, dev); return -ENOMEM; diff --git a/drivers/net/arcnet/Kconfig b/drivers/net/arcnet/Kconfig index 4030274..3b2f7f1 100644 --- a/drivers/net/arcnet/Kconfig +++ b/drivers/net/arcnet/Kconfig @@ -19,8 +19,7 @@ menuconfig ARCNET from <http://www.tldp.org/docs.html#howto>(even though ARCnet is not really Ethernet). - To compile this driver as a module, choose M here and read - <file:Documentation/networking/net-modules.txt>. The module will + To compile this driver as a module, choose M here. The module will be called arcnet. if ARCNET @@ -81,8 +80,7 @@ config ARCNET_COM90xx have always used the old ARCnet driver without knowing what type of card you had, this is probably the one for you. - To compile this driver as a module, choose M here and read - <file:Documentation/networking/net-modules.txt>. The module will + To compile this driver as a module, choose M here. The module will be called com90xx. config ARCNET_COM90xxIO @@ -93,8 +91,7 @@ config ARCNET_COM90xxIO the normal driver. Only use it if your card doesn't support shared memory. - To compile this driver as a module, choose M here and read - <file:Documentation/networking/net-modules.txt>. The module will + To compile this driver as a module, choose M here. The module will be called com90io. config ARCNET_RIM_I @@ -105,8 +102,7 @@ config ARCNET_RIM_I driver is completely untested, so if you have one of these cards, please mail <dwmw2@infradead.org>, especially if it works! - To compile this driver as a module, choose M here and read - <file:Documentation/networking/net-modules.txt>. The module will + To compile this driver as a module, choose M here. The module will be called arc-rimi. config ARCNET_COM20020 @@ -116,8 +112,7 @@ config ARCNET_COM20020 things as promiscuous mode, so packet sniffing is possible, and extra diagnostic information. - To compile this driver as a module, choose M here and read - <file:Documentation/networking/net-modules.txt>. The module will + To compile this driver as a module, choose M here. The module will be called com20020. config ARCNET_COM20020_ISA diff --git a/drivers/net/arm/ep93xx_eth.c b/drivers/net/arm/ep93xx_eth.c index 7f016f3..91a6590 100644 --- a/drivers/net/arm/ep93xx_eth.c +++ b/drivers/net/arm/ep93xx_eth.c @@ -417,7 +417,7 @@ static irqreturn_t ep93xx_irq(int irq, void *dev_id) if (status & REG_INTSTS_RX) { spin_lock(&ep->rx_lock); - if (likely(__netif_rx_schedule_prep(dev, &ep->napi))) { + if (likely(netif_rx_schedule_prep(dev, &ep->napi))) { wrl(ep, REG_INTEN, REG_INTEN_TX); __netif_rx_schedule(dev, &ep->napi); } diff --git a/drivers/net/bfin_mac.c b/drivers/net/bfin_mac.c index 084acfd..eb97175 100644 --- a/drivers/net/bfin_mac.c +++ b/drivers/net/bfin_mac.c @@ -676,7 +676,7 @@ static void bf537mac_rx(struct net_device *dev) skb->protocol = eth_type_trans(skb, dev); #if defined(BFIN_MAC_CSUM_OFFLOAD) skb->csum = current_rx_ptr->status.ip_payload_csum; - skb->ip_summed = CHECKSUM_PARTIAL; + skb->ip_summed = CHECKSUM_COMPLETE; #endif netif_rx(skb); @@ -924,7 +924,7 @@ static int __init bf537mac_probe(struct net_device *dev) if (!is_valid_ether_addr(dev->dev_addr)) { /* Grab the MAC from the board somehow - this is done in the arch/blackfin/mach-bf537/boards/eth_mac.c */ - get_bf537_ether_addr(dev->dev_addr); + bfin_get_ether_addr(dev->dev_addr); } /* If still not valid, get a random one */ diff --git a/drivers/net/bfin_mac.h b/drivers/net/bfin_mac.h index 3a107ad..5970ea7 100644 --- a/drivers/net/bfin_mac.h +++ b/drivers/net/bfin_mac.h @@ -92,4 +92,4 @@ struct bf537mac_local { struct mii_bus mii_bus; }; -extern void get_bf537_ether_addr(char *addr); +extern void bfin_get_ether_addr(char *addr); diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index 6937ef0..423298c 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -1847,9 +1847,9 @@ int bond_release(struct net_device *bond_dev, struct net_device *slave_dev) */ void bond_destroy(struct bonding *bond) { - unregister_netdevice(bond->dev); bond_deinit(bond->dev); bond_destroy_sysfs_entry(bond); + unregister_netdevice(bond->dev); } /* @@ -4405,6 +4405,7 @@ static int bond_init(struct net_device *bond_dev, struct bond_params *params) bond_dev->set_multicast_list = bond_set_multicast_list; bond_dev->change_mtu = bond_change_mtu; bond_dev->set_mac_address = bond_set_mac_address; + bond_dev->validate_addr = NULL; bond_set_mode_ops(bond, bond->params.mode); @@ -4474,8 +4475,8 @@ static void bond_free_all(void) bond_mc_list_destroy(bond); /* Release the bonded slaves */ bond_release_all(bond_dev); - unregister_netdevice(bond_dev); bond_deinit(bond_dev); + unregister_netdevice(bond_dev); } #ifdef CONFIG_PROC_FS diff --git a/drivers/net/bonding/bond_sysfs.c b/drivers/net/bonding/bond_sysfs.c index 7a06ade..b29330d 100644 --- a/drivers/net/bonding/bond_sysfs.c +++ b/drivers/net/bonding/bond_sysfs.c @@ -1193,8 +1193,6 @@ static ssize_t bonding_show_active_slave(struct device *d, struct bonding *bond = to_bond(d); int count; - rtnl_lock(); - read_lock(&bond->curr_slave_lock); curr = bond->curr_active_slave; read_unlock(&bond->curr_slave_lock); @@ -1216,7 +1214,9 @@ static ssize_t bonding_store_active_slave(struct device *d, struct slave *new_active = NULL; struct bonding *bond = to_bond(d); + rtnl_lock(); write_lock_bh(&bond->lock); + if (!USES_PRIMARY(bond->params.mode)) { printk(KERN_INFO DRV_NAME ": %s: Unable to change active slave; %s is in mode %d\n", diff --git a/drivers/net/chelsio/cxgb2.c b/drivers/net/chelsio/cxgb2.c index 2dbf8dc..c597504 100644..100755 --- a/drivers/net/chelsio/cxgb2.c +++ b/drivers/net/chelsio/cxgb2.c @@ -374,7 +374,9 @@ static char stats_strings[][ETH_GSTRING_LEN] = { "TxInternalMACXmitError", "TxFramesWithExcessiveDeferral", "TxFCSErrors", - + "TxJumboFramesOk", + "TxJumboOctetsOk", + "RxOctetsOK", "RxOctetsBad", "RxUnicastFramesOK", @@ -392,16 +394,17 @@ static char stats_strings[][ETH_GSTRING_LEN] = { "RxInRangeLengthErrors", "RxOutOfRangeLengthField", "RxFrameTooLongErrors", + "RxJumboFramesOk", + "RxJumboOctetsOk", /* Port stats */ - "RxPackets", "RxCsumGood", - "TxPackets", "TxCsumOffload", "TxTso", "RxVlan", "TxVlan", - + "TxNeedHeadroom", + /* Interrupt stats */ "rx drops", "pure_rsps", @@ -463,23 +466,56 @@ static void get_stats(struct net_device *dev, struct ethtool_stats *stats, const struct cmac_statistics *s; const struct sge_intr_counts *t; struct sge_port_stats ss; - unsigned int len; s = mac->ops->statistics_update(mac, MAC_STATS_UPDATE_FULL); - - len = sizeof(u64)*(&s->TxFCSErrors + 1 - &s->TxOctetsOK); - memcpy(data, &s->TxOctetsOK, len); - data += len; - - len = sizeof(u64)*(&s->RxFrameTooLongErrors + 1 - &s->RxOctetsOK); - memcpy(data, &s->RxOctetsOK, len); - data += len; - + t = t1_sge_get_intr_counts(adapter->sge); t1_sge_get_port_stats(adapter->sge, dev->if_port, &ss); - memcpy(data, &ss, sizeof(ss)); - data += sizeof(ss); - t = t1_sge_get_intr_counts(adapter->sge); + *data++ = s->TxOctetsOK; + *data++ = s->TxOctetsBad; + *data++ = s->TxUnicastFramesOK; + *data++ = s->TxMulticastFramesOK; + *data++ = s->TxBroadcastFramesOK; + *data++ = s->TxPauseFrames; + *data++ = s->TxFramesWithDeferredXmissions; + *data++ = s->TxLateCollisions; + *data++ = s->TxTotalCollisions; + *data++ = s->TxFramesAbortedDueToXSCollisions; + *data++ = s->TxUnderrun; + *data++ = s->TxLengthErrors; + *data++ = s->TxInternalMACXmitError; + *data++ = s->TxFramesWithExcessiveDeferral; + *data++ = s->TxFCSErrors; + *data++ = s->TxJumboFramesOK; + *data++ = s->TxJumboOctetsOK; + + *data++ = s->RxOctetsOK; + *data++ = s->RxOctetsBad; + *data++ = s->RxUnicastFramesOK; + *data++ = s->RxMulticastFramesOK; + *data++ = s->RxBroadcastFramesOK; + *data++ = s->RxPauseFrames; + *data++ = s->RxFCSErrors; + *data++ = s->RxAlignErrors; + *data++ = s->RxSymbolErrors; + *data++ = s->RxDataErrors; + *data++ = s->RxSequenceErrors; + *data++ = s->RxRuntErrors; + *data++ = s->RxJabberErrors; + *data++ = s->RxInternalMACRcvError; + *data++ = s->RxInRangeLengthErrors; + *data++ = s->RxOutOfRangeLengthField; + *data++ = s->RxFrameTooLongErrors; + *data++ = s->RxJumboFramesOK; + *data++ = s->RxJumboOctetsOK; + + *data++ = ss.rx_cso_good; + *data++ = ss.tx_cso; + *data++ = ss.tx_tso; + *data++ = ss.vlan_xtract; + *data++ = ss.vlan_insert; + *data++ = ss.tx_need_hdrroom; + *data++ = t->rx_drops; *data++ = t->pure_rsps; *data++ = t->unhandled_irqs; diff --git a/drivers/net/chelsio/pm3393.c b/drivers/net/chelsio/pm3393.c index 678778a..2117c4f 100644..100755 --- a/drivers/net/chelsio/pm3393.c +++ b/drivers/net/chelsio/pm3393.c @@ -45,7 +45,7 @@ #include <linux/crc32.h> -#define OFFSET(REG_ADDR) (REG_ADDR << 2) +#define OFFSET(REG_ADDR) ((REG_ADDR) << 2) /* Max frame size PM3393 can handle. Includes Ethernet header and CRC. */ #define MAX_FRAME_SIZE 9600 @@ -428,69 +428,26 @@ static int pm3393_set_speed_duplex_fc(struct cmac *cmac, int speed, int duplex, return 0; } -static void pm3393_rmon_update(struct adapter *adapter, u32 offs, u64 *val, - int over) -{ - u32 val0, val1, val2; - - t1_tpi_read(adapter, offs, &val0); - t1_tpi_read(adapter, offs + 4, &val1); - t1_tpi_read(adapter, offs + 8, &val2); - - *val &= ~0ull << 40; - *val |= val0 & 0xffff; - *val |= (val1 & 0xffff) << 16; - *val |= (u64)(val2 & 0xff) << 32; - - if (over) - *val += 1ull << 40; +#define RMON_UPDATE(mac, name, stat_name) \ +{ \ + t1_tpi_read((mac)->adapter, OFFSET(name), &val0); \ + t1_tpi_read((mac)->adapter, OFFSET((name)+1), &val1); \ + t1_tpi_read((mac)->adapter, OFFSET((name)+2), &val2); \ + (mac)->stats.stat_name = (u64)(val0 & 0xffff) | \ + ((u64)(val1 & 0xffff) << 16) | \ + ((u64)(val2 & 0xff) << 32) | \ + ((mac)->stats.stat_name & \ + 0xffffff0000000000ULL); \ + if (ro & \ + (1ULL << ((name - SUNI1x10GEXP_REG_MSTAT_COUNTER_0_LOW) >> 2))) \ + (mac)->stats.stat_name += 1ULL << 40; \ } static const struct cmac_statistics *pm3393_update_statistics(struct cmac *mac, int flag) { - static struct { - unsigned int reg; - unsigned int offset; - } hw_stats [] = { - -#define HW_STAT(name, stat_name) \ - { name, (&((struct cmac_statistics *)NULL)->stat_name) - (u64 *)NULL } - - /* Rx stats */ - HW_STAT(RxOctetsReceivedOK, RxOctetsOK), - HW_STAT(RxUnicastFramesReceivedOK, RxUnicastFramesOK), - HW_STAT(RxMulticastFramesReceivedOK, RxMulticastFramesOK), - HW_STAT(RxBroadcastFramesReceivedOK, RxBroadcastFramesOK), - HW_STAT(RxPAUSEMACCtrlFramesReceived, RxPauseFrames), - HW_STAT(RxFrameCheckSequenceErrors, RxFCSErrors), - HW_STAT(RxFramesLostDueToInternalMACErrors, - RxInternalMACRcvError), - HW_STAT(RxSymbolErrors, RxSymbolErrors), - HW_STAT(RxInRangeLengthErrors, RxInRangeLengthErrors), - HW_STAT(RxFramesTooLongErrors , RxFrameTooLongErrors), - HW_STAT(RxJabbers, RxJabberErrors), - HW_STAT(RxFragments, RxRuntErrors), - HW_STAT(RxUndersizedFrames, RxRuntErrors), - HW_STAT(RxJumboFramesReceivedOK, RxJumboFramesOK), - HW_STAT(RxJumboOctetsReceivedOK, RxJumboOctetsOK), - - /* Tx stats */ - HW_STAT(TxOctetsTransmittedOK, TxOctetsOK), - HW_STAT(TxFramesLostDueToInternalMACTransmissionError, - TxInternalMACXmitError), - HW_STAT(TxTransmitSystemError, TxFCSErrors), - HW_STAT(TxUnicastFramesTransmittedOK, TxUnicastFramesOK), - HW_STAT(TxMulticastFramesTransmittedOK, TxMulticastFramesOK), - HW_STAT(TxBroadcastFramesTransmittedOK, TxBroadcastFramesOK), - HW_STAT(TxPAUSEMACCtrlFramesTransmitted, TxPauseFrames), - HW_STAT(TxJumboFramesReceivedOK, TxJumboFramesOK), - HW_STAT(TxJumboOctetsReceivedOK, TxJumboOctetsOK) - }, *p = hw_stats; - u64 ro; - u32 val0, val1, val2, val3; - u64 *stats = (u64 *) &mac->stats; - unsigned int i; + u64 ro; + u32 val0, val1, val2, val3; /* Snap the counters */ pmwrite(mac, SUNI1x10GEXP_REG_MSTAT_CONTROL, @@ -504,14 +461,35 @@ static const struct cmac_statistics *pm3393_update_statistics(struct cmac *mac, ro = ((u64)val0 & 0xffff) | (((u64)val1 & 0xffff) << 16) | (((u64)val2 & 0xffff) << 32) | (((u64)val3 & 0xffff) << 48); - for (i = 0; i < ARRAY_SIZE(hw_stats); i++) { - unsigned reg = p->reg - SUNI1x10GEXP_REG_MSTAT_COUNTER_0_LOW; - - pm3393_rmon_update((mac)->adapter, OFFSET(p->reg), - stats + p->offset, ro & (reg >> 2)); - } - - + /* Rx stats */ + RMON_UPDATE(mac, RxOctetsReceivedOK, RxOctetsOK); + RMON_UPDATE(mac, RxUnicastFramesReceivedOK, RxUnicastFramesOK); + RMON_UPDATE(mac, RxMulticastFramesReceivedOK, RxMulticastFramesOK); + RMON_UPDATE(mac, RxBroadcastFramesReceivedOK, RxBroadcastFramesOK); + RMON_UPDATE(mac, RxPAUSEMACCtrlFramesReceived, RxPauseFrames); + RMON_UPDATE(mac, RxFrameCheckSequenceErrors, RxFCSErrors); + RMON_UPDATE(mac, RxFramesLostDueToInternalMACErrors, + RxInternalMACRcvError); + RMON_UPDATE(mac, RxSymbolErrors, RxSymbolErrors); + RMON_UPDATE(mac, RxInRangeLengthErrors, RxInRangeLengthErrors); + RMON_UPDATE(mac, RxFramesTooLongErrors , RxFrameTooLongErrors); + RMON_UPDATE(mac, RxJabbers, RxJabberErrors); + RMON_UPDATE(mac, RxFragments, RxRuntErrors); + RMON_UPDATE(mac, RxUndersizedFrames, RxRuntErrors); + RMON_UPDATE(mac, RxJumboFramesReceivedOK, RxJumboFramesOK); + RMON_UPDATE(mac, RxJumboOctetsReceivedOK, RxJumboOctetsOK); + + /* Tx stats */ + RMON_UPDATE(mac, TxOctetsTransmittedOK, TxOctetsOK); + RMON_UPDATE(mac, TxFramesLostDueToInternalMACTransmissionError, + TxInternalMACXmitError); + RMON_UPDATE(mac, TxTransmitSystemError, TxFCSErrors); + RMON_UPDATE(mac, TxUnicastFramesTransmittedOK, TxUnicastFramesOK); + RMON_UPDATE(mac, TxMulticastFramesTransmittedOK, TxMulticastFramesOK); + RMON_UPDATE(mac, TxBroadcastFramesTransmittedOK, TxBroadcastFramesOK); + RMON_UPDATE(mac, TxPAUSEMACCtrlFramesTransmitted, TxPauseFrames); + RMON_UPDATE(mac, TxJumboFramesReceivedOK, TxJumboFramesOK); + RMON_UPDATE(mac, TxJumboOctetsReceivedOK, TxJumboOctetsOK); return &mac->stats; } diff --git a/drivers/net/chelsio/sge.c b/drivers/net/chelsio/sge.c index ffa7e64..b301c04 100644..100755 --- a/drivers/net/chelsio/sge.c +++ b/drivers/net/chelsio/sge.c @@ -986,11 +986,10 @@ void t1_sge_get_port_stats(const struct sge *sge, int port, for_each_possible_cpu(cpu) { struct sge_port_stats *st = per_cpu_ptr(sge->port_stats[port], cpu); - ss->rx_packets += st->rx_packets; ss->rx_cso_good += st->rx_cso_good; - ss->tx_packets += st->tx_packets; ss->tx_cso += st->tx_cso; ss->tx_tso += st->tx_tso; + ss->tx_need_hdrroom += st->tx_need_hdrroom; ss->vlan_xtract += st->vlan_xtract; ss->vlan_insert += st->vlan_insert; } @@ -1379,11 +1378,10 @@ static void sge_rx(struct sge *sge, struct freelQ *fl, unsigned int len) } __skb_pull(skb, sizeof(*p)); - skb->dev->last_rx = jiffies; st = per_cpu_ptr(sge->port_stats[p->iff], smp_processor_id()); - st->rx_packets++; skb->protocol = eth_type_trans(skb, adapter->port[p->iff].dev); + skb->dev->last_rx = jiffies; if ((adapter->flags & RX_CSUM_ENABLED) && p->csum == 0xffff && skb->protocol == htons(ETH_P_IP) && (skb->data[9] == IPPROTO_TCP || skb->data[9] == IPPROTO_UDP)) { @@ -1624,11 +1622,9 @@ int t1_poll(struct napi_struct *napi, int budget) { struct adapter *adapter = container_of(napi, struct adapter, napi); struct net_device *dev = adapter->port[0].dev; - int work_done; - - work_done = process_responses(adapter, budget); + int work_done = process_responses(adapter, budget); - if (likely(!responses_pending(adapter))) { + if (likely(work_done < budget)) { netif_rx_complete(dev, napi); writel(adapter->sge->respQ.cidx, adapter->regs + A_SG_SLEEPING); @@ -1848,7 +1844,8 @@ int t1_start_xmit(struct sk_buff *skb, struct net_device *dev) { struct adapter *adapter = dev->priv; struct sge *sge = adapter->sge; - struct sge_port_stats *st = per_cpu_ptr(sge->port_stats[dev->if_port], smp_processor_id()); + struct sge_port_stats *st = per_cpu_ptr(sge->port_stats[dev->if_port], + smp_processor_id()); struct cpl_tx_pkt *cpl; struct sk_buff *orig_skb = skb; int ret; @@ -1856,6 +1853,18 @@ int t1_start_xmit(struct sk_buff *skb, struct net_device *dev) if (skb->protocol == htons(ETH_P_CPL5)) goto send; + /* + * We are using a non-standard hard_header_len. + * Allocate more header room in the rare cases it is not big enough. + */ + if (unlikely(skb_headroom(skb) < dev->hard_header_len - ETH_HLEN)) { + skb = skb_realloc_headroom(skb, sizeof(struct cpl_tx_pkt_lso)); + ++st->tx_need_hdrroom; + dev_kfree_skb_any(orig_skb); + if (!skb) + return NETDEV_TX_OK; + } + if (skb_shinfo(skb)->gso_size) { int eth_type; struct cpl_tx_pkt_lso *hdr; @@ -1889,24 +1898,6 @@ int t1_start_xmit(struct sk_buff *skb, struct net_device *dev) return NETDEV_TX_OK; } - /* - * We are using a non-standard hard_header_len and some kernel - * components, such as pktgen, do not handle it right. - * Complain when this happens but try to fix things up. - */ - if (unlikely(skb_headroom(skb) < dev->hard_header_len - ETH_HLEN)) { - pr_debug("%s: headroom %d header_len %d\n", dev->name, - skb_headroom(skb), dev->hard_header_len); - - if (net_ratelimit()) - printk(KERN_ERR "%s: inadequate headroom in " - "Tx packet\n", dev->name); - skb = skb_realloc_headroom(skb, sizeof(*cpl)); - dev_kfree_skb_any(orig_skb); - if (!skb) - return NETDEV_TX_OK; - } - if (!(adapter->flags & UDP_CSUM_CAPABLE) && skb->ip_summed == CHECKSUM_PARTIAL && ip_hdr(skb)->protocol == IPPROTO_UDP) { @@ -1952,7 +1943,6 @@ int t1_start_xmit(struct sk_buff *skb, struct net_device *dev) cpl->vlan_valid = 0; send: - st->tx_packets++; dev->trans_start = jiffies; ret = t1_sge_tx(skb, adapter, 0, dev); diff --git a/drivers/net/chelsio/sge.h b/drivers/net/chelsio/sge.h index 713d9c5..cced9df 100644..100755 --- a/drivers/net/chelsio/sge.h +++ b/drivers/net/chelsio/sge.h @@ -57,13 +57,12 @@ struct sge_intr_counts { }; struct sge_port_stats { - u64 rx_packets; /* # of Ethernet packets received */ u64 rx_cso_good; /* # of successful RX csum offloads */ - u64 tx_packets; /* # of TX packets */ u64 tx_cso; /* # of TX checksum offloads */ u64 tx_tso; /* # of TSO requests */ u64 vlan_xtract; /* # of VLAN tag extractions */ u64 vlan_insert; /* # of VLAN tag insertions */ + u64 tx_need_hdrroom; /* # of TX skbs in need of more header room */ }; struct sk_buff; diff --git a/drivers/net/cris/eth_v10.c b/drivers/net/cris/eth_v10.c index edd6828..917b7b4 100644 --- a/drivers/net/cris/eth_v10.c +++ b/drivers/net/cris/eth_v10.c @@ -250,6 +250,7 @@ #include <asm/system.h> #include <asm/ethernet.h> #include <asm/cache.h> +#include <asm/arch/io_interface_mux.h> //#define ETHDEBUG #define D(x) @@ -279,6 +280,9 @@ struct net_local { * by this lock as well. */ spinlock_t lock; + + spinlock_t led_lock; /* Protect LED state */ + spinlock_t transceiver_lock; /* Protect transceiver state. */ }; typedef struct etrax_eth_descr @@ -295,8 +299,6 @@ struct transceiver_ops void (*check_duplex)(struct net_device* dev); }; -struct transceiver_ops* transceiver; - /* Duplex settings */ enum duplex { @@ -307,7 +309,7 @@ enum duplex /* Dma descriptors etc. */ -#define MAX_MEDIA_DATA_SIZE 1518 +#define MAX_MEDIA_DATA_SIZE 1522 #define MIN_PACKET_LEN 46 #define ETHER_HEAD_LEN 14 @@ -332,8 +334,8 @@ enum duplex /*Intel LXT972A specific*/ #define MDIO_INT_STATUS_REG_2 0x0011 -#define MDIO_INT_FULL_DUPLEX_IND ( 1 << 9 ) -#define MDIO_INT_SPEED ( 1 << 14 ) +#define MDIO_INT_FULL_DUPLEX_IND (1 << 9) +#define MDIO_INT_SPEED (1 << 14) /* Network flash constants */ #define NET_FLASH_TIME (HZ/50) /* 20 ms */ @@ -344,8 +346,8 @@ enum duplex #define NO_NETWORK_ACTIVITY 0 #define NETWORK_ACTIVITY 1 -#define NBR_OF_RX_DESC 64 -#define NBR_OF_TX_DESC 256 +#define NBR_OF_RX_DESC 32 +#define NBR_OF_TX_DESC 16 /* Large packets are sent directly to upper layers while small packets are */ /* copied (to reduce memory waste). The following constant decides the breakpoint */ @@ -367,7 +369,6 @@ enum duplex static etrax_eth_descr *myNextRxDesc; /* Points to the next descriptor to to be processed */ static etrax_eth_descr *myLastRxDesc; /* The last processed descriptor */ -static etrax_eth_descr *myPrevRxDesc; /* The descriptor right before myNextRxDesc */ static etrax_eth_descr RxDescList[NBR_OF_RX_DESC] __attribute__ ((aligned(32))); @@ -377,7 +378,6 @@ static etrax_eth_descr* myNextTxDesc; /* Next descriptor to use */ static etrax_eth_descr TxDescList[NBR_OF_TX_DESC] __attribute__ ((aligned(32))); static unsigned int network_rec_config_shadow = 0; -static unsigned int mdio_phy_addr; /* Transciever address */ static unsigned int network_tr_ctrl_shadow = 0; @@ -411,7 +411,7 @@ static int e100_set_config(struct net_device* dev, struct ifmap* map); static void e100_tx_timeout(struct net_device *dev); static struct net_device_stats *e100_get_stats(struct net_device *dev); static void set_multicast_list(struct net_device *dev); -static void e100_hardware_send_packet(char *buf, int length); +static void e100_hardware_send_packet(struct net_local* np, char *buf, int length); static void update_rx_stats(struct net_device_stats *); static void update_tx_stats(struct net_device_stats *); static int e100_probe_transceiver(struct net_device* dev); @@ -434,7 +434,10 @@ static void e100_clear_network_leds(unsigned long dummy); static void e100_set_network_leds(int active); static const struct ethtool_ops e100_ethtool_ops; - +#if defined(CONFIG_ETRAX_NO_PHY) +static void dummy_check_speed(struct net_device* dev); +static void dummy_check_duplex(struct net_device* dev); +#else static void broadcom_check_speed(struct net_device* dev); static void broadcom_check_duplex(struct net_device* dev); static void tdk_check_speed(struct net_device* dev); @@ -443,16 +446,28 @@ static void intel_check_speed(struct net_device* dev); static void intel_check_duplex(struct net_device* dev); static void generic_check_speed(struct net_device* dev); static void generic_check_duplex(struct net_device* dev); +#endif +#ifdef CONFIG_NET_POLL_CONTROLLER +static void e100_netpoll(struct net_device* dev); +#endif + +static int autoneg_normal = 1; struct transceiver_ops transceivers[] = { +#if defined(CONFIG_ETRAX_NO_PHY) + {0x0000, dummy_check_speed, dummy_check_duplex} /* Dummy */ +#else {0x1018, broadcom_check_speed, broadcom_check_duplex}, /* Broadcom */ {0xC039, tdk_check_speed, tdk_check_duplex}, /* TDK 2120 */ {0x039C, tdk_check_speed, tdk_check_duplex}, /* TDK 2120C */ {0x04de, intel_check_speed, intel_check_duplex}, /* Intel LXT972A*/ {0x0000, generic_check_speed, generic_check_duplex} /* Generic, must be last */ +#endif }; +struct transceiver_ops* transceiver = &transceivers[0]; + #define tx_done(dev) (*R_DMA_CH0_CMD == 0) /* @@ -471,14 +486,22 @@ etrax_ethernet_init(void) int i, err; printk(KERN_INFO - "ETRAX 100LX 10/100MBit ethernet v2.0 (c) 2000-2003 Axis Communications AB\n"); + "ETRAX 100LX 10/100MBit ethernet v2.0 (c) 1998-2007 Axis Communications AB\n"); - dev = alloc_etherdev(sizeof(struct net_local)); - np = dev->priv; + if (cris_request_io_interface(if_eth, cardname)) { + printk(KERN_CRIT "etrax_ethernet_init failed to get IO interface\n"); + return -EBUSY; + } + dev = alloc_etherdev(sizeof(struct net_local)); if (!dev) return -ENOMEM; + np = netdev_priv(dev); + + /* we do our own locking */ + dev->features |= NETIF_F_LLTX; + dev->base_addr = (unsigned int)R_NETWORK_SA_0; /* just to have something to show */ /* now setup our etrax specific stuff */ @@ -498,14 +521,22 @@ etrax_ethernet_init(void) dev->do_ioctl = e100_ioctl; dev->set_config = e100_set_config; dev->tx_timeout = e100_tx_timeout; +#ifdef CONFIG_NET_POLL_CONTROLLER + dev->poll_controller = e100_netpoll; +#endif + + spin_lock_init(&np->lock); + spin_lock_init(&np->led_lock); + spin_lock_init(&np->transceiver_lock); /* Initialise the list of Etrax DMA-descriptors */ /* Initialise receive descriptors */ for (i = 0; i < NBR_OF_RX_DESC; i++) { - /* Allocate two extra cachelines to make sure that buffer used by DMA - * does not share cacheline with any other data (to avoid cache bug) + /* Allocate two extra cachelines to make sure that buffer used + * by DMA does not share cacheline with any other data (to + * avoid cache bug) */ RxDescList[i].skb = dev_alloc_skb(MAX_MEDIA_DATA_SIZE + 2 * L1_CACHE_BYTES); if (!RxDescList[i].skb) @@ -541,7 +572,6 @@ etrax_ethernet_init(void) myNextRxDesc = &RxDescList[0]; myLastRxDesc = &RxDescList[NBR_OF_RX_DESC - 1]; - myPrevRxDesc = &RxDescList[NBR_OF_RX_DESC - 1]; myFirstTxDesc = &TxDescList[0]; myNextTxDesc = &TxDescList[0]; myLastTxDesc = &TxDescList[NBR_OF_TX_DESC - 1]; @@ -562,10 +592,11 @@ etrax_ethernet_init(void) current_speed = 10; current_speed_selection = 0; /* Auto */ speed_timer.expires = jiffies + NET_LINK_UP_CHECK_INTERVAL; - duplex_timer.data = (unsigned long)dev; + speed_timer.data = (unsigned long)dev; speed_timer.function = e100_check_speed; clear_led_timer.function = e100_clear_network_leds; + clear_led_timer.data = (unsigned long)dev; full_duplex = 0; current_duplex = autoneg; @@ -574,7 +605,6 @@ etrax_ethernet_init(void) duplex_timer.function = e100_check_duplex; /* Initialize mii interface */ - np->mii_if.phy_id = mdio_phy_addr; np->mii_if.phy_id_mask = 0x1f; np->mii_if.reg_num_mask = 0x1f; np->mii_if.dev = dev; @@ -585,6 +615,9 @@ etrax_ethernet_init(void) /* unwanted addresses are matched */ *R_NETWORK_GA_0 = 0x00000000; *R_NETWORK_GA_1 = 0x00000000; + + /* Initialize next time the led can flash */ + led_next_time = jiffies; return 0; } @@ -595,9 +628,9 @@ etrax_ethernet_init(void) static int e100_set_mac_address(struct net_device *dev, void *p) { - struct net_local *np = (struct net_local *)dev->priv; + struct net_local *np = netdev_priv(dev); struct sockaddr *addr = p; - int i; + DECLARE_MAC_BUF(mac); spin_lock(&np->lock); /* preemption protection */ @@ -686,6 +719,25 @@ e100_open(struct net_device *dev) goto grace_exit2; } + /* + * Always allocate the DMA channels after the IRQ, + * and clean up on failure. + */ + + if (cris_request_dma(NETWORK_TX_DMA_NBR, + cardname, + DMA_VERBOSE_ON_ERROR, + dma_eth)) { + goto grace_exit3; + } + + if (cris_request_dma(NETWORK_RX_DMA_NBR, + cardname, + DMA_VERBOSE_ON_ERROR, + dma_eth)) { + goto grace_exit4; + } + /* give the HW an idea of what MAC address we want */ *R_NETWORK_SA_0 = dev->dev_addr[0] | (dev->dev_addr[1] << 8) | @@ -700,6 +752,7 @@ e100_open(struct net_device *dev) *R_NETWORK_REC_CONFIG = 0xd; /* broadcast rec, individ. rec, ma0 enabled */ #else + SETS(network_rec_config_shadow, R_NETWORK_REC_CONFIG, max_size, size1522); SETS(network_rec_config_shadow, R_NETWORK_REC_CONFIG, broadcast, receive); SETS(network_rec_config_shadow, R_NETWORK_REC_CONFIG, ma0, enable); SETF(network_rec_config_shadow, R_NETWORK_REC_CONFIG, duplex, full_duplex); @@ -719,8 +772,7 @@ e100_open(struct net_device *dev) SETS(network_tr_ctrl_shadow, R_NETWORK_TR_CTRL, crc, enable); *R_NETWORK_TR_CTRL = network_tr_ctrl_shadow; - save_flags(flags); - cli(); + local_irq_save(flags); /* enable the irq's for ethernet DMA */ @@ -752,12 +804,13 @@ e100_open(struct net_device *dev) *R_DMA_CH0_FIRST = 0; *R_DMA_CH0_DESCR = virt_to_phys(myLastTxDesc); + netif_start_queue(dev); - restore_flags(flags); + local_irq_restore(flags); /* Probe for transceiver */ if (e100_probe_transceiver(dev)) - goto grace_exit3; + goto grace_exit5; /* Start duplex/speed timers */ add_timer(&speed_timer); @@ -766,10 +819,14 @@ e100_open(struct net_device *dev) /* We are now ready to accept transmit requeusts from * the queueing layer of the networking. */ - netif_start_queue(dev); + netif_carrier_on(dev); return 0; +grace_exit5: + cris_free_dma(NETWORK_RX_DMA_NBR, cardname); +grace_exit4: + cris_free_dma(NETWORK_TX_DMA_NBR, cardname); grace_exit3: free_irq(NETWORK_STATUS_IRQ_NBR, (void *)dev); grace_exit2: @@ -780,12 +837,20 @@ grace_exit0: return -EAGAIN; } - +#if defined(CONFIG_ETRAX_NO_PHY) +static void +dummy_check_speed(struct net_device* dev) +{ + current_speed = 100; +} +#else static void generic_check_speed(struct net_device* dev) { unsigned long data; - data = e100_get_mdio_reg(dev, mdio_phy_addr, MII_ADVERTISE); + struct net_local *np = netdev_priv(dev); + + data = e100_get_mdio_reg(dev, np->mii_if.phy_id, MII_ADVERTISE); if ((data & ADVERTISE_100FULL) || (data & ADVERTISE_100HALF)) current_speed = 100; @@ -797,7 +862,10 @@ static void tdk_check_speed(struct net_device* dev) { unsigned long data; - data = e100_get_mdio_reg(dev, mdio_phy_addr, MDIO_TDK_DIAGNOSTIC_REG); + struct net_local *np = netdev_priv(dev); + + data = e100_get_mdio_reg(dev, np->mii_if.phy_id, + MDIO_TDK_DIAGNOSTIC_REG); current_speed = (data & MDIO_TDK_DIAGNOSTIC_RATE ? 100 : 10); } @@ -805,7 +873,10 @@ static void broadcom_check_speed(struct net_device* dev) { unsigned long data; - data = e100_get_mdio_reg(dev, mdio_phy_addr, MDIO_AUX_CTRL_STATUS_REG); + struct net_local *np = netdev_priv(dev); + + data = e100_get_mdio_reg(dev, np->mii_if.phy_id, + MDIO_AUX_CTRL_STATUS_REG); current_speed = (data & MDIO_BC_SPEED ? 100 : 10); } @@ -813,46 +884,62 @@ static void intel_check_speed(struct net_device* dev) { unsigned long data; - data = e100_get_mdio_reg(dev, mdio_phy_addr, MDIO_INT_STATUS_REG_2); + struct net_local *np = netdev_priv(dev); + + data = e100_get_mdio_reg(dev, np->mii_if.phy_id, + MDIO_INT_STATUS_REG_2); current_speed = (data & MDIO_INT_SPEED ? 100 : 10); } - +#endif static void e100_check_speed(unsigned long priv) { struct net_device* dev = (struct net_device*)priv; + struct net_local *np = netdev_priv(dev); static int led_initiated = 0; unsigned long data; int old_speed = current_speed; - data = e100_get_mdio_reg(dev, mdio_phy_addr, MII_BMSR); + spin_lock(&np->transceiver_lock); + + data = e100_get_mdio_reg(dev, np->mii_if.phy_id, MII_BMSR); if (!(data & BMSR_LSTATUS)) { current_speed = 0; } else { transceiver->check_speed(dev); } + spin_lock(&np->led_lock); if ((old_speed != current_speed) || !led_initiated) { led_initiated = 1; e100_set_network_leds(NO_NETWORK_ACTIVITY); + if (current_speed) + netif_carrier_on(dev); + else + netif_carrier_off(dev); } + spin_unlock(&np->led_lock); /* Reinitialize the timer. */ speed_timer.expires = jiffies + NET_LINK_UP_CHECK_INTERVAL; add_timer(&speed_timer); + + spin_unlock(&np->transceiver_lock); } static void e100_negotiate(struct net_device* dev) { - unsigned short data = e100_get_mdio_reg(dev, mdio_phy_addr, MII_ADVERTISE); + struct net_local *np = netdev_priv(dev); + unsigned short data = e100_get_mdio_reg(dev, np->mii_if.phy_id, + MII_ADVERTISE); /* Discard old speed and duplex settings */ data &= ~(ADVERTISE_100HALF | ADVERTISE_100FULL | ADVERTISE_10HALF | ADVERTISE_10FULL); switch (current_speed_selection) { - case 10 : + case 10: if (current_duplex == full) data |= ADVERTISE_10FULL; else if (current_duplex == half) @@ -861,7 +948,7 @@ e100_negotiate(struct net_device* dev) data |= ADVERTISE_10HALF | ADVERTISE_10FULL; break; - case 100 : + case 100: if (current_duplex == full) data |= ADVERTISE_100FULL; else if (current_duplex == half) @@ -870,7 +957,7 @@ e100_negotiate(struct net_device* dev) data |= ADVERTISE_100HALF | ADVERTISE_100FULL; break; - case 0 : /* Auto */ + case 0: /* Auto */ if (current_duplex == full) data |= ADVERTISE_100FULL | ADVERTISE_10FULL; else if (current_duplex == half) @@ -880,35 +967,44 @@ e100_negotiate(struct net_device* dev) ADVERTISE_100HALF | ADVERTISE_100FULL; break; - default : /* assume autoneg speed and duplex */ + default: /* assume autoneg speed and duplex */ data |= ADVERTISE_10HALF | ADVERTISE_10FULL | ADVERTISE_100HALF | ADVERTISE_100FULL; + break; } - e100_set_mdio_reg(dev, mdio_phy_addr, MII_ADVERTISE, data); + e100_set_mdio_reg(dev, np->mii_if.phy_id, MII_ADVERTISE, data); /* Renegotiate with link partner */ - data = e100_get_mdio_reg(dev, mdio_phy_addr, MII_BMCR); + if (autoneg_normal) { + data = e100_get_mdio_reg(dev, np->mii_if.phy_id, MII_BMCR); data |= BMCR_ANENABLE | BMCR_ANRESTART; - - e100_set_mdio_reg(dev, mdio_phy_addr, MII_BMCR, data); + } + e100_set_mdio_reg(dev, np->mii_if.phy_id, MII_BMCR, data); } static void e100_set_speed(struct net_device* dev, unsigned long speed) { + struct net_local *np = netdev_priv(dev); + + spin_lock(&np->transceiver_lock); if (speed != current_speed_selection) { current_speed_selection = speed; e100_negotiate(dev); } + spin_unlock(&np->transceiver_lock); } static void e100_check_duplex(unsigned long priv) { struct net_device *dev = (struct net_device *)priv; - struct net_local *np = (struct net_local *)dev->priv; - int old_duplex = full_duplex; + struct net_local *np = netdev_priv(dev); + int old_duplex; + + spin_lock(&np->transceiver_lock); + old_duplex = full_duplex; transceiver->check_duplex(dev); if (old_duplex != full_duplex) { /* Duplex changed */ @@ -920,13 +1016,22 @@ e100_check_duplex(unsigned long priv) duplex_timer.expires = jiffies + NET_DUPLEX_CHECK_INTERVAL; add_timer(&duplex_timer); np->mii_if.full_duplex = full_duplex; + spin_unlock(&np->transceiver_lock); } - +#if defined(CONFIG_ETRAX_NO_PHY) +static void +dummy_check_duplex(struct net_device* dev) +{ + full_duplex = 1; +} +#else static void generic_check_duplex(struct net_device* dev) { unsigned long data; - data = e100_get_mdio_reg(dev, mdio_phy_addr, MII_ADVERTISE); + struct net_local *np = netdev_priv(dev); + + data = e100_get_mdio_reg(dev, np->mii_if.phy_id, MII_ADVERTISE); if ((data & ADVERTISE_10FULL) || (data & ADVERTISE_100FULL)) full_duplex = 1; @@ -938,7 +1043,10 @@ static void tdk_check_duplex(struct net_device* dev) { unsigned long data; - data = e100_get_mdio_reg(dev, mdio_phy_addr, MDIO_TDK_DIAGNOSTIC_REG); + struct net_local *np = netdev_priv(dev); + + data = e100_get_mdio_reg(dev, np->mii_if.phy_id, + MDIO_TDK_DIAGNOSTIC_REG); full_duplex = (data & MDIO_TDK_DIAGNOSTIC_DPLX) ? 1 : 0; } @@ -946,7 +1054,10 @@ static void broadcom_check_duplex(struct net_device* dev) { unsigned long data; - data = e100_get_mdio_reg(dev, mdio_phy_addr, MDIO_AUX_CTRL_STATUS_REG); + struct net_local *np = netdev_priv(dev); + + data = e100_get_mdio_reg(dev, np->mii_if.phy_id, + MDIO_AUX_CTRL_STATUS_REG); full_duplex = (data & MDIO_BC_FULL_DUPLEX_IND) ? 1 : 0; } @@ -954,38 +1065,55 @@ static void intel_check_duplex(struct net_device* dev) { unsigned long data; - data = e100_get_mdio_reg(dev, mdio_phy_addr, MDIO_INT_STATUS_REG_2); + struct net_local *np = netdev_priv(dev); + + data = e100_get_mdio_reg(dev, np->mii_if.phy_id, + MDIO_INT_STATUS_REG_2); full_duplex = (data & MDIO_INT_FULL_DUPLEX_IND) ? 1 : 0; } - +#endif static void e100_set_duplex(struct net_device* dev, enum duplex new_duplex) { + struct net_local *np = netdev_priv(dev); + + spin_lock(&np->transceiver_lock); if (new_duplex != current_duplex) { current_duplex = new_duplex; e100_negotiate(dev); } + spin_unlock(&np->transceiver_lock); } static int e100_probe_transceiver(struct net_device* dev) { + int ret = 0; + +#if !defined(CONFIG_ETRAX_NO_PHY) unsigned int phyid_high; unsigned int phyid_low; unsigned int oui; struct transceiver_ops* ops = NULL; + struct net_local *np = netdev_priv(dev); + + spin_lock(&np->transceiver_lock); /* Probe MDIO physical address */ - for (mdio_phy_addr = 0; mdio_phy_addr <= 31; mdio_phy_addr++) { - if (e100_get_mdio_reg(dev, mdio_phy_addr, MII_BMSR) != 0xffff) + for (np->mii_if.phy_id = 0; np->mii_if.phy_id <= 31; + np->mii_if.phy_id++) { + if (e100_get_mdio_reg(dev, + np->mii_if.phy_id, MII_BMSR) != 0xffff) break; } - if (mdio_phy_addr == 32) - return -ENODEV; + if (np->mii_if.phy_id == 32) { + ret = -ENODEV; + goto out; + } /* Get manufacturer */ - phyid_high = e100_get_mdio_reg(dev, mdio_phy_addr, MII_PHYSID1); - phyid_low = e100_get_mdio_reg(dev, mdio_phy_addr, MII_PHYSID2); + phyid_high = e100_get_mdio_reg(dev, np->mii_if.phy_id, MII_PHYSID1); + phyid_low = e100_get_mdio_reg(dev, np->mii_if.phy_id, MII_PHYSID2); oui = (phyid_high << 6) | (phyid_low >> 10); for (ops = &transceivers[0]; ops->oui; ops++) { @@ -993,8 +1121,10 @@ e100_probe_transceiver(struct net_device* dev) break; } transceiver = ops; - - return 0; +out: + spin_unlock(&np->transceiver_lock); +#endif + return ret; } static int @@ -1088,13 +1218,14 @@ e100_receive_mdio_bit() static void e100_reset_transceiver(struct net_device* dev) { + struct net_local *np = netdev_priv(dev); unsigned short cmd; unsigned short data; int bitCounter; - data = e100_get_mdio_reg(dev, mdio_phy_addr, MII_BMCR); + data = e100_get_mdio_reg(dev, np->mii_if.phy_id, MII_BMCR); - cmd = (MDIO_START << 14) | (MDIO_WRITE << 12) | (mdio_phy_addr << 7) | (MII_BMCR << 2); + cmd = (MDIO_START << 14) | (MDIO_WRITE << 12) | (np->mii_if.phy_id << 7) | (MII_BMCR << 2); e100_send_mdio_cmd(cmd, 1); @@ -1112,7 +1243,7 @@ e100_reset_transceiver(struct net_device* dev) static void e100_tx_timeout(struct net_device *dev) { - struct net_local *np = (struct net_local *)dev->priv; + struct net_local *np = netdev_priv(dev); unsigned long flags; spin_lock_irqsave(&np->lock, flags); @@ -1134,8 +1265,7 @@ e100_tx_timeout(struct net_device *dev) e100_reset_transceiver(dev); /* and get rid of the packets that never got an interrupt */ - while (myFirstTxDesc != myNextTxDesc) - { + while (myFirstTxDesc != myNextTxDesc) { dev_kfree_skb(myFirstTxDesc->skb); myFirstTxDesc->skb = 0; myFirstTxDesc = phys_to_virt(myFirstTxDesc->descr.next); @@ -1161,7 +1291,7 @@ e100_tx_timeout(struct net_device *dev) static int e100_send_packet(struct sk_buff *skb, struct net_device *dev) { - struct net_local *np = (struct net_local *)dev->priv; + struct net_local *np = netdev_priv(dev); unsigned char *buf = skb->data; unsigned long flags; @@ -1174,7 +1304,7 @@ e100_send_packet(struct sk_buff *skb, struct net_device *dev) dev->trans_start = jiffies; - e100_hardware_send_packet(buf, skb->len); + e100_hardware_send_packet(np, buf, skb->len); myNextTxDesc = phys_to_virt(myNextTxDesc->descr.next); @@ -1197,13 +1327,15 @@ static irqreturn_t e100rxtx_interrupt(int irq, void *dev_id) { struct net_device *dev = (struct net_device *)dev_id; - struct net_local *np = (struct net_local *)dev->priv; - unsigned long irqbits = *R_IRQ_MASK2_RD; + struct net_local *np = netdev_priv(dev); + unsigned long irqbits; - /* Disable RX/TX IRQs to avoid reentrancy */ - *R_IRQ_MASK2_CLR = - IO_STATE(R_IRQ_MASK2_CLR, dma0_eop, clr) | - IO_STATE(R_IRQ_MASK2_CLR, dma1_eop, clr); + /* + * Note that both rx and tx interrupts are blocked at this point, + * regardless of which got us here. + */ + + irqbits = *R_IRQ_MASK2_RD; /* Handle received packets */ if (irqbits & IO_STATE(R_IRQ_MASK2_RD, dma1_eop, active)) { @@ -1219,7 +1351,7 @@ e100rxtx_interrupt(int irq, void *dev_id) * allocate a new buffer to put a packet in. */ e100_rx(dev); - ((struct net_local *)dev->priv)->stats.rx_packets++; + np->stats.rx_packets++; /* restart/continue on the channel, for safety */ *R_DMA_CH1_CMD = IO_STATE(R_DMA_CH1_CMD, cmd, restart); /* clear dma channel 1 eop/descr irq bits */ @@ -1233,9 +1365,8 @@ e100rxtx_interrupt(int irq, void *dev_id) } /* Report any packets that have been sent */ - while (myFirstTxDesc != phys_to_virt(*R_DMA_CH0_FIRST) && - myFirstTxDesc != myNextTxDesc) - { + while (virt_to_phys(myFirstTxDesc) != *R_DMA_CH0_FIRST && + (netif_queue_stopped(dev) || myFirstTxDesc != myNextTxDesc)) { np->stats.tx_bytes += myFirstTxDesc->skb->len; np->stats.tx_packets++; @@ -1244,19 +1375,15 @@ e100rxtx_interrupt(int irq, void *dev_id) dev_kfree_skb_irq(myFirstTxDesc->skb); myFirstTxDesc->skb = 0; myFirstTxDesc = phys_to_virt(myFirstTxDesc->descr.next); + /* Wake up queue. */ + netif_wake_queue(dev); } if (irqbits & IO_STATE(R_IRQ_MASK2_RD, dma0_eop, active)) { - /* acknowledge the eop interrupt and wake up queue */ + /* acknowledge the eop interrupt. */ *R_DMA_CH0_CLR_INTR = IO_STATE(R_DMA_CH0_CLR_INTR, clr_eop, do); - netif_wake_queue(dev); } - /* Enable RX/TX IRQs again */ - *R_IRQ_MASK2_SET = - IO_STATE(R_IRQ_MASK2_SET, dma0_eop, set) | - IO_STATE(R_IRQ_MASK2_SET, dma1_eop, set); - return IRQ_HANDLED; } @@ -1264,7 +1391,7 @@ static irqreturn_t e100nw_interrupt(int irq, void *dev_id) { struct net_device *dev = (struct net_device *)dev_id; - struct net_local *np = (struct net_local *)dev->priv; + struct net_local *np = netdev_priv(dev); unsigned long irqbits = *R_IRQ_MASK0_RD; /* check for underrun irq */ @@ -1286,7 +1413,6 @@ e100nw_interrupt(int irq, void *dev_id) SETS(network_tr_ctrl_shadow, R_NETWORK_TR_CTRL, clr_error, clr); *R_NETWORK_TR_CTRL = network_tr_ctrl_shadow; SETS(network_tr_ctrl_shadow, R_NETWORK_TR_CTRL, clr_error, nop); - *R_NETWORK_TR_CTRL = IO_STATE(R_NETWORK_TR_CTRL, clr_error, clr); np->stats.tx_errors++; D(printk("ethernet excessive collisions!\n")); } @@ -1299,12 +1425,13 @@ e100_rx(struct net_device *dev) { struct sk_buff *skb; int length = 0; - struct net_local *np = (struct net_local *)dev->priv; + struct net_local *np = netdev_priv(dev); unsigned char *skb_data_ptr; #ifdef ETHDEBUG int i; #endif - + etrax_eth_descr *prevRxDesc; /* The descriptor right before myNextRxDesc */ + spin_lock(&np->led_lock); if (!led_active && time_after(jiffies, led_next_time)) { /* light the network leds depending on the current speed. */ e100_set_network_leds(NETWORK_ACTIVITY); @@ -1314,9 +1441,10 @@ e100_rx(struct net_device *dev) led_active = 1; mod_timer(&clear_led_timer, jiffies + HZ/10); } + spin_unlock(&np->led_lock); length = myNextRxDesc->descr.hw_len - 4; - ((struct net_local *)dev->priv)->stats.rx_bytes += length; + np->stats.rx_bytes += length; #ifdef ETHDEBUG printk("Got a packet of length %d:\n", length); @@ -1336,7 +1464,7 @@ e100_rx(struct net_device *dev) if (!skb) { np->stats.rx_errors++; printk(KERN_NOTICE "%s: Memory squeeze, dropping packet.\n", dev->name); - return; + goto update_nextrxdesc; } skb_put(skb, length - ETHER_HEAD_LEN); /* allocate room for the packet body */ @@ -1354,15 +1482,15 @@ e100_rx(struct net_device *dev) else { /* Large packet, send directly to upper layers and allocate new * memory (aligned to cache line boundary to avoid bug). - * Before sending the skb to upper layers we must make sure that - * skb->data points to the aligned start of the packet. + * Before sending the skb to upper layers we must make sure + * that skb->data points to the aligned start of the packet. */ int align; struct sk_buff *new_skb = dev_alloc_skb(MAX_MEDIA_DATA_SIZE + 2 * L1_CACHE_BYTES); if (!new_skb) { np->stats.rx_errors++; printk(KERN_NOTICE "%s: Memory squeeze, dropping packet.\n", dev->name); - return; + goto update_nextrxdesc; } skb = myNextRxDesc->skb; align = (int)phys_to_virt(myNextRxDesc->descr.buf) - (int)skb->data; @@ -1377,9 +1505,10 @@ e100_rx(struct net_device *dev) /* Send the packet to the upper layers */ netif_rx(skb); + update_nextrxdesc: /* Prepare for next packet */ myNextRxDesc->descr.status = 0; - myPrevRxDesc = myNextRxDesc; + prevRxDesc = myNextRxDesc; myNextRxDesc = phys_to_virt(myNextRxDesc->descr.next); rx_queue_len++; @@ -1387,9 +1516,9 @@ e100_rx(struct net_device *dev) /* Check if descriptors should be returned */ if (rx_queue_len == RX_QUEUE_THRESHOLD) { flush_etrax_cache(); - myPrevRxDesc->descr.ctrl |= d_eol; + prevRxDesc->descr.ctrl |= d_eol; myLastRxDesc->descr.ctrl &= ~d_eol; - myLastRxDesc = myPrevRxDesc; + myLastRxDesc = prevRxDesc; rx_queue_len = 0; } } @@ -1398,7 +1527,7 @@ e100_rx(struct net_device *dev) static int e100_close(struct net_device *dev) { - struct net_local *np = (struct net_local *)dev->priv; + struct net_local *np = netdev_priv(dev); printk(KERN_INFO "Closing %s.\n", dev->name); @@ -1426,6 +1555,9 @@ e100_close(struct net_device *dev) free_irq(NETWORK_DMA_TX_IRQ_NBR, (void *)dev); free_irq(NETWORK_STATUS_IRQ_NBR, (void *)dev); + cris_free_dma(NETWORK_TX_DMA_NBR, cardname); + cris_free_dma(NETWORK_RX_DMA_NBR, cardname); + /* Update the statistics here. */ update_rx_stats(&np->stats); @@ -1443,18 +1575,11 @@ e100_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) { struct mii_ioctl_data *data = if_mii(ifr); struct net_local *np = netdev_priv(dev); + int rc = 0; + int old_autoneg; spin_lock(&np->lock); /* Preempt protection */ switch (cmd) { - case SIOCGMIIPHY: /* Get PHY address */ - data->phy_id = mdio_phy_addr; - break; - case SIOCGMIIREG: /* Read MII register */ - data->val_out = e100_get_mdio_reg(dev, mdio_phy_addr, data->reg_num); - break; - case SIOCSMIIREG: /* Write MII register */ - e100_set_mdio_reg(dev, mdio_phy_addr, data->reg_num, data->val_in); - break; /* The ioctls below should be considered obsolete but are */ /* still present for compatability with old scripts/apps */ case SET_ETH_SPEED_10: /* 10 Mbps */ @@ -1463,60 +1588,47 @@ e100_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) case SET_ETH_SPEED_100: /* 100 Mbps */ e100_set_speed(dev, 100); break; - case SET_ETH_SPEED_AUTO: /* Auto negotiate speed */ + case SET_ETH_SPEED_AUTO: /* Auto-negotiate speed */ e100_set_speed(dev, 0); break; - case SET_ETH_DUPLEX_HALF: /* Half duplex. */ + case SET_ETH_DUPLEX_HALF: /* Half duplex */ e100_set_duplex(dev, half); break; - case SET_ETH_DUPLEX_FULL: /* Full duplex. */ + case SET_ETH_DUPLEX_FULL: /* Full duplex */ e100_set_duplex(dev, full); break; - case SET_ETH_DUPLEX_AUTO: /* Autonegotiate duplex*/ + case SET_ETH_DUPLEX_AUTO: /* Auto-negotiate duplex */ e100_set_duplex(dev, autoneg); break; + case SET_ETH_AUTONEG: + old_autoneg = autoneg_normal; + autoneg_normal = *(int*)data; + if (autoneg_normal != old_autoneg) + e100_negotiate(dev); + break; default: - return -EINVAL; + rc = generic_mii_ioctl(&np->mii_if, if_mii(ifr), + cmd, NULL); + break; } spin_unlock(&np->lock); - return 0; + return rc; } -static int e100_set_settings(struct net_device *dev, - struct ethtool_cmd *ecmd) +static int e100_get_settings(struct net_device *dev, + struct ethtool_cmd *cmd) { - ecmd->supported = SUPPORTED_Autoneg | SUPPORTED_TP | SUPPORTED_MII | - SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full | - SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full; - ecmd->port = PORT_TP; - ecmd->transceiver = XCVR_EXTERNAL; - ecmd->phy_address = mdio_phy_addr; - ecmd->speed = current_speed; - ecmd->duplex = full_duplex ? DUPLEX_FULL : DUPLEX_HALF; - ecmd->advertising = ADVERTISED_TP; + struct net_local *np = netdev_priv(dev); + int err; - if (current_duplex == autoneg && current_speed_selection == 0) - ecmd->advertising |= ADVERTISED_Autoneg; - else { - ecmd->advertising |= - ADVERTISED_10baseT_Half | ADVERTISED_10baseT_Full | - ADVERTISED_100baseT_Half | ADVERTISED_100baseT_Full; - if (current_speed_selection == 10) - ecmd->advertising &= ~(ADVERTISED_100baseT_Half | - ADVERTISED_100baseT_Full); - else if (current_speed_selection == 100) - ecmd->advertising &= ~(ADVERTISED_10baseT_Half | - ADVERTISED_10baseT_Full); - if (current_duplex == half) - ecmd->advertising &= ~(ADVERTISED_10baseT_Full | - ADVERTISED_100baseT_Full); - else if (current_duplex == full) - ecmd->advertising &= ~(ADVERTISED_10baseT_Half | - ADVERTISED_100baseT_Half); - } + spin_lock_irq(&np->lock); + err = mii_ethtool_gset(&np->mii_if, cmd); + spin_unlock_irq(&np->lock); - ecmd->autoneg = AUTONEG_ENABLE; - return 0; + /* The PHY may support 1000baseT, but the Etrax100 does not. */ + cmd->supported &= ~(SUPPORTED_1000baseT_Half + | SUPPORTED_1000baseT_Full); + return err; } static int e100_set_settings(struct net_device *dev, @@ -1560,7 +1672,8 @@ static const struct ethtool_ops e100_ethtool_ops = { static int e100_set_config(struct net_device *dev, struct ifmap *map) { - struct net_local *np = (struct net_local *)dev->priv; + struct net_local *np = netdev_priv(dev); + spin_lock(&np->lock); /* Preempt protection */ switch(map->port) { @@ -1612,7 +1725,6 @@ update_tx_stats(struct net_device_stats *es) es->collisions += IO_EXTRACT(R_TR_COUNTERS, single_col, r) + IO_EXTRACT(R_TR_COUNTERS, multiple_col, r); - es->tx_errors += IO_EXTRACT(R_TR_COUNTERS, deferred, r); } /* @@ -1622,8 +1734,9 @@ update_tx_stats(struct net_device_stats *es) static struct net_device_stats * e100_get_stats(struct net_device *dev) { - struct net_local *lp = (struct net_local *)dev->priv; + struct net_local *lp = netdev_priv(dev); unsigned long flags; + spin_lock_irqsave(&lp->lock, flags); update_rx_stats(&lp->stats); @@ -1643,13 +1756,13 @@ e100_get_stats(struct net_device *dev) static void set_multicast_list(struct net_device *dev) { - struct net_local *lp = (struct net_local *)dev->priv; + struct net_local *lp = netdev_priv(dev); int num_addr = dev->mc_count; unsigned long int lo_bits; unsigned long int hi_bits; + spin_lock(&lp->lock); - if (dev->flags & IFF_PROMISC) - { + if (dev->flags & IFF_PROMISC) { /* promiscuous mode */ lo_bits = 0xfffffffful; hi_bits = 0xfffffffful; @@ -1679,9 +1792,10 @@ set_multicast_list(struct net_device *dev) struct dev_mc_list *dmi = dev->mc_list; int i; char *baddr; + lo_bits = 0x00000000ul; hi_bits = 0x00000000ul; - for (i=0; i<num_addr; i++) { + for (i = 0; i < num_addr; i++) { /* Calculate the hash index for the GA registers */ hash_ix = 0; @@ -1708,8 +1822,7 @@ set_multicast_list(struct net_device *dev) if (hash_ix >= 32) { hi_bits |= (1 << (hash_ix-32)); - } - else { + } else { lo_bits |= (1 << hash_ix); } dmi = dmi->next; @@ -1724,10 +1837,11 @@ set_multicast_list(struct net_device *dev) } void -e100_hardware_send_packet(char *buf, int length) +e100_hardware_send_packet(struct net_local *np, char *buf, int length) { D(printk("e100 send pack, buf 0x%x len %d\n", buf, length)); + spin_lock(&np->led_lock); if (!led_active && time_after(jiffies, led_next_time)) { /* light the network leds depending on the current speed. */ e100_set_network_leds(NETWORK_ACTIVITY); @@ -1737,6 +1851,7 @@ e100_hardware_send_packet(char *buf, int length) led_active = 1; mod_timer(&clear_led_timer, jiffies + HZ/10); } + spin_unlock(&np->led_lock); /* configure the tx dma descriptor */ myNextTxDesc->descr.sw_len = length; @@ -1754,6 +1869,11 @@ e100_hardware_send_packet(char *buf, int length) static void e100_clear_network_leds(unsigned long dummy) { + struct net_device *dev = (struct net_device *)dummy; + struct net_local *np = netdev_priv(dev); + + spin_lock(&np->led_lock); + if (led_active && time_after(jiffies, led_next_time)) { e100_set_network_leds(NO_NETWORK_ACTIVITY); @@ -1761,6 +1881,8 @@ e100_clear_network_leds(unsigned long dummy) led_next_time = jiffies + NET_FLASH_PAUSE; led_active = 0; } + + spin_unlock(&np->led_lock); } static void @@ -1781,19 +1903,25 @@ e100_set_network_leds(int active) #else LED_NETWORK_SET(LED_OFF); #endif - } - else if (light_leds) { + } else if (light_leds) { if (current_speed == 10) { LED_NETWORK_SET(LED_ORANGE); } else { LED_NETWORK_SET(LED_GREEN); } - } - else { + } else { LED_NETWORK_SET(LED_OFF); } } +#ifdef CONFIG_NET_POLL_CONTROLLER +static void +e100_netpoll(struct net_device* netdev) +{ + e100rxtx_interrupt(NETWORK_DMA_TX_IRQ_NBR, netdev, NULL); +} +#endif + static int etrax_init_module(void) { diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index 72deff0..4f37506 100644 --- a/drivers/net/e1000/e1000_main.c +++ b/drivers/net/e1000/e1000_main.c @@ -3942,7 +3942,7 @@ e1000_clean(struct napi_struct *napi, int budget) &work_done, budget); /* If no Tx and not enough Rx work done, exit the polling mode */ - if ((!tx_cleaned && (work_done < budget)) || + if ((!tx_cleaned && (work_done == 0)) || !netif_running(poll_dev)) { quit_polling: if (likely(adapter->itr_setting & 3)) @@ -4804,6 +4804,7 @@ e1000_mii_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) spin_unlock_irqrestore(&adapter->stats_lock, flags); return -EIO; } + spin_unlock_irqrestore(&adapter->stats_lock, flags); if (adapter->hw.media_type == e1000_media_type_copper) { switch (data->reg_num) { case PHY_CTRL: @@ -4824,12 +4825,8 @@ e1000_mii_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) DUPLEX_HALF; retval = e1000_set_spd_dplx(adapter, spddplx); - if (retval) { - spin_unlock_irqrestore( - &adapter->stats_lock, - flags); + if (retval) return retval; - } } if (netif_running(adapter->netdev)) e1000_reinit_locked(adapter); @@ -4838,11 +4835,8 @@ e1000_mii_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) break; case M88E1000_PHY_SPEC_CTRL: case M88E1000_EXT_PHY_SPEC_CTRL: - if (e1000_phy_reset(&adapter->hw)) { - spin_unlock_irqrestore( - &adapter->stats_lock, flags); + if (e1000_phy_reset(&adapter->hw)) return -EIO; - } break; } } else { @@ -4857,7 +4851,6 @@ e1000_mii_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) break; } } - spin_unlock_irqrestore(&adapter->stats_lock, flags); break; default: return -EOPNOTSUPP; diff --git a/drivers/net/ehea/ehea.h b/drivers/net/ehea/ehea.h index f78e5bf..5f82a46 100644 --- a/drivers/net/ehea/ehea.h +++ b/drivers/net/ehea/ehea.h @@ -40,7 +40,7 @@ #include <asm/io.h> #define DRV_NAME "ehea" -#define DRV_VERSION "EHEA_0080" +#define DRV_VERSION "EHEA_0083" /* eHEA capability flags */ #define DLPAR_PORT_ADD_REM 1 diff --git a/drivers/net/ehea/ehea_main.c b/drivers/net/ehea/ehea_main.c index f0319f1..869e160 100644 --- a/drivers/net/ehea/ehea_main.c +++ b/drivers/net/ehea/ehea_main.c @@ -136,7 +136,7 @@ static struct net_device_stats *ehea_get_stats(struct net_device *dev) struct ehea_port *port = netdev_priv(dev); struct net_device_stats *stats = &port->stats; struct hcp_ehea_port_cb2 *cb2; - u64 hret, rx_packets; + u64 hret, rx_packets, tx_packets; int i; memset(stats, 0, sizeof(*stats)); @@ -162,7 +162,11 @@ static struct net_device_stats *ehea_get_stats(struct net_device *dev) for (i = 0; i < port->num_def_qps; i++) rx_packets += port->port_res[i].rx_packets; - stats->tx_packets = cb2->txucp + cb2->txmcp + cb2->txbcp; + tx_packets = 0; + for (i = 0; i < port->num_def_qps + port->num_add_tx_qps; i++) + tx_packets += port->port_res[i].tx_packets; + + stats->tx_packets = tx_packets; stats->multicast = cb2->rxmcp; stats->rx_errors = cb2->rxuerr; stats->rx_bytes = cb2->rxo; @@ -406,11 +410,6 @@ static int ehea_treat_poll_error(struct ehea_port_res *pr, int rq, if (cqe->status & EHEA_CQE_STAT_ERR_CRC) pr->p_stats.err_frame_crc++; - if (netif_msg_rx_err(pr->port)) { - ehea_error("CQE Error for QP %d", pr->qp->init_attr.qp_nr); - ehea_dump(cqe, sizeof(*cqe), "CQE"); - } - if (rq == 2) { *processed_rq2 += 1; skb = get_skb_by_index(pr->rq2_skba.arr, pr->rq2_skba.len, cqe); @@ -422,7 +421,11 @@ static int ehea_treat_poll_error(struct ehea_port_res *pr, int rq, } if (cqe->status & EHEA_CQE_STAT_FAT_ERR_MASK) { - ehea_error("Critical receive error. Resetting port."); + if (netif_msg_rx_err(pr->port)) { + ehea_error("Critical receive error for QP %d. " + "Resetting port.", pr->qp->init_attr.qp_nr); + ehea_dump(cqe, sizeof(*cqe), "CQE"); + } schedule_work(&pr->port->reset_task); return 1; } @@ -2000,6 +2003,7 @@ static int ehea_start_xmit(struct sk_buff *skb, struct net_device *dev) } ehea_post_swqe(pr->qp, swqe); + pr->tx_packets++; if (unlikely(atomic_read(&pr->swqe_avail) <= 1)) { spin_lock_irqsave(&pr->netif_queue, flags); diff --git a/drivers/net/ehea/ehea_qmr.h b/drivers/net/ehea/ehea_qmr.h index 562de0e..bc62d38 100644 --- a/drivers/net/ehea/ehea_qmr.h +++ b/drivers/net/ehea/ehea_qmr.h @@ -145,8 +145,8 @@ struct ehea_rwqe { #define EHEA_CQE_VLAN_TAG_XTRACT 0x0400 #define EHEA_CQE_TYPE_RQ 0x60 -#define EHEA_CQE_STAT_ERR_MASK 0x720F -#define EHEA_CQE_STAT_FAT_ERR_MASK 0x1F +#define EHEA_CQE_STAT_ERR_MASK 0x700F +#define EHEA_CQE_STAT_FAT_ERR_MASK 0xF #define EHEA_CQE_STAT_ERR_TCP 0x4000 #define EHEA_CQE_STAT_ERR_IP 0x2000 #define EHEA_CQE_STAT_ERR_CRC 0x1000 diff --git a/drivers/net/fec_mpc52xx.c b/drivers/net/fec_mpc52xx.c index a8a0ee2..bf5a7ca 100644 --- a/drivers/net/fec_mpc52xx.c +++ b/drivers/net/fec_mpc52xx.c @@ -971,6 +971,8 @@ mpc52xx_fec_probe(struct of_device *op, const struct of_device_id *match) mpc52xx_fec_reset_stats(ndev); + SET_NETDEV_DEV(ndev, &op->dev); + /* Register the new network device */ rv = register_netdev(ndev); if (rv < 0) diff --git a/drivers/net/forcedeth.c b/drivers/net/forcedeth.c index 92ce2e3..a96583c 100644 --- a/drivers/net/forcedeth.c +++ b/drivers/net/forcedeth.c @@ -5286,19 +5286,15 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i if (readl(base + NvRegTransmitterControl) & NVREG_XMITCTL_SYNC_PHY_INIT) { np->mac_in_use = readl(base + NvRegTransmitterControl) & NVREG_XMITCTL_MGMT_ST; dprintk(KERN_INFO "%s: mgmt unit is running. mac in use %x.\n", pci_name(pci_dev), np->mac_in_use); - for (i = 0; i < 5000; i++) { - msleep(1); - if (nv_mgmt_acquire_sema(dev)) { - /* management unit setup the phy already? */ - if ((readl(base + NvRegTransmitterControl) & NVREG_XMITCTL_SYNC_MASK) == - NVREG_XMITCTL_SYNC_PHY_INIT) { - /* phy is inited by mgmt unit */ - phyinitialized = 1; - dprintk(KERN_INFO "%s: Phy already initialized by mgmt unit.\n", pci_name(pci_dev)); - } else { - /* we need to init the phy */ - } - break; + if (nv_mgmt_acquire_sema(dev)) { + /* management unit setup the phy already? */ + if ((readl(base + NvRegTransmitterControl) & NVREG_XMITCTL_SYNC_MASK) == + NVREG_XMITCTL_SYNC_PHY_INIT) { + /* phy is inited by mgmt unit */ + phyinitialized = 1; + dprintk(KERN_INFO "%s: Phy already initialized by mgmt unit.\n", pci_name(pci_dev)); + } else { + /* we need to init the phy */ } } } @@ -5613,6 +5609,22 @@ static struct pci_device_id pci_tbl[] = { PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_35), .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT, }, + { /* MCP79 Ethernet Controller */ + PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_36), + .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT, + }, + { /* MCP79 Ethernet Controller */ + PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_37), + .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT, + }, + { /* MCP79 Ethernet Controller */ + PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_38), + .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT, + }, + { /* MCP79 Ethernet Controller */ + PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_39), + .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT, + }, {0,}, }; diff --git a/drivers/net/fs_enet/Kconfig b/drivers/net/fs_enet/Kconfig index 2765e49..562ea68 100644 --- a/drivers/net/fs_enet/Kconfig +++ b/drivers/net/fs_enet/Kconfig @@ -2,6 +2,7 @@ config FS_ENET tristate "Freescale Ethernet Driver" depends on CPM1 || CPM2 select MII + select PHYLIB config FS_ENET_HAS_SCC bool "Chip has an SCC usable for ethernet" @@ -11,11 +12,19 @@ config FS_ENET_HAS_SCC config FS_ENET_HAS_FCC bool "Chip has an FCC usable for ethernet" depends on FS_ENET && CPM2 - select MDIO_BITBANG default y config FS_ENET_HAS_FEC bool "Chip has an FEC usable for ethernet" depends on FS_ENET && CPM1 + select FS_ENET_MDIO_FEC default y +config FS_ENET_MDIO_FEC + tristate "MDIO driver for FEC" + depends on FS_ENET && CPM1 + +config FS_ENET_MDIO_FCC + tristate "MDIO driver for FCC" + depends on FS_ENET && CPM2 + select MDIO_BITBANG diff --git a/drivers/net/fs_enet/Makefile b/drivers/net/fs_enet/Makefile index 02d4dc1..1ffbe07 100644 --- a/drivers/net/fs_enet/Makefile +++ b/drivers/net/fs_enet/Makefile @@ -4,7 +4,16 @@ obj-$(CONFIG_FS_ENET) += fs_enet.o -obj-$(CONFIG_8xx) += mac-fec.o mac-scc.o mii-fec.o -obj-$(CONFIG_CPM2) += mac-fcc.o mii-bitbang.o +fs_enet-$(CONFIG_FS_ENET_HAS_SCC) += mac-scc.o +fs_enet-$(CONFIG_FS_ENET_HAS_FEC) += mac-fec.o +fs_enet-$(CONFIG_FS_ENET_HAS_FCC) += mac-fcc.o -fs_enet-objs := fs_enet-main.o +ifeq ($(CONFIG_PPC_CPM_NEW_BINDING),y) +obj-$(CONFIG_FS_ENET_MDIO_FEC) += mii-fec.o +obj-$(CONFIG_FS_ENET_MDIO_FCC) += mii-bitbang.o +else +fs_enet-$(CONFIG_FS_ENET_MDIO_FEC) += mii-fec.o +fs_enet-$(CONFIG_FS_ENET_MDIO_FCC) += mii-bitbang.o +endif + +fs_enet-objs := fs_enet-main.o $(fs_enet-m) diff --git a/drivers/net/hamradio/6pack.c b/drivers/net/hamradio/6pack.c index e0119f6..580cb4a 100644 --- a/drivers/net/hamradio/6pack.c +++ b/drivers/net/hamradio/6pack.c @@ -762,26 +762,20 @@ static int sixpack_ioctl(struct tty_struct *tty, struct file *file, if (copy_from_user(&addr, (void __user *) arg, AX25_ADDR_LEN)) { - err = -EFAULT; - break; - } + err = -EFAULT; + break; + } - netif_tx_lock_bh(dev); - memcpy(dev->dev_addr, &addr, AX25_ADDR_LEN); - netif_tx_unlock_bh(dev); + netif_tx_lock_bh(dev); + memcpy(dev->dev_addr, &addr, AX25_ADDR_LEN); + netif_tx_unlock_bh(dev); - err = 0; - break; - } - - /* Allow stty to read, but not set, the serial port */ - case TCGETS: - case TCGETA: - err = n_tty_ioctl(tty, (struct file *) file, cmd, arg); - break; + err = 0; + break; + } default: - err = -ENOIOCTLCMD; + err = tty_mode_ioctl(tty, file, cmd, arg); } sp_put(sp); diff --git a/drivers/net/ibm_newemac/core.c b/drivers/net/ibm_newemac/core.c index 0de3aa2..eb0718b 100644 --- a/drivers/net/ibm_newemac/core.c +++ b/drivers/net/ibm_newemac/core.c @@ -642,9 +642,11 @@ static void emac_reset_work(struct work_struct *work) DBG(dev, "reset_work" NL); mutex_lock(&dev->link_lock); - emac_netif_stop(dev); - emac_full_tx_reset(dev); - emac_netif_start(dev); + if (dev->opened) { + emac_netif_stop(dev); + emac_full_tx_reset(dev); + emac_netif_start(dev); + } mutex_unlock(&dev->link_lock); } @@ -1063,10 +1065,9 @@ static int emac_open(struct net_device *ndev) dev->rx_sg_skb = NULL; mutex_lock(&dev->link_lock); + dev->opened = 1; - /* XXX Start PHY polling now. Shouldn't wr do like sungem instead and - * always poll the PHY even when the iface is down ? That would allow - * things like laptop-net to work. --BenH + /* Start PHY polling now. */ if (dev->phy.address >= 0) { int link_poll_interval; @@ -1145,9 +1146,11 @@ static void emac_link_timer(struct work_struct *work) int link_poll_interval; mutex_lock(&dev->link_lock); - DBG2(dev, "link timer" NL); + if (!dev->opened) + goto bail; + if (dev->phy.def->ops->poll_link(&dev->phy)) { if (!netif_carrier_ok(dev->ndev)) { /* Get new link parameters */ @@ -1170,13 +1173,14 @@ static void emac_link_timer(struct work_struct *work) link_poll_interval = PHY_POLL_LINK_OFF; } schedule_delayed_work(&dev->link_work, link_poll_interval); - + bail: mutex_unlock(&dev->link_lock); } static void emac_force_link_update(struct emac_instance *dev) { netif_carrier_off(dev->ndev); + smp_rmb(); if (dev->link_polling) { cancel_rearming_delayed_work(&dev->link_work); if (dev->link_polling) @@ -1191,11 +1195,14 @@ static int emac_close(struct net_device *ndev) DBG(dev, "close" NL); - if (dev->phy.address >= 0) + if (dev->phy.address >= 0) { + dev->link_polling = 0; cancel_rearming_delayed_work(&dev->link_work); - + } + mutex_lock(&dev->link_lock); emac_netif_stop(dev); - flush_scheduled_work(); + dev->opened = 0; + mutex_unlock(&dev->link_lock); emac_rx_disable(dev); emac_tx_disable(dev); @@ -2756,6 +2763,8 @@ static int __devexit emac_remove(struct of_device *ofdev) unregister_netdev(dev->ndev); + flush_scheduled_work(); + if (emac_has_feature(dev, EMAC_FTR_HAS_TAH)) tah_detach(dev->tah_dev, dev->tah_port); if (emac_has_feature(dev, EMAC_FTR_HAS_RGMII)) diff --git a/drivers/net/ibm_newemac/core.h b/drivers/net/ibm_newemac/core.h index 4011803..a010b24 100644 --- a/drivers/net/ibm_newemac/core.h +++ b/drivers/net/ibm_newemac/core.h @@ -258,6 +258,7 @@ struct emac_instance { int stop_timeout; /* in us */ int no_mcast; int mcast_pending; + int opened; struct work_struct reset_work; spinlock_t lock; }; diff --git a/drivers/net/irda/irtty-sir.c b/drivers/net/irda/irtty-sir.c index 2c6f7be..fc753d7 100644 --- a/drivers/net/irda/irtty-sir.c +++ b/drivers/net/irda/irtty-sir.c @@ -434,11 +434,6 @@ static int irtty_ioctl(struct tty_struct *tty, struct file *file, unsigned int c IRDA_ASSERT(dev != NULL, return -1;); switch (cmd) { - case TCGETS: - case TCGETA: - err = n_tty_ioctl(tty, file, cmd, arg); - break; - case IRTTY_IOCTDONGLE: /* this call blocks for completion */ err = sirdev_set_dongle(dev, (IRDA_DONGLE) arg); @@ -454,7 +449,7 @@ static int irtty_ioctl(struct tty_struct *tty, struct file *file, unsigned int c err = -EFAULT; break; default: - err = -ENOIOCTLCMD; + err = tty_mode_ioctl(tty, file, cmd, arg); break; } return err; diff --git a/drivers/net/lib82596.c b/drivers/net/lib82596.c index 9a855e5..b59f442 100644 --- a/drivers/net/lib82596.c +++ b/drivers/net/lib82596.c @@ -176,8 +176,8 @@ struct i596_reg { struct i596_tbd { unsigned short size; unsigned short pad; - dma_addr_t next; - dma_addr_t data; + u32 next; + u32 data; u32 cache_pad[5]; /* Total 32 bytes... */ }; @@ -195,12 +195,12 @@ struct i596_cmd { struct i596_cmd *v_next; /* Address from CPUs viewpoint */ unsigned short status; unsigned short command; - dma_addr_t b_next; /* Address from i596 viewpoint */ + u32 b_next; /* Address from i596 viewpoint */ }; struct tx_cmd { struct i596_cmd cmd; - dma_addr_t tbd; + u32 tbd; unsigned short size; unsigned short pad; struct sk_buff *skb; /* So we can free it after tx */ @@ -237,8 +237,8 @@ struct cf_cmd { struct i596_rfd { unsigned short stat; unsigned short cmd; - dma_addr_t b_next; /* Address from i596 viewpoint */ - dma_addr_t rbd; + u32 b_next; /* Address from i596 viewpoint */ + u32 rbd; unsigned short count; unsigned short size; struct i596_rfd *v_next; /* Address from CPUs viewpoint */ @@ -249,18 +249,18 @@ struct i596_rfd { }; struct i596_rbd { - /* hardware data */ - unsigned short count; - unsigned short zero1; - dma_addr_t b_next; - dma_addr_t b_data; /* Address from i596 viewpoint */ - unsigned short size; - unsigned short zero2; - /* driver data */ - struct sk_buff *skb; - struct i596_rbd *v_next; - dma_addr_t b_addr; /* This rbd addr from i596 view */ - unsigned char *v_data; /* Address from CPUs viewpoint */ + /* hardware data */ + unsigned short count; + unsigned short zero1; + u32 b_next; + u32 b_data; /* Address from i596 viewpoint */ + unsigned short size; + unsigned short zero2; + /* driver data */ + struct sk_buff *skb; + struct i596_rbd *v_next; + u32 b_addr; /* This rbd addr from i596 view */ + unsigned char *v_data; /* Address from CPUs viewpoint */ /* Total 32 bytes... */ #ifdef __LP64__ u32 cache_pad[4]; @@ -275,8 +275,8 @@ struct i596_rbd { struct i596_scb { unsigned short status; unsigned short command; - dma_addr_t cmd; - dma_addr_t rfd; + u32 cmd; + u32 rfd; u32 crc_err; u32 align_err; u32 resource_err; @@ -288,14 +288,14 @@ struct i596_scb { }; struct i596_iscp { - u32 stat; - dma_addr_t scb; + u32 stat; + u32 scb; }; struct i596_scp { - u32 sysbus; - u32 pad; - dma_addr_t iscp; + u32 sysbus; + u32 pad; + u32 iscp; }; struct i596_dma { diff --git a/drivers/net/loopback.c b/drivers/net/loopback.c index 45f30a2..662b8d1 100644 --- a/drivers/net/loopback.c +++ b/drivers/net/loopback.c @@ -284,7 +284,7 @@ static __net_exit void loopback_net_exit(struct net *net) unregister_netdev(dev); } -static struct pernet_operations loopback_net_ops = { +static struct pernet_operations __net_initdata loopback_net_ops = { .init = loopback_net_init, .exit = loopback_net_exit, }; diff --git a/drivers/net/mlx4/alloc.c b/drivers/net/mlx4/alloc.c index f8d63d3..b226e01 100644 --- a/drivers/net/mlx4/alloc.c +++ b/drivers/net/mlx4/alloc.c @@ -171,9 +171,10 @@ void mlx4_buf_free(struct mlx4_dev *dev, int size, struct mlx4_buf *buf) buf->u.direct.map); else { for (i = 0; i < buf->nbufs; ++i) - dma_free_coherent(&dev->pdev->dev, PAGE_SIZE, - buf->u.page_list[i].buf, - buf->u.page_list[i].map); + if (buf->u.page_list[i].buf) + dma_free_coherent(&dev->pdev->dev, PAGE_SIZE, + buf->u.page_list[i].buf, + buf->u.page_list[i].map); kfree(buf->u.page_list); } } diff --git a/drivers/net/mlx4/qp.c b/drivers/net/mlx4/qp.c index cc4b1be..fa24e65 100644 --- a/drivers/net/mlx4/qp.c +++ b/drivers/net/mlx4/qp.c @@ -113,7 +113,7 @@ int mlx4_qp_modify(struct mlx4_dev *dev, struct mlx4_mtt *mtt, struct mlx4_cmd_mailbox *mailbox; int ret = 0; - if (cur_state >= MLX4_QP_NUM_STATE || cur_state >= MLX4_QP_NUM_STATE || + if (cur_state >= MLX4_QP_NUM_STATE || new_state >= MLX4_QP_NUM_STATE || !op[cur_state][new_state]) return -EINVAL; @@ -240,7 +240,7 @@ void mlx4_qp_free(struct mlx4_dev *dev, struct mlx4_qp *qp) mlx4_table_put(dev, &qp_table->auxc_table, qp->qpn); mlx4_table_put(dev, &qp_table->qp_table, qp->qpn); - if (qp->qpn < dev->caps.sqp_start + 8) + if (qp->qpn >= dev->caps.sqp_start + 8) mlx4_bitmap_free(&qp_table->bitmap, qp->qpn); } EXPORT_SYMBOL_GPL(mlx4_qp_free); diff --git a/drivers/net/myri_sbus.c b/drivers/net/myri_sbus.c index 8d29319..656a260 100644 --- a/drivers/net/myri_sbus.c +++ b/drivers/net/myri_sbus.c @@ -134,7 +134,7 @@ static int myri_do_handshake(struct myri_eth *mp) myri_disable_irq(mp->lregs, cregs); - while (tick++ <= 25) { + while (tick++ < 25) { u32 softstate; /* Wake it up. */ diff --git a/drivers/net/netx-eth.c b/drivers/net/netx-eth.c index eb0aff7..5267e03 100644 --- a/drivers/net/netx-eth.c +++ b/drivers/net/netx-eth.c @@ -128,8 +128,8 @@ netx_eth_hard_start_xmit(struct sk_buff *skb, struct net_device *ndev) FIFO_PTR_FRAMELEN(len)); ndev->trans_start = jiffies; - dev->stats.tx_packets++; - dev->stats.tx_bytes += skb->len; + ndev->stats.tx_packets++; + ndev->stats.tx_bytes += skb->len; netif_stop_queue(ndev); spin_unlock_irq(&priv->lock); @@ -155,7 +155,7 @@ static void netx_eth_receive(struct net_device *ndev) if (unlikely(skb == NULL)) { printk(KERN_NOTICE "%s: Low memory, packet dropped.\n", ndev->name); - dev->stats.rx_dropped++; + ndev->stats.rx_dropped++; return; } diff --git a/drivers/net/pasemi_mac.c b/drivers/net/pasemi_mac.c index ab4d309..09b4fde 100644 --- a/drivers/net/pasemi_mac.c +++ b/drivers/net/pasemi_mac.c @@ -580,6 +580,16 @@ static int pasemi_mac_clean_rx(struct pasemi_mac *mac, int limit) len = (macrx & XCT_MACRX_LLEN_M) >> XCT_MACRX_LLEN_S; + pci_unmap_single(mac->dma_pdev, dma, len, PCI_DMA_FROMDEVICE); + + if (macrx & XCT_MACRX_CRC) { + /* CRC error flagged */ + mac->netdev->stats.rx_errors++; + mac->netdev->stats.rx_crc_errors++; + dev_kfree_skb_irq(skb); + goto next; + } + if (len < 256) { struct sk_buff *new_skb; @@ -595,11 +605,10 @@ static int pasemi_mac_clean_rx(struct pasemi_mac *mac, int limit) } else info->skb = NULL; - pci_unmap_single(mac->dma_pdev, dma, len, PCI_DMA_FROMDEVICE); - info->dma = 0; - skb_put(skb, len); + /* Don't include CRC */ + skb_put(skb, len-4); if (likely((macrx & XCT_MACRX_HTY_M) == XCT_MACRX_HTY_IPV4_OK)) { skb->ip_summed = CHECKSUM_UNNECESSARY; @@ -614,6 +623,7 @@ static int pasemi_mac_clean_rx(struct pasemi_mac *mac, int limit) skb->protocol = eth_type_trans(skb, mac->netdev); netif_receive_skb(skb); +next: RX_RING(mac, n) = 0; RX_RING(mac, n+1) = 0; @@ -1126,7 +1136,7 @@ static int pasemi_mac_start_tx(struct sk_buff *skb, struct net_device *dev) unsigned long flags; int i, nfrags; - dflags = XCT_MACTX_O | XCT_MACTX_ST | XCT_MACTX_SS | XCT_MACTX_CRC_PAD; + dflags = XCT_MACTX_O | XCT_MACTX_ST | XCT_MACTX_CRC_PAD; if (skb->ip_summed == CHECKSUM_PARTIAL) { const unsigned char *nh = skb_network_header(skb); diff --git a/drivers/net/phy/marvell.c b/drivers/net/phy/marvell.c index 035fd41..f057407 100644 --- a/drivers/net/phy/marvell.c +++ b/drivers/net/phy/marvell.c @@ -143,21 +143,29 @@ static int m88e1111_config_init(struct phy_device *phydev) int err; if ((phydev->interface == PHY_INTERFACE_MODE_RGMII) || - (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID)) { + (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID) || + (phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID) || + (phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID)) { int temp; - if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID) { - temp = phy_read(phydev, MII_M1111_PHY_EXT_CR); - if (temp < 0) - return temp; + temp = phy_read(phydev, MII_M1111_PHY_EXT_CR); + if (temp < 0) + return temp; + if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID) { temp |= (MII_M1111_RX_DELAY | MII_M1111_TX_DELAY); - - err = phy_write(phydev, MII_M1111_PHY_EXT_CR, temp); - if (err < 0) - return err; + } else if (phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID) { + temp &= ~MII_M1111_TX_DELAY; + temp |= MII_M1111_RX_DELAY; + } else if (phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID) { + temp &= ~MII_M1111_RX_DELAY; + temp |= MII_M1111_TX_DELAY; } + err = phy_write(phydev, MII_M1111_PHY_EXT_CR, temp); + if (err < 0) + return err; + temp = phy_read(phydev, MII_M1111_PHY_EXT_SR); if (temp < 0) return temp; diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c index 9bc1177..7c9e6e3 100644 --- a/drivers/net/phy/phy.c +++ b/drivers/net/phy/phy.c @@ -406,6 +406,9 @@ int phy_mii_ioctl(struct phy_device *phydev, && phydev->drv->config_init) phydev->drv->config_init(phydev); break; + + default: + return -ENOTTY; } return 0; diff --git a/drivers/net/plip.c b/drivers/net/plip.c index 5071fcd..57c9866 100644 --- a/drivers/net/plip.c +++ b/drivers/net/plip.c @@ -663,7 +663,7 @@ plip_receive_packet(struct net_device *dev, struct net_local *nl, case PLIP_PK_DONE: /* Inform the upper layer for the arrival of a packet. */ rcv->skb->protocol=plip_type_trans(rcv->skb, dev); - netif_rx(rcv->skb); + netif_rx_ni(rcv->skb); dev->last_rx = jiffies; dev->stats.rx_bytes += rcv->length.h; dev->stats.rx_packets++; @@ -1269,7 +1269,7 @@ static void plip_attach (struct parport *port) nl = netdev_priv(dev); nl->dev = dev; - nl->pardev = parport_register_device(port, name, plip_preempt, + nl->pardev = parport_register_device(port, dev->name, plip_preempt, plip_wakeup, plip_interrupt, 0, dev); diff --git a/drivers/net/ppp_async.c b/drivers/net/ppp_async.c index 27f5b90..f023d5b 100644 --- a/drivers/net/ppp_async.c +++ b/drivers/net/ppp_async.c @@ -160,7 +160,7 @@ ppp_asynctty_open(struct tty_struct *tty) err = -ENOMEM; ap = kzalloc(sizeof(*ap), GFP_KERNEL); - if (ap == 0) + if (!ap) goto out; /* initialize the asyncppp structure */ @@ -215,7 +215,7 @@ ppp_asynctty_close(struct tty_struct *tty) ap = tty->disc_data; tty->disc_data = NULL; write_unlock_irq(&disc_data_lock); - if (ap == 0) + if (!ap) return; /* @@ -230,10 +230,10 @@ ppp_asynctty_close(struct tty_struct *tty) tasklet_kill(&ap->tsk); ppp_unregister_channel(&ap->chan); - if (ap->rpkt != 0) + if (ap->rpkt) kfree_skb(ap->rpkt); skb_queue_purge(&ap->rqueue); - if (ap->tpkt != 0) + if (ap->tpkt) kfree_skb(ap->tpkt); kfree(ap); } @@ -285,13 +285,13 @@ ppp_asynctty_ioctl(struct tty_struct *tty, struct file *file, int err, val; int __user *p = (int __user *)arg; - if (ap == 0) + if (!ap) return -ENXIO; err = -EFAULT; switch (cmd) { case PPPIOCGCHAN: err = -ENXIO; - if (ap == 0) + if (!ap) break; err = -EFAULT; if (put_user(ppp_channel_index(&ap->chan), p)) @@ -301,7 +301,7 @@ ppp_asynctty_ioctl(struct tty_struct *tty, struct file *file, case PPPIOCGUNIT: err = -ENXIO; - if (ap == 0) + if (!ap) break; err = -EFAULT; if (put_user(ppp_unit_number(&ap->chan), p)) @@ -309,16 +309,11 @@ ppp_asynctty_ioctl(struct tty_struct *tty, struct file *file, err = 0; break; - case TCGETS: - case TCGETA: - err = n_tty_ioctl(tty, file, cmd, arg); - break; - case TCFLSH: /* flush our buffers and the serial port's buffer */ if (arg == TCIOFLUSH || arg == TCOFLUSH) ppp_async_flush_output(ap); - err = n_tty_ioctl(tty, file, cmd, arg); + err = tty_perform_flush(tty, arg); break; case FIONREAD: @@ -329,7 +324,8 @@ ppp_asynctty_ioctl(struct tty_struct *tty, struct file *file, break; default: - err = -ENOIOCTLCMD; + /* Try the various mode ioctls */ + err = tty_mode_ioctl(tty, file, cmd, arg); } ap_put(ap); @@ -354,7 +350,7 @@ ppp_asynctty_receive(struct tty_struct *tty, const unsigned char *buf, struct asyncppp *ap = ap_get(tty); unsigned long flags; - if (ap == 0) + if (!ap) return; spin_lock_irqsave(&ap->recv_lock, flags); ppp_async_input(ap, buf, cflags, count); @@ -373,7 +369,7 @@ ppp_asynctty_wakeup(struct tty_struct *tty) struct asyncppp *ap = ap_get(tty); clear_bit(TTY_DO_WRITE_WAKEUP, &tty->flags); - if (ap == 0) + if (!ap) return; set_bit(XMIT_WAKEUP, &ap->xmit_flags); tasklet_schedule(&ap->tsk); @@ -688,7 +684,7 @@ ppp_async_push(struct asyncppp *ap) tty_stuffed = 1; continue; } - if (ap->optr >= ap->olim && ap->tpkt != 0) { + if (ap->optr >= ap->olim && ap->tpkt) { if (ppp_async_encode(ap)) { /* finished processing ap->tpkt */ clear_bit(XMIT_FULL, &ap->xmit_flags); @@ -708,7 +704,7 @@ ppp_async_push(struct asyncppp *ap) clear_bit(XMIT_BUSY, &ap->xmit_flags); /* any more work to do? if not, exit the loop */ if (!(test_bit(XMIT_WAKEUP, &ap->xmit_flags) - || (!tty_stuffed && ap->tpkt != 0))) + || (!tty_stuffed && ap->tpkt))) break; /* more work to do, see if we can do it now */ if (test_and_set_bit(XMIT_BUSY, &ap->xmit_flags)) @@ -719,7 +715,7 @@ ppp_async_push(struct asyncppp *ap) flush: clear_bit(XMIT_BUSY, &ap->xmit_flags); - if (ap->tpkt != 0) { + if (ap->tpkt) { kfree_skb(ap->tpkt); ap->tpkt = NULL; clear_bit(XMIT_FULL, &ap->xmit_flags); @@ -852,7 +848,7 @@ ppp_async_input(struct asyncppp *ap, const unsigned char *buf, s = 0; for (i = 0; i < count; ++i) { c = buf[i]; - if (flags != 0 && flags[i] != 0) + if (flags && flags[i] != 0) continue; s |= (c & 0x80)? SC_RCV_B7_1: SC_RCV_B7_0; c = ((c >> 4) ^ c) & 0xf; @@ -869,7 +865,7 @@ ppp_async_input(struct asyncppp *ap, const unsigned char *buf, n = scan_ordinary(ap, buf, count); f = 0; - if (flags != 0 && (ap->state & SC_TOSS) == 0) { + if (flags && (ap->state & SC_TOSS) == 0) { /* check the flags to see if any char had an error */ for (j = 0; j < n; ++j) if ((f = flags[j]) != 0) @@ -882,9 +878,9 @@ ppp_async_input(struct asyncppp *ap, const unsigned char *buf, } else if (n > 0 && (ap->state & SC_TOSS) == 0) { /* stuff the chars in the skb */ skb = ap->rpkt; - if (skb == 0) { + if (!skb) { skb = dev_alloc_skb(ap->mru + PPP_HDRLEN + 2); - if (skb == 0) + if (!skb) goto nomem; ap->rpkt = skb; } @@ -931,7 +927,7 @@ ppp_async_input(struct asyncppp *ap, const unsigned char *buf, ++n; buf += n; - if (flags != 0) + if (flags) flags += n; count -= n; } diff --git a/drivers/net/ppp_generic.c b/drivers/net/ppp_generic.c index 4b49d0e..4f69037 100644 --- a/drivers/net/ppp_generic.c +++ b/drivers/net/ppp_generic.c @@ -367,7 +367,7 @@ static int ppp_release(struct inode *inode, struct file *file) struct ppp_file *pf = file->private_data; struct ppp *ppp; - if (pf != 0) { + if (pf) { file->private_data = NULL; if (pf->kind == INTERFACE) { ppp = PF_TO_PPP(pf); @@ -398,7 +398,7 @@ static ssize_t ppp_read(struct file *file, char __user *buf, ret = count; - if (pf == 0) + if (!pf) return -ENXIO; add_wait_queue(&pf->rwait, &wait); for (;;) { @@ -431,7 +431,7 @@ static ssize_t ppp_read(struct file *file, char __user *buf, set_current_state(TASK_RUNNING); remove_wait_queue(&pf->rwait, &wait); - if (skb == 0) + if (!skb) goto out; ret = -EOVERFLOW; @@ -455,11 +455,11 @@ static ssize_t ppp_write(struct file *file, const char __user *buf, struct sk_buff *skb; ssize_t ret; - if (pf == 0) + if (!pf) return -ENXIO; ret = -ENOMEM; skb = alloc_skb(count + pf->hdrlen, GFP_KERNEL); - if (skb == 0) + if (!skb) goto out; skb_reserve(skb, pf->hdrlen); ret = -EFAULT; @@ -491,11 +491,11 @@ static unsigned int ppp_poll(struct file *file, poll_table *wait) struct ppp_file *pf = file->private_data; unsigned int mask; - if (pf == 0) + if (!pf) return 0; poll_wait(file, &pf->rwait, wait); mask = POLLOUT | POLLWRNORM; - if (skb_peek(&pf->rq) != 0) + if (skb_peek(&pf->rq)) mask |= POLLIN | POLLRDNORM; if (pf->dead) mask |= POLLHUP; @@ -559,7 +559,7 @@ static int ppp_ioctl(struct inode *inode, struct file *file, void __user *argp = (void __user *)arg; int __user *p = argp; - if (pf == 0) + if (!pf) return ppp_unattached_ioctl(pf, file, cmd, arg); if (cmd == PPPIOCDETACH) { @@ -689,13 +689,13 @@ static int ppp_ioctl(struct inode *inode, struct file *file, val &= 0xffff; } vj = slhc_init(val2+1, val+1); - if (vj == 0) { + if (!vj) { printk(KERN_ERR "PPP: no memory (VJ compressor)\n"); err = -ENOMEM; break; } ppp_lock(ppp); - if (ppp->vj != 0) + if (ppp->vj) slhc_free(ppp->vj); ppp->vj = vj; ppp_unlock(ppp); @@ -786,7 +786,7 @@ static int ppp_unattached_ioctl(struct ppp_file *pf, struct file *file, if (get_user(unit, p)) break; ppp = ppp_create_interface(unit, &err); - if (ppp == 0) + if (!ppp) break; file->private_data = &ppp->file; ppp->owner = file; @@ -803,7 +803,7 @@ static int ppp_unattached_ioctl(struct ppp_file *pf, struct file *file, mutex_lock(&all_ppp_mutex); err = -ENXIO; ppp = ppp_find_unit(unit); - if (ppp != 0) { + if (ppp) { atomic_inc(&ppp->file.refcnt); file->private_data = &ppp->file; err = 0; @@ -817,7 +817,7 @@ static int ppp_unattached_ioctl(struct ppp_file *pf, struct file *file, spin_lock_bh(&all_channels_lock); err = -ENXIO; chan = ppp_find_channel(unit); - if (chan != 0) { + if (chan) { atomic_inc(&chan->file.refcnt); file->private_data = &chan->file; err = 0; @@ -946,9 +946,9 @@ ppp_net_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) case SIOCGPPPCSTATS: memset(&cstats, 0, sizeof(cstats)); - if (ppp->xc_state != 0) + if (ppp->xc_state) ppp->xcomp->comp_stat(ppp->xc_state, &cstats.c); - if (ppp->rc_state != 0) + if (ppp->rc_state) ppp->rcomp->decomp_stat(ppp->rc_state, &cstats.d); if (copy_to_user(addr, &cstats, sizeof(cstats))) break; @@ -993,14 +993,14 @@ ppp_xmit_process(struct ppp *ppp) struct sk_buff *skb; ppp_xmit_lock(ppp); - if (ppp->dev != 0) { + if (ppp->dev) { ppp_push(ppp); - while (ppp->xmit_pending == 0 - && (skb = skb_dequeue(&ppp->file.xq)) != 0) + while (!ppp->xmit_pending + && (skb = skb_dequeue(&ppp->file.xq))) ppp_send_frame(ppp, skb); /* If there's no work left to do, tell the core net code that we can accept some more. */ - if (ppp->xmit_pending == 0 && skb_peek(&ppp->file.xq) == 0) + if (!ppp->xmit_pending && !skb_peek(&ppp->file.xq)) netif_wake_queue(ppp->dev); } ppp_xmit_unlock(ppp); @@ -1100,12 +1100,12 @@ ppp_send_frame(struct ppp *ppp, struct sk_buff *skb) switch (proto) { case PPP_IP: - if (ppp->vj == 0 || (ppp->flags & SC_COMP_TCP) == 0) + if (!ppp->vj || (ppp->flags & SC_COMP_TCP) == 0) break; /* try to do VJ TCP header compression */ new_skb = alloc_skb(skb->len + ppp->dev->hard_header_len - 2, GFP_ATOMIC); - if (new_skb == 0) { + if (!new_skb) { printk(KERN_ERR "PPP: no memory (VJ comp pkt)\n"); goto drop; } @@ -1140,7 +1140,7 @@ ppp_send_frame(struct ppp *ppp, struct sk_buff *skb) } /* try to do packet compression */ - if ((ppp->xstate & SC_COMP_RUN) && ppp->xc_state != 0 + if ((ppp->xstate & SC_COMP_RUN) && ppp->xc_state && proto != PPP_LCP && proto != PPP_CCP) { if (!(ppp->flags & SC_CCP_UP) && (ppp->flags & SC_MUST_COMP)) { if (net_ratelimit()) @@ -1185,7 +1185,7 @@ ppp_push(struct ppp *ppp) struct channel *pch; struct sk_buff *skb = ppp->xmit_pending; - if (skb == 0) + if (!skb) return; list = &ppp->channels; @@ -1355,7 +1355,7 @@ static int ppp_mp_explode(struct ppp *ppp, struct sk_buff *skb) if (flen == len && nfree == 0) bits |= E; frag = alloc_skb(flen + hdrlen + (flen == 0), GFP_ATOMIC); - if (frag == 0) + if (!frag) goto noskb; q = skb_put(frag, flen + hdrlen); @@ -1425,7 +1425,7 @@ ppp_channel_push(struct channel *pch) struct ppp *ppp; spin_lock_bh(&pch->downl); - if (pch->chan != 0) { + if (pch->chan) { while (!skb_queue_empty(&pch->file.xq)) { skb = skb_dequeue(&pch->file.xq); if (!pch->chan->ops->start_xmit(pch->chan, skb)) { @@ -1443,7 +1443,7 @@ ppp_channel_push(struct channel *pch) if (skb_queue_empty(&pch->file.xq)) { read_lock_bh(&pch->upl); ppp = pch->ppp; - if (ppp != 0) + if (ppp) ppp_xmit_process(ppp); read_unlock_bh(&pch->upl); } @@ -1462,7 +1462,7 @@ ppp_do_recv(struct ppp *ppp, struct sk_buff *skb, struct channel *pch) { ppp_recv_lock(ppp); /* ppp->dev == 0 means interface is closing down */ - if (ppp->dev != 0) + if (ppp->dev) ppp_receive_frame(ppp, skb, pch); else kfree_skb(skb); @@ -1475,19 +1475,19 @@ ppp_input(struct ppp_channel *chan, struct sk_buff *skb) struct channel *pch = chan->ppp; int proto; - if (pch == 0 || skb->len == 0) { + if (!pch || skb->len == 0) { kfree_skb(skb); return; } proto = PPP_PROTO(skb); read_lock_bh(&pch->upl); - if (pch->ppp == 0 || proto >= 0xc000 || proto == PPP_CCPFRAG) { + if (!pch->ppp || proto >= 0xc000 || proto == PPP_CCPFRAG) { /* put it on the channel queue */ skb_queue_tail(&pch->file.rq, skb); /* drop old frames if queue too long */ while (pch->file.rq.qlen > PPP_MAX_RQLEN - && (skb = skb_dequeue(&pch->file.rq)) != 0) + && (skb = skb_dequeue(&pch->file.rq))) kfree_skb(skb); wake_up_interruptible(&pch->file.rwait); } else { @@ -1503,13 +1503,13 @@ ppp_input_error(struct ppp_channel *chan, int code) struct channel *pch = chan->ppp; struct sk_buff *skb; - if (pch == 0) + if (!pch) return; read_lock_bh(&pch->upl); - if (pch->ppp != 0) { + if (pch->ppp) { skb = alloc_skb(0, GFP_ATOMIC); - if (skb != 0) { + if (skb) { skb->len = 0; /* probably unnecessary */ skb->cb[0] = code; ppp_do_recv(pch->ppp, skb, pch); @@ -1548,7 +1548,7 @@ static void ppp_receive_error(struct ppp *ppp) { ++ppp->stats.rx_errors; - if (ppp->vj != 0) + if (ppp->vj) slhc_toss(ppp->vj); } @@ -1563,7 +1563,7 @@ ppp_receive_nonmp_frame(struct ppp *ppp, struct sk_buff *skb) * Note that some decompressors need to see uncompressed frames * that come in as well as compressed frames. */ - if (ppp->rc_state != 0 && (ppp->rstate & SC_DECOMP_RUN) + if (ppp->rc_state && (ppp->rstate & SC_DECOMP_RUN) && (ppp->rstate & (SC_DC_FERROR | SC_DC_ERROR)) == 0) skb = ppp_decompress_frame(ppp, skb); @@ -1574,13 +1574,13 @@ ppp_receive_nonmp_frame(struct ppp *ppp, struct sk_buff *skb) switch (proto) { case PPP_VJC_COMP: /* decompress VJ compressed packets */ - if (ppp->vj == 0 || (ppp->flags & SC_REJ_COMP_TCP)) + if (!ppp->vj || (ppp->flags & SC_REJ_COMP_TCP)) goto err; if (skb_tailroom(skb) < 124 || skb_cloned(skb)) { /* copy to a new sk_buff with more tailroom */ ns = dev_alloc_skb(skb->len + 128); - if (ns == 0) { + if (!ns) { printk(KERN_ERR"PPP: no memory (VJ decomp)\n"); goto err; } @@ -1606,7 +1606,7 @@ ppp_receive_nonmp_frame(struct ppp *ppp, struct sk_buff *skb) break; case PPP_VJC_UNCOMP: - if (ppp->vj == 0 || (ppp->flags & SC_REJ_COMP_TCP)) + if (!ppp->vj || (ppp->flags & SC_REJ_COMP_TCP)) goto err; /* Until we fix the decompressor need to make sure @@ -1636,7 +1636,7 @@ ppp_receive_nonmp_frame(struct ppp *ppp, struct sk_buff *skb) skb_queue_tail(&ppp->file.rq, skb); /* limit queue length by dropping old frames */ while (ppp->file.rq.qlen > PPP_MAX_RQLEN - && (skb = skb_dequeue(&ppp->file.rq)) != 0) + && (skb = skb_dequeue(&ppp->file.rq))) kfree_skb(skb); /* wake up any process polling or blocking on read */ wake_up_interruptible(&ppp->file.rwait); @@ -1718,7 +1718,7 @@ ppp_decompress_frame(struct ppp *ppp, struct sk_buff *skb) } ns = dev_alloc_skb(obuff_size); - if (ns == 0) { + if (!ns) { printk(KERN_ERR "ppp_decompress_frame: no memory\n"); goto err; } @@ -1836,7 +1836,7 @@ ppp_receive_mp_frame(struct ppp *ppp, struct sk_buff *skb, struct channel *pch) ppp->minseq = ppp->mrq.next->sequence; /* Pull completed packets off the queue and receive them. */ - while ((skb = ppp_mp_reconstruct(ppp)) != 0) + while ((skb = ppp_mp_reconstruct(ppp))) ppp_receive_nonmp_frame(ppp, skb); return; @@ -2002,7 +2002,7 @@ ppp_register_channel(struct ppp_channel *chan) struct channel *pch; pch = kzalloc(sizeof(struct channel), GFP_KERNEL); - if (pch == 0) + if (!pch) return -ENOMEM; pch->ppp = NULL; pch->chan = chan; @@ -2030,7 +2030,7 @@ int ppp_channel_index(struct ppp_channel *chan) { struct channel *pch = chan->ppp; - if (pch != 0) + if (pch) return pch->file.index; return -1; } @@ -2043,9 +2043,9 @@ int ppp_unit_number(struct ppp_channel *chan) struct channel *pch = chan->ppp; int unit = -1; - if (pch != 0) { + if (pch) { read_lock_bh(&pch->upl); - if (pch->ppp != 0) + if (pch->ppp) unit = pch->ppp->file.index; read_unlock_bh(&pch->upl); } @@ -2061,7 +2061,7 @@ ppp_unregister_channel(struct ppp_channel *chan) { struct channel *pch = chan->ppp; - if (pch == 0) + if (!pch) return; /* should never happen */ chan->ppp = NULL; @@ -2093,7 +2093,7 @@ ppp_output_wakeup(struct ppp_channel *chan) { struct channel *pch = chan->ppp; - if (pch == 0) + if (!pch) return; ppp_channel_push(pch); } @@ -2124,18 +2124,18 @@ ppp_set_compress(struct ppp *ppp, unsigned long arg) cp = find_compressor(ccp_option[0]); #ifdef CONFIG_KMOD - if (cp == 0) { + if (!cp) { request_module("ppp-compress-%d", ccp_option[0]); cp = find_compressor(ccp_option[0]); } #endif /* CONFIG_KMOD */ - if (cp == 0) + if (!cp) goto out; err = -ENOBUFS; if (data.transmit) { state = cp->comp_alloc(ccp_option, data.length); - if (state != 0) { + if (state) { ppp_xmit_lock(ppp); ppp->xstate &= ~SC_COMP_RUN; ocomp = ppp->xcomp; @@ -2143,7 +2143,7 @@ ppp_set_compress(struct ppp *ppp, unsigned long arg) ppp->xcomp = cp; ppp->xc_state = state; ppp_xmit_unlock(ppp); - if (ostate != 0) { + if (ostate) { ocomp->comp_free(ostate); module_put(ocomp->owner); } @@ -2153,7 +2153,7 @@ ppp_set_compress(struct ppp *ppp, unsigned long arg) } else { state = cp->decomp_alloc(ccp_option, data.length); - if (state != 0) { + if (state) { ppp_recv_lock(ppp); ppp->rstate &= ~SC_DECOMP_RUN; ocomp = ppp->rcomp; @@ -2161,7 +2161,7 @@ ppp_set_compress(struct ppp *ppp, unsigned long arg) ppp->rcomp = cp; ppp->rc_state = state; ppp_recv_unlock(ppp); - if (ostate != 0) { + if (ostate) { ocomp->decomp_free(ostate); module_put(ocomp->owner); } @@ -2228,7 +2228,7 @@ ppp_ccp_peek(struct ppp *ppp, struct sk_buff *skb, int inbound) break; if (inbound) { /* we will start receiving compressed packets */ - if (ppp->rc_state == 0) + if (!ppp->rc_state) break; if (ppp->rcomp->decomp_init(ppp->rc_state, dp, len, ppp->file.index, 0, ppp->mru, ppp->debug)) { @@ -2237,7 +2237,7 @@ ppp_ccp_peek(struct ppp *ppp, struct sk_buff *skb, int inbound) } } else { /* we will soon start sending compressed packets */ - if (ppp->xc_state == 0) + if (!ppp->xc_state) break; if (ppp->xcomp->comp_init(ppp->xc_state, dp, len, ppp->file.index, 0, ppp->debug)) @@ -2320,11 +2320,11 @@ ppp_register_compressor(struct compressor *cp) int ret; spin_lock(&compressor_list_lock); ret = -EEXIST; - if (find_comp_entry(cp->compress_proto) != 0) + if (find_comp_entry(cp->compress_proto)) goto out; ret = -ENOMEM; ce = kmalloc(sizeof(struct compressor_entry), GFP_ATOMIC); - if (ce == 0) + if (!ce) goto out; ret = 0; ce->comp = cp; @@ -2342,7 +2342,7 @@ ppp_unregister_compressor(struct compressor *cp) spin_lock(&compressor_list_lock); ce = find_comp_entry(cp->compress_proto); - if (ce != 0 && ce->comp == cp) { + if (ce && ce->comp == cp) { list_del(&ce->list); kfree(ce); } @@ -2358,7 +2358,7 @@ find_compressor(int type) spin_lock(&compressor_list_lock); ce = find_comp_entry(type); - if (ce != 0) { + if (ce) { cp = ce->comp; if (!try_module_get(cp->owner)) cp = NULL; @@ -2383,7 +2383,7 @@ ppp_get_stats(struct ppp *ppp, struct ppp_stats *st) st->p.ppp_opackets = ppp->stats.tx_packets; st->p.ppp_oerrors = ppp->stats.tx_errors; st->p.ppp_obytes = ppp->stats.tx_bytes; - if (vj == 0) + if (!vj) return; st->vj.vjs_packets = vj->sls_o_compressed + vj->sls_o_uncompressed; st->vj.vjs_compressed = vj->sls_o_compressed; @@ -2604,11 +2604,11 @@ ppp_connect_channel(struct channel *pch, int unit) mutex_lock(&all_ppp_mutex); ppp = ppp_find_unit(unit); - if (ppp == 0) + if (!ppp) goto out; write_lock_bh(&pch->upl); ret = -EINVAL; - if (pch->ppp != 0) + if (pch->ppp) goto outl; ppp_lock(ppp); @@ -2644,7 +2644,7 @@ ppp_disconnect_channel(struct channel *pch) ppp = pch->ppp; pch->ppp = NULL; write_unlock_bh(&pch->upl); - if (ppp != 0) { + if (ppp) { /* remove it from the ppp unit's list */ ppp_lock(ppp); list_del(&pch->clist); diff --git a/drivers/net/ppp_synctty.c b/drivers/net/ppp_synctty.c index ce64032..f0c6a19 100644 --- a/drivers/net/ppp_synctty.c +++ b/drivers/net/ppp_synctty.c @@ -209,7 +209,7 @@ ppp_sync_open(struct tty_struct *tty) ap = kzalloc(sizeof(*ap), GFP_KERNEL); err = -ENOMEM; - if (ap == 0) + if (!ap) goto out; /* initialize the syncppp structure */ @@ -262,7 +262,7 @@ ppp_sync_close(struct tty_struct *tty) ap = tty->disc_data; tty->disc_data = NULL; write_unlock_irq(&disc_data_lock); - if (ap == 0) + if (!ap) return; /* @@ -278,7 +278,7 @@ ppp_sync_close(struct tty_struct *tty) ppp_unregister_channel(&ap->chan); skb_queue_purge(&ap->rqueue); - if (ap->tpkt != 0) + if (ap->tpkt) kfree_skb(ap->tpkt); kfree(ap); } @@ -325,13 +325,13 @@ ppp_synctty_ioctl(struct tty_struct *tty, struct file *file, int __user *p = (int __user *)arg; int err, val; - if (ap == 0) + if (!ap) return -ENXIO; err = -EFAULT; switch (cmd) { case PPPIOCGCHAN: err = -ENXIO; - if (ap == 0) + if (!ap) break; err = -EFAULT; if (put_user(ppp_channel_index(&ap->chan), p)) @@ -341,7 +341,7 @@ ppp_synctty_ioctl(struct tty_struct *tty, struct file *file, case PPPIOCGUNIT: err = -ENXIO; - if (ap == 0) + if (!ap) break; err = -EFAULT; if (put_user(ppp_unit_number(&ap->chan), p)) @@ -349,16 +349,11 @@ ppp_synctty_ioctl(struct tty_struct *tty, struct file *file, err = 0; break; - case TCGETS: - case TCGETA: - err = n_tty_ioctl(tty, file, cmd, arg); - break; - case TCFLSH: /* flush our buffers and the serial port's buffer */ if (arg == TCIOFLUSH || arg == TCOFLUSH) ppp_sync_flush_output(ap); - err = n_tty_ioctl(tty, file, cmd, arg); + err = tty_perform_flush(tty, arg); break; case FIONREAD: @@ -369,7 +364,8 @@ ppp_synctty_ioctl(struct tty_struct *tty, struct file *file, break; default: - err = -ENOIOCTLCMD; + err = tty_mode_ioctl(tty, file, cmd, arg); + break; } sp_put(ap); @@ -394,7 +390,7 @@ ppp_sync_receive(struct tty_struct *tty, const unsigned char *buf, struct syncppp *ap = sp_get(tty); unsigned long flags; - if (ap == 0) + if (!ap) return; spin_lock_irqsave(&ap->recv_lock, flags); ppp_sync_input(ap, buf, cflags, count); @@ -413,7 +409,7 @@ ppp_sync_wakeup(struct tty_struct *tty) struct syncppp *ap = sp_get(tty); clear_bit(TTY_DO_WRITE_WAKEUP, &tty->flags); - if (ap == 0) + if (!ap) return; set_bit(XMIT_WAKEUP, &ap->xmit_flags); tasklet_schedule(&ap->tsk); @@ -655,7 +651,7 @@ ppp_sync_push(struct syncppp *ap) for (;;) { if (test_and_clear_bit(XMIT_WAKEUP, &ap->xmit_flags)) tty_stuffed = 0; - if (!tty_stuffed && ap->tpkt != 0) { + if (!tty_stuffed && ap->tpkt) { set_bit(TTY_DO_WRITE_WAKEUP, &tty->flags); sent = tty->driver->write(tty, ap->tpkt->data, ap->tpkt->len); if (sent < 0) @@ -673,7 +669,7 @@ ppp_sync_push(struct syncppp *ap) /* haven't made any progress */ spin_unlock_bh(&ap->xmit_lock); if (!(test_bit(XMIT_WAKEUP, &ap->xmit_flags) - || (!tty_stuffed && ap->tpkt != 0))) + || (!tty_stuffed && ap->tpkt))) break; if (!spin_trylock_bh(&ap->xmit_lock)) break; @@ -681,7 +677,7 @@ ppp_sync_push(struct syncppp *ap) return done; flush: - if (ap->tpkt != 0) { + if (ap->tpkt) { kfree_skb(ap->tpkt); ap->tpkt = NULL; clear_bit(XMIT_FULL, &ap->xmit_flags); @@ -736,7 +732,8 @@ ppp_sync_input(struct syncppp *ap, const unsigned char *buf, ppp_print_buffer ("receive buffer", buf, count); /* stuff the chars in the skb */ - if ((skb = dev_alloc_skb(ap->mru + PPP_HDRLEN + 2)) == 0) { + skb = dev_alloc_skb(ap->mru + PPP_HDRLEN + 2); + if (!skb) { printk(KERN_ERR "PPPsync: no memory (input pkt)\n"); goto err; } @@ -744,7 +741,7 @@ ppp_sync_input(struct syncppp *ap, const unsigned char *buf, if (buf[0] != PPP_ALLSTATIONS) skb_reserve(skb, 2 + (buf[0] & 1)); - if (flags != 0 && *flags) { + if (flags && *flags) { /* error flag set, ignore frame */ goto err; } else if (count > skb_tailroom(skb)) { diff --git a/drivers/net/pppol2tp.c b/drivers/net/pppol2tp.c index f8904fd..a7556cd 100644 --- a/drivers/net/pppol2tp.c +++ b/drivers/net/pppol2tp.c @@ -488,7 +488,7 @@ static int pppol2tp_recv_core(struct sock *sock, struct sk_buff *skb) { struct pppol2tp_session *session = NULL; struct pppol2tp_tunnel *tunnel; - unsigned char *ptr; + unsigned char *ptr, *optr; u16 hdrflags; u16 tunnel_id, session_id; int length; @@ -496,7 +496,7 @@ static int pppol2tp_recv_core(struct sock *sock, struct sk_buff *skb) tunnel = pppol2tp_sock_to_tunnel(sock); if (tunnel == NULL) - goto error; + goto no_tunnel; /* UDP always verifies the packet length. */ __skb_pull(skb, sizeof(struct udphdr)); @@ -509,7 +509,7 @@ static int pppol2tp_recv_core(struct sock *sock, struct sk_buff *skb) } /* Point to L2TP header */ - ptr = skb->data; + optr = ptr = skb->data; /* Get L2TP header flags */ hdrflags = ntohs(*(__be16*)ptr); @@ -637,12 +637,14 @@ static int pppol2tp_recv_core(struct sock *sock, struct sk_buff *skb) /* If offset bit set, skip it. */ if (hdrflags & L2TP_HDRFLAG_O) { offset = ntohs(*(__be16 *)ptr); - skb->transport_header += 2 + offset; - if (!pskb_may_pull(skb, skb_transport_offset(skb) + 2)) - goto discard; + ptr += 2 + offset; } - __skb_pull(skb, skb_transport_offset(skb)); + offset = ptr - optr; + if (!pskb_may_pull(skb, offset)) + goto discard; + + __skb_pull(skb, offset); /* Skip PPP header, if present. In testing, Microsoft L2TP clients * don't send the PPP header (PPP header compression enabled), but @@ -652,6 +654,9 @@ static int pppol2tp_recv_core(struct sock *sock, struct sk_buff *skb) * Note that skb->data[] isn't dereferenced from a u16 ptr here since * the field may be unaligned. */ + if (!pskb_may_pull(skb, 2)) + goto discard; + if ((skb->data[0] == 0xff) && (skb->data[1] == 0x03)) skb_pull(skb, 2); @@ -709,6 +714,10 @@ discard: return 0; error: + /* Put UDP header back */ + __skb_push(skb, sizeof(struct udphdr)); + +no_tunnel: return 1; } @@ -1050,6 +1059,8 @@ static int pppol2tp_xmit(struct ppp_channel *chan, struct sk_buff *skb) /* Get routing info from the tunnel socket */ dst_release(skb->dst); skb->dst = sk_dst_get(sk_tun); + skb_orphan(skb); + skb->sk = sk_tun; /* Queue the packet to IP for output */ len = skb->len; diff --git a/drivers/net/qla3xxx.c b/drivers/net/qla3xxx.c index 30adf72..a579111 100644 --- a/drivers/net/qla3xxx.c +++ b/drivers/net/qla3xxx.c @@ -1456,16 +1456,11 @@ static void ql_phy_start_neg_ex(struct ql3_adapter *qdev) PHYAddr[qdev->mac_index]); reg &= ~PHY_GIG_ALL_PARAMS; - if(portConfiguration & - PORT_CONFIG_FULL_DUPLEX_ENABLED & - PORT_CONFIG_1000MB_SPEED) { - reg |= PHY_GIG_ADV_1000F; - } - - if(portConfiguration & - PORT_CONFIG_HALF_DUPLEX_ENABLED & - PORT_CONFIG_1000MB_SPEED) { - reg |= PHY_GIG_ADV_1000H; + if(portConfiguration & PORT_CONFIG_1000MB_SPEED) { + if(portConfiguration & PORT_CONFIG_FULL_DUPLEX_ENABLED) + reg |= PHY_GIG_ADV_1000F; + else + reg |= PHY_GIG_ADV_1000H; } ql_mii_write_reg_ex(qdev, PHY_GIG_CONTROL, reg, @@ -1645,8 +1640,11 @@ static int ql_finish_auto_neg(struct ql3_adapter *qdev) return 0; } -static void ql_link_state_machine(struct ql3_adapter *qdev) +static void ql_link_state_machine_work(struct work_struct *work) { + struct ql3_adapter *qdev = + container_of(work, struct ql3_adapter, link_state_work.work); + u32 curr_link_state; unsigned long hw_flags; @@ -1661,6 +1659,10 @@ static void ql_link_state_machine(struct ql3_adapter *qdev) "state.\n", qdev->ndev->name); spin_unlock_irqrestore(&qdev->hw_lock, hw_flags); + + /* Restart timer on 2 second interval. */ + mod_timer(&qdev->adapter_timer, jiffies + HZ * 1);\ + return; } @@ -1705,6 +1707,9 @@ static void ql_link_state_machine(struct ql3_adapter *qdev) break; } spin_unlock_irqrestore(&qdev->hw_lock, hw_flags); + + /* Restart timer on 2 second interval. */ + mod_timer(&qdev->adapter_timer, jiffies + HZ * 1); } /* @@ -3941,19 +3946,7 @@ static void ql_get_board_info(struct ql3_adapter *qdev) static void ql3xxx_timer(unsigned long ptr) { struct ql3_adapter *qdev = (struct ql3_adapter *)ptr; - - if (test_bit(QL_RESET_ACTIVE,&qdev->flags)) { - printk(KERN_DEBUG PFX - "%s: Reset in progress.\n", - qdev->ndev->name); - goto end; - } - - ql_link_state_machine(qdev); - - /* Restart timer on 2 second interval. */ -end: - mod_timer(&qdev->adapter_timer, jiffies + HZ * 1); + queue_delayed_work(qdev->workqueue, &qdev->link_state_work, 0); } static int __devinit ql3xxx_probe(struct pci_dev *pdev, @@ -4103,6 +4096,7 @@ static int __devinit ql3xxx_probe(struct pci_dev *pdev, qdev->workqueue = create_singlethread_workqueue(ndev->name); INIT_DELAYED_WORK(&qdev->reset_work, ql_reset_work); INIT_DELAYED_WORK(&qdev->tx_timeout_work, ql_tx_timeout_work); + INIT_DELAYED_WORK(&qdev->link_state_work, ql_link_state_machine_work); init_timer(&qdev->adapter_timer); qdev->adapter_timer.function = ql3xxx_timer; diff --git a/drivers/net/qla3xxx.h b/drivers/net/qla3xxx.h index fbcb0b9..d0ffb30 100644 --- a/drivers/net/qla3xxx.h +++ b/drivers/net/qla3xxx.h @@ -1286,6 +1286,7 @@ struct ql3_adapter { struct workqueue_struct *workqueue; struct delayed_work reset_work; struct delayed_work tx_timeout_work; + struct delayed_work link_state_work; u32 max_frame_size; u32 device_id; u16 phyType; diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c index b94fa7e..1f647b9 100644 --- a/drivers/net/r8169.c +++ b/drivers/net/r8169.c @@ -171,6 +171,8 @@ static struct pci_device_id rtl8169_pci_tbl[] = { { PCI_DEVICE(0x16ec, 0x0116), 0, 0, RTL_CFG_0 }, { PCI_VENDOR_ID_LINKSYS, 0x1032, PCI_ANY_ID, 0x0024, 0, 0, RTL_CFG_0 }, + { 0x0001, 0x8168, + PCI_ANY_ID, 0x2410, 0, 0, RTL_CFG_2 }, {0,}, }; @@ -468,7 +470,7 @@ static void mdio_write(void __iomem *ioaddr, int reg_addr, int value) { int i; - RTL_W32(PHYAR, 0x80000000 | (reg_addr & 0xFF) << 16 | value); + RTL_W32(PHYAR, 0x80000000 | (reg_addr & 0x1f) << 16 | (value & 0xffff)); for (i = 20; i > 0; i--) { /* @@ -485,7 +487,7 @@ static int mdio_read(void __iomem *ioaddr, int reg_addr) { int i, value = -1; - RTL_W32(PHYAR, 0x0 | (reg_addr & 0xFF) << 16); + RTL_W32(PHYAR, 0x0 | (reg_addr & 0x1f) << 16); for (i = 20; i > 0; i--) { /* @@ -493,7 +495,7 @@ static int mdio_read(void __iomem *ioaddr, int reg_addr) * the specified MII register. */ if (RTL_R32(PHYAR) & 0x80000000) { - value = (int) (RTL_R32(PHYAR) & 0xFFFF); + value = RTL_R32(PHYAR) & 0xffff; break; } udelay(25); @@ -1245,16 +1247,6 @@ static void rtl8169sb_hw_phy_config(void __iomem *ioaddr) rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); } -static void rtl8168b_hw_phy_config(void __iomem *ioaddr) -{ - struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0000 }, - { 0x10, 0xf41b }, - { 0x1f, 0x0000 } - }; - - rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init)); -} static void rtl8168cp_hw_phy_config(void __iomem *ioaddr) { @@ -1324,11 +1316,6 @@ static void rtl_hw_phy_config(struct net_device *dev) case RTL_GIGA_MAC_VER_04: rtl8169sb_hw_phy_config(ioaddr); break; - case RTL_GIGA_MAC_VER_11: - case RTL_GIGA_MAC_VER_12: - case RTL_GIGA_MAC_VER_17: - rtl8168b_hw_phy_config(ioaddr); - break; case RTL_GIGA_MAC_VER_18: rtl8168cp_hw_phy_config(ioaddr); break; @@ -1739,7 +1726,8 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) tp->features |= rtl_try_msi(pdev, ioaddr, cfg); RTL_W8(Cfg9346, Cfg9346_Lock); - if (RTL_R8(PHYstatus) & TBI_Enable) { + if ((tp->mac_version <= RTL_GIGA_MAC_VER_06) && + (RTL_R8(PHYstatus) & TBI_Enable)) { tp->set_speed = rtl8169_set_speed_tbi; tp->get_settings = rtl8169_gset_tbi; tp->phy_reset_enable = rtl8169_tbi_reset_enable; diff --git a/drivers/net/rrunner.c b/drivers/net/rrunner.c index b822859..73a7e65 100644 --- a/drivers/net/rrunner.c +++ b/drivers/net/rrunner.c @@ -78,12 +78,6 @@ static char version[] __devinitdata = "rrunner.c: v0.50 11/11/2002 Jes Sorensen * stack will need to know about I/O vectors or something similar. */ -/* - * sysctl_[wr]mem_max are checked at init time to see if they are at - * least 256KB and increased to 256KB if they are not. This is done to - * avoid ending up with socket buffers smaller than the MTU size, - */ - static int __devinit rr_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) { @@ -561,18 +555,6 @@ static int __devinit rr_init(struct net_device *dev) sram_size = rr_read_eeprom_word(rrpriv, (void *)8); printk(" SRAM size 0x%06x\n", sram_size); - if (sysctl_rmem_max < 262144){ - printk(" Receive socket buffer limit too low (%i), " - "setting to 262144\n", sysctl_rmem_max); - sysctl_rmem_max = 262144; - } - - if (sysctl_wmem_max < 262144){ - printk(" Transmit socket buffer limit too low (%i), " - "setting to 262144\n", sysctl_wmem_max); - sysctl_wmem_max = 262144; - } - return 0; } diff --git a/drivers/net/s2io.c b/drivers/net/s2io.c index b8c0e7b..d5113dd 100644 --- a/drivers/net/s2io.c +++ b/drivers/net/s2io.c @@ -84,7 +84,7 @@ #include "s2io.h" #include "s2io-regs.h" -#define DRV_VERSION "2.0.26.5" +#define DRV_VERSION "2.0.26.6" /* S2io Driver name & version. */ static char s2io_driver_name[] = "Neterion"; @@ -1081,7 +1081,7 @@ static int init_nic(struct s2io_nic *nic) /* to set the swapper controle on the card */ if(s2io_set_swapper(nic)) { DBG_PRINT(ERR_DBG,"ERROR: Setting Swapper failed\n"); - return -1; + return -EIO; } /* @@ -1503,7 +1503,7 @@ static int init_nic(struct s2io_nic *nic) DBG_PRINT(ERR_DBG, "%s: failed rts ds steering", dev->name); DBG_PRINT(ERR_DBG, "set on codepoint %d\n", i); - return FAILURE; + return -ENODEV; } } @@ -1570,7 +1570,7 @@ static int init_nic(struct s2io_nic *nic) if (time > 10) { DBG_PRINT(ERR_DBG, "%s: TTI init Failed\n", dev->name); - return -1; + return -ENODEV; } msleep(50); time++; @@ -1623,7 +1623,7 @@ static int init_nic(struct s2io_nic *nic) if (time > 10) { DBG_PRINT(ERR_DBG, "%s: RTI init Failed\n", dev->name); - return -1; + return -ENODEV; } time++; msleep(50); @@ -3775,6 +3775,40 @@ static int __devinit s2io_test_msi(struct s2io_nic *sp) return err; } + +static void remove_msix_isr(struct s2io_nic *sp) +{ + int i; + u16 msi_control; + + for (i = 0; i < MAX_REQUESTED_MSI_X; i++) { + if (sp->s2io_entries[i].in_use == + MSIX_REGISTERED_SUCCESS) { + int vector = sp->entries[i].vector; + void *arg = sp->s2io_entries[i].arg; + free_irq(vector, arg); + } + } + + kfree(sp->entries); + kfree(sp->s2io_entries); + sp->entries = NULL; + sp->s2io_entries = NULL; + + pci_read_config_word(sp->pdev, 0x42, &msi_control); + msi_control &= 0xFFFE; /* Disable MSI */ + pci_write_config_word(sp->pdev, 0x42, msi_control); + + pci_disable_msix(sp->pdev); +} + +static void remove_inta_isr(struct s2io_nic *sp) +{ + struct net_device *dev = sp->dev; + + free_irq(sp->pdev->irq, dev); +} + /* ********************************************************* * * Functions defined below concern the OS part of the driver * * ********************************************************* */ @@ -3809,28 +3843,9 @@ static int s2io_open(struct net_device *dev) int ret = s2io_enable_msi_x(sp); if (!ret) { - u16 msi_control; - ret = s2io_test_msi(sp); - /* rollback MSI-X, will re-enable during add_isr() */ - kfree(sp->entries); - sp->mac_control.stats_info->sw_stat.mem_freed += - (MAX_REQUESTED_MSI_X * - sizeof(struct msix_entry)); - kfree(sp->s2io_entries); - sp->mac_control.stats_info->sw_stat.mem_freed += - (MAX_REQUESTED_MSI_X * - sizeof(struct s2io_msix_entry)); - sp->entries = NULL; - sp->s2io_entries = NULL; - - pci_read_config_word(sp->pdev, 0x42, &msi_control); - msi_control &= 0xFFFE; /* Disable MSI */ - pci_write_config_word(sp->pdev, 0x42, msi_control); - - pci_disable_msix(sp->pdev); - + remove_msix_isr(sp); } if (ret) { @@ -3899,6 +3914,12 @@ static int s2io_close(struct net_device *dev) { struct s2io_nic *sp = dev->priv; + /* Return if the device is already closed * + * Can happen when s2io_card_up failed in change_mtu * + */ + if (!is_s2io_card_up(sp)) + return 0; + netif_stop_queue(dev); napi_disable(&sp->napi); /* Reset card, kill tasklet and free Tx and Rx buffers. */ @@ -6340,6 +6361,7 @@ static int s2io_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) static int s2io_change_mtu(struct net_device *dev, int new_mtu) { struct s2io_nic *sp = dev->priv; + int ret = 0; if ((new_mtu < MIN_MTU) || (new_mtu > S2IO_JUMBO_SIZE)) { DBG_PRINT(ERR_DBG, "%s: MTU size is invalid.\n", @@ -6351,9 +6373,11 @@ static int s2io_change_mtu(struct net_device *dev, int new_mtu) if (netif_running(dev)) { s2io_card_down(sp); netif_stop_queue(dev); - if (s2io_card_up(sp)) { + ret = s2io_card_up(sp); + if (ret) { DBG_PRINT(ERR_DBG, "%s: Device bring up failed\n", __FUNCTION__); + return ret; } if (netif_queue_stopped(dev)) netif_wake_queue(dev); @@ -6364,7 +6388,7 @@ static int s2io_change_mtu(struct net_device *dev, int new_mtu) writeq(vBIT(val64, 2, 14), &bar0->rmac_max_pyld_len); } - return 0; + return ret; } /** @@ -6719,15 +6743,22 @@ static int s2io_add_isr(struct s2io_nic * sp) } } if (err) { + remove_msix_isr(sp); DBG_PRINT(ERR_DBG,"%s:MSI-X-%d registration " "failed\n", dev->name, i); - DBG_PRINT(ERR_DBG, "Returned: %d\n", err); - return -1; + DBG_PRINT(ERR_DBG, "%s: defaulting to INTA\n", + dev->name); + sp->config.intr_type = INTA; + break; } sp->s2io_entries[i].in_use = MSIX_REGISTERED_SUCCESS; } - printk("MSI-X-TX %d entries enabled\n",msix_tx_cnt); - printk("MSI-X-RX %d entries enabled\n",msix_rx_cnt); + if (!err) { + printk(KERN_INFO "MSI-X-TX %d entries enabled\n", + msix_tx_cnt); + printk(KERN_INFO "MSI-X-RX %d entries enabled\n", + msix_rx_cnt); + } } if (sp->config.intr_type == INTA) { err = request_irq((int) sp->pdev->irq, s2io_isr, IRQF_SHARED, @@ -6742,40 +6773,10 @@ static int s2io_add_isr(struct s2io_nic * sp) } static void s2io_rem_isr(struct s2io_nic * sp) { - struct net_device *dev = sp->dev; - struct swStat *stats = &sp->mac_control.stats_info->sw_stat; - - if (sp->config.intr_type == MSI_X) { - int i; - u16 msi_control; - - for (i=1; (sp->s2io_entries[i].in_use == - MSIX_REGISTERED_SUCCESS); i++) { - int vector = sp->entries[i].vector; - void *arg = sp->s2io_entries[i].arg; - - synchronize_irq(vector); - free_irq(vector, arg); - } - - kfree(sp->entries); - stats->mem_freed += - (MAX_REQUESTED_MSI_X * sizeof(struct msix_entry)); - kfree(sp->s2io_entries); - stats->mem_freed += - (MAX_REQUESTED_MSI_X * sizeof(struct s2io_msix_entry)); - sp->entries = NULL; - sp->s2io_entries = NULL; - - pci_read_config_word(sp->pdev, 0x42, &msi_control); - msi_control &= 0xFFFE; /* Disable MSI */ - pci_write_config_word(sp->pdev, 0x42, msi_control); - - pci_disable_msix(sp->pdev); - } else { - synchronize_irq(sp->pdev->irq); - free_irq(sp->pdev->irq, dev); - } + if (sp->config.intr_type == MSI_X) + remove_msix_isr(sp); + else + remove_inta_isr(sp); } static void do_s2io_card_down(struct s2io_nic * sp, int do_io) @@ -6785,6 +6786,9 @@ static void do_s2io_card_down(struct s2io_nic * sp, int do_io) unsigned long flags; register u64 val64 = 0; + if (!is_s2io_card_up(sp)) + return; + del_timer_sync(&sp->alarm_timer); /* If s2io_set_link task is executing, wait till it completes. */ while (test_and_set_bit(__S2IO_STATE_LINK_TASK, &(sp->state))) { @@ -6858,11 +6862,13 @@ static int s2io_card_up(struct s2io_nic * sp) u16 interruptible; /* Initialize the H/W I/O registers */ - if (init_nic(sp) != 0) { + ret = init_nic(sp); + if (ret != 0) { DBG_PRINT(ERR_DBG, "%s: H/W initialization failed\n", dev->name); - s2io_reset(sp); - return -ENODEV; + if (ret != -EIO) + s2io_reset(sp); + return ret; } /* diff --git a/drivers/net/skge.c b/drivers/net/skge.c index b9961dc..186eb8e 100644 --- a/drivers/net/skge.c +++ b/drivers/net/skge.c @@ -44,7 +44,7 @@ #include "skge.h" #define DRV_NAME "skge" -#define DRV_VERSION "1.12" +#define DRV_VERSION "1.13" #define PFX DRV_NAME " " #define DEFAULT_TX_RING_SIZE 128 @@ -1095,16 +1095,9 @@ static void xm_link_down(struct skge_hw *hw, int port) { struct net_device *dev = hw->dev[port]; struct skge_port *skge = netdev_priv(dev); - u16 cmd = xm_read16(hw, port, XM_MMU_CMD); xm_write16(hw, port, XM_IMSK, XM_IMSK_DISABLE); - cmd &= ~(XM_MMU_ENA_RX | XM_MMU_ENA_TX); - xm_write16(hw, port, XM_MMU_CMD, cmd); - - /* dummy read to ensure writing */ - xm_read16(hw, port, XM_MMU_CMD); - if (netif_carrier_ok(dev)) skge_link_down(skge); } @@ -1194,6 +1187,7 @@ static void genesis_init(struct skge_hw *hw) static void genesis_reset(struct skge_hw *hw, int port) { const u8 zero[8] = { 0 }; + u32 reg; skge_write8(hw, SK_REG(port, GMAC_IRQ_MSK), 0); @@ -1209,6 +1203,11 @@ static void genesis_reset(struct skge_hw *hw, int port) xm_write16(hw, port, PHY_BCOM_INT_MASK, 0xffff); xm_outhash(hw, port, XM_HSM, zero); + + /* Flush TX and RX fifo */ + reg = xm_read32(hw, port, XM_MODE); + xm_write32(hw, port, XM_MODE, reg | XM_MD_FTF); + xm_write32(hw, port, XM_MODE, reg | XM_MD_FRF); } @@ -1634,15 +1633,14 @@ static void genesis_mac_init(struct skge_hw *hw, int port) } xm_write16(hw, port, XM_RX_CMD, r); - /* We want short frames padded to 60 bytes. */ xm_write16(hw, port, XM_TX_CMD, XM_TX_AUTO_PAD); - /* - * Bump up the transmit threshold. This helps hold off transmit - * underruns when we're blasting traffic from both ports at once. - */ - xm_write16(hw, port, XM_TX_THR, 512); + /* Increase threshold for jumbo frames on dual port */ + if (hw->ports > 1 && jumbo) + xm_write16(hw, port, XM_TX_THR, 1020); + else + xm_write16(hw, port, XM_TX_THR, 512); /* * Enable the reception of all error frames. This is is @@ -1713,7 +1711,13 @@ static void genesis_stop(struct skge_port *skge) { struct skge_hw *hw = skge->hw; int port = skge->port; - u32 reg; + unsigned retries = 1000; + u16 cmd; + + /* Disable Tx and Rx */ + cmd = xm_read16(hw, port, XM_MMU_CMD); + cmd &= ~(XM_MMU_ENA_RX | XM_MMU_ENA_TX); + xm_write16(hw, port, XM_MMU_CMD, cmd); genesis_reset(hw, port); @@ -1721,20 +1725,17 @@ static void genesis_stop(struct skge_port *skge) skge_write16(hw, B3_PA_CTRL, port == 0 ? PA_CLR_TO_TX1 : PA_CLR_TO_TX2); - /* - * If the transfer sticks at the MAC the STOP command will not - * terminate if we don't flush the XMAC's transmit FIFO ! - */ - xm_write32(hw, port, XM_MODE, - xm_read32(hw, port, XM_MODE)|XM_MD_FTF); - - /* Reset the MAC */ - skge_write16(hw, SK_REG(port, TX_MFF_CTRL1), MFF_SET_MAC_RST); + skge_write16(hw, SK_REG(port, TX_MFF_CTRL1), MFF_CLR_MAC_RST); + do { + skge_write16(hw, SK_REG(port, TX_MFF_CTRL1), MFF_SET_MAC_RST); + if (!(skge_read16(hw, SK_REG(port, TX_MFF_CTRL1)) & MFF_SET_MAC_RST)) + break; + } while (--retries > 0); /* For external PHYs there must be special handling */ if (hw->phy_type != SK_PHY_XMAC) { - reg = skge_read32(hw, B2_GP_IO); + u32 reg = skge_read32(hw, B2_GP_IO); if (port == 0) { reg |= GP_DIR_0; reg &= ~GP_IO_0; @@ -1801,11 +1802,6 @@ static void genesis_mac_intr(struct skge_hw *hw, int port) xm_write32(hw, port, XM_MODE, XM_MD_FTF); ++dev->stats.tx_fifo_errors; } - - if (status & XM_IS_RXF_OV) { - xm_write32(hw, port, XM_MODE, XM_MD_FRF); - ++dev->stats.rx_fifo_errors; - } } static void genesis_link_up(struct skge_port *skge) @@ -1862,9 +1858,9 @@ static void genesis_link_up(struct skge_port *skge) xm_write32(hw, port, XM_MODE, mode); - /* Turn on detection of Tx underrun, Rx overrun */ + /* Turn on detection of Tx underrun */ msk = xm_read16(hw, port, XM_IMSK); - msk &= ~(XM_IS_RXF_OV | XM_IS_TXF_UR); + msk &= ~XM_IS_TXF_UR; xm_write16(hw, port, XM_IMSK, msk); xm_read16(hw, port, XM_ISRC); @@ -2194,9 +2190,12 @@ static void yukon_mac_init(struct skge_hw *hw, int port) TX_JAM_IPG_VAL(TX_JAM_IPG_DEF) | TX_IPG_JAM_DATA(TX_IPG_JAM_DEF)); - /* serial mode register */ - reg = GM_SMOD_VLAN_ENA | IPG_DATA_VAL(IPG_DATA_DEF); - if (hw->dev[port]->mtu > 1500) + /* configure the Serial Mode Register */ + reg = DATA_BLIND_VAL(DATA_BLIND_DEF) + | GM_SMOD_VLAN_ENA + | IPG_DATA_VAL(IPG_DATA_DEF); + + if (hw->dev[port]->mtu > ETH_DATA_LEN) reg |= GM_SMOD_JUMBO_ENA; gma_write16(hw, port, GM_SERIAL_MODE, reg); @@ -2512,31 +2511,32 @@ static int skge_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) return err; } -/* Assign Ram Buffer allocation to queue */ -static void skge_ramset(struct skge_hw *hw, u16 q, u32 start, u32 space) +static void skge_ramset(struct skge_hw *hw, u16 q, u32 start, size_t len) { u32 end; - /* convert from K bytes to qwords used for hw register */ - start *= 1024/8; - space *= 1024/8; - end = start + space - 1; + start /= 8; + len /= 8; + end = start + len - 1; skge_write8(hw, RB_ADDR(q, RB_CTRL), RB_RST_CLR); skge_write32(hw, RB_ADDR(q, RB_START), start); - skge_write32(hw, RB_ADDR(q, RB_END), end); skge_write32(hw, RB_ADDR(q, RB_WP), start); skge_write32(hw, RB_ADDR(q, RB_RP), start); + skge_write32(hw, RB_ADDR(q, RB_END), end); if (q == Q_R1 || q == Q_R2) { - u32 tp = space - space/4; - /* Set thresholds on receive queue's */ - skge_write32(hw, RB_ADDR(q, RB_RX_UTPP), tp); - skge_write32(hw, RB_ADDR(q, RB_RX_LTPP), space/4); - } else if (hw->chip_id != CHIP_ID_GENESIS) - /* Genesis Tx Fifo is too small for normal store/forward */ + skge_write32(hw, RB_ADDR(q, RB_RX_UTPP), + start + (2*len)/3); + skge_write32(hw, RB_ADDR(q, RB_RX_LTPP), + start + (len/3)); + } else { + /* Enable store & forward on Tx queue's because + * Tx FIFO is only 4K on Genesis and 1K on Yukon + */ skge_write8(hw, RB_ADDR(q, RB_CTRL), RB_ENA_STFWD); + } skge_write8(hw, RB_ADDR(q, RB_CTRL), RB_ENA_OP_MD); } @@ -2564,7 +2564,7 @@ static int skge_up(struct net_device *dev) struct skge_port *skge = netdev_priv(dev); struct skge_hw *hw = skge->hw; int port = skge->port; - u32 ramaddr, ramsize, rxspace; + u32 chunk, ram_addr; size_t rx_size, tx_size; int err; @@ -2618,16 +2618,15 @@ static int skge_up(struct net_device *dev) yukon_mac_init(hw, port); spin_unlock_bh(&hw->phy_lock); - /* Configure RAMbuffers */ - ramsize = (hw->ram_size - hw->ram_offset) / hw->ports; - ramaddr = hw->ram_offset + port * ramsize; - rxspace = 8 + (2*(ramsize - 16))/3; - - skge_ramset(hw, rxqaddr[port], ramaddr, rxspace); - skge_ramset(hw, txqaddr[port], ramaddr + rxspace, ramsize - rxspace); + /* Configure RAMbuffers - equally between ports and tx/rx */ + chunk = (hw->ram_size - hw->ram_offset) / (hw->ports * 2); + ram_addr = hw->ram_offset + 2 * chunk * port; + skge_ramset(hw, rxqaddr[port], ram_addr, chunk); skge_qset(skge, rxqaddr[port], skge->rx_ring.to_clean); + BUG_ON(skge->tx_ring.to_use != skge->tx_ring.to_clean); + skge_ramset(hw, txqaddr[port], ram_addr+chunk, chunk); skge_qset(skge, txqaddr[port], skge->tx_ring.to_use); /* Start receiver BMU */ @@ -2897,11 +2896,7 @@ static void skge_tx_timeout(struct net_device *dev) static int skge_change_mtu(struct net_device *dev, int new_mtu) { - struct skge_port *skge = netdev_priv(dev); - struct skge_hw *hw = skge->hw; - int port = skge->port; int err; - u16 ctl, reg; if (new_mtu < ETH_ZLEN || new_mtu > ETH_JUMBO_MTU) return -EINVAL; @@ -2911,40 +2906,13 @@ static int skge_change_mtu(struct net_device *dev, int new_mtu) return 0; } - skge_write32(hw, B0_IMSK, 0); - dev->trans_start = jiffies; /* prevent tx timeout */ - netif_stop_queue(dev); - napi_disable(&skge->napi); - - ctl = gma_read16(hw, port, GM_GP_CTRL); - gma_write16(hw, port, GM_GP_CTRL, ctl & ~GM_GPCR_RX_ENA); - - skge_rx_clean(skge); - skge_rx_stop(hw, port); + skge_down(dev); dev->mtu = new_mtu; - reg = GM_SMOD_VLAN_ENA | IPG_DATA_VAL(IPG_DATA_DEF); - if (new_mtu > 1500) - reg |= GM_SMOD_JUMBO_ENA; - gma_write16(hw, port, GM_SERIAL_MODE, reg); - - skge_write8(hw, RB_ADDR(rxqaddr[port], RB_CTRL), RB_ENA_OP_MD); - - err = skge_rx_fill(dev); - wmb(); - if (!err) - skge_write8(hw, Q_ADDR(rxqaddr[port], Q_CSR), CSR_START | CSR_IRQ_CL_F); - skge_write32(hw, B0_IMSK, hw->intr_mask); - + err = skge_up(dev); if (err) dev_close(dev); - else { - gma_write16(hw, port, GM_GP_CTRL, ctl); - - napi_enable(&skge->napi); - netif_wake_queue(dev); - } return err; } @@ -3591,12 +3559,15 @@ static int skge_reset(struct skge_hw *hw) if (hw->chip_id == CHIP_ID_GENESIS) { if (t8 == 3) { /* special case: 4 x 64k x 36, offset = 0x80000 */ - hw->ram_size = 1024; - hw->ram_offset = 512; + hw->ram_size = 0x100000; + hw->ram_offset = 0x80000; } else hw->ram_size = t8 * 512; - } else /* Yukon */ - hw->ram_size = t8 ? t8 * 4 : 128; + } + else if (t8 == 0) + hw->ram_size = 0x20000; + else + hw->ram_size = t8 * 4096; hw->intr_mask = IS_HW_ERR; diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index c27c7d6..3d1dfc9 100644 --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c @@ -31,7 +31,6 @@ #include <linux/etherdevice.h> #include <linux/ethtool.h> #include <linux/pci.h> -#include <linux/aer.h> #include <linux/ip.h> #include <net/ip.h> #include <linux/tcp.h> @@ -52,7 +51,7 @@ #include "sky2.h" #define DRV_NAME "sky2" -#define DRV_VERSION "1.19" +#define DRV_VERSION "1.20" #define PFX DRV_NAME " " /* @@ -121,6 +120,7 @@ static const struct pci_device_id sky2_id_table[] = { { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4353) }, /* 88E8039 */ { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4354) }, /* 88E8040 */ { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4356) }, /* 88EC033 */ + { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4357) }, /* 88E8042 */ { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x435A) }, /* 88E8048 */ { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4360) }, /* 88E8052 */ { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4361) }, /* 88E8050 */ @@ -134,6 +134,7 @@ static const struct pci_device_id sky2_id_table[] = { { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4369) }, /* 88EC042 */ { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x436A) }, /* 88E8058 */ { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x436B) }, /* 88E8071 */ + { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x436C) }, /* 88E8072 */ { 0 } }; @@ -156,7 +157,7 @@ static const char *yukon2_name[] = { static void sky2_set_multicast(struct net_device *dev); -/* Access to external PHY */ +/* Access to PHY via serial interconnect */ static int gm_phy_write(struct sky2_hw *hw, unsigned port, u16 reg, u16 val) { int i; @@ -166,13 +167,22 @@ static int gm_phy_write(struct sky2_hw *hw, unsigned port, u16 reg, u16 val) GM_SMI_CT_PHY_AD(PHY_ADDR_MARV) | GM_SMI_CT_REG_AD(reg)); for (i = 0; i < PHY_RETRIES; i++) { - if (!(gma_read16(hw, port, GM_SMI_CTRL) & GM_SMI_CT_BUSY)) + u16 ctrl = gma_read16(hw, port, GM_SMI_CTRL); + if (ctrl == 0xffff) + goto io_error; + + if (!(ctrl & GM_SMI_CT_BUSY)) return 0; - udelay(1); + + udelay(10); } - printk(KERN_WARNING PFX "%s: phy write timeout\n", hw->dev[port]->name); + dev_warn(&hw->pdev->dev,"%s: phy write timeout\n", hw->dev[port]->name); return -ETIMEDOUT; + +io_error: + dev_err(&hw->pdev->dev, "%s: phy I/O error\n", hw->dev[port]->name); + return -EIO; } static int __gm_phy_read(struct sky2_hw *hw, unsigned port, u16 reg, u16 *val) @@ -183,23 +193,29 @@ static int __gm_phy_read(struct sky2_hw *hw, unsigned port, u16 reg, u16 *val) | GM_SMI_CT_REG_AD(reg) | GM_SMI_CT_OP_RD); for (i = 0; i < PHY_RETRIES; i++) { - if (gma_read16(hw, port, GM_SMI_CTRL) & GM_SMI_CT_RD_VAL) { + u16 ctrl = gma_read16(hw, port, GM_SMI_CTRL); + if (ctrl == 0xffff) + goto io_error; + + if (ctrl & GM_SMI_CT_RD_VAL) { *val = gma_read16(hw, port, GM_SMI_DATA); return 0; } - udelay(1); + udelay(10); } + dev_warn(&hw->pdev->dev, "%s: phy read timeout\n", hw->dev[port]->name); return -ETIMEDOUT; +io_error: + dev_err(&hw->pdev->dev, "%s: phy I/O error\n", hw->dev[port]->name); + return -EIO; } -static u16 gm_phy_read(struct sky2_hw *hw, unsigned port, u16 reg) +static inline u16 gm_phy_read(struct sky2_hw *hw, unsigned port, u16 reg) { u16 v; - - if (__gm_phy_read(hw, port, reg, &v) != 0) - printk(KERN_WARNING PFX "%s: phy read timeout\n", hw->dev[port]->name); + __gm_phy_read(hw, port, reg, &v); return v; } @@ -223,22 +239,21 @@ static void sky2_power_on(struct sky2_hw *hw) sky2_write8(hw, B2_Y2_CLK_GATE, 0); if (hw->flags & SKY2_HW_ADV_POWER_CTL) { - struct pci_dev *pdev = hw->pdev; u32 reg; - pci_write_config_dword(pdev, PCI_DEV_REG3, 0); + sky2_pci_write32(hw, PCI_DEV_REG3, 0); - pci_read_config_dword(pdev, PCI_DEV_REG4, ®); + reg = sky2_pci_read32(hw, PCI_DEV_REG4); /* set all bits to 0 except bits 15..12 and 8 */ reg &= P_ASPM_CONTROL_MSK; - pci_write_config_dword(pdev, PCI_DEV_REG4, reg); + sky2_pci_write32(hw, PCI_DEV_REG4, reg); - pci_read_config_dword(pdev, PCI_DEV_REG5, ®); + reg = sky2_pci_read32(hw, PCI_DEV_REG5); /* set all bits to 0 except bits 28 & 27 */ reg &= P_CTL_TIM_VMAIN_AV_MSK; - pci_write_config_dword(pdev, PCI_DEV_REG5, reg); + sky2_pci_write32(hw, PCI_DEV_REG5, reg); - pci_write_config_dword(pdev, PCI_CFG_REG_1, 0); + sky2_pci_write32(hw, PCI_CFG_REG_1, 0); /* Enable workaround for dev 4.107 on Yukon-Ultra & Extreme */ reg = sky2_read32(hw, B2_GP_IO); @@ -273,8 +288,6 @@ static void sky2_gmac_reset(struct sky2_hw *hw, unsigned port) /* disable all GMAC IRQ's */ sky2_write8(hw, SK_REG(port, GMAC_IRQ_MSK), 0); - /* disable PHY IRQs */ - gm_phy_write(hw, port, PHY_MARV_INT_MASK, 0); gma_write16(hw, port, GM_MC_ADDR_H1, 0); /* clear MC hash */ gma_write16(hw, port, GM_MC_ADDR_H2, 0); @@ -604,12 +617,11 @@ static void sky2_phy_init(struct sky2_hw *hw, unsigned port) static void sky2_phy_power(struct sky2_hw *hw, unsigned port, int onoff) { - struct pci_dev *pdev = hw->pdev; u32 reg1; static const u32 phy_power[] = { PCI_Y2_PHY1_POWD, PCI_Y2_PHY2_POWD }; static const u32 coma_mode[] = { PCI_Y2_PHY1_COMA, PCI_Y2_PHY2_COMA }; - pci_read_config_dword(pdev, PCI_DEV_REG1, ®1); + reg1 = sky2_pci_read32(hw, PCI_DEV_REG1); /* Turn on/off phy power saving */ if (onoff) reg1 &= ~phy_power[port]; @@ -619,8 +631,8 @@ static void sky2_phy_power(struct sky2_hw *hw, unsigned port, int onoff) if (onoff && hw->chip_id == CHIP_ID_YUKON_XL && hw->chip_rev > 1) reg1 |= coma_mode[port]; - pci_write_config_dword(pdev, PCI_DEV_REG1, reg1); - pci_read_config_dword(pdev, PCI_DEV_REG1, ®1); + sky2_pci_write32(hw, PCI_DEV_REG1, reg1); + reg1 = sky2_pci_read32(hw, PCI_DEV_REG1); udelay(100); } @@ -689,9 +701,9 @@ static void sky2_wol_init(struct sky2_port *sky2) sky2_write16(hw, WOL_REGS(port, WOL_CTRL_STAT), ctrl); /* Turn on legacy PCI-Express PME mode */ - pci_read_config_dword(hw->pdev, PCI_DEV_REG1, ®1); + reg1 = sky2_pci_read32(hw, PCI_DEV_REG1); reg1 |= PCI_Y2_PME_LEGACY; - pci_write_config_dword(hw->pdev, PCI_DEV_REG1, reg1); + sky2_pci_write32(hw, PCI_DEV_REG1, reg1); /* block receiver */ sky2_write8(hw, SK_REG(port, RX_GMF_CTRL_T), GMF_RST_SET); @@ -833,6 +845,13 @@ static void sky2_mac_init(struct sky2_hw *hw, unsigned port) sky2_set_tx_stfwd(hw, port); } + if (hw->chip_id == CHIP_ID_YUKON_FE_P && + hw->chip_rev == CHIP_REV_YU_FE2_A0) { + /* disable dynamic watermark */ + reg = sky2_read16(hw, SK_REG(port, TX_GMF_EA)); + reg &= ~TX_DYN_WM_ENA; + sky2_write16(hw, SK_REG(port, TX_GMF_EA), reg); + } } /* Assign Ram Buffer allocation to queue */ @@ -1305,15 +1324,12 @@ static int sky2_up(struct net_device *dev) */ if (otherdev && netif_running(otherdev) && (cap = pci_find_capability(hw->pdev, PCI_CAP_ID_PCIX))) { - struct sky2_port *osky2 = netdev_priv(otherdev); u16 cmd; - pci_read_config_word(hw->pdev, cap + PCI_X_CMD, &cmd); + cmd = sky2_pci_read16(hw, cap + PCI_X_CMD); cmd &= ~PCI_X_CMD_MAX_SPLIT; - pci_write_config_word(hw->pdev, cap + PCI_X_CMD, cmd); + sky2_pci_write16(hw, cap + PCI_X_CMD, cmd); - sky2->rx_csum = 0; - osky2->rx_csum = 0; } if (netif_msg_ifup(sky2)) @@ -1805,29 +1821,6 @@ static void sky2_link_up(struct sky2_port *sky2) sky2_write8(hw, SK_REG(port, LNK_LED_REG), LINKLED_ON | LINKLED_BLINK_OFF | LINKLED_LINKSYNC_OFF); - if (hw->flags & SKY2_HW_NEWER_PHY) { - u16 pg = gm_phy_read(hw, port, PHY_MARV_EXT_ADR); - u16 led = PHY_M_LEDC_LOS_CTRL(1); /* link active */ - - switch(sky2->speed) { - case SPEED_10: - led |= PHY_M_LEDC_INIT_CTRL(7); - break; - - case SPEED_100: - led |= PHY_M_LEDC_STA1_CTRL(7); - break; - - case SPEED_1000: - led |= PHY_M_LEDC_STA0_CTRL(7); - break; - } - - gm_phy_write(hw, port, PHY_MARV_EXT_ADR, 3); - gm_phy_write(hw, port, PHY_MARV_PHY_CTRL, led); - gm_phy_write(hw, port, PHY_MARV_EXT_ADR, pg); - } - if (netif_msg_link(sky2)) printk(KERN_INFO PFX "%s: Link is up at %d Mbps, %s duplex, flow control %s\n", @@ -2247,20 +2240,26 @@ static int sky2_status_intr(struct sky2_hw *hw, int to_do, u16 idx) do { struct sky2_port *sky2; struct sky2_status_le *le = hw->st_le + hw->st_idx; - unsigned port = le->css & CSS_LINK_BIT; + unsigned port; struct net_device *dev; struct sk_buff *skb; u32 status; u16 length; + u8 opcode = le->opcode; + + if (!(opcode & HW_OWNER)) + break; hw->st_idx = RING_NEXT(hw->st_idx, STATUS_RING_SIZE); + port = le->css & CSS_LINK_BIT; dev = hw->dev[port]; sky2 = netdev_priv(dev); length = le16_to_cpu(le->length); status = le32_to_cpu(le->status); - switch (le->opcode & ~HW_OWNER) { + le->opcode = 0; + switch (opcode & ~HW_OWNER) { case OP_RXSTAT: ++rx[port]; skb = sky2_receive(dev, length, status); @@ -2353,7 +2352,7 @@ static int sky2_status_intr(struct sky2_hw *hw, int to_do, u16 idx) default: if (net_ratelimit()) printk(KERN_WARNING PFX - "unknown status opcode 0x%x\n", le->opcode); + "unknown status opcode 0x%x\n", opcode); } } while (hw->st_idx != idx); @@ -2428,24 +2427,26 @@ static void sky2_hw_intr(struct sky2_hw *hw) if (status & (Y2_IS_MST_ERR | Y2_IS_IRQ_STAT)) { u16 pci_err; - pci_read_config_word(pdev, PCI_STATUS, &pci_err); + pci_err = sky2_pci_read16(hw, PCI_STATUS); if (net_ratelimit()) dev_err(&pdev->dev, "PCI hardware error (0x%x)\n", pci_err); - pci_write_config_word(pdev, PCI_STATUS, + sky2_pci_write16(hw, PCI_STATUS, pci_err | PCI_STATUS_ERROR_BITS); } if (status & Y2_IS_PCI_EXP) { /* PCI-Express uncorrectable Error occurred */ - int pos = pci_find_aer_capability(hw->pdev); u32 err; - pci_read_config_dword(pdev, pos + PCI_ERR_UNCOR_STATUS, &err); + err = sky2_read32(hw, Y2_CFG_AER + PCI_ERR_UNCOR_STATUS); + sky2_write32(hw, Y2_CFG_AER + PCI_ERR_UNCOR_STATUS, + 0xfffffffful); if (net_ratelimit()) dev_err(&pdev->dev, "PCI Express error (0x%x)\n", err); - pci_cleanup_aer_uncorrect_error_status(pdev); + + sky2_read32(hw, Y2_CFG_AER + PCI_ERR_UNCOR_STATUS); } if (status & Y2_HWE_L1_MASK) @@ -2692,13 +2693,10 @@ static inline u32 sky2_clk2us(const struct sky2_hw *hw, u32 clk) static int __devinit sky2_init(struct sky2_hw *hw) { - int rc; u8 t8; /* Enable all clocks and check for bad PCI access */ - rc = pci_write_config_dword(hw->pdev, PCI_DEV_REG3, 0); - if (rc) - return rc; + sky2_pci_write32(hw, PCI_DEV_REG3, 0); sky2_write8(hw, B0_CTST, CS_RST_CLR); @@ -2791,24 +2789,25 @@ static void sky2_reset(struct sky2_hw *hw) sky2_write8(hw, B0_CTST, CS_RST_SET); sky2_write8(hw, B0_CTST, CS_RST_CLR); + /* allow writes to PCI config */ + sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_ON); + /* clear PCI errors, if any */ - pci_read_config_word(pdev, PCI_STATUS, &status); + status = sky2_pci_read16(hw, PCI_STATUS); status |= PCI_STATUS_ERROR_BITS; - pci_write_config_word(pdev, PCI_STATUS, status); + sky2_pci_write16(hw, PCI_STATUS, status); sky2_write8(hw, B0_CTST, CS_MRST_CLR); cap = pci_find_capability(pdev, PCI_CAP_ID_EXP); if (cap) { - /* Check for advanced error reporting */ - pci_cleanup_aer_uncorrect_error_status(pdev); - pci_cleanup_aer_correct_error_status(pdev); + sky2_write32(hw, Y2_CFG_AER + PCI_ERR_UNCOR_STATUS, + 0xfffffffful); /* If error bit is stuck on ignore it */ if (sky2_read32(hw, B0_HWE_ISRC) & Y2_IS_PCI_EXP) dev_info(&pdev->dev, "ignoring stuck error report bit\n"); - - else if (pci_enable_pcie_error_reporting(pdev)) + else hwe_mask |= Y2_IS_PCI_EXP; } @@ -3649,32 +3648,33 @@ static int sky2_set_tso(struct net_device *dev, u32 data) static int sky2_get_eeprom_len(struct net_device *dev) { struct sky2_port *sky2 = netdev_priv(dev); + struct sky2_hw *hw = sky2->hw; u16 reg2; - pci_read_config_word(sky2->hw->pdev, PCI_DEV_REG2, ®2); + reg2 = sky2_pci_read16(hw, PCI_DEV_REG2); return 1 << ( ((reg2 & PCI_VPD_ROM_SZ) >> 14) + 8); } -static u32 sky2_vpd_read(struct pci_dev *pdev, int cap, u16 offset) +static u32 sky2_vpd_read(struct sky2_hw *hw, int cap, u16 offset) { u32 val; - pci_write_config_word(pdev, cap + PCI_VPD_ADDR, offset); + sky2_pci_write16(hw, cap + PCI_VPD_ADDR, offset); do { - pci_read_config_word(pdev, cap + PCI_VPD_ADDR, &offset); + offset = sky2_pci_read16(hw, cap + PCI_VPD_ADDR); } while (!(offset & PCI_VPD_ADDR_F)); - pci_read_config_dword(pdev, cap + PCI_VPD_DATA, &val); + val = sky2_pci_read32(hw, cap + PCI_VPD_DATA); return val; } -static void sky2_vpd_write(struct pci_dev *pdev, int cap, u16 offset, u32 val) +static void sky2_vpd_write(struct sky2_hw *hw, int cap, u16 offset, u32 val) { - pci_write_config_word(pdev, cap + PCI_VPD_DATA, val); - pci_write_config_dword(pdev, cap + PCI_VPD_ADDR, offset | PCI_VPD_ADDR_F); + sky2_pci_write16(hw, cap + PCI_VPD_DATA, val); + sky2_pci_write32(hw, cap + PCI_VPD_ADDR, offset | PCI_VPD_ADDR_F); do { - pci_read_config_word(pdev, cap + PCI_VPD_ADDR, &offset); + offset = sky2_pci_read16(hw, cap + PCI_VPD_ADDR); } while (offset & PCI_VPD_ADDR_F); } @@ -3692,7 +3692,7 @@ static int sky2_get_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom eeprom->magic = SKY2_EEPROM_MAGIC; while (length > 0) { - u32 val = sky2_vpd_read(sky2->hw->pdev, cap, offset); + u32 val = sky2_vpd_read(sky2->hw, cap, offset); int n = min_t(int, length, sizeof(val)); memcpy(data, &val, n); @@ -3722,10 +3722,10 @@ static int sky2_set_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom int n = min_t(int, length, sizeof(val)); if (n < sizeof(val)) - val = sky2_vpd_read(sky2->hw->pdev, cap, offset); + val = sky2_vpd_read(sky2->hw, cap, offset); memcpy(&val, data, n); - sky2_vpd_write(sky2->hw->pdev, cap, offset, val); + sky2_vpd_write(sky2->hw, cap, offset, val); length -= n; data += n; @@ -3974,7 +3974,8 @@ static __devinit struct net_device *sky2_init_netdev(struct sky2_hw *hw, dev->tx_timeout = sky2_tx_timeout; dev->watchdog_timeo = TX_WATCHDOG; #ifdef CONFIG_NET_POLL_CONTROLLER - dev->poll_controller = sky2_netpoll; + if (port == 0) + dev->poll_controller = sky2_netpoll; #endif sky2 = netdev_priv(dev); @@ -3989,7 +3990,7 @@ static __devinit struct net_device *sky2_init_netdev(struct sky2_hw *hw, sky2->duplex = -1; sky2->speed = -1; sky2->advertising = sky2_supported_modes(hw); - sky2->rx_csum = 1; + sky2->rx_csum = (hw->chip_id != CHIP_ID_YUKON_XL); sky2->wol = wol; spin_lock_init(&sky2->phy_lock); @@ -4160,9 +4161,9 @@ static int __devinit sky2_probe(struct pci_dev *pdev, */ { u32 reg; - pci_read_config_dword(pdev,PCI_DEV_REG2, ®); + reg = sky2_pci_read32(hw, PCI_DEV_REG2); reg &= ~PCI_REV_DESC; - pci_write_config_dword(pdev, PCI_DEV_REG2, reg); + sky2_pci_write32(hw, PCI_DEV_REG2, reg); } #endif @@ -4353,7 +4354,7 @@ static int sky2_resume(struct pci_dev *pdev) if (hw->chip_id == CHIP_ID_YUKON_EX || hw->chip_id == CHIP_ID_YUKON_EC_U || hw->chip_id == CHIP_ID_YUKON_FE_P) - pci_write_config_dword(pdev, PCI_DEV_REG3, 0); + sky2_pci_write32(hw, PCI_DEV_REG3, 0); sky2_reset(hw); sky2_write32(hw, B0_IMSK, Y2_IS_BASE); diff --git a/drivers/net/sky2.h b/drivers/net/sky2.h index 49ee264..bc646a4 100644 --- a/drivers/net/sky2.h +++ b/drivers/net/sky2.h @@ -247,7 +247,8 @@ enum csr_regs { B3_PA_CTRL = 0x01f0, B3_PA_TEST = 0x01f2, - Y2_CFG_SPC = 0x1c00, + Y2_CFG_SPC = 0x1c00, /* PCI config space region */ + Y2_CFG_AER = 0x1d00, /* PCI Advanced Error Report region */ }; /* B0_CTST 16 bit Control/Status register */ @@ -2127,4 +2128,25 @@ static inline void gma_set_addr(struct sky2_hw *hw, unsigned port, unsigned reg, gma_write16(hw, port, reg+4,(u16) addr[2] | ((u16) addr[3] << 8)); gma_write16(hw, port, reg+8,(u16) addr[4] | ((u16) addr[5] << 8)); } + +/* PCI config space access */ +static inline u32 sky2_pci_read32(const struct sky2_hw *hw, unsigned reg) +{ + return sky2_read32(hw, Y2_CFG_SPC + reg); +} + +static inline u16 sky2_pci_read16(const struct sky2_hw *hw, unsigned reg) +{ + return sky2_read16(hw, Y2_CFG_SPC + reg); +} + +static inline void sky2_pci_write32(struct sky2_hw *hw, unsigned reg, u32 val) +{ + sky2_write32(hw, Y2_CFG_SPC + reg, val); +} + +static inline void sky2_pci_write16(struct sky2_hw *hw, unsigned reg, u16 val) +{ + sky2_write16(hw, Y2_CFG_SPC + reg, val); +} #endif diff --git a/drivers/net/slip.c b/drivers/net/slip.c index 335b7cc..251a3ce 100644 --- a/drivers/net/slip.c +++ b/drivers/net/slip.c @@ -1218,14 +1218,8 @@ static int slip_ioctl(struct tty_struct *tty, struct file *file, unsigned int cm return 0; /* VSV changes end */ #endif - - /* Allow stty to read, but not set, the serial port */ - case TCGETS: - case TCGETA: - return n_tty_ioctl(tty, file, cmd, arg); - default: - return -ENOIOCTLCMD; + return tty_mode_ioctl(tty, file, cmd, arg); } } diff --git a/drivers/net/smc911x.c b/drivers/net/smc911x.c index dd18af0..1a3d80b 100644 --- a/drivers/net/smc911x.c +++ b/drivers/net/smc911x.c @@ -428,7 +428,6 @@ static inline void smc911x_drop_pkt(struct net_device *dev) */ static inline void smc911x_rcv(struct net_device *dev) { - struct smc911x_local *lp = netdev_priv(dev); unsigned long ioaddr = dev->base_addr; unsigned int pkt_len, status; struct sk_buff *skb; @@ -473,6 +472,7 @@ static inline void smc911x_rcv(struct net_device *dev) skb_put(skb,pkt_len-4); #ifdef SMC_USE_DMA { + struct smc911x_local *lp = netdev_priv(dev); unsigned int fifo; /* Lower the FIFO threshold if possible */ fifo = SMC_GET_FIFO_INT(); @@ -1379,13 +1379,6 @@ static void smc911x_set_multicast_list(struct net_device *dev) unsigned int multicast_table[2]; unsigned int mcr, update_multicast = 0; unsigned long flags; - /* table for flipping the order of 5 bits */ - static const unsigned char invert5[] = - {0x00, 0x10, 0x08, 0x18, 0x04, 0x14, 0x0C, 0x1C, - 0x02, 0x12, 0x0A, 0x1A, 0x06, 0x16, 0x0E, 0x1E, - 0x01, 0x11, 0x09, 0x19, 0x05, 0x15, 0x0D, 0x1D, - 0x03, 0x13, 0x0B, 0x1B, 0x07, 0x17, 0x0F, 0x1F}; - DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", dev->name, __FUNCTION__); @@ -1432,7 +1425,7 @@ static void smc911x_set_multicast_list(struct net_device *dev) cur_addr = dev->mc_list; for (i = 0; i < dev->mc_count; i++, cur_addr = cur_addr->next) { - int position; + u32 position; /* do we have a pointer here? */ if (!cur_addr) @@ -1442,12 +1435,10 @@ static void smc911x_set_multicast_list(struct net_device *dev) if (!(*cur_addr->dmi_addr & 1)) continue; - /* only use the low order bits */ - position = crc32_le(~0, cur_addr->dmi_addr, 6) & 0x3f; + /* upper 6 bits are used as hash index */ + position = ether_crc(ETH_ALEN, cur_addr->dmi_addr)>>26; - /* do some messy swapping to put the bit in the right spot */ - multicast_table[invert5[position&0x1F]&0x1] |= - (1<<invert5[(position>>1)&0x1F]); + multicast_table[position>>5] |= 1 << (position&0x1f); } /* be sure I get rid of flags I might have set */ diff --git a/drivers/net/smc911x.h b/drivers/net/smc911x.h index 16a0edc..d04e4fa 100644 --- a/drivers/net/smc911x.h +++ b/drivers/net/smc911x.h @@ -37,7 +37,7 @@ #define SMC_USE_16BIT 0 #define SMC_USE_32BIT 1 #define SMC_IRQ_SENSE IRQF_TRIGGER_FALLING -#elif CONFIG_SH_MAGIC_PANEL_R2 +#elif defined(CONFIG_SH_MAGIC_PANEL_R2) #define SMC_USE_SH_DMA 0 #define SMC_USE_16BIT 0 #define SMC_USE_32BIT 1 diff --git a/drivers/net/smc91x.h b/drivers/net/smc91x.h index 729fd28..07b7f71 100644 --- a/drivers/net/smc91x.h +++ b/drivers/net/smc91x.h @@ -55,7 +55,7 @@ #define SMC_insw(a, r, p, l) readsw((a) + (r), p, l) #define SMC_outsw(a, r, p, l) writesw((a) + (r), p, l) -#elif defined(CONFIG_BFIN) +#elif defined(CONFIG_BLACKFIN) #define SMC_IRQ_FLAGS IRQF_TRIGGER_HIGH #define RPC_LSA_DEFAULT RPC_LED_100_10 @@ -224,6 +224,21 @@ SMC_outw(u16 val, void __iomem *ioaddr, int reg) } } +#elif defined(CONFIG_MACH_ZYLONITE) + +#define SMC_CAN_USE_8BIT 1 +#define SMC_CAN_USE_16BIT 1 +#define SMC_CAN_USE_32BIT 0 +#define SMC_IO_SHIFT 0 +#define SMC_NOWAIT 1 +#define SMC_USE_PXA_DMA 1 +#define SMC_inb(a, r) readb((a) + (r)) +#define SMC_inw(a, r) readw((a) + (r)) +#define SMC_insw(a, r, p, l) insw((a) + (r), p, l) +#define SMC_outsw(a, r, p, l) outsw((a) + (r), p, l) +#define SMC_outb(v, a, r) writeb(v, (a) + (r)) +#define SMC_outw(v, a, r) writew(v, (a) + (r)) + #elif defined(CONFIG_ARCH_OMAP) /* We can only do 16-bit reads and writes in the static memory space. */ diff --git a/drivers/net/sungem.c b/drivers/net/sungem.c index 53b8344..6887214 100644 --- a/drivers/net/sungem.c +++ b/drivers/net/sungem.c @@ -2281,14 +2281,12 @@ static void gem_reset_task(struct work_struct *work) mutex_lock(&gp->pm_mutex); - napi_disable(&gp->napi); + if (gp->opened) + napi_disable(&gp->napi); spin_lock_irq(&gp->lock); spin_lock(&gp->tx_lock); - if (gp->running == 0) - goto not_running; - if (gp->running) { netif_stop_queue(gp->dev); @@ -2298,13 +2296,14 @@ static void gem_reset_task(struct work_struct *work) gem_set_link_modes(gp); netif_wake_queue(gp->dev); } - not_running: + gp->reset_task_pending = 0; spin_unlock(&gp->tx_lock); spin_unlock_irq(&gp->lock); - napi_enable(&gp->napi); + if (gp->opened) + napi_enable(&gp->napi); mutex_unlock(&gp->pm_mutex); } @@ -2333,10 +2332,10 @@ static int gem_close(struct net_device *dev) { struct gem *gp = dev->priv; - napi_disable(&gp->napi); - mutex_lock(&gp->pm_mutex); + napi_disable(&gp->napi); + gp->opened = 0; if (!gp->asleep) gem_do_stop(dev, 0); @@ -2355,8 +2354,6 @@ static int gem_suspend(struct pci_dev *pdev, pm_message_t state) mutex_lock(&gp->pm_mutex); - napi_disable(&gp->napi); - printk(KERN_INFO "%s: suspending, WakeOnLan %s\n", dev->name, (gp->wake_on_lan && gp->opened) ? "enabled" : "disabled"); @@ -2370,6 +2367,8 @@ static int gem_suspend(struct pci_dev *pdev, pm_message_t state) /* If the driver is opened, we stop the MAC */ if (gp->opened) { + napi_disable(&gp->napi); + /* Stop traffic, mark us closed */ netif_device_detach(dev); @@ -2460,6 +2459,7 @@ static int gem_resume(struct pci_dev *pdev) /* Re-attach net device */ netif_device_attach(dev); + napi_enable(&gp->napi); } spin_lock_irqsave(&gp->lock, flags); @@ -2479,8 +2479,6 @@ static int gem_resume(struct pci_dev *pdev) spin_unlock(&gp->tx_lock); spin_unlock_irqrestore(&gp->lock, flags); - napi_enable(&gp->napi); - mutex_unlock(&gp->pm_mutex); return 0; diff --git a/drivers/net/sunhme.c b/drivers/net/sunhme.c index c20a3bd..9cc13dd 100644 --- a/drivers/net/sunhme.c +++ b/drivers/net/sunhme.c @@ -1281,7 +1281,7 @@ static void happy_meal_init_rings(struct happy_meal *hp) skb->dev = dev; /* Because we reserve afterwards. */ - skb_put(skb, (ETH_FRAME_LEN + RX_OFFSET)); + skb_put(skb, (ETH_FRAME_LEN + RX_OFFSET + 4)); hme_write_rxd(hp, &hb->happy_meal_rxd[i], (RXFLAG_OWN | ((RX_BUF_ALLOC_SIZE - RX_OFFSET) << 16)), hme_dma_map(hp, skb->data, RX_BUF_ALLOC_SIZE, DMA_FROMDEVICE)); @@ -1700,6 +1700,11 @@ static int happy_meal_init(struct happy_meal *hp) HMD(("tx old[%08x] and rx [%08x] ON!\n", hme_read32(hp, bregs + BMAC_TXCFG), hme_read32(hp, bregs + BMAC_RXCFG))); + + /* Set larger TX/RX size to allow for 802.1q */ + hme_write32(hp, bregs + BMAC_TXMAX, ETH_FRAME_LEN + 8); + hme_write32(hp, bregs + BMAC_RXMAX, ETH_FRAME_LEN + 8); + hme_write32(hp, bregs + BMAC_TXCFG, hme_read32(hp, bregs + BMAC_TXCFG) | BIGMAC_TXCFG_ENABLE); hme_write32(hp, bregs + BMAC_RXCFG, @@ -2039,7 +2044,7 @@ static void happy_meal_rx(struct happy_meal *hp, struct net_device *dev) hme_dma_unmap(hp, dma_addr, RX_BUF_ALLOC_SIZE, DMA_FROMDEVICE); hp->rx_skbs[elem] = new_skb; new_skb->dev = dev; - skb_put(new_skb, (ETH_FRAME_LEN + RX_OFFSET)); + skb_put(new_skb, (ETH_FRAME_LEN + RX_OFFSET + 4)); hme_write_rxd(hp, this, (RXFLAG_OWN|((RX_BUF_ALLOC_SIZE-RX_OFFSET)<<16)), hme_dma_map(hp, new_skb->data, RX_BUF_ALLOC_SIZE, DMA_FROMDEVICE)); @@ -2809,8 +2814,8 @@ static int __devinit happy_meal_sbus_probe_one(struct sbus_dev *sdev, int is_qfe dev->watchdog_timeo = 5*HZ; dev->ethtool_ops = &hme_ethtool_ops; - /* Happy Meal can do it all... except VLAN. */ - dev->features |= NETIF_F_SG | NETIF_F_HW_CSUM | NETIF_F_VLAN_CHALLENGED; + /* Happy Meal can do it all... */ + dev->features |= NETIF_F_SG | NETIF_F_HW_CSUM; dev->irq = sdev->irqs[0]; @@ -3143,8 +3148,8 @@ static int __devinit happy_meal_pci_probe(struct pci_dev *pdev, dev->irq = pdev->irq; dev->dma = 0; - /* Happy Meal can do it all... except VLAN. */ - dev->features |= NETIF_F_SG | NETIF_F_HW_CSUM | NETIF_F_VLAN_CHALLENGED; + /* Happy Meal can do it all... */ + dev->features |= NETIF_F_SG | NETIF_F_HW_CSUM; #if defined(CONFIG_SBUS) && defined(CONFIG_PCI) /* Hook up PCI register/dma accessors. */ diff --git a/drivers/net/tehuti.c b/drivers/net/tehuti.c index 4e1b84e..21230c9 100644 --- a/drivers/net/tehuti.c +++ b/drivers/net/tehuti.c @@ -2168,10 +2168,10 @@ bdx_get_drvinfo(struct net_device *netdev, struct ethtool_drvinfo *drvinfo) { struct bdx_priv *priv = netdev->priv; - strncat(drvinfo->driver, BDX_DRV_NAME, sizeof(drvinfo->driver)); - strncat(drvinfo->version, BDX_DRV_VERSION, sizeof(drvinfo->version)); - strncat(drvinfo->fw_version, "N/A", sizeof(drvinfo->fw_version)); - strncat(drvinfo->bus_info, pci_name(priv->pdev), + strlcat(drvinfo->driver, BDX_DRV_NAME, sizeof(drvinfo->driver)); + strlcat(drvinfo->version, BDX_DRV_VERSION, sizeof(drvinfo->version)); + strlcat(drvinfo->fw_version, "N/A", sizeof(drvinfo->fw_version)); + strlcat(drvinfo->bus_info, pci_name(priv->pdev), sizeof(drvinfo->bus_info)); drvinfo->n_stats = ((priv->stats_flag) ? diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index cad5199..4942f7d 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -64,8 +64,8 @@ #define DRV_MODULE_NAME "tg3" #define PFX DRV_MODULE_NAME ": " -#define DRV_MODULE_VERSION "3.85" -#define DRV_MODULE_RELDATE "October 18, 2007" +#define DRV_MODULE_VERSION "3.86" +#define DRV_MODULE_RELDATE "November 9, 2007" #define TG3_DEF_MAC_MODE 0 #define TG3_DEF_RX_MODE 0 @@ -1106,6 +1106,24 @@ static int tg3_phy_reset(struct tg3 *tp) if (err) return err; + if (tp->tg3_flags3 & TG3_FLG3_5761_5784_AX_FIXES) { + u32 val; + + val = tr32(TG3_CPMU_LSPD_1000MB_CLK); + if ((val & CPMU_LSPD_1000MB_MACCLK_MASK) == + CPMU_LSPD_1000MB_MACCLK_12_5) { + val &= ~CPMU_LSPD_1000MB_MACCLK_MASK; + udelay(40); + tw32_f(TG3_CPMU_LSPD_1000MB_CLK, val); + } + + /* Disable GPHY autopowerdown. */ + tg3_writephy(tp, MII_TG3_MISC_SHDW, + MII_TG3_MISC_SHDW_WREN | + MII_TG3_MISC_SHDW_APD_SEL | + MII_TG3_MISC_SHDW_APD_WKTM_84MS); + } + out: if (tp->tg3_flags2 & TG3_FLG2_PHY_ADC_BUG) { tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x0c00); @@ -1297,6 +1315,8 @@ static void tg3_nvram_unlock(struct tg3 *); static void tg3_power_down_phy(struct tg3 *tp) { + u32 val; + if (tp->tg3_flags2 & TG3_FLG2_PHY_SERDES) { if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704) { u32 sg_dig_ctrl = tr32(SG_DIG_CTRL); @@ -1311,8 +1331,6 @@ static void tg3_power_down_phy(struct tg3 *tp) } if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) { - u32 val; - tg3_bmcr_reset(tp); val = tr32(GRC_MISC_CFG); tw32_f(GRC_MISC_CFG, val | GRC_MISC_CFG_EPHY_IDDQ); @@ -1332,6 +1350,14 @@ static void tg3_power_down_phy(struct tg3 *tp) (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5780 && (tp->tg3_flags2 & TG3_FLG2_MII_SERDES))) return; + + if (tp->tg3_flags3 & TG3_FLG3_5761_5784_AX_FIXES) { + val = tr32(TG3_CPMU_LSPD_1000MB_CLK); + val &= ~CPMU_LSPD_1000MB_MACCLK_MASK; + val |= CPMU_LSPD_1000MB_MACCLK_12_5; + tw32_f(TG3_CPMU_LSPD_1000MB_CLK, val); + } + tg3_writephy(tp, MII_BMCR, BMCR_PDOWN); } @@ -3126,6 +3152,23 @@ static int tg3_setup_phy(struct tg3 *tp, int force_reset) err = tg3_setup_copper_phy(tp, force_reset); } + if (tp->pci_chip_rev_id == CHIPREV_ID_5784_A0 || + tp->pci_chip_rev_id == CHIPREV_ID_5784_A1) { + u32 val, scale; + + val = tr32(TG3_CPMU_CLCK_STAT) & CPMU_CLCK_STAT_MAC_CLCK_MASK; + if (val == CPMU_CLCK_STAT_MAC_CLCK_62_5) + scale = 65; + else if (val == CPMU_CLCK_STAT_MAC_CLCK_6_25) + scale = 6; + else + scale = 12; + + val = tr32(GRC_MISC_CFG) & ~GRC_MISC_CFG_PRESCALAR_MASK; + val |= (scale << GRC_MISC_CFG_PRESCALAR_SHIFT); + tw32(GRC_MISC_CFG, val); + } + if (tp->link_config.active_speed == SPEED_1000 && tp->link_config.active_duplex == DUPLEX_HALF) tw32(MAC_TX_LENGTHS, @@ -5054,12 +5097,15 @@ static void tg3_restore_pci_state(struct tg3 *tp) pci_write_config_word(tp->pdev, PCI_COMMAND, tp->pci_cmd); - if (!(tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS)) { + if (tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS) + pcie_set_readrq(tp->pdev, 4096); + else { pci_write_config_byte(tp->pdev, PCI_CACHE_LINE_SIZE, tp->pci_cacheline_sz); pci_write_config_byte(tp->pdev, PCI_LATENCY_TIMER, tp->pci_lat_timer); } + /* Make sure PCI-X relaxed ordering bit is clear. */ if (tp->pcix_cap) { u16 pcix_cmd; @@ -6343,10 +6389,26 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) tg3_write_sig_legacy(tp, RESET_KIND_INIT); - if (tp->pci_chip_rev_id == CHIPREV_ID_5784_A0) { + if (tp->pci_chip_rev_id == CHIPREV_ID_5784_A0 || + tp->pci_chip_rev_id == CHIPREV_ID_5784_A1) { val = tr32(TG3_CPMU_CTRL); val &= ~(CPMU_CTRL_LINK_AWARE_MODE | CPMU_CTRL_LINK_IDLE_MODE); tw32(TG3_CPMU_CTRL, val); + + val = tr32(TG3_CPMU_LSPD_10MB_CLK); + val &= ~CPMU_LSPD_10MB_MACCLK_MASK; + val |= CPMU_LSPD_10MB_MACCLK_6_25; + tw32(TG3_CPMU_LSPD_10MB_CLK, val); + + val = tr32(TG3_CPMU_LNK_AWARE_PWRMD); + val &= ~CPMU_LNK_AWARE_MACCLK_MASK; + val |= CPMU_LNK_AWARE_MACCLK_6_25; + tw32(TG3_CPMU_LNK_AWARE_PWRMD, val); + + val = tr32(TG3_CPMU_HST_ACC); + val &= ~CPMU_HST_ACC_MACCLK_MASK; + val |= CPMU_HST_ACC_MACCLK_6_25; + tw32(TG3_CPMU_HST_ACC, val); } /* This works around an issue with Athlon chipsets on @@ -8267,7 +8329,7 @@ static int tg3_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) SUPPORTED_100baseT_Full | SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full | - SUPPORTED_MII); + SUPPORTED_TP); cmd->port = PORT_TP; } else { cmd->supported |= SUPPORTED_FIBRE; @@ -8664,7 +8726,9 @@ static void tg3_get_ethtool_stats (struct net_device *dev, } #define NVRAM_TEST_SIZE 0x100 -#define NVRAM_SELFBOOT_FORMAT1_SIZE 0x14 +#define NVRAM_SELFBOOT_FORMAT1_0_SIZE 0x14 +#define NVRAM_SELFBOOT_FORMAT1_2_SIZE 0x18 +#define NVRAM_SELFBOOT_FORMAT1_3_SIZE 0x1c #define NVRAM_SELFBOOT_HW_SIZE 0x20 #define NVRAM_SELFBOOT_DATA_SIZE 0x1c @@ -8679,9 +8743,22 @@ static int tg3_test_nvram(struct tg3 *tp) if (magic == TG3_EEPROM_MAGIC) size = NVRAM_TEST_SIZE; else if ((magic & TG3_EEPROM_MAGIC_FW_MSK) == TG3_EEPROM_MAGIC_FW) { - if ((magic & 0xe00000) == 0x200000) - size = NVRAM_SELFBOOT_FORMAT1_SIZE; - else + if ((magic & TG3_EEPROM_SB_FORMAT_MASK) == + TG3_EEPROM_SB_FORMAT_1) { + switch (magic & TG3_EEPROM_SB_REVISION_MASK) { + case TG3_EEPROM_SB_REVISION_0: + size = NVRAM_SELFBOOT_FORMAT1_0_SIZE; + break; + case TG3_EEPROM_SB_REVISION_2: + size = NVRAM_SELFBOOT_FORMAT1_2_SIZE; + break; + case TG3_EEPROM_SB_REVISION_3: + size = NVRAM_SELFBOOT_FORMAT1_3_SIZE; + break; + default: + return 0; + } + } else return 0; } else if ((magic & TG3_EEPROM_MAGIC_HW_MSK) == TG3_EEPROM_MAGIC_HW) size = NVRAM_SELFBOOT_HW_SIZE; @@ -8708,8 +8785,17 @@ static int tg3_test_nvram(struct tg3 *tp) TG3_EEPROM_MAGIC_FW) { u8 *buf8 = (u8 *) buf, csum8 = 0; - for (i = 0; i < size; i++) - csum8 += buf8[i]; + if ((cpu_to_be32(buf[0]) & TG3_EEPROM_SB_REVISION_MASK) == + TG3_EEPROM_SB_REVISION_2) { + /* For rev 2, the csum doesn't include the MBA. */ + for (i = 0; i < TG3_EEPROM_SB_F1R2_MBA_OFF; i++) + csum8 += buf8[i]; + for (i = TG3_EEPROM_SB_F1R2_MBA_OFF + 4; i < size; i++) + csum8 += buf8[i]; + } else { + for (i = 0; i < size; i++) + csum8 += buf8[i]; + } if (csum8 == 0) { err = 0; @@ -9293,7 +9379,7 @@ static int tg3_test_loopback(struct tg3 *tp) if (err) return TG3_LOOPBACK_FAILED; - if (tp->tg3_flags & TG3_FLAG_CPMU_PRESENT) { + if (tp->tg3_flags3 & TG3_FLG3_5761_5784_AX_FIXES) { int i; u32 status; @@ -9310,17 +9396,17 @@ static int tg3_test_loopback(struct tg3 *tp) if (status != CPMU_MUTEX_GNT_DRIVER) return TG3_LOOPBACK_FAILED; - cpmuctrl = tr32(TG3_CPMU_CTRL); - /* Turn off power management based on link speed. */ + cpmuctrl = tr32(TG3_CPMU_CTRL); tw32(TG3_CPMU_CTRL, - cpmuctrl & ~CPMU_CTRL_LINK_SPEED_MODE); + cpmuctrl & ~(CPMU_CTRL_LINK_SPEED_MODE | + CPMU_CTRL_LINK_AWARE_MODE)); } if (tg3_run_loopback(tp, TG3_MAC_LOOPBACK)) err |= TG3_MAC_LOOPBACK_FAILED; - if (tp->tg3_flags & TG3_FLAG_CPMU_PRESENT) { + if (tp->tg3_flags3 & TG3_FLG3_5761_5784_AX_FIXES) { tw32(TG3_CPMU_CTRL, cpmuctrl); /* Release the mutex */ @@ -10541,6 +10627,10 @@ static void __devinit tg3_get_eeprom_hw_cfg(struct tg3 *tp) tp->pdev->subsystem_vendor == PCI_VENDOR_ID_DELL) tp->led_ctrl = LED_CTRL_MODE_PHY_2; + if (tp->pci_chip_rev_id == CHIPREV_ID_5784_A0 || + tp->pci_chip_rev_id == CHIPREV_ID_5784_A1) + tp->led_ctrl = LED_CTRL_MODE_MAC; + if (nic_cfg & NIC_SRAM_DATA_CFG_EEPROM_WP) { tp->tg3_flags |= TG3_FLAG_EEPROM_WRITE_PROT; if ((tp->pdev->subsystem_vendor == @@ -10859,7 +10949,7 @@ static void __devinit tg3_read_fw_ver(struct tg3 *tp) } if (!(tp->tg3_flags & TG3_FLAG_ENABLE_ASF) || - (tp->tg3_flags & TG3_FLG3_ENABLE_APE)) + (tp->tg3_flags3 & TG3_FLG3_ENABLE_APE)) return; for (offset = TG3_NVM_DIR_START; @@ -11127,6 +11217,9 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) pcie_cap = pci_find_capability(tp->pdev, PCI_CAP_ID_EXP); if (pcie_cap != 0) { tp->tg3_flags2 |= TG3_FLG2_PCI_EXPRESS; + + pcie_set_readrq(tp->pdev, 4096); + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) { u16 lnkctl; @@ -11307,9 +11400,16 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) } if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784 || - GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761) + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761) { tp->tg3_flags |= TG3_FLAG_CPMU_PRESENT; + if (tp->pci_chip_rev_id == CHIPREV_ID_5784_A0 || + tp->pci_chip_rev_id == CHIPREV_ID_5784_A1 || + tp->pci_chip_rev_id == CHIPREV_ID_5761_A0 || + tp->pci_chip_rev_id == CHIPREV_ID_5761_A1) + tp->tg3_flags3 |= TG3_FLG3_5761_5784_AX_FIXES; + } + /* Set up tp->grc_local_ctrl before calling tg3_set_power_state(). * GPIO1 driven high will bring 5700's external PHY out of reset. * It is also used as eeprom write protect on LOMs. @@ -12464,6 +12564,28 @@ static int __devinit tg3_init_one(struct pci_dev *pdev, goto err_out_iounmap; } + if (tp->tg3_flags3 & TG3_FLG3_ENABLE_APE) { + if (!(pci_resource_flags(pdev, 2) & IORESOURCE_MEM)) { + printk(KERN_ERR PFX "Cannot find proper PCI device " + "base address for APE, aborting.\n"); + err = -ENODEV; + goto err_out_iounmap; + } + + tg3reg_base = pci_resource_start(pdev, 2); + tg3reg_len = pci_resource_len(pdev, 2); + + tp->aperegs = ioremap_nocache(tg3reg_base, tg3reg_len); + if (tp->aperegs == 0UL) { + printk(KERN_ERR PFX "Cannot map APE registers, " + "aborting.\n"); + err = -ENOMEM; + goto err_out_iounmap; + } + + tg3_ape_lock_init(tp); + } + /* * Reset chip in case UNDI or EFI driver did not shutdown * DMA self test will enable WDMAC and we'll see (spurious) @@ -12478,7 +12600,7 @@ static int __devinit tg3_init_one(struct pci_dev *pdev, err = tg3_test_dma(tp); if (err) { printk(KERN_ERR PFX "DMA engine test failed, aborting.\n"); - goto err_out_iounmap; + goto err_out_apeunmap; } /* Tigon3 can do ipv4 only... and some chips have buggy @@ -12501,28 +12623,6 @@ static int __devinit tg3_init_one(struct pci_dev *pdev, tg3_init_coal(tp); - if (tp->tg3_flags3 & TG3_FLG3_ENABLE_APE) { - if (!(pci_resource_flags(pdev, 2) & IORESOURCE_MEM)) { - printk(KERN_ERR PFX "Cannot find proper PCI device " - "base address for APE, aborting.\n"); - err = -ENODEV; - goto err_out_iounmap; - } - - tg3reg_base = pci_resource_start(pdev, 2); - tg3reg_len = pci_resource_len(pdev, 2); - - tp->aperegs = ioremap_nocache(tg3reg_base, tg3reg_len); - if (tp->aperegs == 0UL) { - printk(KERN_ERR PFX "Cannot map APE registers, " - "aborting.\n"); - err = -ENOMEM; - goto err_out_iounmap; - } - - tg3_ape_lock_init(tp); - } - pci_set_drvdata(pdev, dev); err = register_netdev(dev); diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h index 1d5b2a3..da18fb2 100644 --- a/drivers/net/tg3.h +++ b/drivers/net/tg3.h @@ -109,6 +109,9 @@ #define CHIPREV_ID_5714_A2 0x9002 #define CHIPREV_ID_5906_A1 0xc001 #define CHIPREV_ID_5784_A0 0x5784000 +#define CHIPREV_ID_5784_A1 0x5784001 +#define CHIPREV_ID_5761_A0 0x5761000 +#define CHIPREV_ID_5761_A1 0x5761001 #define GET_ASIC_REV(CHIP_REV_ID) ((CHIP_REV_ID) >> 12) #define ASIC_REV_5700 0x07 #define ASIC_REV_5701 0x00 @@ -856,7 +859,31 @@ #define CPMU_CTRL_LINK_IDLE_MODE 0x00000200 #define CPMU_CTRL_LINK_AWARE_MODE 0x00000400 #define CPMU_CTRL_LINK_SPEED_MODE 0x00004000 -/* 0x3604 --> 0x365c unused */ +#define TG3_CPMU_LSPD_10MB_CLK 0x00003604 +#define CPMU_LSPD_10MB_MACCLK_MASK 0x001f0000 +#define CPMU_LSPD_10MB_MACCLK_6_25 0x00130000 +/* 0x3608 --> 0x360c unused */ + +#define TG3_CPMU_LSPD_1000MB_CLK 0x0000360c +#define CPMU_LSPD_1000MB_MACCLK_62_5 0x00000000 +#define CPMU_LSPD_1000MB_MACCLK_12_5 0x00110000 +#define CPMU_LSPD_1000MB_MACCLK_MASK 0x001f0000 +#define TG3_CPMU_LNK_AWARE_PWRMD 0x00003610 +#define CPMU_LNK_AWARE_MACCLK_MASK 0x001f0000 +#define CPMU_LNK_AWARE_MACCLK_6_25 0x00130000 +/* 0x3614 --> 0x361c unused */ + +#define TG3_CPMU_HST_ACC 0x0000361c +#define CPMU_HST_ACC_MACCLK_MASK 0x001f0000 +#define CPMU_HST_ACC_MACCLK_6_25 0x00130000 +/* 0x3620 --> 0x3630 unused */ + +#define TG3_CPMU_CLCK_STAT 0x00003630 +#define CPMU_CLCK_STAT_MAC_CLCK_MASK 0x001f0000 +#define CPMU_CLCK_STAT_MAC_CLCK_62_5 0x00000000 +#define CPMU_CLCK_STAT_MAC_CLCK_12_5 0x00110000 +#define CPMU_CLCK_STAT_MAC_CLCK_6_25 0x00130000 +/* 0x3634 --> 0x365c unused */ #define TG3_CPMU_MUTEX_REQ 0x0000365c #define CPMU_MUTEX_REQ_DRIVER 0x00001000 @@ -1537,6 +1564,12 @@ #define TG3_EEPROM_MAGIC 0x669955aa #define TG3_EEPROM_MAGIC_FW 0xa5000000 #define TG3_EEPROM_MAGIC_FW_MSK 0xff000000 +#define TG3_EEPROM_SB_FORMAT_MASK 0x00e00000 +#define TG3_EEPROM_SB_FORMAT_1 0x00200000 +#define TG3_EEPROM_SB_REVISION_MASK 0x001f0000 +#define TG3_EEPROM_SB_REVISION_0 0x00000000 +#define TG3_EEPROM_SB_REVISION_2 0x00020000 +#define TG3_EEPROM_SB_REVISION_3 0x00030000 #define TG3_EEPROM_MAGIC_HW 0xabcd #define TG3_EEPROM_MAGIC_HW_MSK 0xffff @@ -1691,6 +1724,12 @@ #define MII_TG3_ISTAT 0x1a /* IRQ status register */ #define MII_TG3_IMASK 0x1b /* IRQ mask register */ +#define MII_TG3_MISC_SHDW 0x1c +#define MII_TG3_MISC_SHDW_WREN 0x8000 +#define MII_TG3_MISC_SHDW_APD_SEL 0x2800 + +#define MII_TG3_MISC_SHDW_APD_WKTM_84MS 0x0001 + /* ISTAT/IMASK event bits */ #define MII_TG3_INT_LINKCHG 0x0002 #define MII_TG3_INT_SPEEDCHG 0x0004 @@ -1747,6 +1786,8 @@ /* APE convenience enumerations. */ #define TG3_APE_LOCK_MEM 4 +#define TG3_EEPROM_SB_F1R2_MBA_OFF 0x10 + /* There are two ways to manage the TX descriptors on the tigon3. * Either the descriptors are in host DMA'able memory, or they @@ -2352,6 +2393,7 @@ struct tg3 { u32 tg3_flags3; #define TG3_FLG3_NO_NVRAM_ADDR_TRANS 0x00000001 #define TG3_FLG3_ENABLE_APE 0x00000002 +#define TG3_FLG3_5761_5784_AX_FIXES 0x00000004 struct timer_list timer; u16 timer_counter; diff --git a/drivers/net/tulip/Kconfig b/drivers/net/tulip/Kconfig index 49d7a29..20ac150 100644 --- a/drivers/net/tulip/Kconfig +++ b/drivers/net/tulip/Kconfig @@ -24,8 +24,7 @@ config DE2104X will say Y here.) Do read the Ethernet-HOWTO, available from <http://www.tldp.org/docs.html#howto>. - To compile this driver as a module, choose M here and read - <file:Documentation/networking/net-modules.txt>. The module will + To compile this driver as a module, choose M here. The module will be called de2104x. config TULIP @@ -42,8 +41,7 @@ config TULIP will say Y here.) Do read the Ethernet-HOWTO, available from <http://www.tldp.org/docs.html#howto>. - To compile this driver as a module, choose M here and read - <file:Documentation/networking/net-modules.txt>. The module will + To compile this driver as a module, choose M here. The module will be called tulip. config TULIP_MWI @@ -104,8 +102,7 @@ config DE4X5 information is contained in <file:Documentation/networking/de4x5.txt>. - To compile this driver as a module, choose M here and read - <file:Documentation/networking/net-modules.txt>. The module will + To compile this driver as a module, choose M here. The module will be called de4x5. config WINBOND_840 @@ -129,8 +126,7 @@ config DM9102 (Ethernet) card, say Y. Some information is contained in the file <file:Documentation/networking/dmfe.txt>. - To compile this driver as a module, choose M here and read - <file:Documentation/networking/net-modules.txt>. The module will + To compile this driver as a module, choose M here. The module will be called dmfe. config ULI526X @@ -141,8 +137,7 @@ config ULI526X This driver is for ULi M5261/M5263 10/100M Ethernet Controller (<http://www.uli.com.tw/>). - To compile this driver as a module, choose M here and read - <file:Documentation/networking/net-modules.txt>. The module will + To compile this driver as a module, choose M here. The module will be called uli526x. config PCMCIA_XIRCOM @@ -154,8 +149,7 @@ config PCMCIA_XIRCOM as with work-alike chips from Lite-On (PNIC) and Macronix (MXIC) and ASIX. - To compile this driver as a module, choose M here and read - <file:Documentation/networking/net-modules.txt>. The module will + To compile this driver as a module, choose M here. The module will be called xircom_cb. If unsure, say N. config PCMCIA_XIRTULIP @@ -168,8 +162,7 @@ config PCMCIA_XIRTULIP as with work-alike chips from Lite-On (PNIC) and Macronix (MXIC) and ASIX. - To compile this driver as a module, choose M here and read - <file:Documentation/networking/net-modules.txt>. The module will + To compile this driver as a module, choose M here. The module will be called xircom_tulip_cb. If unsure, say N. endif # NET_TULIP diff --git a/drivers/net/tulip/dmfe.c b/drivers/net/tulip/dmfe.c index ca90566..b4891ca 100644 --- a/drivers/net/tulip/dmfe.c +++ b/drivers/net/tulip/dmfe.c @@ -2118,8 +2118,8 @@ static int dmfe_suspend(struct pci_dev *pci_dev, pm_message_t state) pci_enable_wake(pci_dev, PCI_D3cold, 1); /* Power down device*/ - pci_set_power_state(pci_dev, pci_choose_state (pci_dev,state)); pci_save_state(pci_dev); + pci_set_power_state(pci_dev, pci_choose_state (pci_dev, state)); return 0; } @@ -2129,8 +2129,8 @@ static int dmfe_resume(struct pci_dev *pci_dev) struct net_device *dev = pci_get_drvdata(pci_dev); u32 tmp; - pci_restore_state(pci_dev); pci_set_power_state(pci_dev, PCI_D0); + pci_restore_state(pci_dev); /* Re-initilize DM910X board */ dmfe_init_dm910x(dev); diff --git a/drivers/net/ucc_geth.c b/drivers/net/ucc_geth.c index a3ff270..7f68990 100644 --- a/drivers/net/ucc_geth.c +++ b/drivers/net/ucc_geth.c @@ -1460,6 +1460,8 @@ static int adjust_enet_interface(struct ucc_geth_private *ugeth) if ((ugeth->phy_interface == PHY_INTERFACE_MODE_RMII) || (ugeth->phy_interface == PHY_INTERFACE_MODE_RGMII) || (ugeth->phy_interface == PHY_INTERFACE_MODE_RGMII_ID) || + (ugeth->phy_interface == PHY_INTERFACE_MODE_RGMII_RXID) || + (ugeth->phy_interface == PHY_INTERFACE_MODE_RGMII_TXID) || (ugeth->phy_interface == PHY_INTERFACE_MODE_RTBI)) { upsmr |= UPSMR_RPM; switch (ugeth->max_speed) { @@ -1557,6 +1559,8 @@ static void adjust_link(struct net_device *dev) if ((ugeth->phy_interface == PHY_INTERFACE_MODE_RMII) || (ugeth->phy_interface == PHY_INTERFACE_MODE_RGMII) || (ugeth->phy_interface == PHY_INTERFACE_MODE_RGMII_ID) || + (ugeth->phy_interface == PHY_INTERFACE_MODE_RGMII_RXID) || + (ugeth->phy_interface == PHY_INTERFACE_MODE_RGMII_TXID) || (ugeth->phy_interface == PHY_INTERFACE_MODE_RTBI)) { if (phydev->speed == SPEED_10) upsmr |= UPSMR_R10M; @@ -3795,6 +3799,10 @@ static phy_interface_t to_phy_interface(const char *phy_connection_type) return PHY_INTERFACE_MODE_RGMII; if (strcasecmp(phy_connection_type, "rgmii-id") == 0) return PHY_INTERFACE_MODE_RGMII_ID; + if (strcasecmp(phy_connection_type, "rgmii-txid") == 0) + return PHY_INTERFACE_MODE_RGMII_TXID; + if (strcasecmp(phy_connection_type, "rgmii-rxid") == 0) + return PHY_INTERFACE_MODE_RGMII_RXID; if (strcasecmp(phy_connection_type, "rtbi") == 0) return PHY_INTERFACE_MODE_RTBI; @@ -3889,6 +3897,8 @@ static int ucc_geth_probe(struct of_device* ofdev, const struct of_device_id *ma case PHY_INTERFACE_MODE_GMII: case PHY_INTERFACE_MODE_RGMII: case PHY_INTERFACE_MODE_RGMII_ID: + case PHY_INTERFACE_MODE_RGMII_RXID: + case PHY_INTERFACE_MODE_RGMII_TXID: case PHY_INTERFACE_MODE_TBI: case PHY_INTERFACE_MODE_RTBI: max_speed = SPEED_1000; diff --git a/drivers/net/usb/Kconfig b/drivers/net/usb/Kconfig index 5a96d74..a12c9c4 100644 --- a/drivers/net/usb/Kconfig +++ b/drivers/net/usb/Kconfig @@ -93,13 +93,9 @@ config USB_RTL8150 To compile this driver as a module, choose M here: the module will be called rtl8150. -config USB_USBNET_MII - tristate - default n - config USB_USBNET tristate "Multi-purpose USB Networking Framework" - select MII if USB_USBNET_MII != n + select MII ---help--- This driver supports several kinds of network links over USB, with "minidrivers" built around a common network driver core @@ -135,7 +131,6 @@ config USB_NET_AX8817X tristate "ASIX AX88xxx Based USB 2.0 Ethernet Adapters" depends on USB_USBNET && NET_ETHERNET select CRC32 - select USB_USBNET_MII default y help This option adds support for ASIX AX88xxx based USB 2.0 @@ -190,7 +185,6 @@ config USB_NET_DM9601 tristate "Davicom DM9601 based USB 1.1 10/100 ethernet devices" depends on USB_USBNET select CRC32 - select USB_USBNET_MII help This option adds support for Davicom DM9601 based USB 1.1 10/100 Ethernet adapters. @@ -225,7 +219,6 @@ config USB_NET_PLUSB config USB_NET_MCS7830 tristate "MosChip MCS7830 based Ethernet adapters" depends on USB_USBNET - select USB_USBNET_MII help Choose this option if you're using a 10/100 Ethernet USB2 adapter based on the MosChip 7830 controller. This includes diff --git a/drivers/net/usb/dm9601.c b/drivers/net/usb/dm9601.c index 2c68573..1ffdd10 100644 --- a/drivers/net/usb/dm9601.c +++ b/drivers/net/usb/dm9601.c @@ -94,7 +94,7 @@ static void dm_write_async_callback(struct urb *urb) struct usb_ctrlrequest *req = (struct usb_ctrlrequest *)urb->context; if (urb->status < 0) - printk(KERN_DEBUG "dm_write_async_callback() failed with %d", + printk(KERN_DEBUG "dm_write_async_callback() failed with %d\n", urb->status); kfree(req); diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c index acd5f1c..8ed1fc5 100644 --- a/drivers/net/usb/usbnet.c +++ b/drivers/net/usb/usbnet.c @@ -683,9 +683,6 @@ done_nopm: * they'll probably want to use this base set. */ -#if defined(CONFIG_MII) || defined(CONFIG_MII_MODULE) -#define HAVE_MII - int usbnet_get_settings (struct net_device *net, struct ethtool_cmd *cmd) { struct usbnet *dev = netdev_priv(net); @@ -744,8 +741,6 @@ int usbnet_nway_reset(struct net_device *net) } EXPORT_SYMBOL_GPL(usbnet_nway_reset); -#endif /* HAVE_MII */ - void usbnet_get_drvinfo (struct net_device *net, struct ethtool_drvinfo *info) { struct usbnet *dev = netdev_priv(net); @@ -776,12 +771,10 @@ EXPORT_SYMBOL_GPL(usbnet_set_msglevel); /* drivers may override default ethtool_ops in their bind() routine */ static struct ethtool_ops usbnet_ethtool_ops = { -#ifdef HAVE_MII .get_settings = usbnet_get_settings, .set_settings = usbnet_set_settings, .get_link = usbnet_get_link, .nway_reset = usbnet_nway_reset, -#endif .get_drvinfo = usbnet_get_drvinfo, .get_msglevel = usbnet_get_msglevel, .set_msglevel = usbnet_set_msglevel, diff --git a/drivers/net/via-velocity.c b/drivers/net/via-velocity.c index 5c4a92d..35cd65d 100644 --- a/drivers/net/via-velocity.c +++ b/drivers/net/via-velocity.c @@ -1242,6 +1242,9 @@ static int velocity_rx_refill(struct velocity_info *vptr) static int velocity_init_rd_ring(struct velocity_info *vptr) { int ret; + int mtu = vptr->dev->mtu; + + vptr->rx_buf_sz = (mtu <= ETH_DATA_LEN) ? PKT_BUF_SZ : mtu + 32; vptr->rd_info = kcalloc(vptr->options.numrx, sizeof(struct velocity_rd_info), GFP_KERNEL); @@ -1898,8 +1901,6 @@ static int velocity_open(struct net_device *dev) struct velocity_info *vptr = netdev_priv(dev); int ret; - vptr->rx_buf_sz = (dev->mtu <= 1504 ? PKT_BUF_SZ : dev->mtu + 32); - ret = velocity_init_rings(vptr); if (ret < 0) goto out; @@ -1963,6 +1964,11 @@ static int velocity_change_mtu(struct net_device *dev, int new_mtu) return -EINVAL; } + if (!netif_running(dev)) { + dev->mtu = new_mtu; + return 0; + } + if (new_mtu != oldmtu) { spin_lock_irqsave(&vptr->lock, flags); @@ -1973,12 +1979,6 @@ static int velocity_change_mtu(struct net_device *dev, int new_mtu) velocity_free_rd_ring(vptr); dev->mtu = new_mtu; - if (new_mtu > 8192) - vptr->rx_buf_sz = 9 * 1024; - else if (new_mtu > 4096) - vptr->rx_buf_sz = 8192; - else - vptr->rx_buf_sz = 4 * 1024; ret = velocity_init_rd_ring(vptr); if (ret < 0) diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index e396c9d..5413dbf 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c @@ -146,6 +146,7 @@ static void try_fill_recv(struct virtnet_info *vi) struct scatterlist sg[1+MAX_SKB_FRAGS]; int num, err; + sg_init_table(sg, 1+MAX_SKB_FRAGS); for (;;) { skb = netdev_alloc_skb(vi->dev, MAX_PACKET_LEN); if (unlikely(!skb)) @@ -197,8 +198,8 @@ again: if (vi->num < vi->max / 2) try_fill_recv(vi); - /* All done? */ - if (!skb) { + /* Out of packets? */ + if (received < budget) { netif_rx_complete(vi->dev, napi); if (unlikely(!vi->rvq->vq_ops->restart(vi->rvq)) && netif_rx_reschedule(vi->dev, napi)) @@ -231,6 +232,8 @@ static int start_xmit(struct sk_buff *skb, struct net_device *dev) const unsigned char *dest = ((struct ethhdr *)skb->data)->h_dest; DECLARE_MAC_BUF(mac); + sg_init_table(sg, 1+MAX_SKB_FRAGS); + pr_debug("%s: xmit %p %s\n", dev->name, skb, print_mac(mac, dest)); free_old_xmit_skbs(vi); @@ -401,8 +404,12 @@ free: static void virtnet_remove(struct virtio_device *vdev) { - unregister_netdev(vdev->priv); - free_netdev(vdev->priv); + struct virtnet_info *vi = vdev->priv; + + vdev->config->del_vq(vi->svq); + vdev->config->del_vq(vi->rvq); + unregister_netdev(vi->dev); + free_netdev(vi->dev); } static struct virtio_device_id id_table[] = { diff --git a/drivers/net/wan/x25_asy.c b/drivers/net/wan/x25_asy.c index c48b1cc..1e89d4d 100644 --- a/drivers/net/wan/x25_asy.c +++ b/drivers/net/wan/x25_asy.c @@ -719,12 +719,8 @@ static int x25_asy_ioctl(struct tty_struct *tty, struct file *file, return 0; case SIOCSIFHWADDR: return -EINVAL; - /* Allow stty to read, but not set, the serial port */ - case TCGETS: - case TCGETA: - return n_tty_ioctl(tty, file, cmd, arg); default: - return -ENOIOCTLCMD; + return tty_mode_ioctl(tty, file, cmd, arg); } } diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig index dae5c8d..2b733c5 100644 --- a/drivers/net/wireless/Kconfig +++ b/drivers/net/wireless/Kconfig @@ -325,7 +325,7 @@ config HERMES Cabletron/EnteraSys Roamabout, ELSA AirLancer, MELCO Buffalo, Avaya, IBM High Rate Wireless, Farralon Syyline, Samsung MagicLAN, Netgear MA401, LinkSys WPC-11, D-Link DWL-650, 3Com AirConnect, Intel - PRO/Wireless, and Symbol Spectrum24 High Rate amongst others. + IPW2011, and Symbol Spectrum24 High Rate amongst others. This option includes the guts of the driver, but in order to actually use a card you will also need to enable support for PCMCIA diff --git a/drivers/net/wireless/b43/Kconfig b/drivers/net/wireless/b43/Kconfig index e3c573e..fdbc351 100644 --- a/drivers/net/wireless/b43/Kconfig +++ b/drivers/net/wireless/b43/Kconfig @@ -61,16 +61,18 @@ config B43_PCMCIA If unsure, say N. -# LED support +# This config option automatically enables b43 LEDS support, +# if it's possible. config B43_LEDS bool - depends on B43 && MAC80211_LEDS + depends on B43 && MAC80211_LEDS && (LEDS_CLASS = y || LEDS_CLASS = B43) default y -# RFKILL support +# This config option automatically enables b43 RFKILL support, +# if it's possible. config B43_RFKILL bool - depends on B43 && RFKILL && RFKILL_INPUT && INPUT_POLLDEV + depends on B43 && (RFKILL = y || RFKILL = B43) && RFKILL_INPUT && (INPUT_POLLDEV = y || INPUT_POLLDEV = B43) default y config B43_DEBUG diff --git a/drivers/net/wireless/b43/debugfs.c b/drivers/net/wireless/b43/debugfs.c index 734e70e..ef0075d 100644 --- a/drivers/net/wireless/b43/debugfs.c +++ b/drivers/net/wireless/b43/debugfs.c @@ -128,7 +128,7 @@ static ssize_t shm_read_file(struct b43_wldev *dev, __le16 *le16buf = (__le16 *)buf; for (i = 0; i < 0x1000; i++) { - if (bufsize <= 0) + if (bufsize < sizeof(tmp)) break; tmp = b43_shm_read16(dev, B43_SHM_SHARED, 2 * i); le16buf[i] = cpu_to_le16(tmp); diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index 5058e60..b45eecc 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c @@ -1566,7 +1566,7 @@ static void b43_release_firmware(struct b43_wldev *dev) static void b43_print_fw_helptext(struct b43_wl *wl) { b43err(wl, "You must go to " - "http://linuxwireless.org/en/users/Drivers/bcm43xx#devicefirmware " + "http://linuxwireless.org/en/users/Drivers/b43#devicefirmware " "and download the correct firmware (version 4).\n"); } @@ -2985,6 +2985,16 @@ static void b43_wireless_core_stop(struct b43_wldev *dev) if (b43_status(dev) < B43_STAT_STARTED) return; + + /* Disable and sync interrupts. We must do this before than + * setting the status to INITIALIZED, as the interrupt handler + * won't care about IRQs then. */ + spin_lock_irqsave(&wl->irq_lock, flags); + dev->irq_savedstate = b43_interrupt_disable(dev, B43_IRQ_ALL); + b43_read32(dev, B43_MMIO_GEN_IRQ_MASK); /* flush */ + spin_unlock_irqrestore(&wl->irq_lock, flags); + b43_synchronize_irq(dev); + b43_set_status(dev, B43_STAT_INITIALIZED); mutex_unlock(&wl->mutex); @@ -2995,13 +3005,6 @@ static void b43_wireless_core_stop(struct b43_wldev *dev) ieee80211_stop_queues(wl->hw); //FIXME this could cause a deadlock, as mac80211 seems buggy. - /* Disable and sync interrupts. */ - spin_lock_irqsave(&wl->irq_lock, flags); - dev->irq_savedstate = b43_interrupt_disable(dev, B43_IRQ_ALL); - b43_read32(dev, B43_MMIO_GEN_IRQ_MASK); /* flush */ - spin_unlock_irqrestore(&wl->irq_lock, flags); - b43_synchronize_irq(dev); - b43_mac_suspend(dev); free_irq(dev->dev->irq, dev); b43dbg(wl, "Wireless interface stopped\n"); @@ -3661,7 +3664,6 @@ static int b43_setup_modes(struct b43_wldev *dev, static void b43_wireless_core_detach(struct b43_wldev *dev) { - b43_rfkill_free(dev); /* We release firmware that late to not be required to re-request * is all the time when we reinit the core. */ b43_release_firmware(dev); @@ -3747,7 +3749,6 @@ static int b43_wireless_core_attach(struct b43_wldev *dev) if (!wl->current_dev) wl->current_dev = dev; INIT_WORK(&dev->restart_work, b43_chip_reset); - b43_rfkill_alloc(dev); b43_radio_turn_off(dev, 1); b43_switch_analog(dev, 0); diff --git a/drivers/net/wireless/b43/pcmcia.c b/drivers/net/wireless/b43/pcmcia.c index b242a9a..b79a6bd 100644 --- a/drivers/net/wireless/b43/pcmcia.c +++ b/drivers/net/wireless/b43/pcmcia.c @@ -65,12 +65,12 @@ static int __devinit b43_pcmcia_probe(struct pcmcia_device *dev) tuple_t tuple; cisparse_t parse; int err = -ENOMEM; - int res; + int res = 0; unsigned char buf[64]; ssb = kzalloc(sizeof(*ssb), GFP_KERNEL); if (!ssb) - goto out; + goto out_error; err = -ENODEV; tuple.DesiredTuple = CISTPL_CONFIG; @@ -96,10 +96,12 @@ static int __devinit b43_pcmcia_probe(struct pcmcia_device *dev) dev->io.NumPorts2 = 0; dev->io.Attributes2 = 0; - win.Attributes = WIN_MEMORY_TYPE_CM | WIN_ENABLE | WIN_USE_WAIT; + win.Attributes = WIN_ADDR_SPACE_MEM | WIN_MEMORY_TYPE_CM | + WIN_ENABLE | WIN_DATA_WIDTH_16 | + WIN_USE_WAIT; win.Base = 0; win.Size = SSB_CORE_SIZE; - win.AccessSpeed = 1000; + win.AccessSpeed = 250; res = pcmcia_request_window(&dev, &win, &dev->win); if (res != CS_SUCCESS) goto err_kfree_ssb; @@ -108,21 +110,34 @@ static int __devinit b43_pcmcia_probe(struct pcmcia_device *dev) mem.Page = 0; res = pcmcia_map_mem_page(dev->win, &mem); if (res != CS_SUCCESS) - goto err_kfree_ssb; + goto err_disable; + + dev->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING | IRQ_FIRST_SHARED; + dev->irq.IRQInfo1 = IRQ_LEVEL_ID | IRQ_SHARE_ID; + dev->irq.Handler = NULL; /* The handler is registered later. */ + dev->irq.Instance = NULL; + res = pcmcia_request_irq(dev, &dev->irq); + if (res != CS_SUCCESS) + goto err_disable; res = pcmcia_request_configuration(dev, &dev->conf); if (res != CS_SUCCESS) goto err_disable; err = ssb_bus_pcmciabus_register(ssb, dev, win.Base); + if (err) + goto err_disable; dev->priv = ssb; - out: - return err; - err_disable: + return 0; + +err_disable: pcmcia_disable_device(dev); - err_kfree_ssb: +err_kfree_ssb: kfree(ssb); +out_error: + printk(KERN_ERR "b43-pcmcia: Initialization failed (%d, %d)\n", + res, err); return err; } @@ -131,22 +146,21 @@ static void __devexit b43_pcmcia_remove(struct pcmcia_device *dev) struct ssb_bus *ssb = dev->priv; ssb_bus_unregister(ssb); - pcmcia_release_window(dev->win); pcmcia_disable_device(dev); kfree(ssb); dev->priv = NULL; } static struct pcmcia_driver b43_pcmcia_driver = { - .owner = THIS_MODULE, - .drv = { - .name = "b43-pcmcia", - }, - .id_table = b43_pcmcia_tbl, - .probe = b43_pcmcia_probe, - .remove = b43_pcmcia_remove, - .suspend = b43_pcmcia_suspend, - .resume = b43_pcmcia_resume, + .owner = THIS_MODULE, + .drv = { + .name = "b43-pcmcia", + }, + .id_table = b43_pcmcia_tbl, + .probe = b43_pcmcia_probe, + .remove = __devexit_p(b43_pcmcia_remove), + .suspend = b43_pcmcia_suspend, + .resume = b43_pcmcia_resume, }; int b43_pcmcia_init(void) diff --git a/drivers/net/wireless/b43/phy.c b/drivers/net/wireless/b43/phy.c index 3d4ed64..7ff091e 100644 --- a/drivers/net/wireless/b43/phy.c +++ b/drivers/net/wireless/b43/phy.c @@ -2214,7 +2214,7 @@ int b43_phy_init_tssi2dbm_table(struct b43_wldev *dev) } dyn_tssi2dbm = kmalloc(64, GFP_KERNEL); if (dyn_tssi2dbm == NULL) { - b43err(dev->wl, "Could not allocate memory" + b43err(dev->wl, "Could not allocate memory " "for tssi2dbm table\n"); return -ENOMEM; } diff --git a/drivers/net/wireless/b43/rfkill.c b/drivers/net/wireless/b43/rfkill.c index 800e0a6..9b1f905 100644 --- a/drivers/net/wireless/b43/rfkill.c +++ b/drivers/net/wireless/b43/rfkill.c @@ -47,32 +47,35 @@ static void b43_rfkill_poll(struct input_polled_dev *poll_dev) struct b43_wldev *dev = poll_dev->private; struct b43_wl *wl = dev->wl; bool enabled; + bool report_change = 0; mutex_lock(&wl->mutex); B43_WARN_ON(b43_status(dev) < B43_STAT_INITIALIZED); enabled = b43_is_hw_radio_enabled(dev); if (unlikely(enabled != dev->radio_hw_enable)) { dev->radio_hw_enable = enabled; + report_change = 1; b43info(wl, "Radio hardware status changed to %s\n", enabled ? "ENABLED" : "DISABLED"); - mutex_unlock(&wl->mutex); + } + mutex_unlock(&wl->mutex); + + if (unlikely(report_change)) input_report_key(poll_dev->input, KEY_WLAN, enabled); - } else - mutex_unlock(&wl->mutex); } -/* Called when the RFKILL toggled in software. - * This is called without locking. */ +/* Called when the RFKILL toggled in software. */ static int b43_rfkill_soft_toggle(void *data, enum rfkill_state state) { struct b43_wldev *dev = data; struct b43_wl *wl = dev->wl; int err = 0; - mutex_lock(&wl->mutex); - if (b43_status(dev) < B43_STAT_INITIALIZED) - goto out_unlock; + if (!wl->rfkill.registered) + return 0; + mutex_lock(&wl->mutex); + B43_WARN_ON(b43_status(dev) < B43_STAT_INITIALIZED); switch (state) { case RFKILL_STATE_ON: if (!dev->radio_hw_enable) { @@ -89,7 +92,6 @@ static int b43_rfkill_soft_toggle(void *data, enum rfkill_state state) b43_radio_turn_off(dev, 0); break; } - out_unlock: mutex_unlock(&wl->mutex); @@ -98,11 +100,11 @@ out_unlock: char * b43_rfkill_led_name(struct b43_wldev *dev) { - struct b43_wl *wl = dev->wl; + struct b43_rfkill *rfk = &(dev->wl->rfkill); - if (!wl->rfkill.rfkill) + if (!rfk->registered) return NULL; - return rfkill_get_led_name(wl->rfkill.rfkill); + return rfkill_get_led_name(rfk->rfkill); } void b43_rfkill_init(struct b43_wldev *dev) @@ -111,53 +113,13 @@ void b43_rfkill_init(struct b43_wldev *dev) struct b43_rfkill *rfk = &(wl->rfkill); int err; - if (rfk->rfkill) { - err = rfkill_register(rfk->rfkill); - if (err) { - b43warn(wl, "Failed to register RF-kill button\n"); - goto err_free_rfk; - } - } - if (rfk->poll_dev) { - err = input_register_polled_device(rfk->poll_dev); - if (err) { - b43warn(wl, "Failed to register RF-kill polldev\n"); - goto err_free_polldev; - } - } - - return; -err_free_rfk: - rfkill_free(rfk->rfkill); - rfk->rfkill = NULL; -err_free_polldev: - input_free_polled_device(rfk->poll_dev); - rfk->poll_dev = NULL; -} - -void b43_rfkill_exit(struct b43_wldev *dev) -{ - struct b43_rfkill *rfk = &(dev->wl->rfkill); - - if (rfk->poll_dev) - input_unregister_polled_device(rfk->poll_dev); - if (rfk->rfkill) - rfkill_unregister(rfk->rfkill); -} - -void b43_rfkill_alloc(struct b43_wldev *dev) -{ - struct b43_wl *wl = dev->wl; - struct b43_rfkill *rfk = &(wl->rfkill); + rfk->registered = 0; + rfk->rfkill = rfkill_allocate(dev->dev->dev, RFKILL_TYPE_WLAN); + if (!rfk->rfkill) + goto out_error; snprintf(rfk->name, sizeof(rfk->name), "b43-%s", wiphy_name(wl->hw->wiphy)); - - rfk->rfkill = rfkill_allocate(dev->dev->dev, RFKILL_TYPE_WLAN); - if (!rfk->rfkill) { - b43warn(wl, "Failed to allocate RF-kill button\n"); - return; - } rfk->rfkill->name = rfk->name; rfk->rfkill->state = RFKILL_STATE_ON; rfk->rfkill->data = dev; @@ -165,18 +127,45 @@ void b43_rfkill_alloc(struct b43_wldev *dev) rfk->rfkill->user_claim_unsupported = 1; rfk->poll_dev = input_allocate_polled_device(); - if (rfk->poll_dev) { - rfk->poll_dev->private = dev; - rfk->poll_dev->poll = b43_rfkill_poll; - rfk->poll_dev->poll_interval = 1000; /* msecs */ - } else - b43warn(wl, "Failed to allocate RF-kill polldev\n"); + if (!rfk->poll_dev) + goto err_free_rfk; + rfk->poll_dev->private = dev; + rfk->poll_dev->poll = b43_rfkill_poll; + rfk->poll_dev->poll_interval = 1000; /* msecs */ + + err = rfkill_register(rfk->rfkill); + if (err) + goto err_free_polldev; + err = input_register_polled_device(rfk->poll_dev); + if (err) + goto err_unreg_rfk; + + rfk->registered = 1; + + return; +err_unreg_rfk: + rfkill_unregister(rfk->rfkill); +err_free_polldev: + input_free_polled_device(rfk->poll_dev); + rfk->poll_dev = NULL; +err_free_rfk: + rfkill_free(rfk->rfkill); + rfk->rfkill = NULL; +out_error: + rfk->registered = 0; + b43warn(wl, "RF-kill button init failed\n"); } -void b43_rfkill_free(struct b43_wldev *dev) +void b43_rfkill_exit(struct b43_wldev *dev) { struct b43_rfkill *rfk = &(dev->wl->rfkill); + if (!rfk->registered) + return; + rfk->registered = 0; + + input_unregister_polled_device(rfk->poll_dev); + rfkill_unregister(rfk->rfkill); input_free_polled_device(rfk->poll_dev); rfk->poll_dev = NULL; rfkill_free(rfk->rfkill); diff --git a/drivers/net/wireless/b43/rfkill.h b/drivers/net/wireless/b43/rfkill.h index 29544e8..adacf93 100644 --- a/drivers/net/wireless/b43/rfkill.h +++ b/drivers/net/wireless/b43/rfkill.h @@ -15,14 +15,14 @@ struct b43_rfkill { struct rfkill *rfkill; /* The poll device for the RFKILL input button */ struct input_polled_dev *poll_dev; + /* Did initialization succeed? Used for freeing. */ + bool registered; /* The unique name of this rfkill switch */ - char name[32]; + char name[sizeof("b43-phy4294967295")]; }; -/* All the init functions return void, because we are not interested +/* The init function returns void, because we are not interested * in failing the b43 init process when rfkill init failed. */ -void b43_rfkill_alloc(struct b43_wldev *dev); -void b43_rfkill_free(struct b43_wldev *dev); void b43_rfkill_init(struct b43_wldev *dev); void b43_rfkill_exit(struct b43_wldev *dev); @@ -36,12 +36,6 @@ struct b43_rfkill { /* empty */ }; -static inline void b43_rfkill_alloc(struct b43_wldev *dev) -{ -} -static inline void b43_rfkill_free(struct b43_wldev *dev) -{ -} static inline void b43_rfkill_init(struct b43_wldev *dev) { } diff --git a/drivers/net/wireless/b43legacy/debugfs.c b/drivers/net/wireless/b43legacy/debugfs.c index eefa6fb79..619b453 100644 --- a/drivers/net/wireless/b43legacy/debugfs.c +++ b/drivers/net/wireless/b43legacy/debugfs.c @@ -124,7 +124,7 @@ static ssize_t shm_read_file(struct b43legacy_wldev *dev, char *buf, size_t bufs __le16 *le16buf = (__le16 *)buf; for (i = 0; i < 0x1000; i++) { - if (bufsize <= 0) + if (bufsize < sizeof(tmp)) break; tmp = b43legacy_shm_read16(dev, B43legacy_SHM_SHARED, 2 * i); le16buf[i] = cpu_to_le16(tmp); diff --git a/drivers/net/wireless/b43legacy/dma.c b/drivers/net/wireless/b43legacy/dma.c index 8cb3dc4..83161d9 100644 --- a/drivers/net/wireless/b43legacy/dma.c +++ b/drivers/net/wireless/b43legacy/dma.c @@ -996,7 +996,7 @@ int b43legacy_dma_init(struct b43legacy_wldev *dev) err = ssb_dma_set_mask(dev->dev, dmamask); if (err) { -#ifdef BCM43XX_PIO +#ifdef CONFIG_B43LEGACY_PIO b43legacywarn(dev->wl, "DMA for this device not supported. " "Falling back to PIO\n"); dev->__using_pio = 1; diff --git a/drivers/net/wireless/b43legacy/main.c b/drivers/net/wireless/b43legacy/main.c index f0e56df..32d5e17 100644 --- a/drivers/net/wireless/b43legacy/main.c +++ b/drivers/net/wireless/b43legacy/main.c @@ -1419,7 +1419,7 @@ static void b43legacy_release_firmware(struct b43legacy_wldev *dev) static void b43legacy_print_fw_helptext(struct b43legacy_wl *wl) { b43legacyerr(wl, "You must go to http://linuxwireless.org/en/users/" - "Drivers/bcm43xx#devicefirmware " + "Drivers/b43#devicefirmware " "and download the correct firmware (version 3).\n"); } @@ -2781,6 +2781,17 @@ static void b43legacy_wireless_core_stop(struct b43legacy_wldev *dev) if (b43legacy_status(dev) < B43legacy_STAT_STARTED) return; + + /* Disable and sync interrupts. We must do this before than + * setting the status to INITIALIZED, as the interrupt handler + * won't care about IRQs then. */ + spin_lock_irqsave(&wl->irq_lock, flags); + dev->irq_savedstate = b43legacy_interrupt_disable(dev, + B43legacy_IRQ_ALL); + b43legacy_read32(dev, B43legacy_MMIO_GEN_IRQ_MASK); /* flush */ + spin_unlock_irqrestore(&wl->irq_lock, flags); + b43legacy_synchronize_irq(dev); + b43legacy_set_status(dev, B43legacy_STAT_INITIALIZED); mutex_unlock(&wl->mutex); @@ -2791,14 +2802,6 @@ static void b43legacy_wireless_core_stop(struct b43legacy_wldev *dev) ieee80211_stop_queues(wl->hw); /* FIXME this could cause a deadlock */ - /* Disable and sync interrupts. */ - spin_lock_irqsave(&wl->irq_lock, flags); - dev->irq_savedstate = b43legacy_interrupt_disable(dev, - B43legacy_IRQ_ALL); - b43legacy_read32(dev, B43legacy_MMIO_GEN_IRQ_MASK); /* flush */ - spin_unlock_irqrestore(&wl->irq_lock, flags); - b43legacy_synchronize_irq(dev); - b43legacy_mac_suspend(dev); free_irq(dev->dev->irq, dev); b43legacydbg(wl, "Wireless interface stopped\n"); @@ -3332,7 +3335,7 @@ out_mutex_unlock: return err; } -void b43legacy_stop(struct ieee80211_hw *hw) +static void b43legacy_stop(struct ieee80211_hw *hw) { struct b43legacy_wl *wl = hw_to_b43legacy_wl(hw); struct b43legacy_wldev *dev = wl->current_dev; diff --git a/drivers/net/wireless/b43legacy/phy.c b/drivers/net/wireless/b43legacy/phy.c index 22a4b3d..491e518 100644 --- a/drivers/net/wireless/b43legacy/phy.c +++ b/drivers/net/wireless/b43legacy/phy.c @@ -2020,7 +2020,7 @@ int b43legacy_phy_init_tssi2dbm_table(struct b43legacy_wldev *dev) phy->idle_tssi = 62; dyn_tssi2dbm = kmalloc(64, GFP_KERNEL); if (dyn_tssi2dbm == NULL) { - b43legacyerr(dev->wl, "Could not allocate memory" + b43legacyerr(dev->wl, "Could not allocate memory " "for tssi2dbm table\n"); return -ENOMEM; } diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_phy.c b/drivers/net/wireless/bcm43xx/bcm43xx_phy.c index b37f1e3..af3de33 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_phy.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_phy.c @@ -2149,7 +2149,7 @@ int bcm43xx_phy_init_tssi2dbm_table(struct bcm43xx_private *bcm) } dyn_tssi2dbm = kmalloc(64, GFP_KERNEL); if (dyn_tssi2dbm == NULL) { - printk(KERN_ERR PFX "Could not allocate memory" + printk(KERN_ERR PFX "Could not allocate memory " "for tssi2dbm table\n"); return -ENOMEM; } diff --git a/drivers/net/wireless/hostap/hostap_pci.c b/drivers/net/wireless/hostap/hostap_pci.c index 7da3664..fc876ba 100644 --- a/drivers/net/wireless/hostap/hostap_pci.c +++ b/drivers/net/wireless/hostap/hostap_pci.c @@ -444,7 +444,7 @@ static int prism2_pci_resume(struct pci_dev *pdev) MODULE_DEVICE_TABLE(pci, prism2_pci_id_table); -static struct pci_driver prism2_pci_drv_id = { +static struct pci_driver prism2_pci_driver = { .name = "hostap_pci", .id_table = prism2_pci_id_table, .probe = prism2_pci_probe, @@ -458,13 +458,13 @@ static struct pci_driver prism2_pci_drv_id = { static int __init init_prism2_pci(void) { - return pci_register_driver(&prism2_pci_drv_id); + return pci_register_driver(&prism2_pci_driver); } static void __exit exit_prism2_pci(void) { - pci_unregister_driver(&prism2_pci_drv_id); + pci_unregister_driver(&prism2_pci_driver); } diff --git a/drivers/net/wireless/ipw2100.c b/drivers/net/wireless/ipw2100.c index 8d53d08..fc6cdd8 100644 --- a/drivers/net/wireless/ipw2100.c +++ b/drivers/net/wireless/ipw2100.c @@ -1267,7 +1267,7 @@ static int ipw2100_start_adapter(struct ipw2100_priv *priv) IPW2100_INTA_FATAL_ERROR | IPW2100_INTA_PARITY_ERROR); } - } while (i--); + } while (--i); /* Clear out any pending INTAs since we aren't supposed to have * interrupts enabled at this point... */ @@ -1339,7 +1339,7 @@ static int ipw2100_power_cycle_adapter(struct ipw2100_priv *priv) if (reg & IPW_AUX_HOST_RESET_REG_MASTER_DISABLED) break; - } while (i--); + } while (--i); priv->status &= ~STATUS_RESET_PENDING; diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-rs.c b/drivers/net/wireless/iwlwifi/iwl-3945-rs.c index 262ab0b..c48b1b5 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945-rs.c @@ -71,19 +71,19 @@ struct iwl_rate_scale_priv { }; static s32 iwl_expected_tpt_g[IWL_RATE_COUNT] = { - 0, 0, 76, 104, 130, 168, 191, 202, 7, 13, 35, 58 + 7, 13, 35, 58, 0, 0, 76, 104, 130, 168, 191, 202 }; static s32 iwl_expected_tpt_g_prot[IWL_RATE_COUNT] = { - 0, 0, 0, 80, 93, 113, 123, 125, 7, 13, 35, 58 + 7, 13, 35, 58, 0, 0, 0, 80, 93, 113, 123, 125 }; static s32 iwl_expected_tpt_a[IWL_RATE_COUNT] = { - 40, 57, 72, 98, 121, 154, 177, 186, 0, 0, 0, 0 + 0, 0, 0, 0, 40, 57, 72, 98, 121, 154, 177, 186 }; static s32 iwl_expected_tpt_b[IWL_RATE_COUNT] = { - 0, 0, 0, 0, 0, 0, 0, 0, 7, 13, 35, 58 + 7, 13, 35, 58, 0, 0, 0, 0, 0, 0, 0, 0 }; struct iwl_tpt_entry { @@ -350,6 +350,10 @@ static void rs_rate_init(void *priv_rate, void *priv_sta, sta->last_txrate = sta->txrate; + /* For MODE_IEEE80211A mode it start at IWL_FIRST_OFDM_RATE */ + if (local->hw.conf.phymode == MODE_IEEE80211A) + sta->last_txrate += IWL_FIRST_OFDM_RATE; + IWL_DEBUG_RATE("leave\n"); } @@ -417,6 +421,33 @@ static void rs_free_sta(void *priv, void *priv_sta) IWL_DEBUG_RATE("leave\n"); } + +/* + * get ieee prev rate from rate scale table. + * for A and B mode we need to overright prev + * value + */ +static int rs_adjust_next_rate(struct iwl_priv *priv, int rate) +{ + int next_rate = iwl_get_prev_ieee_rate(rate); + + switch (priv->phymode) { + case MODE_IEEE80211A: + if (rate == IWL_RATE_12M_INDEX) + next_rate = IWL_RATE_9M_INDEX; + else if (rate == IWL_RATE_6M_INDEX) + next_rate = IWL_RATE_6M_INDEX; + break; + case MODE_IEEE80211B: + if (rate == IWL_RATE_11M_INDEX_TABLE) + next_rate = IWL_RATE_5M_INDEX_TABLE; + break; + default: + break; + } + + return next_rate; +} /** * rs_tx_status - Update rate control values based on Tx results * @@ -479,7 +510,8 @@ static void rs_tx_status(void *priv_rate, last_index = scale_rate_index; } else { current_count = priv->retry_rate; - last_index = iwl_get_prev_ieee_rate(scale_rate_index); + last_index = rs_adjust_next_rate(priv, + scale_rate_index); } /* Update this rate accounting for as many retries @@ -494,9 +526,10 @@ static void rs_tx_status(void *priv_rate, if (retries) scale_rate_index = - iwl_get_prev_ieee_rate(scale_rate_index); + rs_adjust_next_rate(priv, scale_rate_index); } + /* Update the last index window with success/failure based on ACK */ IWL_DEBUG_RATE("Update rate %d with %s.\n", last_index, @@ -672,7 +705,10 @@ static struct ieee80211_rate *rs_get_rate(void *priv_rate, } rate_mask = sta->supp_rates; - index = min(sta->txrate & 0xffff, IWL_RATE_COUNT - 1); + index = min(sta->last_txrate & 0xffff, IWL_RATE_COUNT - 1); + + if (priv->phymode == (u8) MODE_IEEE80211A) + rate_mask = rate_mask << IWL_FIRST_OFDM_RATE; rs_priv = (void *)sta->rate_ctrl_priv; @@ -801,7 +837,11 @@ static struct ieee80211_rate *rs_get_rate(void *priv_rate, out: sta->last_txrate = index; - sta->txrate = sta->last_txrate; + if (priv->phymode == (u8) MODE_IEEE80211A) + sta->txrate = sta->last_txrate - IWL_FIRST_OFDM_RATE; + else + sta->txrate = sta->last_txrate; + sta_info_put(sta); IWL_DEBUG_RATE("leave: %d\n", index); diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-rs.h b/drivers/net/wireless/iwlwifi/iwl-3945-rs.h index b926738..bec4d3f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945-rs.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945-rs.h @@ -36,10 +36,17 @@ struct iwl_rate_info { u8 next_rs; /* next rate used in rs algo */ u8 prev_rs_tgg; /* previous rate used in TGG rs algo */ u8 next_rs_tgg; /* next rate used in TGG rs algo */ + u8 table_rs_index; /* index in rate scale table cmd */ + u8 prev_table_rs; /* prev in rate table cmd */ + }; enum { - IWL_RATE_6M_INDEX = 0, + IWL_RATE_1M_INDEX = 0, + IWL_RATE_2M_INDEX, + IWL_RATE_5M_INDEX, + IWL_RATE_11M_INDEX, + IWL_RATE_6M_INDEX, IWL_RATE_9M_INDEX, IWL_RATE_12M_INDEX, IWL_RATE_18M_INDEX, @@ -47,16 +54,28 @@ enum { IWL_RATE_36M_INDEX, IWL_RATE_48M_INDEX, IWL_RATE_54M_INDEX, - IWL_RATE_1M_INDEX, - IWL_RATE_2M_INDEX, - IWL_RATE_5M_INDEX, - IWL_RATE_11M_INDEX, IWL_RATE_COUNT, IWL_RATE_INVM_INDEX, IWL_RATE_INVALID = IWL_RATE_INVM_INDEX }; enum { + IWL_RATE_6M_INDEX_TABLE = 0, + IWL_RATE_9M_INDEX_TABLE, + IWL_RATE_12M_INDEX_TABLE, + IWL_RATE_18M_INDEX_TABLE, + IWL_RATE_24M_INDEX_TABLE, + IWL_RATE_36M_INDEX_TABLE, + IWL_RATE_48M_INDEX_TABLE, + IWL_RATE_54M_INDEX_TABLE, + IWL_RATE_1M_INDEX_TABLE, + IWL_RATE_2M_INDEX_TABLE, + IWL_RATE_5M_INDEX_TABLE, + IWL_RATE_11M_INDEX_TABLE, + IWL_RATE_INVM_INDEX_TABLE = IWL_RATE_INVM_INDEX, +}; + +enum { IWL_FIRST_OFDM_RATE = IWL_RATE_6M_INDEX, IWL_LAST_OFDM_RATE = IWL_RATE_54M_INDEX, IWL_FIRST_CCK_RATE = IWL_RATE_1M_INDEX, diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c index 19bcb01..3a45fe9 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c @@ -54,7 +54,9 @@ IWL_RATE_##rp##M_INDEX, \ IWL_RATE_##rn##M_INDEX, \ IWL_RATE_##pp##M_INDEX, \ - IWL_RATE_##np##M_INDEX } + IWL_RATE_##np##M_INDEX, \ + IWL_RATE_##r##M_INDEX_TABLE, \ + IWL_RATE_##ip##M_INDEX_TABLE } /* * Parameter order: @@ -65,6 +67,10 @@ * */ const struct iwl_rate_info iwl_rates[IWL_RATE_COUNT] = { + IWL_DECLARE_RATE_INFO(1, INV, 2, INV, 2, INV, 2), /* 1mbps */ + IWL_DECLARE_RATE_INFO(2, 1, 5, 1, 5, 1, 5), /* 2mbps */ + IWL_DECLARE_RATE_INFO(5, 2, 6, 2, 11, 2, 11), /*5.5mbps */ + IWL_DECLARE_RATE_INFO(11, 9, 12, 5, 12, 5, 18), /* 11mbps */ IWL_DECLARE_RATE_INFO(6, 5, 9, 5, 11, 5, 11), /* 6mbps */ IWL_DECLARE_RATE_INFO(9, 6, 11, 5, 11, 5, 11), /* 9mbps */ IWL_DECLARE_RATE_INFO(12, 11, 18, 11, 18, 11, 18), /* 12mbps */ @@ -73,10 +79,6 @@ const struct iwl_rate_info iwl_rates[IWL_RATE_COUNT] = { IWL_DECLARE_RATE_INFO(36, 24, 48, 24, 48, 24, 48), /* 36mbps */ IWL_DECLARE_RATE_INFO(48, 36, 54, 36, 54, 36, 54), /* 48mbps */ IWL_DECLARE_RATE_INFO(54, 48, INV, 48, INV, 48, INV),/* 54mbps */ - IWL_DECLARE_RATE_INFO(1, INV, 2, INV, 2, INV, 2), /* 1mbps */ - IWL_DECLARE_RATE_INFO(2, 1, 5, 1, 5, 1, 5), /* 2mbps */ - IWL_DECLARE_RATE_INFO(5, 2, 6, 2, 11, 2, 11), /*5.5mbps */ - IWL_DECLARE_RATE_INFO(11, 9, 12, 5, 12, 5, 18), /* 11mbps */ }; /* 1 = enable the iwl_disable_events() function */ @@ -662,10 +664,11 @@ void iwl_hw_build_tx_cmd_rate(struct iwl_priv *priv, cmd->cmd.tx.tx_flags = tx_flags; /* OFDM */ - cmd->cmd.tx.supp_rates[0] = rate_mask & IWL_OFDM_RATES_MASK; + cmd->cmd.tx.supp_rates[0] = + ((rate_mask & IWL_OFDM_RATES_MASK) >> IWL_FIRST_OFDM_RATE) & 0xFF; /* CCK */ - cmd->cmd.tx.supp_rates[1] = (rate_mask >> 8) & 0xF; + cmd->cmd.tx.supp_rates[1] = (rate_mask & 0xF); IWL_DEBUG_RATE("Tx sta id: %d, rate: %d (plcp), flags: 0x%4X " "cck/ofdm mask: 0x%x/0x%x\n", sta_id, @@ -1432,7 +1435,7 @@ static void iwl_hw_reg_set_scan_power(struct iwl_priv *priv, u32 scan_tbl_index, /* use this channel group's 6Mbit clipping/saturation pwr, * but cap at regulatory scan power restriction (set during init * based on eeprom channel data) for this channel. */ - power = min(ch_info->scan_power, clip_pwrs[IWL_RATE_6M_INDEX]); + power = min(ch_info->scan_power, clip_pwrs[IWL_RATE_6M_INDEX_TABLE]); /* further limit to user's max power preference. * FIXME: Other spectrum management power limitations do not @@ -1447,7 +1450,7 @@ static void iwl_hw_reg_set_scan_power(struct iwl_priv *priv, u32 scan_tbl_index, * *index*. */ power_index = ch_info->power_info[rate_index].power_table_index - (power - ch_info->power_info - [IWL_RATE_6M_INDEX].requested_power) * 2; + [IWL_RATE_6M_INDEX_TABLE].requested_power) * 2; /* store reference index that we use when adjusting *all* scan * powers. So we can accommodate user (all channel) or spectrum @@ -1476,7 +1479,7 @@ static void iwl_hw_reg_set_scan_power(struct iwl_priv *priv, u32 scan_tbl_index, */ int iwl_hw_reg_send_txpower(struct iwl_priv *priv) { - int rate_idx; + int rate_idx, i; const struct iwl_channel_info *ch_info = NULL; struct iwl_txpowertable_cmd txpower = { .channel = priv->active_rxon.channel, @@ -1500,20 +1503,36 @@ int iwl_hw_reg_send_txpower(struct iwl_priv *priv) } /* fill cmd with power settings for all rates for current channel */ - for (rate_idx = 0; rate_idx < IWL_RATE_COUNT; rate_idx++) { - txpower.power[rate_idx].tpc = ch_info->power_info[rate_idx].tpc; - txpower.power[rate_idx].rate = iwl_rates[rate_idx].plcp; + /* Fill OFDM rate */ + for (rate_idx = IWL_FIRST_OFDM_RATE, i = 0; + rate_idx <= IWL_LAST_OFDM_RATE; rate_idx++, i++) { + + txpower.power[i].tpc = ch_info->power_info[i].tpc; + txpower.power[i].rate = iwl_rates[rate_idx].plcp; IWL_DEBUG_POWER("ch %d:%d rf %d dsp %3d rate code 0x%02x\n", le16_to_cpu(txpower.channel), txpower.band, - txpower.power[rate_idx].tpc.tx_gain, - txpower.power[rate_idx].tpc.dsp_atten, - txpower.power[rate_idx].rate); + txpower.power[i].tpc.tx_gain, + txpower.power[i].tpc.dsp_atten, + txpower.power[i].rate); + } + /* Fill CCK rates */ + for (rate_idx = IWL_FIRST_CCK_RATE; + rate_idx <= IWL_LAST_CCK_RATE; rate_idx++, i++) { + txpower.power[i].tpc = ch_info->power_info[i].tpc; + txpower.power[i].rate = iwl_rates[rate_idx].plcp; + + IWL_DEBUG_POWER("ch %d:%d rf %d dsp %3d rate code 0x%02x\n", + le16_to_cpu(txpower.channel), + txpower.band, + txpower.power[i].tpc.tx_gain, + txpower.power[i].tpc.dsp_atten, + txpower.power[i].rate); } return iwl_send_cmd_pdu(priv, REPLY_TX_PWR_TABLE_CMD, - sizeof(struct iwl_txpowertable_cmd), &txpower); + sizeof(struct iwl_txpowertable_cmd), &txpower); } @@ -1549,7 +1568,7 @@ static int iwl_hw_reg_set_new_power(struct iwl_priv *priv, power_info = ch_info->power_info; /* update OFDM Txpower settings */ - for (i = IWL_FIRST_OFDM_RATE; i <= IWL_LAST_OFDM_RATE; + for (i = IWL_RATE_6M_INDEX_TABLE; i <= IWL_RATE_54M_INDEX_TABLE; i++, ++power_info) { int delta_idx; @@ -1573,14 +1592,14 @@ static int iwl_hw_reg_set_new_power(struct iwl_priv *priv, * ... all CCK power settings for a given channel are the *same*. */ if (power_changed) { power = - ch_info->power_info[IWL_RATE_12M_INDEX]. + ch_info->power_info[IWL_RATE_12M_INDEX_TABLE]. requested_power + IWL_CCK_FROM_OFDM_POWER_DIFF; /* do all CCK rates' iwl_channel_power_info structures */ - for (i = IWL_FIRST_CCK_RATE; i <= IWL_LAST_CCK_RATE; i++) { + for (i = IWL_RATE_1M_INDEX_TABLE; i <= IWL_RATE_11M_INDEX_TABLE; i++) { power_info->requested_power = power; power_info->base_power_index = - ch_info->power_info[IWL_RATE_12M_INDEX]. + ch_info->power_info[IWL_RATE_12M_INDEX_TABLE]. base_power_index + IWL_CCK_FROM_OFDM_INDEX_DIFF; ++power_info; } @@ -1674,7 +1693,7 @@ static int iwl_hw_reg_comp_txpower_temp(struct iwl_priv *priv) for (scan_tbl_index = 0; scan_tbl_index < IWL_NUM_SCAN_RATES; scan_tbl_index++) { s32 actual_index = (scan_tbl_index == 0) ? - IWL_RATE_1M_INDEX : IWL_RATE_6M_INDEX; + IWL_RATE_1M_INDEX_TABLE : IWL_RATE_6M_INDEX_TABLE; iwl_hw_reg_set_scan_power(priv, scan_tbl_index, actual_index, clip_pwrs, ch_info, a_band); @@ -1905,19 +1924,19 @@ static void iwl_hw_reg_init_channel_groups(struct iwl_priv *priv) for (rate_index = 0; rate_index < IWL_RATE_COUNT; rate_index++, clip_pwrs++) { switch (rate_index) { - case IWL_RATE_36M_INDEX: + case IWL_RATE_36M_INDEX_TABLE: if (i == 0) /* B/G */ *clip_pwrs = satur_pwr; else /* A */ *clip_pwrs = satur_pwr - 5; break; - case IWL_RATE_48M_INDEX: + case IWL_RATE_48M_INDEX_TABLE: if (i == 0) *clip_pwrs = satur_pwr - 7; else *clip_pwrs = satur_pwr - 10; break; - case IWL_RATE_54M_INDEX: + case IWL_RATE_54M_INDEX_TABLE: if (i == 0) *clip_pwrs = satur_pwr - 9; else @@ -2031,7 +2050,7 @@ int iwl3945_txpower_set_from_eeprom(struct iwl_priv *priv) } /* set tx power for CCK rates, based on OFDM 12 Mbit settings*/ - pwr_info = &ch_info->power_info[IWL_RATE_12M_INDEX]; + pwr_info = &ch_info->power_info[IWL_RATE_12M_INDEX_TABLE]; power = pwr_info->requested_power + IWL_CCK_FROM_OFDM_POWER_DIFF; pwr_index = pwr_info->power_table_index + @@ -2047,9 +2066,9 @@ int iwl3945_txpower_set_from_eeprom(struct iwl_priv *priv) /* fill each CCK rate's iwl_channel_power_info structure * NOTE: All CCK-rate Txpwrs are the same for a given chnl! * NOTE: CCK rates start at end of OFDM rates! */ - for (rate_index = IWL_OFDM_RATES; - rate_index < IWL_RATE_COUNT; rate_index++) { - pwr_info = &ch_info->power_info[rate_index]; + for (rate_index = 0; + rate_index < IWL_CCK_RATES; rate_index++) { + pwr_info = &ch_info->power_info[rate_index+IWL_OFDM_RATES]; pwr_info->requested_power = power; pwr_info->power_table_index = pwr_index; pwr_info->base_power_index = base_pwr_index; @@ -2061,7 +2080,7 @@ int iwl3945_txpower_set_from_eeprom(struct iwl_priv *priv) for (scan_tbl_index = 0; scan_tbl_index < IWL_NUM_SCAN_RATES; scan_tbl_index++) { s32 actual_index = (scan_tbl_index == 0) ? - IWL_RATE_1M_INDEX : IWL_RATE_6M_INDEX; + IWL_RATE_1M_INDEX_TABLE : IWL_RATE_6M_INDEX_TABLE; iwl_hw_reg_set_scan_power(priv, scan_tbl_index, actual_index, clip_pwrs, ch_info, a_band); } @@ -2139,17 +2158,20 @@ int iwl_hw_get_rx_read(struct iwl_priv *priv) */ int iwl3945_init_hw_rate_table(struct iwl_priv *priv) { - int rc, i; + int rc, i, index, prev_index; struct iwl_rate_scaling_cmd rate_cmd = { .reserved = {0, 0, 0}, }; struct iwl_rate_scaling_info *table = rate_cmd.table; for (i = 0; i < ARRAY_SIZE(iwl_rates); i++) { - table[i].rate_n_flags = + index = iwl_rates[i].table_rs_index; + + table[index].rate_n_flags = iwl_hw_set_rate_n_flags(iwl_rates[i].plcp, 0); - table[i].try_cnt = priv->retry_rate; - table[i].next_rate_index = iwl_get_prev_ieee_rate(i); + table[index].try_cnt = priv->retry_rate; + prev_index = iwl_get_prev_ieee_rate(i); + table[index].next_rate_index = iwl_rates[prev_index].table_rs_index; } switch (priv->phymode) { @@ -2157,26 +2179,26 @@ int iwl3945_init_hw_rate_table(struct iwl_priv *priv) IWL_DEBUG_RATE("Select A mode rate scale\n"); /* If one of the following CCK rates is used, * have it fall back to the 6M OFDM rate */ - for (i = IWL_FIRST_CCK_RATE; i <= IWL_LAST_CCK_RATE; i++) - table[i].next_rate_index = IWL_FIRST_OFDM_RATE; + for (i = IWL_RATE_1M_INDEX_TABLE; i <= IWL_RATE_11M_INDEX_TABLE; i++) + table[i].next_rate_index = iwl_rates[IWL_FIRST_OFDM_RATE].table_rs_index; /* Don't fall back to CCK rates */ - table[IWL_RATE_12M_INDEX].next_rate_index = IWL_RATE_9M_INDEX; + table[IWL_RATE_12M_INDEX_TABLE].next_rate_index = IWL_RATE_9M_INDEX_TABLE; /* Don't drop out of OFDM rates */ - table[IWL_FIRST_OFDM_RATE].next_rate_index = - IWL_FIRST_OFDM_RATE; + table[IWL_RATE_6M_INDEX_TABLE].next_rate_index = + iwl_rates[IWL_FIRST_OFDM_RATE].table_rs_index; break; case MODE_IEEE80211B: IWL_DEBUG_RATE("Select B mode rate scale\n"); /* If an OFDM rate is used, have it fall back to the * 1M CCK rates */ - for (i = IWL_FIRST_OFDM_RATE; i <= IWL_LAST_OFDM_RATE; i++) - table[i].next_rate_index = IWL_FIRST_CCK_RATE; + for (i = IWL_RATE_6M_INDEX_TABLE; i <= IWL_RATE_54M_INDEX_TABLE; i++) + table[i].next_rate_index = iwl_rates[IWL_FIRST_CCK_RATE].table_rs_index; /* CCK shouldn't fall back to OFDM... */ - table[IWL_RATE_11M_INDEX].next_rate_index = IWL_RATE_5M_INDEX; + table[IWL_RATE_11M_INDEX_TABLE].next_rate_index = IWL_RATE_5M_INDEX_TABLE; break; default: @@ -2248,22 +2270,12 @@ unsigned int iwl_hw_get_beacon_cmd(struct iwl_priv *priv, tx_beacon_cmd->tx.tx_flags = (TX_CMD_FLG_SEQ_CTL_MSK | TX_CMD_FLG_TSF_MSK); - /* supp_rates[0] == OFDM */ - tx_beacon_cmd->tx.supp_rates[0] = IWL_OFDM_BASIC_RATES_MASK; - - /* supp_rates[1] == CCK - * - * NOTE: IWL_*_RATES_MASK are not in the order that supp_rates - * expects so we have to shift them around. - * - * supp_rates expects: - * CCK rates are bit0..3 - * - * However IWL_*_RATES_MASK has: - * CCK rates are bit8..11 - */ + /* supp_rates[0] == OFDM start at IWL_FIRST_OFDM_RATE*/ + tx_beacon_cmd->tx.supp_rates[0] = + (IWL_OFDM_BASIC_RATES_MASK >> IWL_FIRST_OFDM_RATE) & 0xFF; + tx_beacon_cmd->tx.supp_rates[1] = - (IWL_CCK_BASIC_RATES_MASK >> 8) & 0xF; + (IWL_CCK_BASIC_RATES_MASK & 0xF); return (sizeof(struct iwl_tx_beacon_cmd) + frame_size); } diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 4f22a71..4bdf237 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -2915,6 +2915,10 @@ static void iwl_set_rate(struct iwl_priv *priv) int i; hw = iwl_get_hw_mode(priv, priv->phymode); + if (!hw) { + IWL_ERROR("Failed to set rate: unable to get hw mode\n"); + return; + } priv->active_rate = 0; priv->active_rate_basic = 0; @@ -4850,7 +4854,7 @@ static irqreturn_t iwl_isr(int irq, void *data) if ((inta == 0xFFFFFFFF) || ((inta & 0xFFFFFFF0) == 0xa5a5a5a0)) { /* Hardware disappeared */ IWL_WARNING("HARDWARE GONE?? INTA == 0x%080x\n", inta); - goto none; + goto unplugged; } IWL_DEBUG_ISR("ISR inta 0x%08x, enabled 0x%08x, fh 0x%08x\n", @@ -4858,6 +4862,7 @@ static irqreturn_t iwl_isr(int irq, void *data) /* iwl_irq_tasklet() will service interrupts and re-enable them */ tasklet_schedule(&priv->irq_tasklet); +unplugged: spin_unlock(&priv->lock); return IRQ_HANDLED; @@ -5331,13 +5336,13 @@ static int iwl_init_geos(struct iwl_priv *priv) /* 5.2GHz channels start after the 2.4GHz channels */ modes[A].mode = MODE_IEEE80211A; modes[A].channels = &channels[ARRAY_SIZE(iwl_eeprom_band_1)]; - modes[A].rates = rates; + modes[A].rates = &rates[4]; modes[A].num_rates = 8; /* just OFDM */ modes[A].num_channels = 0; modes[B].mode = MODE_IEEE80211B; modes[B].channels = channels; - modes[B].rates = &rates[8]; + modes[B].rates = rates; modes[B].num_rates = 4; /* just CCK */ modes[B].num_channels = 0; @@ -6935,13 +6940,10 @@ static int iwl_mac_add_interface(struct ieee80211_hw *hw, DECLARE_MAC_BUF(mac); IWL_DEBUG_MAC80211("enter: id %d, type %d\n", conf->if_id, conf->type); - if (conf->mac_addr) - IWL_DEBUG_MAC80211("enter: MAC %s\n", - print_mac(mac, conf->mac_addr)); if (priv->interface_id) { IWL_DEBUG_MAC80211("leave - interface_id != 0\n"); - return 0; + return -EOPNOTSUPP; } spin_lock_irqsave(&priv->lock, flags); @@ -6950,6 +6952,12 @@ static int iwl_mac_add_interface(struct ieee80211_hw *hw, spin_unlock_irqrestore(&priv->lock, flags); mutex_lock(&priv->mutex); + + if (conf->mac_addr) { + IWL_DEBUG_MAC80211("Set: %s\n", print_mac(mac, conf->mac_addr)); + memcpy(priv->mac_addr, conf->mac_addr, ETH_ALEN); + } + iwl_set_mode(priv, conf->type); IWL_DEBUG_MAC80211("leave\n"); @@ -8269,6 +8277,7 @@ static void iwl_cancel_deferred_work(struct iwl_priv *priv) { iwl_hw_cancel_deferred_work(priv); + cancel_delayed_work_sync(&priv->init_alive_start); cancel_delayed_work(&priv->scan_check); cancel_delayed_work(&priv->alive_start); cancel_delayed_work(&priv->post_associate); @@ -8354,6 +8363,8 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) } SET_IEEE80211_DEV(hw, &pdev->dev); + hw->rate_control_algorithm = "iwl-3945-rs"; + IWL_DEBUG_INFO("*** LOAD DRIVER ***\n"); priv = hw->priv; priv->hw = hw; diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c index d60adcb..8f85564 100644 --- a/drivers/net/wireless/iwlwifi/iwl4965-base.c +++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c @@ -3003,6 +3003,10 @@ static void iwl_set_rate(struct iwl_priv *priv) int i; hw = iwl_get_hw_mode(priv, priv->phymode); + if (!hw) { + IWL_ERROR("Failed to set rate: unable to get hw mode\n"); + return; + } priv->active_rate = 0; priv->active_rate_basic = 0; @@ -5156,9 +5160,10 @@ static irqreturn_t iwl_isr(int irq, void *data) } if ((inta == 0xFFFFFFFF) || ((inta & 0xFFFFFFF0) == 0xa5a5a5a0)) { - /* Hardware disappeared */ + /* Hardware disappeared. It might have already raised + * an interrupt */ IWL_WARNING("HARDWARE GONE?? INTA == 0x%080x\n", inta); - goto none; + goto unplugged; } IWL_DEBUG_ISR("ISR inta 0x%08x, enabled 0x%08x, fh 0x%08x\n", @@ -5166,8 +5171,9 @@ static irqreturn_t iwl_isr(int irq, void *data) /* iwl_irq_tasklet() will service interrupts and re-enable them */ tasklet_schedule(&priv->irq_tasklet); - spin_unlock(&priv->lock); + unplugged: + spin_unlock(&priv->lock); return IRQ_HANDLED; none: @@ -7324,9 +7330,6 @@ static int iwl_mac_add_interface(struct ieee80211_hw *hw, DECLARE_MAC_BUF(mac); IWL_DEBUG_MAC80211("enter: id %d, type %d\n", conf->if_id, conf->type); - if (conf->mac_addr) - IWL_DEBUG_MAC80211("enter: MAC %s\n", - print_mac(mac, conf->mac_addr)); if (priv->interface_id) { IWL_DEBUG_MAC80211("leave - interface_id != 0\n"); @@ -7339,6 +7342,11 @@ static int iwl_mac_add_interface(struct ieee80211_hw *hw, spin_unlock_irqrestore(&priv->lock, flags); mutex_lock(&priv->mutex); + + if (conf->mac_addr) { + IWL_DEBUG_MAC80211("Set %s\n", print_mac(mac, conf->mac_addr)); + memcpy(priv->mac_addr, conf->mac_addr, ETH_ALEN); + } iwl_set_mode(priv, conf->type); IWL_DEBUG_MAC80211("leave\n"); @@ -8862,6 +8870,7 @@ static void iwl_cancel_deferred_work(struct iwl_priv *priv) { iwl_hw_cancel_deferred_work(priv); + cancel_delayed_work_sync(&priv->init_alive_start); cancel_delayed_work(&priv->scan_check); cancel_delayed_work(&priv->alive_start); cancel_delayed_work(&priv->post_associate); @@ -8955,6 +8964,8 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) } SET_IEEE80211_DEV(hw, &pdev->dev); + hw->rate_control_algorithm = "iwl-4965-rs"; + IWL_DEBUG_INFO("*** LOAD DRIVER ***\n"); priv = hw->priv; priv->hw = hw; diff --git a/drivers/net/wireless/libertas/cmd.c b/drivers/net/wireless/libertas/cmd.c index 1cbbd96..be5cfd8 100644 --- a/drivers/net/wireless/libertas/cmd.c +++ b/drivers/net/wireless/libertas/cmd.c @@ -912,6 +912,10 @@ static int wlan_cmd_set_boot2_ver(wlan_private * priv, return 0; } +/* + * Note: NEVER use libertas_queue_cmd() with addtail==0 other than for + * the command timer, because it does not account for queued commands. + */ void libertas_queue_cmd(wlan_adapter * adapter, struct cmd_ctrl_node *cmdnode, u8 addtail) { unsigned long flags; @@ -941,10 +945,11 @@ void libertas_queue_cmd(wlan_adapter * adapter, struct cmd_ctrl_node *cmdnode, u spin_lock_irqsave(&adapter->driver_lock, flags); - if (addtail) + if (addtail) { list_add_tail((struct list_head *)cmdnode, &adapter->cmdpendingq); - else + adapter->nr_cmd_pending++; + } else list_add((struct list_head *)cmdnode, &adapter->cmdpendingq); spin_unlock_irqrestore(&adapter->driver_lock, flags); @@ -1412,7 +1417,6 @@ int libertas_prepare_and_send_command(wlan_private * priv, cmdnode->cmdwaitqwoken = 0; libertas_queue_cmd(adapter, cmdnode, 1); - adapter->nr_cmd_pending++; wake_up_interruptible(&priv->waitq); if (wait_option & CMD_OPTION_WAITFORRSP) { diff --git a/drivers/net/wireless/libertas/if_cs.c b/drivers/net/wireless/libertas/if_cs.c index 0360cad..ba4fc2b 100644 --- a/drivers/net/wireless/libertas/if_cs.c +++ b/drivers/net/wireless/libertas/if_cs.c @@ -148,11 +148,11 @@ static int if_cs_poll_while_fw_download(struct if_cs_card *card, uint addr, u8 r { int i; - for (i = 0; i < 500; i++) { + for (i = 0; i < 1000; i++) { u8 val = if_cs_read8(card, addr); if (val == reg) return i; - udelay(100); + udelay(500); } return -ETIME; } @@ -170,7 +170,8 @@ static int if_cs_poll_while_fw_download(struct if_cs_card *card, uint addr, u8 r #define IF_CS_H_IC_TX_OVER 0x0001 #define IF_CS_H_IC_RX_OVER 0x0002 #define IF_CS_H_IC_DNLD_OVER 0x0004 -#define IF_CS_H_IC_HOST_EVENT 0x0008 +#define IF_CS_H_IC_POWER_DOWN 0x0008 +#define IF_CS_H_IC_HOST_EVENT 0x0010 #define IF_CS_H_IC_MASK 0x001f #define IF_CS_H_INT_MASK 0x00000004 @@ -878,6 +879,9 @@ static int if_cs_probe(struct pcmcia_device *p_dev) goto out3; } + /* Clear any interrupt cause that happend while sending + * firmware/initializing card */ + if_cs_write16(card, IF_CS_C_INT_CAUSE, IF_CS_C_IC_MASK); if_cs_enable_ints(card); /* And finally bring the card up */ diff --git a/drivers/net/wireless/libertas/if_sdio.c b/drivers/net/wireless/libertas/if_sdio.c index a8e1707..b24425f 100644 --- a/drivers/net/wireless/libertas/if_sdio.c +++ b/drivers/net/wireless/libertas/if_sdio.c @@ -182,12 +182,14 @@ static int if_sdio_handle_data(struct if_sdio_card *card, goto out; } - skb = dev_alloc_skb(MRVDRV_ETH_RX_PACKET_BUFFER_SIZE); + skb = dev_alloc_skb(MRVDRV_ETH_RX_PACKET_BUFFER_SIZE + NET_IP_ALIGN); if (!skb) { ret = -ENOMEM; goto out; } + skb_reserve(skb, NET_IP_ALIGN); + data = skb_put(skb, size); memcpy(data, buffer, size); diff --git a/drivers/net/wireless/libertas/main.c b/drivers/net/wireless/libertas/main.c index 5ead083..1823b48 100644 --- a/drivers/net/wireless/libertas/main.c +++ b/drivers/net/wireless/libertas/main.c @@ -1165,8 +1165,6 @@ wlan_private *libertas_add_card(void *card, struct device *dmdev) #ifdef WIRELESS_EXT dev->wireless_handlers = (struct iw_handler_def *)&libertas_handler_def; #endif -#define NETIF_F_DYNALLOC 16 - dev->features |= NETIF_F_DYNALLOC; dev->flags |= IFF_BROADCAST | IFF_MULTICAST; dev->set_multicast_list = libertas_set_multicast_list; @@ -1348,8 +1346,6 @@ int libertas_add_mesh(wlan_private *priv, struct device *dev) #ifdef WIRELESS_EXT mesh_dev->wireless_handlers = (struct iw_handler_def *)&mesh_handler_def; #endif -#define NETIF_F_DYNALLOC 16 - /* Register virtual mesh interface */ ret = register_netdev(mesh_dev); if (ret) { diff --git a/drivers/net/wireless/libertas/wext.c b/drivers/net/wireless/libertas/wext.c index c6f5aa3..395b788 100644 --- a/drivers/net/wireless/libertas/wext.c +++ b/drivers/net/wireless/libertas/wext.c @@ -1528,7 +1528,7 @@ static int wlan_set_encodeext(struct net_device *dev, && (ext->key_len != KEY_LEN_WPA_TKIP)) || ((alg == IW_ENCODE_ALG_CCMP) && (ext->key_len != KEY_LEN_WPA_AES))) { - lbs_deb_wext("invalid size %d for key of alg" + lbs_deb_wext("invalid size %d for key of alg " "type %d\n", ext->key_len, alg); diff --git a/drivers/net/wireless/netwave_cs.c b/drivers/net/wireless/netwave_cs.c index 2402cb8..d2fa079 100644 --- a/drivers/net/wireless/netwave_cs.c +++ b/drivers/net/wireless/netwave_cs.c @@ -806,7 +806,7 @@ static int netwave_pcmcia_config(struct pcmcia_device *link) { for (i = 0; i < 6; i++) dev->dev_addr[i] = readb(ramBase + NETWAVE_EREG_PA + i); - printk(KERN_INFO "%s: Netwave: port %#3lx, irq %d, mem %lx" + printk(KERN_INFO "%s: Netwave: port %#3lx, irq %d, mem %lx, " "id %c%c, hw_addr %s\n", dev->name, dev->base_addr, dev->irq, (u_long) ramBase, diff --git a/drivers/net/wireless/p54usb.c b/drivers/net/wireless/p54usb.c index 755482a..60d286e 100644 --- a/drivers/net/wireless/p54usb.c +++ b/drivers/net/wireless/p54usb.c @@ -308,7 +308,7 @@ static int p54u_read_eeprom(struct ieee80211_hw *dev) buf = kmalloc(0x2020, GFP_KERNEL); if (!buf) { - printk(KERN_ERR "prism54usb: cannot allocate memory for" + printk(KERN_ERR "prism54usb: cannot allocate memory for " "eeprom readback!\n"); return -ENOMEM; } diff --git a/drivers/net/wireless/rt2x00/rt2500pci.c b/drivers/net/wireless/rt2x00/rt2500pci.c index ff2d632..702321c 100644 --- a/drivers/net/wireless/rt2x00/rt2500pci.c +++ b/drivers/net/wireless/rt2x00/rt2500pci.c @@ -620,7 +620,7 @@ static void rt2500pci_link_tuner(struct rt2x00_dev *rt2x00dev) * up to version C the link tuning should halt after 20 * seconds. */ - if (rt2x00_get_rev(&rt2x00dev->chip) < RT2560_VERSION_D && + if (rt2x00_rev(&rt2x00dev->chip) < RT2560_VERSION_D && rt2x00dev->link.count > 20) return; @@ -630,7 +630,7 @@ static void rt2500pci_link_tuner(struct rt2x00_dev *rt2x00dev) * Chipset versions C and lower should directly continue * to the dynamic CCA tuning. */ - if (rt2x00_get_rev(&rt2x00dev->chip) < RT2560_VERSION_D) + if (rt2x00_rev(&rt2x00dev->chip) < RT2560_VERSION_D) goto dynamic_cca_tune; /* diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c index 7cdc80a..50775f9 100644 --- a/drivers/net/wireless/rt2x00/rt2500usb.c +++ b/drivers/net/wireless/rt2x00/rt2500usb.c @@ -753,7 +753,7 @@ static int rt2500usb_init_registers(struct rt2x00_dev *rt2x00dev) rt2x00_set_field16(®, MAC_CSR1_HOST_READY, 1); rt2500usb_register_write(rt2x00dev, MAC_CSR1, reg); - if (rt2x00_get_rev(&rt2x00dev->chip) >= RT2570_VERSION_C) { + if (rt2x00_rev(&rt2x00dev->chip) >= RT2570_VERSION_C) { rt2500usb_register_read(rt2x00dev, PHY_CSR2, ®); reg &= ~0x0002; } else { @@ -1032,7 +1032,7 @@ static void rt2500usb_write_tx_desc(struct rt2x00_dev *rt2x00dev, } static int rt2500usb_get_tx_data_len(struct rt2x00_dev *rt2x00dev, - int maxpacket, struct sk_buff *skb) + struct sk_buff *skb) { int length; @@ -1041,7 +1041,7 @@ static int rt2500usb_get_tx_data_len(struct rt2x00_dev *rt2x00dev, * but it must _not_ be a multiple of the USB packet size. */ length = roundup(skb->len, 2); - length += (2 * !(length % maxpacket)); + length += (2 * !(length % rt2x00dev->usb_maxpacket)); return length; } @@ -1257,7 +1257,7 @@ static int rt2500usb_init_eeprom(struct rt2x00_dev *rt2x00dev) rt2500usb_register_read(rt2x00dev, MAC_CSR0, ®); rt2x00_set_chip(rt2x00dev, RT2570, value, reg); - if (rt2x00_rev(&rt2x00dev->chip, 0xffff0)) { + if (!rt2x00_check_rev(&rt2x00dev->chip, 0)) { ERROR(rt2x00dev, "Invalid RT chipset detected.\n"); return -ENODEV; } @@ -1643,7 +1643,6 @@ static int rt2500usb_beacon_update(struct ieee80211_hw *hw, struct data_entry *beacon; struct data_entry *guardian; int pipe = usb_sndbulkpipe(usb_dev, 1); - int max_packet = usb_maxpacket(usb_dev, pipe, 1); int length; /* @@ -1672,7 +1671,7 @@ static int rt2500usb_beacon_update(struct ieee80211_hw *hw, ring->desc_size), skb->len - ring->desc_size, control); - length = rt2500usb_get_tx_data_len(rt2x00dev, max_packet, skb); + length = rt2500usb_get_tx_data_len(rt2x00dev, skb); usb_fill_bulk_urb(beacon->priv, usb_dev, pipe, skb->data, length, rt2500usb_beacondone, beacon); diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h index 9845e58..c8f16f1 100644 --- a/drivers/net/wireless/rt2x00/rt2x00.h +++ b/drivers/net/wireless/rt2x00/rt2x00.h @@ -418,7 +418,7 @@ struct rt2x00lib_ops { int (*write_tx_data) (struct rt2x00_dev *rt2x00dev, struct data_ring *ring, struct sk_buff *skb, struct ieee80211_tx_control *control); - int (*get_tx_data_len) (struct rt2x00_dev *rt2x00dev, int maxpacket, + int (*get_tx_data_len) (struct rt2x00_dev *rt2x00dev, struct sk_buff *skb); void (*kick_tx_queue) (struct rt2x00_dev *rt2x00dev, unsigned int queue); @@ -599,6 +599,11 @@ struct rt2x00_dev { u32 *rf; /* + * USB Max frame size (for rt2500usb & rt73usb). + */ + u16 usb_maxpacket; + + /* * Current TX power value. */ u16 tx_power; @@ -751,14 +756,16 @@ static inline char rt2x00_rf(const struct rt2x00_chip *chipset, const u16 chip) return (chipset->rf == chip); } -static inline u16 rt2x00_get_rev(const struct rt2x00_chip *chipset) +static inline u16 rt2x00_rev(const struct rt2x00_chip *chipset) { return chipset->rev; } -static inline u16 rt2x00_rev(const struct rt2x00_chip *chipset, const u32 mask) +static inline u16 rt2x00_check_rev(const struct rt2x00_chip *chipset, + const u32 rev) { - return chipset->rev & mask; + return (((chipset->rev & 0xffff0) == rev) && + !!(chipset->rev & 0x0000f)); } /* diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c index 4a6a0bd..85ea8a8 100644 --- a/drivers/net/wireless/rt2x00/rt2x00mac.c +++ b/drivers/net/wireless/rt2x00/rt2x00mac.c @@ -196,6 +196,14 @@ int rt2x00mac_add_interface(struct ieee80211_hw *hw, struct rt2x00_dev *rt2x00dev = hw->priv; struct interface *intf = &rt2x00dev->interface; + /* FIXME: Beaconing is broken in rt2x00. */ + if (conf->type == IEEE80211_IF_TYPE_IBSS || + conf->type == IEEE80211_IF_TYPE_AP) { + ERROR(rt2x00dev, + "rt2x00 does not support Adhoc or Master mode"); + return -EOPNOTSUPP; + } + /* * Don't allow interfaces to be added while * either the device has disappeared or when diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.c b/drivers/net/wireless/rt2x00/rt2x00usb.c index 73cc726..1f5675d 100644 --- a/drivers/net/wireless/rt2x00/rt2x00usb.c +++ b/drivers/net/wireless/rt2x00/rt2x00usb.c @@ -159,7 +159,6 @@ int rt2x00usb_write_tx_data(struct rt2x00_dev *rt2x00dev, interface_to_usbdev(rt2x00dev_usb(rt2x00dev)); struct data_entry *entry = rt2x00_get_data_entry(ring); int pipe = usb_sndbulkpipe(usb_dev, 1); - int max_packet = usb_maxpacket(usb_dev, pipe, 1); u32 length; if (rt2x00_ring_full(ring)) { @@ -194,8 +193,7 @@ int rt2x00usb_write_tx_data(struct rt2x00_dev *rt2x00dev, * length of the data to usb_fill_bulk_urb. Pass the skb * to the driver to determine what the length should be. */ - length = rt2x00dev->ops->lib->get_tx_data_len(rt2x00dev, - max_packet, skb); + length = rt2x00dev->ops->lib->get_tx_data_len(rt2x00dev, skb); /* * Initialize URB and send the frame to the device. @@ -490,6 +488,11 @@ int rt2x00usb_probe(struct usb_interface *usb_intf, rt2x00dev->ops = ops; rt2x00dev->hw = hw; + rt2x00dev->usb_maxpacket = + usb_maxpacket(usb_dev, usb_sndbulkpipe(usb_dev, 1), 1); + if (!rt2x00dev->usb_maxpacket) + rt2x00dev->usb_maxpacket = 1; + retval = rt2x00usb_alloc_reg(rt2x00dev); if (retval) goto exit_free_device; diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c index 46c8c08..c0671c2 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.c +++ b/drivers/net/wireless/rt2x00/rt73usb.c @@ -1251,7 +1251,7 @@ static void rt73usb_write_tx_desc(struct rt2x00_dev *rt2x00dev, } static int rt73usb_get_tx_data_len(struct rt2x00_dev *rt2x00dev, - int maxpacket, struct sk_buff *skb) + struct sk_buff *skb) { int length; @@ -1260,7 +1260,7 @@ static int rt73usb_get_tx_data_len(struct rt2x00_dev *rt2x00dev, * but it must _not_ be a multiple of the USB packet size. */ length = roundup(skb->len, 4); - length += (4 * !(length % maxpacket)); + length += (4 * !(length % rt2x00dev->usb_maxpacket)); return length; } @@ -1486,7 +1486,7 @@ static int rt73usb_init_eeprom(struct rt2x00_dev *rt2x00dev) rt73usb_register_read(rt2x00dev, MAC_CSR0, ®); rt2x00_set_chip(rt2x00dev, RT2571, value, reg); - if (!rt2x00_rev(&rt2x00dev->chip, 0x25730)) { + if (!rt2x00_check_rev(&rt2x00dev->chip, 0x25730)) { ERROR(rt2x00dev, "Invalid RT chipset detected.\n"); return -ENODEV; } diff --git a/drivers/net/wireless/strip.c b/drivers/net/wireless/strip.c index 4bd14b3..88efe1b 100644 --- a/drivers/net/wireless/strip.c +++ b/drivers/net/wireless/strip.c @@ -2735,16 +2735,8 @@ static int strip_ioctl(struct tty_struct *tty, struct file *file, return -EFAULT; return set_mac_address(strip_info, &addr); } - /* - * Allow stty to read, but not set, the serial port - */ - - case TCGETS: - case TCGETA: - return n_tty_ioctl(tty, file, cmd, arg); - break; default: - return -ENOIOCTLCMD; + return tty_mode_ioctl(tty, file, cmd, arg); break; } return 0; diff --git a/drivers/oprofile/cpu_buffer.c b/drivers/oprofile/cpu_buffer.c index a83c3db..c93d3d2 100644 --- a/drivers/oprofile/cpu_buffer.c +++ b/drivers/oprofile/cpu_buffer.c @@ -64,6 +64,8 @@ int alloc_cpu_buffers(void) b->head_pos = 0; b->sample_received = 0; b->sample_lost_overflow = 0; + b->backtrace_aborted = 0; + b->sample_invalid_eip = 0; b->cpu = i; INIT_DELAYED_WORK(&b->work, wq_sync_buffer); } @@ -175,6 +177,11 @@ static int log_sample(struct oprofile_cpu_buffer * cpu_buf, unsigned long pc, cpu_buf->sample_received++; + if (pc == ESCAPE_CODE) { + cpu_buf->sample_invalid_eip++; + return 0; + } + if (nr_available_slots(cpu_buf) < 3) { cpu_buf->sample_lost_overflow++; return 0; diff --git a/drivers/oprofile/cpu_buffer.h b/drivers/oprofile/cpu_buffer.h index 49900d9..c66c025 100644 --- a/drivers/oprofile/cpu_buffer.h +++ b/drivers/oprofile/cpu_buffer.h @@ -42,6 +42,7 @@ struct oprofile_cpu_buffer { unsigned long sample_received; unsigned long sample_lost_overflow; unsigned long backtrace_aborted; + unsigned long sample_invalid_eip; int cpu; struct delayed_work work; } ____cacheline_aligned; diff --git a/drivers/oprofile/oprofile_stats.c b/drivers/oprofile/oprofile_stats.c index f0acb66..d1f6d77 100644 --- a/drivers/oprofile/oprofile_stats.c +++ b/drivers/oprofile/oprofile_stats.c @@ -26,6 +26,8 @@ void oprofile_reset_stats(void) cpu_buf = &cpu_buffer[i]; cpu_buf->sample_received = 0; cpu_buf->sample_lost_overflow = 0; + cpu_buf->backtrace_aborted = 0; + cpu_buf->sample_invalid_eip = 0; } atomic_set(&oprofile_stats.sample_lost_no_mm, 0); @@ -61,6 +63,8 @@ void oprofile_create_stats_files(struct super_block * sb, struct dentry * root) &cpu_buf->sample_lost_overflow); oprofilefs_create_ro_ulong(sb, cpudir, "backtrace_aborted", &cpu_buf->backtrace_aborted); + oprofilefs_create_ro_ulong(sb, cpudir, "sample_invalid_eip", + &cpu_buf->sample_invalid_eip); } oprofilefs_create_ro_atomic(sb, dir, "sample_lost_no_mm", diff --git a/drivers/pci/hotplug/acpiphp.h b/drivers/pci/hotplug/acpiphp.h index f6cc0c5..1ef417c 100644 --- a/drivers/pci/hotplug/acpiphp.h +++ b/drivers/pci/hotplug/acpiphp.h @@ -66,7 +66,7 @@ struct slot { char name[SLOT_NAME_SIZE]; }; -/** +/* * struct acpiphp_bridge - PCI bridge information * * for each bridge device in ACPI namespace @@ -97,7 +97,7 @@ struct acpiphp_bridge { }; -/** +/* * struct acpiphp_slot - PCI slot information * * PCI slot information for each *physical* PCI slot @@ -118,7 +118,7 @@ struct acpiphp_slot { }; -/** +/* * struct acpiphp_func - PCI function information * * PCI function information for each object in ACPI namespace @@ -137,7 +137,7 @@ struct acpiphp_func { u32 flags; /* see below */ }; -/** +/* * struct acpiphp_attention_info - device specific attention registration * * ACPI has no generic method of setting/getting attention status diff --git a/drivers/pci/hotplug/acpiphp_core.c b/drivers/pci/hotplug/acpiphp_core.c index a0ca63a..c8c2638 100644 --- a/drivers/pci/hotplug/acpiphp_core.c +++ b/drivers/pci/hotplug/acpiphp_core.c @@ -91,10 +91,10 @@ static struct hotplug_slot_ops acpi_hotplug_slot_ops = { * acpiphp_register_attention - set attention LED callback * @info: must be completely filled with LED callbacks * - * Description: this is used to register a hardware specific ACPI + * Description: This is used to register a hardware specific ACPI * driver that manipulates the attention LED. All the fields in * info must be set. - **/ + */ int acpiphp_register_attention(struct acpiphp_attention_info *info) { int retval = -EINVAL; @@ -112,10 +112,10 @@ int acpiphp_register_attention(struct acpiphp_attention_info *info) * acpiphp_unregister_attention - unset attention LED callback * @info: must match the pointer used to register * - * Description: this is used to un-register a hardware specific acpi + * Description: This is used to un-register a hardware specific acpi * driver that manipulates the attention LED. The pointer to the * info struct must be the same as the one used to set it. - **/ + */ int acpiphp_unregister_attention(struct acpiphp_attention_info *info) { int retval = -EINVAL; @@ -133,7 +133,6 @@ int acpiphp_unregister_attention(struct acpiphp_attention_info *info) * @hotplug_slot: slot to enable * * Actual tasks are done in acpiphp_enable_slot() - * */ static int enable_slot(struct hotplug_slot *hotplug_slot) { @@ -151,7 +150,6 @@ static int enable_slot(struct hotplug_slot *hotplug_slot) * @hotplug_slot: slot to disable * * Actual tasks are done in acpiphp_disable_slot() - * */ static int disable_slot(struct hotplug_slot *hotplug_slot) { @@ -168,15 +166,15 @@ static int disable_slot(struct hotplug_slot *hotplug_slot) } - /** - * set_attention_status - set attention LED +/** + * set_attention_status - set attention LED * @hotplug_slot: slot to set attention LED on * @status: value to set attention LED to (0 or 1) * * attention status LED, so we use a callback that * was registered with us. This allows hardware specific * ACPI implementations to blink the light for us. - **/ + */ static int set_attention_status(struct hotplug_slot *hotplug_slot, u8 status) { int retval = -ENODEV; @@ -199,7 +197,6 @@ static int disable_slot(struct hotplug_slot *hotplug_slot) * * Some platforms may not implement _STA method properly. * In that case, the value returned may not be reliable. - * */ static int get_power_status(struct hotplug_slot *hotplug_slot, u8 *value) { @@ -213,7 +210,7 @@ static int get_power_status(struct hotplug_slot *hotplug_slot, u8 *value) } - /** +/** * get_attention_status - get attention LED status * @hotplug_slot: slot to get status from * @value: returns with value of attention LED @@ -221,8 +218,8 @@ static int get_power_status(struct hotplug_slot *hotplug_slot, u8 *value) * ACPI doesn't have known method to determine the state * of the attention status LED, so we use a callback that * was registered with us. This allows hardware specific - * ACPI implementations to determine its state - **/ + * ACPI implementations to determine its state. + */ static int get_attention_status(struct hotplug_slot *hotplug_slot, u8 *value) { int retval = -EINVAL; @@ -244,8 +241,7 @@ static int get_attention_status(struct hotplug_slot *hotplug_slot, u8 *value) * @value: pointer to store status * * ACPI doesn't provide any formal means to access latch status. - * Instead, we fake latch status from _STA - * + * Instead, we fake latch status from _STA. */ static int get_latch_status(struct hotplug_slot *hotplug_slot, u8 *value) { @@ -265,8 +261,7 @@ static int get_latch_status(struct hotplug_slot *hotplug_slot, u8 *value) * @value: pointer to store status * * ACPI doesn't provide any formal means to access adapter status. - * Instead, we fake adapter status from _STA - * + * Instead, we fake adapter status from _STA. */ static int get_adapter_status(struct hotplug_slot *hotplug_slot, u8 *value) { diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c index 1e125b5..ff1b1c7 100644 --- a/drivers/pci/hotplug/acpiphp_glue.c +++ b/drivers/pci/hotplug/acpiphp_glue.c @@ -82,7 +82,6 @@ static void handle_hotplug_event_func(acpi_handle handle, u32 type, void *contex * 2. has _PS0 method * 3. has _PS3 method * 4. .. - * */ static int is_ejectable(acpi_handle handle) { @@ -986,10 +985,8 @@ static int power_off_slot(struct acpiphp_slot *slot) /** - * acpiphp_max_busnr - return the highest reserved bus number under - * the given bus. + * acpiphp_max_busnr - return the highest reserved bus number under the given bus. * @bus: bus to start search with - * */ static unsigned char acpiphp_max_busnr(struct pci_bus *bus) { @@ -1018,7 +1015,6 @@ static unsigned char acpiphp_max_busnr(struct pci_bus *bus) /** * acpiphp_bus_add - add a new bus to acpi subsystem * @func: acpiphp_func of the bridge - * */ static int acpiphp_bus_add(struct acpiphp_func *func) { @@ -1063,7 +1059,6 @@ acpiphp_bus_add_out: /** * acpiphp_bus_trim - trim a bus from acpi subsystem * @handle: handle to acpi namespace - * */ static int acpiphp_bus_trim(acpi_handle handle) { @@ -1089,7 +1084,6 @@ static int acpiphp_bus_trim(acpi_handle handle) * * This function should be called per *physical slot*, * not per each slot object in ACPI namespace. - * */ static int enable_device(struct acpiphp_slot *slot) { @@ -1185,6 +1179,7 @@ static void disable_bridges(struct pci_bus *bus) /** * disable_device - disable a slot + * @slot: ACPI PHP slot */ static int disable_device(struct acpiphp_slot *slot) { @@ -1240,14 +1235,15 @@ static int disable_device(struct acpiphp_slot *slot) /** * get_slot_status - get ACPI slot status + * @slot: ACPI PHP slot * - * if a slot has _STA for each function and if any one of them - * returned non-zero status, return it + * If a slot has _STA for each function and if any one of them + * returned non-zero status, return it. * - * if a slot doesn't have _STA and if any one of its functions' - * configuration space is configured, return 0x0f as a _STA + * If a slot doesn't have _STA and if any one of its functions' + * configuration space is configured, return 0x0f as a _STA. * - * otherwise return 0 + * Otherwise return 0. */ static unsigned int get_slot_status(struct acpiphp_slot *slot) { @@ -1281,6 +1277,7 @@ static unsigned int get_slot_status(struct acpiphp_slot *slot) /** * acpiphp_eject_slot - physically eject the slot + * @slot: ACPI PHP slot */ int acpiphp_eject_slot(struct acpiphp_slot *slot) { @@ -1314,6 +1311,7 @@ int acpiphp_eject_slot(struct acpiphp_slot *slot) /** * acpiphp_check_bridge - re-enumerate devices + * @bridge: where to begin re-enumeration * * Iterate over all slots under this bridge and make sure that if a * card is present they are enabled, and if not they are disabled. @@ -1538,13 +1536,11 @@ check_sub_bridges(acpi_handle handle, u32 lvl, void *context, void **rv) /** * handle_hotplug_event_bridge - handle ACPI event on bridges - * * @handle: Notify()'ed acpi_handle * @type: Notify code * @context: pointer to acpiphp_bridge structure * - * handles ACPI event notification on {host,p2p} bridges - * + * Handles ACPI event notification on {host,p2p} bridges. */ static void handle_hotplug_event_bridge(acpi_handle handle, u32 type, void *context) { @@ -1634,13 +1630,11 @@ static void handle_hotplug_event_bridge(acpi_handle handle, u32 type, void *cont /** * handle_hotplug_event_func - handle ACPI event on functions (i.e. slots) - * * @handle: Notify()'ed acpi_handle * @type: Notify code * @context: pointer to acpiphp_func structure * - * handles ACPI event notification on slots - * + * Handles ACPI event notification on slots. */ static void handle_hotplug_event_func(acpi_handle handle, u32 type, void *context) { @@ -1705,7 +1699,6 @@ static struct acpi_pci_driver acpi_pci_hp_driver = { /** * acpiphp_glue_init - initializes all PCI hotplug - ACPI glue data structures - * */ int __init acpiphp_glue_init(void) { @@ -1726,7 +1719,7 @@ int __init acpiphp_glue_init(void) /** * acpiphp_glue_exit - terminates all PCI hotplug - ACPI glue data structures * - * This function frees all data allocated in acpiphp_glue_init() + * This function frees all data allocated in acpiphp_glue_init(). */ void acpiphp_glue_exit(void) { @@ -1760,7 +1753,6 @@ int __init acpiphp_get_num_slots(void) * acpiphp_for_each_slot - call function for each slot * @fn: callback function * @data: context to be passed to callback function - * */ static int acpiphp_for_each_slot(acpiphp_callback fn, void *data) { @@ -1786,6 +1778,7 @@ static int acpiphp_for_each_slot(acpiphp_callback fn, void *data) /** * acpiphp_enable_slot - power on slot + * @slot: ACPI PHP slot */ int acpiphp_enable_slot(struct acpiphp_slot *slot) { @@ -1815,6 +1808,7 @@ int acpiphp_enable_slot(struct acpiphp_slot *slot) /** * acpiphp_disable_slot - power off slot + * @slot: ACPI PHP slot */ int acpiphp_disable_slot(struct acpiphp_slot *slot) { diff --git a/drivers/pci/hotplug/acpiphp_ibm.c b/drivers/pci/hotplug/acpiphp_ibm.c index 56829f8..47d26b6 100644 --- a/drivers/pci/hotplug/acpiphp_ibm.c +++ b/drivers/pci/hotplug/acpiphp_ibm.c @@ -134,11 +134,11 @@ static struct acpiphp_attention_info ibm_attention_info = * ibm_slot_from_id - workaround for bad ibm hardware * @id: the slot number that linux refers to the slot by * - * Description: this method returns the aCPI slot descriptor + * Description: This method returns the aCPI slot descriptor * corresponding to the Linux slot number. This descriptor * has info about the aPCI slot id and attention status. * This descriptor must be freed using kfree when done. - **/ + */ static union apci_descriptor *ibm_slot_from_id(int id) { int ind = 0, size; @@ -173,9 +173,9 @@ ibm_slot_done: * @slot: the hotplug_slot to work with * @status: what to set the LED to (0 or 1) * - * Description: this method is registered with the acpiphp module as a - * callback to do the device specific task of setting the LED status - **/ + * Description: This method is registered with the acpiphp module as a + * callback to do the device specific task of setting the LED status. + */ static int ibm_set_attention_status(struct hotplug_slot *slot, u8 status) { union acpi_object args[2]; @@ -213,13 +213,13 @@ static int ibm_set_attention_status(struct hotplug_slot *slot, u8 status) * @slot: the hotplug_slot to work with * @status: returns what the LED is set to (0 or 1) * - * Description: this method is registered with the acpiphp module as a - * callback to do the device specific task of getting the LED status + * Description: This method is registered with the acpiphp module as a + * callback to do the device specific task of getting the LED status. * * Because there is no direct method of getting the LED status directly * from an ACPI call, we read the aPCI table and parse out our * slot descriptor to read the status from that. - **/ + */ static int ibm_get_attention_status(struct hotplug_slot *slot, u8 *status) { union apci_descriptor *ibm_slot; @@ -245,8 +245,8 @@ static int ibm_get_attention_status(struct hotplug_slot *slot, u8 *status) * @event: the event info (device specific) * @context: passed context (our notification struct) * - * Description: this method is registered as a callback with the ACPI - * subsystem it is called when this device has an event to notify the OS of + * Description: This method is registered as a callback with the ACPI + * subsystem it is called when this device has an event to notify the OS of. * * The events actually come from the device as two events that get * synthesized into one event with data by this function. The event @@ -256,7 +256,7 @@ static int ibm_get_attention_status(struct hotplug_slot *slot, u8 *status) * From section 5.6.2.2 of the ACPI 2.0 spec, I understand that the OSPM will * only re-enable the interrupt that causes this event AFTER this method * has returned, thereby enforcing serial access for the notification struct. - **/ + */ static void ibm_handle_events(acpi_handle handle, u32 event, void *context) { u8 detail = event & 0x0f; @@ -279,16 +279,16 @@ static void ibm_handle_events(acpi_handle handle, u32 event, void *context) * ibm_get_table_from_acpi - reads the APLS buffer from ACPI * @bufp: address to pointer to allocate for the table * - * Description: this method reads the APLS buffer in from ACPI and + * Description: This method reads the APLS buffer in from ACPI and * stores the "stripped" table into a single buffer - * it allocates and passes the address back in bufp + * it allocates and passes the address back in bufp. * * If NULL is passed in as buffer, this method only calculates * the size of the table and returns that without filling - * in the buffer + * in the buffer. * - * returns < 0 on error or the size of the table on success - **/ + * Returns < 0 on error or the size of the table on success. + */ static int ibm_get_table_from_acpi(char **bufp) { union acpi_object *package; @@ -349,17 +349,18 @@ read_table_done: /** * ibm_read_apci_table - callback for the sysfs apci_table file * @kobj: the kobject this binary attribute is a part of + * @bin_attr: struct bin_attribute for this file * @buffer: the kernel space buffer to fill * @pos: the offset into the file * @size: the number of bytes requested * - * Description: gets registered with sysfs as the reader callback - * to be executed when /sys/bus/pci/slots/apci_table gets read + * Description: Gets registered with sysfs as the reader callback + * to be executed when /sys/bus/pci/slots/apci_table gets read. * * Since we don't get notified on open and close for this file, * things get really tricky here... - * our solution is to only allow reading the table in all at once - **/ + * our solution is to only allow reading the table in all at once. + */ static ssize_t ibm_read_apci_table(struct kobject *kobj, struct bin_attribute *bin_attr, char *buffer, loff_t pos, size_t size) @@ -385,10 +386,10 @@ static ssize_t ibm_read_apci_table(struct kobject *kobj, * @context: a pointer to our handle to fill when we find the device * @rv: a return value to fill if desired * - * Description: used as a callback when calling acpi_walk_namespace + * Description: Used as a callback when calling acpi_walk_namespace * to find our device. When this method returns non-zero - * acpi_walk_namespace quits its search and returns our value - **/ + * acpi_walk_namespace quits its search and returns our value. + */ static acpi_status __init ibm_find_acpi_device(acpi_handle handle, u32 lvl, void *context, void **rv) { diff --git a/drivers/pci/hotplug/cpqphp_core.c b/drivers/pci/hotplug/cpqphp_core.c index a96b739..7417887 100644 --- a/drivers/pci/hotplug/cpqphp_core.c +++ b/drivers/pci/hotplug/cpqphp_core.c @@ -117,12 +117,10 @@ static inline int is_slot66mhz(struct slot *slot) /** * detect_SMBIOS_pointer - find the System Management BIOS Table in mem region. - * * @begin: begin pointer for region to be scanned. * @end: end pointer for region to be scanned. * - * Returns pointer to the head of the SMBIOS tables (or NULL) - * + * Returns pointer to the head of the SMBIOS tables (or %NULL). */ static void __iomem * detect_SMBIOS_pointer(void __iomem *begin, void __iomem *end) { @@ -157,9 +155,9 @@ static void __iomem * detect_SMBIOS_pointer(void __iomem *begin, void __iomem *e /** * init_SERR - Initializes the per slot SERR generation. + * @ctrl: controller to use * * For unexpected switch opens - * */ static int init_SERR(struct controller * ctrl) { @@ -224,14 +222,15 @@ static int pci_print_IRQ_route (void) /** * get_subsequent_smbios_entry: get the next entry from bios table. - * - * Gets the first entry if previous == NULL - * Otherwise, returns the next entry - * Uses global SMBIOS Table pointer - * + * @smbios_start: where to start in the SMBIOS table + * @smbios_table: location of the SMBIOS table * @curr: %NULL or pointer to previously returned structure * - * returns a pointer to an SMBIOS structure or NULL if none found + * Gets the first entry if previous == NULL; + * otherwise, returns the next entry. + * Uses global SMBIOS Table pointer. + * + * Returns a pointer to an SMBIOS structure or NULL if none found. */ static void __iomem *get_subsequent_smbios_entry(void __iomem *smbios_start, void __iomem *smbios_table, @@ -272,17 +271,18 @@ static void __iomem *get_subsequent_smbios_entry(void __iomem *smbios_start, /** - * get_SMBIOS_entry - * - * @type:SMBIOS structure type to be returned + * get_SMBIOS_entry - return the requested SMBIOS entry or %NULL + * @smbios_start: where to start in the SMBIOS table + * @smbios_table: location of the SMBIOS table + * @type: SMBIOS structure type to be returned * @previous: %NULL or pointer to previously returned structure * - * Gets the first entry of the specified type if previous == NULL + * Gets the first entry of the specified type if previous == %NULL; * Otherwise, returns the next entry of the given type. - * Uses global SMBIOS Table pointer - * Uses get_subsequent_smbios_entry + * Uses global SMBIOS Table pointer. + * Uses get_subsequent_smbios_entry. * - * returns a pointer to an SMBIOS structure or %NULL if none found + * Returns a pointer to an SMBIOS structure or %NULL if none found. */ static void __iomem *get_SMBIOS_entry(void __iomem *smbios_start, void __iomem *smbios_table, @@ -581,7 +581,9 @@ get_slot_mapping(struct pci_bus *bus, u8 bus_num, u8 dev_num, u8 *slot) /** * cpqhp_set_attention_status - Turns the Amber LED for a slot on or off - * + * @ctrl: struct controller to use + * @func: PCI device/function info + * @status: LED control flag: 1 = LED on, 0 = LED off */ static int cpqhp_set_attention_status(struct controller *ctrl, struct pci_func *func, @@ -621,7 +623,8 @@ cpqhp_set_attention_status(struct controller *ctrl, struct pci_func *func, /** * set_attention_status - Turns the Amber LED for a slot on or off - * + * @hotplug_slot: slot to change LED on + * @status: LED control flag */ static int set_attention_status (struct hotplug_slot *hotplug_slot, u8 status) { diff --git a/drivers/pci/hotplug/cpqphp_ctrl.c b/drivers/pci/hotplug/cpqphp_ctrl.c index 856d57b..4018420 100644 --- a/drivers/pci/hotplug/cpqphp_ctrl.c +++ b/drivers/pci/hotplug/cpqphp_ctrl.c @@ -123,7 +123,7 @@ static u8 handle_switch_change(u8 change, struct controller * ctrl) } /** - * cpqhp_find_slot: find the struct slot of given device + * cpqhp_find_slot - find the struct slot of given device * @ctrl: scan lots of this controller * @device: the device id to find */ @@ -305,9 +305,8 @@ static u8 handle_power_fault(u8 change, struct controller * ctrl) /** - * sort_by_size: sort nodes on the list by their length, smallest first. + * sort_by_size - sort nodes on the list by their length, smallest first. * @head: list to sort - * */ static int sort_by_size(struct pci_resource **head) { @@ -354,9 +353,8 @@ static int sort_by_size(struct pci_resource **head) /** - * sort_by_max_size: sort nodes on the list by their length, largest first. + * sort_by_max_size - sort nodes on the list by their length, largest first. * @head: list to sort - * */ static int sort_by_max_size(struct pci_resource **head) { @@ -403,8 +401,10 @@ static int sort_by_max_size(struct pci_resource **head) /** - * do_pre_bridge_resource_split: find node of resources that are unused - * + * do_pre_bridge_resource_split - find node of resources that are unused + * @head: new list head + * @orig_head: original list head + * @alignment: max node size (?) */ static struct pci_resource *do_pre_bridge_resource_split(struct pci_resource **head, struct pci_resource **orig_head, u32 alignment) @@ -477,8 +477,9 @@ static struct pci_resource *do_pre_bridge_resource_split(struct pci_resource **h /** - * do_bridge_resource_split: find one node of resources that aren't in use - * + * do_bridge_resource_split - find one node of resources that aren't in use + * @head: list head + * @alignment: max node size (?) */ static struct pci_resource *do_bridge_resource_split(struct pci_resource **head, u32 alignment) { @@ -525,14 +526,13 @@ error: /** - * get_io_resource: find first node of given size not in ISA aliasing window. + * get_io_resource - find first node of given size not in ISA aliasing window. * @head: list to search * @size: size of node to find, must be a power of two. * - * Description: this function sorts the resource list by size and then returns + * Description: This function sorts the resource list by size and then returns * returns the first node of "size" length that is not in the ISA aliasing * window. If it finds a node larger than "size" it will split it up. - * */ static struct pci_resource *get_io_resource(struct pci_resource **head, u32 size) { @@ -620,7 +620,7 @@ static struct pci_resource *get_io_resource(struct pci_resource **head, u32 size /** - * get_max_resource: get largest node which has at least the given size. + * get_max_resource - get largest node which has at least the given size. * @head: the list to search the node in * @size: the minimum size of the node to find * @@ -712,7 +712,7 @@ static struct pci_resource *get_max_resource(struct pci_resource **head, u32 siz /** - * get_resource: find resource of given size and split up larger ones. + * get_resource - find resource of given size and split up larger ones. * @head: the list to search for resources * @size: the size limit to use * @@ -804,14 +804,14 @@ static struct pci_resource *get_resource(struct pci_resource **head, u32 size) /** - * cpqhp_resource_sort_and_combine: sort nodes by base addresses and clean up. + * cpqhp_resource_sort_and_combine - sort nodes by base addresses and clean up * @head: the list to sort and clean up * * Description: Sorts all of the nodes in the list in ascending order by * their base addresses. Also does garbage collection by * combining adjacent nodes. * - * returns 0 if success + * Returns %0 if success. */ int cpqhp_resource_sort_and_combine(struct pci_resource **head) { @@ -951,9 +951,9 @@ irqreturn_t cpqhp_ctrl_intr(int IRQ, void *data) /** * cpqhp_slot_create - Creates a node and adds it to the proper bus. - * @busnumber - bus where new node is to be located + * @busnumber: bus where new node is to be located * - * Returns pointer to the new node or NULL if unsuccessful + * Returns pointer to the new node or %NULL if unsuccessful. */ struct pci_func *cpqhp_slot_create(u8 busnumber) { @@ -986,7 +986,7 @@ struct pci_func *cpqhp_slot_create(u8 busnumber) * slot_remove - Removes a node from the linked list of slots. * @old_slot: slot to remove * - * Returns 0 if successful, !0 otherwise. + * Returns %0 if successful, !0 otherwise. */ static int slot_remove(struct pci_func * old_slot) { @@ -1026,7 +1026,7 @@ static int slot_remove(struct pci_func * old_slot) * bridge_slot_remove - Removes a node from the linked list of slots. * @bridge: bridge to remove * - * Returns 0 if successful, !0 otherwise. + * Returns %0 if successful, !0 otherwise. */ static int bridge_slot_remove(struct pci_func *bridge) { @@ -1071,7 +1071,7 @@ out: * cpqhp_slot_find - Looks for a node by bus, and device, multiple functions accessed * @bus: bus to find * @device: device to find - * @index: is 0 for first function found, 1 for the second... + * @index: is %0 for first function found, %1 for the second... * * Returns pointer to the node if successful, %NULL otherwise. */ @@ -1115,16 +1115,13 @@ static int is_bridge(struct pci_func * func) /** - * set_controller_speed - set the frequency and/or mode of a specific - * controller segment. - * + * set_controller_speed - set the frequency and/or mode of a specific controller segment. * @ctrl: controller to change frequency/mode for. * @adapter_speed: the speed of the adapter we want to match. * @hp_slot: the slot number where the adapter is installed. * - * Returns 0 if we successfully change frequency and/or mode to match the + * Returns %0 if we successfully change frequency and/or mode to match the * adapter speed. - * */ static u8 set_controller_speed(struct controller *ctrl, u8 adapter_speed, u8 hp_slot) { @@ -1253,13 +1250,14 @@ static u8 set_controller_speed(struct controller *ctrl, u8 adapter_speed, u8 hp_ /** * board_replaced - Called after a board has been replaced in the system. + * @func: PCI device/function information + * @ctrl: hotplug controller * - * This is only used if we don't have resources for hot add - * Turns power on for the board - * Checks to see if board is the same - * If board is same, reconfigures it + * This is only used if we don't have resources for hot add. + * Turns power on for the board. + * Checks to see if board is the same. + * If board is same, reconfigures it. * If board isn't same, turns it back off. - * */ static u32 board_replaced(struct pci_func *func, struct controller *ctrl) { @@ -1403,10 +1401,11 @@ static u32 board_replaced(struct pci_func *func, struct controller *ctrl) /** * board_added - Called after a board has been added to the system. + * @func: PCI device/function info + * @ctrl: hotplug controller * - * Turns power on for the board - * Configures board - * + * Turns power on for the board. + * Configures board. */ static u32 board_added(struct pci_func *func, struct controller *ctrl) { @@ -1607,8 +1606,10 @@ static u32 board_added(struct pci_func *func, struct controller *ctrl) /** - * remove_board - Turns off slot and LED's - * + * remove_board - Turns off slot and LEDs + * @func: PCI device/function info + * @replace_flag: whether replacing or adding a new device + * @ctrl: target controller */ static u32 remove_board(struct pci_func * func, u32 replace_flag, struct controller * ctrl) { @@ -1902,11 +1903,11 @@ static void interrupt_event_handler(struct controller *ctrl) /** - * cpqhp_pushbutton_thread + * cpqhp_pushbutton_thread - handle pushbutton events + * @slot: target slot (struct) * - * Scheduled procedure to handle blocking stuff for the pushbuttons + * Scheduled procedure to handle blocking stuff for the pushbuttons. * Handles all pending events and exits. - * */ void cpqhp_pushbutton_thread(unsigned long slot) { @@ -2137,9 +2138,10 @@ int cpqhp_process_SS(struct controller *ctrl, struct pci_func *func) } /** - * switch_leds: switch the leds, go from one site to the other. + * switch_leds - switch the leds, go from one site to the other. * @ctrl: controller to use * @num_of_slots: number of slots to use + * @work_LED: LED control value * @direction: 1 to start from the left side, 0 to start right. */ static void switch_leds(struct controller *ctrl, const int num_of_slots, @@ -2165,11 +2167,11 @@ static void switch_leds(struct controller *ctrl, const int num_of_slots, } /** - * hardware_test - runs hardware tests + * cpqhp_hardware_test - runs hardware tests + * @ctrl: target controller + * @test_num: the number written to the "test" file in sysfs. * * For hot plug ctrl folks to play with. - * test_num is the number written to the "test" file in sysfs - * */ int cpqhp_hardware_test(struct controller *ctrl, int test_num) { @@ -2249,14 +2251,12 @@ int cpqhp_hardware_test(struct controller *ctrl, int test_num) /** * configure_new_device - Configures the PCI header information of one board. - * * @ctrl: pointer to controller structure * @func: pointer to function structure * @behind_bridge: 1 if this is a recursive call, 0 if not * @resources: pointer to set of resource lists * - * Returns 0 if success - * + * Returns 0 if success. */ static u32 configure_new_device(struct controller * ctrl, struct pci_func * func, u8 behind_bridge, struct resource_lists * resources) @@ -2346,15 +2346,13 @@ static u32 configure_new_device(struct controller * ctrl, struct pci_func * func /** * configure_new_function - Configures the PCI header information of one device - * * @ctrl: pointer to controller structure * @func: pointer to function structure * @behind_bridge: 1 if this is a recursive call, 0 if not * @resources: pointer to set of resource lists * * Calls itself recursively for bridged devices. - * Returns 0 if success - * + * Returns 0 if success. */ static int configure_new_function(struct controller *ctrl, struct pci_func *func, u8 behind_bridge, diff --git a/drivers/pci/hotplug/fakephp.c b/drivers/pci/hotplug/fakephp.c index 027f686..d7a293e 100644 --- a/drivers/pci/hotplug/fakephp.c +++ b/drivers/pci/hotplug/fakephp.c @@ -165,11 +165,11 @@ static void remove_slot(struct dummy_slot *dslot) } /** - * Rescan slot. - * Tries hard not to re-enable already existing devices - * also handles scanning of subfunctions + * pci_rescan_slot - Rescan slot + * @temp: Device template. Should be set: bus and devfn. * - * @param temp Device template. Should be set: bus and devfn. + * Tries hard not to re-enable already existing devices; + * also handles scanning of subfunctions. */ static void pci_rescan_slot(struct pci_dev *temp) { @@ -229,10 +229,10 @@ static void pci_rescan_slot(struct pci_dev *temp) /** - * Rescan PCI bus. - * call pci_rescan_slot for each possible function of the bus + * pci_rescan_bus - Rescan PCI bus + * @bus: the PCI bus to rescan * - * @param bus + * Call pci_rescan_slot for each possible function of the bus. */ static void pci_rescan_bus(const struct pci_bus *bus) { diff --git a/drivers/pci/hotplug/pciehp_ctrl.c b/drivers/pci/hotplug/pciehp_ctrl.c index c8cb49c..f1e0966 100644 --- a/drivers/pci/hotplug/pciehp_ctrl.c +++ b/drivers/pci/hotplug/pciehp_ctrl.c @@ -208,10 +208,10 @@ static void set_slot_off(struct controller *ctrl, struct slot * pslot) /** * board_added - Called after a board has been added to the system. + * @p_slot: &slot where board is added * - * Turns power on for the board - * Configures board - * + * Turns power on for the board. + * Configures board. */ static int board_added(struct slot *p_slot) { @@ -276,8 +276,8 @@ err_exit: } /** - * remove_board - Turns off slot and LED's - * + * remove_board - Turns off slot and LEDs + * @p_slot: slot where board is being removed */ static int remove_board(struct slot *p_slot) { @@ -319,11 +319,11 @@ struct power_work_info { }; /** - * pciehp_pushbutton_thread + * pciehp_power_thread - handle pushbutton events + * @work: &struct work_struct describing work to be done * - * Scheduled procedure to handle blocking stuff for the pushbuttons + * Scheduled procedure to handle blocking stuff for the pushbuttons. * Handles all pending events and exits. - * */ static void pciehp_power_thread(struct work_struct *work) { diff --git a/drivers/pci/hotplug/rpadlpar_core.c b/drivers/pci/hotplug/rpadlpar_core.c index deb6b5e..b169b0e 100644 --- a/drivers/pci/hotplug/rpadlpar_core.c +++ b/drivers/pci/hotplug/rpadlpar_core.c @@ -100,6 +100,7 @@ static struct device_node *find_dlpar_node(char *drc_name, int *node_type) /** * find_php_slot - return hotplug slot structure for device node + * @dn: target &device_node * * This routine will return the hotplug slot structure * for a given device node. Note that built-in PCI slots @@ -293,9 +294,8 @@ static int dlpar_add_vio_slot(char *drc_name, struct device_node *dn) * dlpar_add_slot - DLPAR add an I/O Slot * @drc_name: drc-name of newly added slot * - * Make the hotplug module and the kernel aware - * of a newly added I/O Slot. - * Return Codes - + * Make the hotplug module and the kernel aware of a newly added I/O Slot. + * Return Codes: * 0 Success * -ENODEV Not a valid drc_name * -EINVAL Slot already added @@ -339,9 +339,9 @@ exit: /** * dlpar_remove_vio_slot - DLPAR remove a virtual I/O Slot * @drc_name: drc-name of newly added slot + * @dn: &device_node * - * Remove the kernel and hotplug representations - * of an I/O Slot. + * Remove the kernel and hotplug representations of an I/O Slot. * Return Codes: * 0 Success * -EINVAL Vio dev doesn't exist @@ -359,11 +359,11 @@ static int dlpar_remove_vio_slot(char *drc_name, struct device_node *dn) } /** - * dlpar_remove_slot - DLPAR remove a PCI I/O Slot + * dlpar_remove_pci_slot - DLPAR remove a PCI I/O Slot * @drc_name: drc-name of newly added slot + * @dn: &device_node * - * Remove the kernel and hotplug representations - * of a PCI I/O Slot. + * Remove the kernel and hotplug representations of a PCI I/O Slot. * Return Codes: * 0 Success * -ENODEV Not a valid drc_name @@ -405,8 +405,7 @@ int dlpar_remove_pci_slot(char *drc_name, struct device_node *dn) * dlpar_remove_slot - DLPAR remove an I/O Slot * @drc_name: drc-name of newly added slot * - * Remove the kernel and hotplug representations - * of an I/O Slot. + * Remove the kernel and hotplug representations of an I/O Slot. * Return Codes: * 0 Success * -ENODEV Not a valid drc_name diff --git a/drivers/pci/hotplug/rpaphp_core.c b/drivers/pci/hotplug/rpaphp_core.c index 458c08e..58f1a99 100644 --- a/drivers/pci/hotplug/rpaphp_core.c +++ b/drivers/pci/hotplug/rpaphp_core.c @@ -54,10 +54,12 @@ module_param(debug, bool, 0644); /** * set_attention_status - set attention LED + * @hotplug_slot: target &hotplug_slot + * @value: LED control value + * * echo 0 > attention -- set LED OFF * echo 1 > attention -- set LED ON * echo 2 > attention -- set LED ID(identify, light is blinking) - * */ static int set_attention_status(struct hotplug_slot *hotplug_slot, u8 value) { @@ -99,6 +101,8 @@ static int get_power_status(struct hotplug_slot *hotplug_slot, u8 * value) /** * get_attention_status - get attention LED status + * @hotplug_slot: slot to get status + * @value: pointer to store status */ static int get_attention_status(struct hotplug_slot *hotplug_slot, u8 * value) { @@ -254,6 +258,11 @@ static int is_php_type(char *drc_type) /** * is_php_dn() - return 1 if this is a hotpluggable pci slot, else 0 + * @dn: target &device_node + * @indexes: passed to get_children_props() + * @names: passed to get_children_props() + * @types: returned from get_children_props() + * @power_domains: * * This routine will return true only if the device node is * a hotpluggable slot. This routine will return false @@ -279,7 +288,7 @@ static int is_php_dn(struct device_node *dn, const int **indexes, /** * rpaphp_add_slot -- declare a hotplug slot to the hotplug subsystem. - * @dn device node of slot + * @dn: device node of slot * * This subroutine will register a hotplugable slot with the * PCI hotplug infrastructure. This routine is typicaly called @@ -291,7 +300,7 @@ static int is_php_dn(struct device_node *dn, const int **indexes, * routine will just return without doing anything, since embedded * slots cannot be hotplugged. * - * To remove a slot, it suffices to call rpaphp_deregister_slot() + * To remove a slot, it suffices to call rpaphp_deregister_slot(). */ int rpaphp_add_slot(struct device_node *dn) { diff --git a/drivers/pci/hotplug/rpaphp_pci.c b/drivers/pci/hotplug/rpaphp_pci.c index 54ca865..0de8453 100644 --- a/drivers/pci/hotplug/rpaphp_pci.c +++ b/drivers/pci/hotplug/rpaphp_pci.c @@ -79,6 +79,7 @@ static void set_slot_name(struct slot *slot) /** * rpaphp_enable_slot - record slot state, config pci device + * @slot: target &slot * * Initialize values in the slot, and the hotplug_slot info * structures to indicate if there is a pci card plugged into diff --git a/drivers/pci/hotplug/shpchp_ctrl.c b/drivers/pci/hotplug/shpchp_ctrl.c index d2fc355..eb5cac6 100644 --- a/drivers/pci/hotplug/shpchp_ctrl.c +++ b/drivers/pci/hotplug/shpchp_ctrl.c @@ -231,10 +231,10 @@ static int fix_bus_speed(struct controller *ctrl, struct slot *pslot, /** * board_added - Called after a board has been added to the system. + * @p_slot: target &slot * - * Turns power on for the board - * Configures board - * + * Turns power on for the board. + * Configures board. */ static int board_added(struct slot *p_slot) { @@ -350,8 +350,8 @@ err_exit: /** - * remove_board - Turns off slot and LED's - * + * remove_board - Turns off slot and LEDs + * @p_slot: target &slot */ static int remove_board(struct slot *p_slot) { @@ -397,11 +397,11 @@ struct pushbutton_work_info { }; /** - * shpchp_pushbutton_thread + * shpchp_pushbutton_thread - handle pushbutton events + * @work: &struct work_struct to be handled * - * Scheduled procedure to handle blocking stuff for the pushbuttons + * Scheduled procedure to handle blocking stuff for the pushbuttons. * Handles all pending events and exits. - * */ static void shpchp_pushbutton_thread(struct work_struct *work) { diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c index 1b7b281..7d18773 100644 --- a/drivers/pci/pci-sysfs.c +++ b/drivers/pci/pci-sysfs.c @@ -702,8 +702,10 @@ static int __init pci_sysfs_init(void) sysfs_initialized = 1; for_each_pci_dev(pdev) { retval = pci_create_sysfs_dev_files(pdev); - if (retval) + if (retval) { + pci_dev_put(pdev); return retval; + } } return 0; diff --git a/drivers/pci/pcie/aer/aerdrv_core.c b/drivers/pci/pcie/aer/aerdrv_core.c index 92a8469..3c0d8d1 100644 --- a/drivers/pci/pcie/aer/aerdrv_core.c +++ b/drivers/pci/pcie/aer/aerdrv_core.c @@ -168,11 +168,11 @@ static int find_device_iter(struct device *device, void *data) /** * find_source_device - search through device hierarchy for source device - * @p_dev: pointer to Root Port pci_dev data structure + * @parent: pointer to Root Port pci_dev data structure * @id: device ID of agent who sends an error message to this Root Port * * Invoked when error is detected at the Root Port. - **/ + */ static struct device* find_source_device(struct pci_dev *parent, u16 id) { struct pci_dev *dev = parent; @@ -286,14 +286,15 @@ static void report_resume(struct pci_dev *dev, void *data) /** * broadcast_error_message - handle message broadcast to downstream drivers - * @device: pointer to from where in a hierarchy message is broadcasted down - * @api: callback to be broadcasted + * @dev: pointer to from where in a hierarchy message is broadcasted down * @state: error state + * @error_mesg: message to print + * @cb: callback to be broadcasted * * Invoked during error recovery process. Once being invoked, the content * of error severity will be broadcasted to all downstream drivers in a * hierarchy in question. - **/ + */ static pci_ers_result_t broadcast_error_message(struct pci_dev *dev, enum pci_channel_state state, char *error_mesg, @@ -428,7 +429,7 @@ static pci_ers_result_t reset_link(struct pcie_device *aerdev, * Invoked when an error is nonfatal/fatal. Once being invoked, broadcast * error detected message to all downstream drivers within a hierarchy in * question and return the returned code. - **/ + */ static pci_ers_result_t do_recovery(struct pcie_device *aerdev, struct pci_dev *dev, int severity) @@ -488,7 +489,7 @@ static pci_ers_result_t do_recovery(struct pcie_device *aerdev, * @info: comprehensive error information * * Invoked when an error being detected by Root Port. - **/ + */ static void handle_error_source(struct pcie_device * aerdev, struct pci_dev *dev, struct aer_err_info info) @@ -521,7 +522,7 @@ static void handle_error_source(struct pcie_device * aerdev, * @rpc: pointer to a Root Port data structure * * Invoked when PCIE bus loads AER service driver. - **/ + */ void aer_enable_rootport(struct aer_rpc *rpc) { struct pci_dev *pdev = rpc->rpd->port; @@ -569,7 +570,7 @@ void aer_enable_rootport(struct aer_rpc *rpc) * @rpc: pointer to a Root Port data structure * * Invoked when PCIE bus unloads AER service driver. - **/ + */ static void disable_root_aer(struct aer_rpc *rpc) { struct pci_dev *pdev = rpc->rpd->port; @@ -590,7 +591,7 @@ static void disable_root_aer(struct aer_rpc *rpc) * @rpc: pointer to the root port which holds an error * * Invoked by DPC handler to consume an error. - **/ + */ static struct aer_err_source* get_e_source(struct aer_rpc *rpc) { struct aer_err_source *e_source; @@ -655,7 +656,7 @@ static int get_device_error_info(struct pci_dev *dev, struct aer_err_info *info) * aer_isr_one_error - consume an error detected by root port * @p_device: pointer to error root port service device * @e_src: pointer to an error source - **/ + */ static void aer_isr_one_error(struct pcie_device *p_device, struct aer_err_source *e_src) { @@ -706,7 +707,7 @@ static void aer_isr_one_error(struct pcie_device *p_device, * @work: definition of this work item * * Invoked, as DPC, when root port records new detected error - **/ + */ void aer_isr(struct work_struct *work) { struct aer_rpc *rpc = container_of(work, struct aer_rpc, dpc_handler); @@ -729,7 +730,7 @@ void aer_isr(struct work_struct *work) * @rpc: pointer to a root port device being deleted * * Invoked when AER service unloaded on a specific Root Port - **/ + */ void aer_delete_rootport(struct aer_rpc *rpc) { /* Disable root port AER itself */ @@ -743,7 +744,7 @@ void aer_delete_rootport(struct aer_rpc *rpc) * @dev: pointer to AER pcie device * * Invoked when AER service driver is loaded. - **/ + */ int aer_init(struct pcie_device *dev) { if (aer_osc_setup(dev) && !forceload) diff --git a/drivers/pci/pcie/portdrv_pci.c b/drivers/pci/pcie/portdrv_pci.c index df38364..26057f9 100644 --- a/drivers/pci/pcie/portdrv_pci.c +++ b/drivers/pci/pcie/portdrv_pci.c @@ -217,7 +217,7 @@ static int slot_reset_iter(struct device *device, void *data) static pci_ers_result_t pcie_portdrv_slot_reset(struct pci_dev *dev) { - pci_ers_result_t status; + pci_ers_result_t status = PCI_ERS_RESULT_NONE; int retval; /* If fatal, restore cfg space for possible link reset at upstream */ diff --git a/drivers/pnp/pnpacpi/rsparser.c b/drivers/pnp/pnpacpi/rsparser.c index cd0a204..3c5eb37 100644 --- a/drivers/pnp/pnpacpi/rsparser.c +++ b/drivers/pnp/pnpacpi/rsparser.c @@ -75,6 +75,7 @@ static void pnpacpi_parse_allocated_irqresource(struct pnp_resource_table *res, { int i = 0; int irq; + int p, t; if (!valid_IRQ(gsi)) return; @@ -82,18 +83,27 @@ static void pnpacpi_parse_allocated_irqresource(struct pnp_resource_table *res, while (!(res->irq_resource[i].flags & IORESOURCE_UNSET) && i < PNP_MAX_IRQ) i++; - if (i >= PNP_MAX_IRQ) + if (i >= PNP_MAX_IRQ) { + printk(KERN_ERR "pnpacpi: exceeded the max number of IRQ " + "resources: %d \n", PNP_MAX_IRQ); return; - -#ifdef CONFIG_X86 - if (gsi < 16 && (triggering != ACPI_EDGE_SENSITIVE || - polarity != ACPI_ACTIVE_HIGH)) { - pnp_warn("BIOS BUG: legacy PNP IRQ %d should be edge trigger, " - "active high", gsi); - triggering = ACPI_EDGE_SENSITIVE; - polarity = ACPI_ACTIVE_HIGH; } -#endif + /* + * in IO-APIC mode, use overrided attribute. Two reasons: + * 1. BIOS bug in DSDT + * 2. BIOS uses IO-APIC mode Interrupt Source Override + */ + if (!acpi_get_override_irq(gsi, &t, &p)) { + t = t ? ACPI_LEVEL_SENSITIVE : ACPI_EDGE_SENSITIVE; + p = p ? ACPI_ACTIVE_LOW : ACPI_ACTIVE_HIGH; + + if (triggering != t || polarity != p) { + pnp_warn("IRQ %d override to %s, %s", + gsi, t ? "edge":"level", p ? "low":"high"); + triggering = t; + polarity = p; + } + } res->irq_resource[i].flags = IORESOURCE_IRQ; // Also clears _UNSET flag res->irq_resource[i].flags |= irq_flags(triggering, polarity); @@ -173,6 +183,9 @@ static void pnpacpi_parse_allocated_dmaresource(struct pnp_resource_table *res, } res->dma_resource[i].start = dma; res->dma_resource[i].end = dma; + } else { + printk(KERN_ERR "pnpacpi: exceeded the max number of DMA " + "resources: %d \n", PNP_MAX_DMA); } } @@ -194,6 +207,9 @@ static void pnpacpi_parse_allocated_ioresource(struct pnp_resource_table *res, } res->port_resource[i].start = io; res->port_resource[i].end = io + len - 1; + } else { + printk(KERN_ERR "pnpacpi: exceeded the max number of IO " + "resources: %d \n", PNP_MAX_PORT); } } @@ -217,6 +233,9 @@ static void pnpacpi_parse_allocated_memresource(struct pnp_resource_table *res, res->mem_resource[i].start = mem; res->mem_resource[i].end = mem + len - 1; + } else { + printk(KERN_ERR "pnpacpi: exceeded the max number of mem " + "resources: %d\n", PNP_MAX_MEM); } } diff --git a/drivers/pnp/resource.c b/drivers/pnp/resource.c index 41d73a5..e50ebcf 100644 --- a/drivers/pnp/resource.c +++ b/drivers/pnp/resource.c @@ -367,8 +367,10 @@ int pnp_check_irq(struct pnp_dev *dev, int idx) { struct pci_dev *pci = NULL; for_each_pci_dev(pci) { - if (pci->irq == *irq) + if (pci->irq == *irq) { + pci_dev_put(pci); return 0; + } } } #endif diff --git a/drivers/ps3/Makefile b/drivers/ps3/Makefile index 746031d..1f5a2d3 100644 --- a/drivers/ps3/Makefile +++ b/drivers/ps3/Makefile @@ -1,6 +1,6 @@ -obj-$(CONFIG_PS3_VUART) += vuart.o +obj-$(CONFIG_PS3_VUART) += ps3-vuart.o obj-$(CONFIG_PS3_PS3AV) += ps3av_mod.o ps3av_mod-objs += ps3av.o ps3av_cmd.o obj-$(CONFIG_PPC_PS3) += sys-manager-core.o -obj-$(CONFIG_PS3_SYS_MANAGER) += sys-manager.o +obj-$(CONFIG_PS3_SYS_MANAGER) += ps3-sys-manager.o obj-$(CONFIG_PS3_STORAGE) += ps3stor_lib.o diff --git a/drivers/ps3/sys-manager.c b/drivers/ps3/ps3-sys-manager.c index 8461b08..8461b08 100644 --- a/drivers/ps3/sys-manager.c +++ b/drivers/ps3/ps3-sys-manager.c diff --git a/drivers/ps3/vuart.c b/drivers/ps3/ps3-vuart.c index 9dea585..9dea585 100644 --- a/drivers/ps3/vuart.c +++ b/drivers/ps3/ps3-vuart.c diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index cbde770..1e6715e 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig @@ -36,7 +36,9 @@ config RTC_HCTOSYS_DEVICE help The RTC device that will be used to (re)initialize the system clock, usually rtc0. Initialization is done when the system - starts up, and when it resumes from a low power state. + starts up, and when it resumes from a low power state. This + device should record time in UTC, since the kernel won't do + timezone correction. The driver for this RTC device must be loaded before late_initcall functions run, so it must usually be statically linked. @@ -133,8 +135,8 @@ config RTC_DRV_DS1307 The first seven registers on these chips hold an RTC, and other registers may add features such as NVRAM, a trickle charger for - the RTC/NVRAM backup power, and alarms. This driver may not - expose all those available chip features. + the RTC/NVRAM backup power, and alarms. NVRAM is visible in + sysfs, but other chip features may not be available. This driver can also be built as a module. If so, the module will be called rtc-ds1307. @@ -445,7 +447,7 @@ config RTC_DRV_AT91RM9200 config RTC_DRV_BFIN tristate "Blackfin On-Chip RTC" - depends on BFIN + depends on BLACKFIN help If you say yes here you will get support for the Blackfin On-Chip Real Time Clock. diff --git a/drivers/rtc/hctosys.c b/drivers/rtc/hctosys.c index 1785272..33c0e98 100644 --- a/drivers/rtc/hctosys.c +++ b/drivers/rtc/hctosys.c @@ -47,8 +47,8 @@ static int __init rtc_hctosys(void) do_settimeofday(&tv); dev_info(rtc->dev.parent, - "setting the system clock to " - "%d-%02d-%02d %02d:%02d:%02d (%u)\n", + "setting system clock to " + "%d-%02d-%02d %02d:%02d:%02d UTC (%u)\n", tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec, (unsigned int) tv.tv_sec); diff --git a/drivers/rtc/interface.c b/drivers/rtc/interface.c index de0da54..a4f56e9 100644 --- a/drivers/rtc/interface.c +++ b/drivers/rtc/interface.c @@ -293,7 +293,7 @@ int rtc_irq_register(struct rtc_device *rtc, struct rtc_task *task) return -EINVAL; /* Cannot register while the char dev is in use */ - if (!(mutex_trylock(&rtc->char_lock))) + if (test_and_set_bit(RTC_DEV_BUSY, &rtc->flags)) return -EBUSY; spin_lock_irq(&rtc->irq_task_lock); @@ -303,7 +303,7 @@ int rtc_irq_register(struct rtc_device *rtc, struct rtc_task *task) } spin_unlock_irq(&rtc->irq_task_lock); - mutex_unlock(&rtc->char_lock); + clear_bit(RTC_DEV_BUSY, &rtc->flags); return retval; } diff --git a/drivers/rtc/rtc-dev.c b/drivers/rtc/rtc-dev.c index 814583b..ae1bf17 100644 --- a/drivers/rtc/rtc-dev.c +++ b/drivers/rtc/rtc-dev.c @@ -26,10 +26,7 @@ static int rtc_dev_open(struct inode *inode, struct file *file) struct rtc_device, char_dev); const struct rtc_class_ops *ops = rtc->ops; - /* We keep the lock as long as the device is in use - * and return immediately if busy - */ - if (!(mutex_trylock(&rtc->char_lock))) + if (test_and_set_bit(RTC_DEV_BUSY, &rtc->flags)) return -EBUSY; file->private_data = rtc; @@ -43,8 +40,8 @@ static int rtc_dev_open(struct inode *inode, struct file *file) return 0; } - /* something has gone wrong, release the lock */ - mutex_unlock(&rtc->char_lock); + /* something has gone wrong */ + clear_bit(RTC_DEV_BUSY, &rtc->flags); return err; } @@ -405,7 +402,7 @@ static int rtc_dev_release(struct inode *inode, struct file *file) if (rtc->ops->release) rtc->ops->release(rtc->dev.parent); - mutex_unlock(&rtc->char_lock); + clear_bit(RTC_DEV_BUSY, &rtc->flags); return 0; } @@ -440,7 +437,6 @@ void rtc_dev_prepare(struct rtc_device *rtc) rtc->dev.devt = MKDEV(MAJOR(rtc_devt), rtc->id); - mutex_init(&rtc->char_lock); #ifdef CONFIG_RTC_INTF_DEV_UIE_EMUL INIT_WORK(&rtc->uie_task, rtc_uie_task); setup_timer(&rtc->uie_timer, rtc_uie_timer, (unsigned long)rtc); diff --git a/drivers/rtc/rtc-ds1307.c b/drivers/rtc/rtc-ds1307.c index db6f3f0..bc1c7fe 100644 --- a/drivers/rtc/rtc-ds1307.c +++ b/drivers/rtc/rtc-ds1307.c @@ -89,6 +89,7 @@ enum ds_type { struct ds1307 { u8 reg_addr; + bool has_nvram; u8 regs[8]; enum ds_type type; struct i2c_msg msg[2]; @@ -242,6 +243,87 @@ static const struct rtc_class_ops ds13xx_rtc_ops = { .set_time = ds1307_set_time, }; +/*----------------------------------------------------------------------*/ + +#define NVRAM_SIZE 56 + +static ssize_t +ds1307_nvram_read(struct kobject *kobj, struct bin_attribute *attr, + char *buf, loff_t off, size_t count) +{ + struct i2c_client *client; + struct ds1307 *ds1307; + struct i2c_msg msg[2]; + int result; + + client = to_i2c_client(container_of(kobj, struct device, kobj)); + ds1307 = i2c_get_clientdata(client); + + if (unlikely(off >= NVRAM_SIZE)) + return 0; + if ((off + count) > NVRAM_SIZE) + count = NVRAM_SIZE - off; + if (unlikely(!count)) + return count; + + msg[0].addr = client->addr; + msg[0].flags = 0; + msg[0].len = 1; + msg[0].buf = buf; + + buf[0] = 8 + off; + + msg[1].addr = client->addr; + msg[1].flags = I2C_M_RD; + msg[1].len = count; + msg[1].buf = buf; + + result = i2c_transfer(to_i2c_adapter(client->dev.parent), msg, 2); + if (result != 2) { + dev_err(&client->dev, "%s error %d\n", "nvram read", result); + return -EIO; + } + return count; +} + +static ssize_t +ds1307_nvram_write(struct kobject *kobj, struct bin_attribute *attr, + char *buf, loff_t off, size_t count) +{ + struct i2c_client *client; + u8 buffer[NVRAM_SIZE + 1]; + int ret; + + client = to_i2c_client(container_of(kobj, struct device, kobj)); + + if (unlikely(off >= NVRAM_SIZE)) + return -EFBIG; + if ((off + count) > NVRAM_SIZE) + count = NVRAM_SIZE - off; + if (unlikely(!count)) + return count; + + buffer[0] = 8 + off; + memcpy(buffer + 1, buf, count); + + ret = i2c_master_send(client, buffer, count + 1); + return (ret < 0) ? ret : (ret - 1); +} + +static struct bin_attribute nvram = { + .attr = { + .name = "nvram", + .mode = S_IRUGO | S_IWUSR, + .owner = THIS_MODULE, + }, + + .read = ds1307_nvram_read, + .write = ds1307_nvram_write, + .size = NVRAM_SIZE, +}; + +/*----------------------------------------------------------------------*/ + static struct i2c_driver ds1307_driver; static int __devinit ds1307_probe(struct i2c_client *client) @@ -413,6 +495,14 @@ read_rtc: goto exit_free; } + if (chip->nvram56) { + err = sysfs_create_bin_file(&client->dev.kobj, &nvram); + if (err == 0) { + ds1307->has_nvram = true; + dev_info(&client->dev, "56 bytes nvram\n"); + } + } + return 0; exit_bad: @@ -432,6 +522,9 @@ static int __devexit ds1307_remove(struct i2c_client *client) { struct ds1307 *ds1307 = i2c_get_clientdata(client); + if (ds1307->has_nvram) + sysfs_remove_bin_file(&client->dev.kobj, &nvram); + rtc_device_unregister(ds1307->rtc); kfree(ds1307); return 0; diff --git a/drivers/rtc/rtc-ds1553.c b/drivers/rtc/rtc-ds1553.c index bb53c09..d9e848d 100644 --- a/drivers/rtc/rtc-ds1553.c +++ b/drivers/rtc/rtc-ds1553.c @@ -291,7 +291,7 @@ static ssize_t ds1553_nvram_write(struct kobject *kobj, static struct bin_attribute ds1553_nvram_attr = { .attr = { .name = "nvram", - .mode = S_IRUGO | S_IWUGO, + .mode = S_IRUGO | S_IWUSR, }, .size = RTC_OFFSET, .read = ds1553_nvram_read, diff --git a/drivers/rtc/rtc-ds1742.c b/drivers/rtc/rtc-ds1742.c index c535b78..2e73f0b 100644 --- a/drivers/rtc/rtc-ds1742.c +++ b/drivers/rtc/rtc-ds1742.c @@ -160,10 +160,13 @@ static ssize_t ds1742_nvram_write(struct kobject *kobj, static struct bin_attribute ds1742_nvram_attr = { .attr = { .name = "nvram", - .mode = S_IRUGO | S_IWUGO, + .mode = S_IRUGO | S_IWUSR, }, .read = ds1742_nvram_read, .write = ds1742_nvram_write, + /* REVISIT: size in sysfs won't match actual size... if it's + * not a constant, each RTC should have its own attribute. + */ }; static int __devinit ds1742_rtc_probe(struct platform_device *pdev) diff --git a/drivers/rtc/rtc-m48t59.c b/drivers/rtc/rtc-m48t59.c index 2bad163..cd0bbc0 100644 --- a/drivers/rtc/rtc-m48t59.c +++ b/drivers/rtc/rtc-m48t59.c @@ -353,11 +353,12 @@ static ssize_t m48t59_nvram_write(struct kobject *kobj, static struct bin_attribute m48t59_nvram_attr = { .attr = { .name = "nvram", - .mode = S_IRUGO | S_IWUGO, + .mode = S_IRUGO | S_IWUSR, .owner = THIS_MODULE, }, .read = m48t59_nvram_read, .write = m48t59_nvram_write, + .size = M48T59_NVRAM_SIZE, }; static int __devinit m48t59_rtc_probe(struct platform_device *pdev) diff --git a/drivers/rtc/rtc-sh.c b/drivers/rtc/rtc-sh.c index 78277a1..8e8c8b8 100644 --- a/drivers/rtc/rtc-sh.c +++ b/drivers/rtc/rtc-sh.c @@ -351,8 +351,10 @@ static int sh_rtc_read_time(struct device *dev, struct rtc_time *tm) tm->tm_sec, tm->tm_min, tm->tm_hour, tm->tm_mday, tm->tm_mon + 1, tm->tm_year, tm->tm_wday); - if (rtc_valid_tm(tm) < 0) + if (rtc_valid_tm(tm) < 0) { dev_err(dev, "invalid date\n"); + rtc_time_to_tm(0, tm); + } return 0; } @@ -588,7 +590,7 @@ static int __devinit sh_rtc_probe(struct platform_device *pdev) rtc->rtc_dev = rtc_device_register("sh", &pdev->dev, &sh_rtc_ops, THIS_MODULE); - if (IS_ERR(rtc)) { + if (IS_ERR(rtc->rtc_dev)) { ret = PTR_ERR(rtc->rtc_dev); goto err_badmap; } diff --git a/drivers/rtc/rtc-stk17ta8.c b/drivers/rtc/rtc-stk17ta8.c index 8288b6b..a265da7 100644 --- a/drivers/rtc/rtc-stk17ta8.c +++ b/drivers/rtc/rtc-stk17ta8.c @@ -291,7 +291,7 @@ static ssize_t stk17ta8_nvram_write(struct kobject *kobj, static struct bin_attribute stk17ta8_nvram_attr = { .attr = { .name = "nvram", - .mode = S_IRUGO | S_IWUGO, + .mode = S_IRUGO | S_IWUSR, .owner = THIS_MODULE, }, .size = RTC_OFFSET, diff --git a/drivers/s390/cio/css.c b/drivers/s390/cio/css.c index 838f7ac..6db3108 100644 --- a/drivers/s390/cio/css.c +++ b/drivers/s390/cio/css.c @@ -483,7 +483,7 @@ static DECLARE_WORK(css_reprobe_work, reprobe_all); void css_schedule_reprobe(void) { need_reprobe = 1; - queue_work(ccw_device_work, &css_reprobe_work); + queue_work(slow_path_wq, &css_reprobe_work); } EXPORT_SYMBOL_GPL(css_schedule_reprobe); diff --git a/drivers/s390/cio/device_fsm.c b/drivers/s390/cio/device_fsm.c index 8867443..bfad421 100644 --- a/drivers/s390/cio/device_fsm.c +++ b/drivers/s390/cio/device_fsm.c @@ -1034,7 +1034,7 @@ device_trigger_reprobe(struct subchannel *sch) if (sch->schib.pmcw.dev != cdev->private->dev_id.devno) { PREPARE_WORK(&cdev->private->kick_work, ccw_device_move_to_orphanage); - queue_work(ccw_device_work, &cdev->private->kick_work); + queue_work(slow_path_wq, &cdev->private->kick_work); } else ccw_device_start_id(cdev, 0); } diff --git a/drivers/s390/cio/device_id.c b/drivers/s390/cio/device_id.c index f232832..2f6bf46 100644 --- a/drivers/s390/cio/device_id.c +++ b/drivers/s390/cio/device_id.c @@ -113,19 +113,10 @@ __ccw_device_sense_id_start(struct ccw_device *cdev) { struct subchannel *sch; struct ccw1 *ccw; - int ret; sch = to_subchannel(cdev->dev.parent); /* Setup sense channel program. */ ccw = cdev->private->iccws; - if (sch->schib.pmcw.pim != 0x80) { - /* more than one path installed. */ - ccw->cmd_code = CCW_CMD_SUSPEND_RECONN; - ccw->cda = 0; - ccw->count = 0; - ccw->flags = CCW_FLAG_SLI | CCW_FLAG_CC; - ccw++; - } ccw->cmd_code = CCW_CMD_SENSE_ID; ccw->cda = (__u32) __pa (&cdev->private->senseid); ccw->count = sizeof (struct senseid); @@ -133,25 +124,9 @@ __ccw_device_sense_id_start(struct ccw_device *cdev) /* Reset device status. */ memset(&cdev->private->irb, 0, sizeof(struct irb)); + cdev->private->flags.intretry = 0; - /* Try on every path. */ - ret = -ENODEV; - while (cdev->private->imask != 0) { - if ((sch->opm & cdev->private->imask) != 0 && - cdev->private->iretry > 0) { - cdev->private->iretry--; - /* Reset internal retry indication. */ - cdev->private->flags.intretry = 0; - ret = cio_start (sch, cdev->private->iccws, - cdev->private->imask); - /* ret is 0, -EBUSY, -EACCES or -ENODEV */ - if (ret != -EACCES) - return ret; - } - cdev->private->imask >>= 1; - cdev->private->iretry = 5; - } - return ret; + return cio_start(sch, ccw, LPM_ANYPATH); } void @@ -161,8 +136,7 @@ ccw_device_sense_id_start(struct ccw_device *cdev) memset (&cdev->private->senseid, 0, sizeof (struct senseid)); cdev->private->senseid.cu_type = 0xFFFF; - cdev->private->imask = 0x80; - cdev->private->iretry = 5; + cdev->private->iretry = 3; ret = __ccw_device_sense_id_start(cdev); if (ret && ret != -EBUSY) ccw_device_sense_id_done(cdev, ret); @@ -278,14 +252,13 @@ ccw_device_sense_id_irq(struct ccw_device *cdev, enum dev_event dev_event) ccw_device_sense_id_done(cdev, ret); break; case -EACCES: /* channel is not operational. */ - sch->lpm &= ~cdev->private->imask; - cdev->private->imask >>= 1; - cdev->private->iretry = 5; - /* fall through. */ case -EAGAIN: /* try again. */ - ret = __ccw_device_sense_id_start(cdev); - if (ret == 0 || ret == -EBUSY) - break; + cdev->private->iretry--; + if (cdev->private->iretry > 0) { + ret = __ccw_device_sense_id_start(cdev); + if (ret == 0 || ret == -EBUSY) + break; + } /* fall through. */ default: /* Sense ID failed. Try asking VM. */ if (MACHINE_IS_VM) { diff --git a/drivers/s390/net/ctcmain.c b/drivers/s390/net/ctcmain.c index 6bf3ebb..b3b6f65 100644 --- a/drivers/s390/net/ctcmain.c +++ b/drivers/s390/net/ctcmain.c @@ -2782,35 +2782,14 @@ ctc_probe_device(struct ccwgroup_device *cgdev) } /** - * Initialize everything of the net device except the name and the - * channel structs. + * Device setup function called by alloc_netdev(). + * + * @param dev Device to be setup. */ -static struct net_device * -ctc_init_netdevice(struct net_device * dev, int alloc_device, - struct ctc_priv *privptr) +void ctc_init_netdevice(struct net_device * dev) { - if (!privptr) - return NULL; - DBF_TEXT(setup, 3, __FUNCTION__); - if (alloc_device) { - dev = kzalloc(sizeof(struct net_device), GFP_KERNEL); - if (!dev) - return NULL; - } - - dev->priv = privptr; - privptr->fsm = init_fsm("ctcdev", dev_state_names, - dev_event_names, CTC_NR_DEV_STATES, CTC_NR_DEV_EVENTS, - dev_fsm, DEV_FSM_LEN, GFP_KERNEL); - if (privptr->fsm == NULL) { - if (alloc_device) - kfree(dev); - return NULL; - } - fsm_newstate(privptr->fsm, DEV_STATE_STOPPED); - fsm_settimer(privptr->fsm, &privptr->restart_timer); if (dev->mtu == 0) dev->mtu = CTC_BUFSIZE_DEFAULT - LL_HEADER_LENGTH - 2; dev->hard_start_xmit = ctc_tx; @@ -2823,7 +2802,7 @@ ctc_init_netdevice(struct net_device * dev, int alloc_device, dev->type = ARPHRD_SLIP; dev->tx_queue_len = 100; dev->flags = IFF_POINTOPOINT | IFF_NOARP; - return dev; + SET_MODULE_OWNER(dev); } @@ -2879,14 +2858,22 @@ ctc_new_device(struct ccwgroup_device *cgdev) "ccw_device_set_online (cdev[1]) failed with ret = %d\n", ret); } - dev = ctc_init_netdevice(NULL, 1, privptr); - + dev = alloc_netdev(0, "ctc%d", ctc_init_netdevice); if (!dev) { ctc_pr_warn("ctc_init_netdevice failed\n"); goto out; } + dev->priv = privptr; - strlcpy(dev->name, "ctc%d", IFNAMSIZ); + privptr->fsm = init_fsm("ctcdev", dev_state_names, + dev_event_names, CTC_NR_DEV_STATES, CTC_NR_DEV_EVENTS, + dev_fsm, DEV_FSM_LEN, GFP_KERNEL); + if (privptr->fsm == NULL) { + free_netdev(dev); + goto out; + } + fsm_newstate(privptr->fsm, DEV_STATE_STOPPED); + fsm_settimer(privptr->fsm, &privptr->restart_timer); for (direction = READ; direction <= WRITE; direction++) { privptr->channel[direction] = diff --git a/drivers/scsi/aic94xx/aic94xx_sds.c b/drivers/scsi/aic94xx/aic94xx_sds.c index 5b0932f..06509bf 100644 --- a/drivers/scsi/aic94xx/aic94xx_sds.c +++ b/drivers/scsi/aic94xx/aic94xx_sds.c @@ -377,7 +377,7 @@ out: #define FLASH_RESET 0xF0 -#define FLASH_SIZE 0x200000 +#define ASD_FLASH_SIZE 0x200000 #define FLASH_DIR_COOKIE "*** ADAPTEC FLASH DIRECTORY *** " #define FLASH_NEXT_ENTRY_OFFS 0x2000 #define FLASH_MAX_DIR_ENTRIES 32 @@ -609,7 +609,7 @@ static int asd_find_flash_dir(struct asd_ha_struct *asd_ha, struct asd_flash_dir *flash_dir) { u32 v; - for (v = 0; v < FLASH_SIZE; v += FLASH_NEXT_ENTRY_OFFS) { + for (v = 0; v < ASD_FLASH_SIZE; v += FLASH_NEXT_ENTRY_OFFS) { asd_read_flash_seg(asd_ha, flash_dir, v, sizeof(FLASH_DIR_COOKIE)-1); if (memcmp(flash_dir->cookie, FLASH_DIR_COOKIE, diff --git a/drivers/scsi/ide-scsi.c b/drivers/scsi/ide-scsi.c index 8d0244c..7a835a3 100644 --- a/drivers/scsi/ide-scsi.c +++ b/drivers/scsi/ide-scsi.c @@ -242,16 +242,6 @@ static void idescsi_output_buffers (ide_drive_t *drive, idescsi_pc_t *pc, unsign } } -static void hexdump(u8 *x, int len) -{ - int i; - - printk("[ "); - for (i = 0; i < len; i++) - printk("%x ", x[i]); - printk("]\n"); -} - static int idescsi_check_condition(ide_drive_t *drive, struct request *failed_command) { idescsi_scsi_t *scsi = drive_to_idescsi(drive); @@ -282,7 +272,8 @@ static int idescsi_check_condition(ide_drive_t *drive, struct request *failed_co pc->scsi_cmd = ((idescsi_pc_t *) failed_command->special)->scsi_cmd; if (test_bit(IDESCSI_LOG_CMD, &scsi->log)) { printk ("ide-scsi: %s: queue cmd = ", drive->name); - hexdump(pc->c, 6); + print_hex_dump(KERN_CONT, "", DUMP_PREFIX_NONE, 16, 1, pc->c, + 6, 0); } rq->rq_disk = scsi->disk; return ide_do_drive_cmd(drive, rq, ide_preempt); @@ -337,7 +328,8 @@ static int idescsi_end_request (ide_drive_t *drive, int uptodate, int nrsecs) idescsi_pc_t *opc = (idescsi_pc_t *) rq->buffer; if (log) { printk ("ide-scsi: %s: wrap up check %lu, rst = ", drive->name, opc->scsi_cmd->serial_number); - hexdump(pc->buffer,16); + print_hex_dump(KERN_CONT, "", DUMP_PREFIX_NONE, 16, 1, + pc->buffer, 16, 0); } memcpy((void *) opc->scsi_cmd->sense_buffer, pc->buffer, SCSI_SENSE_BUFFERSIZE); kfree(pc->buffer); @@ -816,10 +808,12 @@ static int idescsi_queue (struct scsi_cmnd *cmd, if (test_bit(IDESCSI_LOG_CMD, &scsi->log)) { printk ("ide-scsi: %s: que %lu, cmd = ", drive->name, cmd->serial_number); - hexdump(cmd->cmnd, cmd->cmd_len); + print_hex_dump(KERN_CONT, "", DUMP_PREFIX_NONE, 16, 1, + cmd->cmnd, cmd->cmd_len, 0); if (memcmp(pc->c, cmd->cmnd, cmd->cmd_len)) { printk ("ide-scsi: %s: que %lu, tsl = ", drive->name, cmd->serial_number); - hexdump(pc->c, 12); + print_hex_dump(KERN_CONT, "", DUMP_PREFIX_NONE, 16, 1, + pc->c, 12, 0); } } diff --git a/drivers/scsi/zorro7xx.c b/drivers/scsi/zorro7xx.c index ac67394..64d40a2 100644 --- a/drivers/scsi/zorro7xx.c +++ b/drivers/scsi/zorro7xx.c @@ -13,7 +13,10 @@ #include <linux/init.h> #include <linux/interrupt.h> #include <linux/zorro.h> + +#include <asm/amigahw.h> #include <asm/amigaints.h> + #include <scsi/scsi_host.h> #include <scsi/scsi_transport_spi.h> diff --git a/drivers/serial/8250_pnp.c b/drivers/serial/8250_pnp.c index 926f58a..1de098e 100644 --- a/drivers/serial/8250_pnp.c +++ b/drivers/serial/8250_pnp.c @@ -69,6 +69,8 @@ static const struct pnp_device_id pnp_dev_table[] = { { "CTL3001", 0 }, /* Creative Labs Modem Blaster 28.8 DSVD PnP Voice */ { "CTL3011", 0 }, + /* Davicom ISA 33.6K Modem */ + { "DAV0336", 0 }, /* Creative */ /* Creative Modem Blaster Flash56 DI5601-1 */ { "DMB1032", 0 }, @@ -345,6 +347,11 @@ static const struct pnp_device_id pnp_dev_table[] = { /* Fujitsu Wacom Tablet PC devices */ { "FUJ02E5", 0 }, { "FUJ02E6", 0 }, + /* + * LG C1 EXPRESS DUAL (C1-PB11A3) touch screen (actually a FUJ02E6 in + * disguise) + */ + { "LTS0001", 0 }, /* Rockwell's (PORALiNK) 33600 INT PNP */ { "WCI0003", 0 }, /* Unkown PnP modems */ @@ -432,7 +439,8 @@ serial_pnp_probe(struct pnp_dev *dev, const struct pnp_device_id *dev_id) } memset(&port, 0, sizeof(struct uart_port)); - port.irq = pnp_irq(dev, 0); + if (pnp_irq_valid(dev, 0)) + port.irq = pnp_irq(dev, 0); if (pnp_port_valid(dev, 0)) { port.iobase = pnp_port_start(dev, 0); port.iotype = UPIO_PORT; diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig index ed438bc..d7e1996 100644 --- a/drivers/serial/Kconfig +++ b/drivers/serial/Kconfig @@ -600,7 +600,7 @@ config SERIAL_SA1100_CONSOLE config SERIAL_BFIN tristate "Blackfin serial port support" - depends on BFIN + depends on BLACKFIN select SERIAL_CORE select SERIAL_BFIN_UART0 if (BF531 || BF532 || BF533 || BF561) help diff --git a/drivers/serial/atmel_serial.c b/drivers/serial/atmel_serial.c index 4d6b3c5..111da57 100644 --- a/drivers/serial/atmel_serial.c +++ b/drivers/serial/atmel_serial.c @@ -204,8 +204,6 @@ static u_int atmel_get_mctrl(struct uart_port *port) */ static void atmel_stop_tx(struct uart_port *port) { - struct atmel_uart_port *atmel_port = (struct atmel_uart_port *) port; - UART_PUT_IDR(port, ATMEL_US_TXRDY); } @@ -214,8 +212,6 @@ static void atmel_stop_tx(struct uart_port *port) */ static void atmel_start_tx(struct uart_port *port) { - struct atmel_uart_port *atmel_port = (struct atmel_uart_port *) port; - UART_PUT_IER(port, ATMEL_US_TXRDY); } @@ -224,8 +220,6 @@ static void atmel_start_tx(struct uart_port *port) */ static void atmel_stop_rx(struct uart_port *port) { - struct atmel_uart_port *atmel_port = (struct atmel_uart_port *) port; - UART_PUT_IDR(port, ATMEL_US_RXRDY); } @@ -409,7 +403,6 @@ static irqreturn_t atmel_interrupt(int irq, void *dev_id) */ static int atmel_startup(struct uart_port *port) { - struct atmel_uart_port *atmel_port = (struct atmel_uart_port *) port; int retval; /* @@ -456,8 +449,6 @@ static int atmel_startup(struct uart_port *port) */ static void atmel_shutdown(struct uart_port *port) { - struct atmel_uart_port *atmel_port = (struct atmel_uart_port *) port; - /* * Disable all interrupts, port and break condition. */ diff --git a/drivers/serial/crisv10.c b/drivers/serial/crisv10.c index f523cdf..a4e23cf 100644 --- a/drivers/serial/crisv10.c +++ b/drivers/serial/crisv10.c @@ -1,426 +1,10 @@ -/* $Id: serial.c,v 1.25 2004/09/29 10:33:49 starvik Exp $ - * +/* * Serial port driver for the ETRAX 100LX chip * - * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Axis Communications AB + * Copyright (C) 1998-2007 Axis Communications AB * * Many, many authors. Based once upon a time on serial.c for 16x50. * - * $Log: serial.c,v $ - * Revision 1.25 2004/09/29 10:33:49 starvik - * Resolved a dealock when printing debug from kernel. - * - * Revision 1.24 2004/08/27 23:25:59 johana - * rs_set_termios() must call change_speed() if c_iflag has changed or - * automatic XOFF handling will be enabled and transmitter will stop - * if 0x13 is received. - * - * Revision 1.23 2004/08/24 06:57:13 starvik - * More whitespace cleanup - * - * Revision 1.22 2004/08/24 06:12:20 starvik - * Whitespace cleanup - * - * Revision 1.20 2004/05/24 12:00:20 starvik - * Big merge of stuff from Linux 2.4 (e.g. manual mode for the serial port). - * - * Revision 1.19 2004/05/17 13:12:15 starvik - * Kernel console hook - * Big merge from Linux 2.4 still pending. - * - * Revision 1.18 2003/10/28 07:18:30 starvik - * Compiles with debug info - * - * Revision 1.17 2003/07/04 08:27:37 starvik - * Merge of Linux 2.5.74 - * - * Revision 1.16 2003/06/13 10:05:19 johana - * Help the user to avoid trouble by: - * Forcing mixed mode for status/control lines if not all pins are used. - * - * Revision 1.15 2003/06/13 09:43:01 johana - * Merged in the following changes from os/linux/arch/cris/drivers/serial.c - * + some minor changes to reduce diff. - * - * Revision 1.49 2003/05/30 11:31:54 johana - * Merged in change-branch--serial9bit that adds CMSPAR support for sticky - * parity (mark/space) - * - * Revision 1.48 2003/05/30 11:03:57 johana - * Implemented rs_send_xchar() by disabling the DMA and writing manually. - * Added e100_disable_txdma_channel() and e100_enable_txdma_channel(). - * Fixed rs_throttle() and rs_unthrottle() to properly call rs_send_xchar - * instead of setting info->x_char and check the CRTSCTS flag before - * controlling the rts pin. - * - * Revision 1.14 2003/04/09 08:12:44 pkj - * Corrected typo changes made upstream. - * - * Revision 1.13 2003/04/09 05:20:47 starvik - * Merge of Linux 2.5.67 - * - * Revision 1.11 2003/01/22 06:48:37 starvik - * Fixed warnings issued by GCC 3.2.1 - * - * Revision 1.9 2002/12/13 09:07:47 starvik - * Alert user that RX_TIMEOUT_TICKS==0 doesn't work - * - * Revision 1.8 2002/12/11 13:13:57 starvik - * Added arch/ to v10 specific includes - * Added fix from Linux 2.4 in serial.c (flush_to_flip_buffer) - * - * Revision 1.7 2002/12/06 07:13:57 starvik - * Corrected work queue stuff - * Removed CONFIG_ETRAX_SERIAL_FLUSH_DMA_FAST - * - * Revision 1.6 2002/11/21 07:17:46 starvik - * Change static inline to extern inline where otherwise outlined with gcc-3.2 - * - * Revision 1.5 2002/11/14 15:59:49 starvik - * Linux 2.5 port of the latest serial driver from 2.4. The work queue stuff - * probably doesn't work yet. - * - * Revision 1.42 2002/11/05 09:08:47 johana - * Better implementation of rs_stop() and rs_start() that uses the XOFF - * register to start/stop transmission. - * change_speed() also initilises XOFF register correctly so that - * auto_xoff is enabled when IXON flag is set by user. - * This gives fast XOFF response times. - * - * Revision 1.41 2002/11/04 18:40:57 johana - * Implemented rs_stop() and rs_start(). - * Simple tests using hwtestserial indicates that this should be enough - * to make it work. - * - * Revision 1.40 2002/10/14 05:33:18 starvik - * RS-485 uses fast timers even if SERIAL_FAST_TIMER is disabled - * - * Revision 1.39 2002/09/30 21:00:57 johana - * Support for CONFIG_ETRAX_SERx_DTR_RI_DSR_CD_MIXED where the status and - * control pins can be mixed between PA and PB. - * If no serial port uses MIXED old solution is used - * (saves a few bytes and cycles). - * control_pins struct uses masks instead of bit numbers. - * Corrected dummy values and polarity in line_info() so - * /proc/tty/driver/serial is now correct. - * (the E100_xxx_GET() macros is really active low - perhaps not obvious) - * - * Revision 1.38 2002/08/23 11:01:36 starvik - * Check that serial port is enabled in all interrupt handlers to avoid - * restarts of DMA channels not assigned to serial ports - * - * Revision 1.37 2002/08/13 13:02:37 bjornw - * Removed some warnings because of unused code - * - * Revision 1.36 2002/08/08 12:50:01 starvik - * Serial interrupt is shared with synchronous serial port driver - * - * Revision 1.35 2002/06/03 10:40:49 starvik - * Increased RS-485 RTS toggle timer to 2 characters - * - * Revision 1.34 2002/05/28 18:59:36 johana - * Whitespace and comment fixing to be more like etrax100ser.c 1.71. - * - * Revision 1.33 2002/05/28 17:55:43 johana - * RS-485 uses FAST_TIMER if enabled, and starts a short (one char time) - * timer from tranismit_chars (interrupt context). - * The timer toggles RTS in interrupt context when expired giving minimum - * latencies. - * - * Revision 1.32 2002/05/22 13:58:00 johana - * Renamed rs_write() to raw_write() and made it inline. - * New rs_write() handles RS-485 if configured and enabled - * (moved code from e100_write_rs485()). - * RS-485 ioctl's uses copy_from_user() instead of verify_area(). - * - * Revision 1.31 2002/04/22 11:20:03 johana - * Updated copyright years. - * - * Revision 1.30 2002/04/22 09:39:12 johana - * RS-485 support compiles. - * - * Revision 1.29 2002/01/14 16:10:01 pkj - * Allocate the receive buffers dynamically. The static 4kB buffer was - * too small for the peaks. This means that we can get rid of the extra - * buffer and the copying to it. It also means we require less memory - * under normal operations, but can use more when needed (there is a - * cap at 64kB for safety reasons). If there is no memory available - * we panic(), and die a horrible death... - * - * Revision 1.28 2001/12/18 15:04:53 johana - * Cleaned up write_rs485() - now it works correctly without padding extra - * char. - * Added sane default initialisation of rs485. - * Added #ifdef around dummy variables. - * - * Revision 1.27 2001/11/29 17:00:41 pkj - * 2kB seems to be too small a buffer when using 921600 bps, - * so increase it to 4kB (this was already done for the elinux - * version of the serial driver). - * - * Revision 1.26 2001/11/19 14:20:41 pkj - * Minor changes to comments and unused code. - * - * Revision 1.25 2001/11/12 20:03:43 pkj - * Fixed compiler warnings. - * - * Revision 1.24 2001/11/12 15:10:05 pkj - * Total redesign of the receiving part of the serial driver. - * Uses eight chained descriptors to write to a 4kB buffer. - * This data is then serialised into a 2kB buffer. From there it - * is copied into the TTY's flip buffers when they become available. - * A lot of copying, and the sizes of the buffers might need to be - * tweaked, but all in all it should work better than the previous - * version, without the need to modify the TTY code in any way. - * Also note that erroneous bytes are now correctly marked in the - * flag buffers (instead of always marking the first byte). - * - * Revision 1.23 2001/10/30 17:53:26 pkj - * * Set info->uses_dma to 0 when a port is closed. - * * Mark the timer1 interrupt as a fast one (SA_INTERRUPT). - * * Call start_flush_timer() in start_receive() if - * CONFIG_ETRAX_SERIAL_FLUSH_DMA_FAST is defined. - * - * Revision 1.22 2001/10/30 17:44:03 pkj - * Use %lu for received and transmitted counters in line_info(). - * - * Revision 1.21 2001/10/30 17:40:34 pkj - * Clean-up. The only change to functionality is that - * CONFIG_ETRAX_SERIAL_RX_TIMEOUT_TICKS(=5) is used instead of - * MAX_FLUSH_TIME(=8). - * - * Revision 1.20 2001/10/30 15:24:49 johana - * Added char_time stuff from 2.0 driver. - * - * Revision 1.19 2001/10/30 15:23:03 johana - * Merged with 1.13.2 branch + fixed indentation - * and changed CONFIG_ETRAX100_XYS to CONFIG_ETRAX_XYZ - * - * Revision 1.18 2001/09/24 09:27:22 pkj - * Completed ext_baud_table[] in cflag_to_baud() and cflag_to_etrax_baud(). - * - * Revision 1.17 2001/08/24 11:32:49 ronny - * More fixes for the CONFIG_ETRAX_SERIAL_PORT0 define. - * - * Revision 1.16 2001/08/24 07:56:22 ronny - * Added config ifdefs around ser0 irq requests. - * - * Revision 1.15 2001/08/16 09:10:31 bjarne - * serial.c - corrected the initialization of rs_table, the wrong defines - * where used. - * Corrected a test in timed_flush_handler. - * Changed configured to enabled. - * serial.h - Changed configured to enabled. - * - * Revision 1.14 2001/08/15 07:31:23 bjarne - * Introduced two new members to the e100_serial struct. - * configured - Will be set to 1 if the port has been configured in .config - * uses_dma - Should be set to 1 if the port uses DMA. Currently it is set - * to 1 - * when a port is opened. This is used to limit the DMA interrupt - * routines to only manipulate DMA channels actually used by the - * serial driver. - * - * Revision 1.13.2.2 2001/10/17 13:57:13 starvik - * Receiver was broken by the break fixes - * - * Revision 1.13.2.1 2001/07/20 13:57:39 ronny - * Merge with new stuff from etrax100ser.c. Works but haven't checked stuff - * like break handling. - * - * Revision 1.13 2001/05/09 12:40:31 johana - * Use DMA_NBR and IRQ_NBR defines from dma.h and irq.h - * - * Revision 1.12 2001/04/19 12:23:07 bjornw - * CONFIG_RS485 -> CONFIG_ETRAX_RS485 - * - * Revision 1.11 2001/04/05 14:29:48 markusl - * Updated according to review remarks i.e. - * -Use correct types in port structure to avoid compiler warnings - * -Try to use IO_* macros whenever possible - * -Open should never return -EBUSY - * - * Revision 1.10 2001/03/05 13:14:07 bjornw - * Another spelling fix - * - * Revision 1.9 2001/02/23 13:46:38 bjornw - * Spellling check - * - * Revision 1.8 2001/01/23 14:56:35 markusl - * Made use of ser1 optional - * Needed by USB - * - * Revision 1.7 2001/01/19 16:14:48 perf - * Added kernel options for serial ports 234. - * Changed option names from CONFIG_ETRAX100_XYZ to CONFIG_ETRAX_XYZ. - * - * Revision 1.6 2000/11/22 16:36:09 bjornw - * Please marketing by using the correct case when spelling Etrax. - * - * Revision 1.5 2000/11/21 16:43:37 bjornw - * Fixed so it compiles under CONFIG_SVINTO_SIM - * - * Revision 1.4 2000/11/15 17:34:12 bjornw - * Added a timeout timer for flushing input channels. The interrupt-based - * fast flush system should be easy to merge with this later (works the same - * way, only with an irq instead of a system timer_list) - * - * Revision 1.3 2000/11/13 17:19:57 bjornw - * * Incredibly, this almost complete rewrite of serial.c worked (at least - * for output) the first time. - * - * Items worth noticing: - * - * No Etrax100 port 1 workarounds (does only compile on 2.4 anyway now) - * RS485 is not ported (why can't it be done in userspace as on x86 ?) - * Statistics done through async_icount - if any more stats are needed, - * that's the place to put them or in an arch-dep version of it. - * timeout_interrupt and the other fast timeout stuff not ported yet - * There be dragons in this 3k+ line driver - * - * Revision 1.2 2000/11/10 16:50:28 bjornw - * First shot at a 2.4 port, does not compile totally yet - * - * Revision 1.1 2000/11/10 16:47:32 bjornw - * Added verbatim copy of rev 1.49 etrax100ser.c from elinux - * - * Revision 1.49 2000/10/30 15:47:14 tobiasa - * Changed version number. - * - * Revision 1.48 2000/10/25 11:02:43 johana - * Changed %ul to %lu in printf's - * - * Revision 1.47 2000/10/18 15:06:53 pkj - * Compile correctly with CONFIG_ETRAX_SERIAL_FLUSH_DMA_FAST and - * CONFIG_ETRAX_SERIAL_PROC_ENTRY together. - * Some clean-up of the /proc/serial file. - * - * Revision 1.46 2000/10/16 12:59:40 johana - * Added CONFIG_ETRAX_SERIAL_PROC_ENTRY for statistics and debug info. - * - * Revision 1.45 2000/10/13 17:10:59 pkj - * Do not flush DMAs while flipping TTY buffers. - * - * Revision 1.44 2000/10/13 16:34:29 pkj - * Added a delay in ser_interrupt() for 2.3ms when an error is detected. - * We do not know why this delay is required yet, but without it the - * irmaflash program does not work (this was the program that needed - * the ser_interrupt() to be needed in the first place). This should not - * affect normal use of the serial ports. - * - * Revision 1.43 2000/10/13 16:30:44 pkj - * New version of the fast flush of serial buffers code. This time - * it is localized to the serial driver and uses a fast timer to - * do the work. - * - * Revision 1.42 2000/10/13 14:54:26 bennyo - * Fix for switching RTS when using rs485 - * - * Revision 1.41 2000/10/12 11:43:44 pkj - * Cleaned up a number of comments. - * - * Revision 1.40 2000/10/10 11:58:39 johana - * Made RS485 support generic for all ports. - * Toggle rts in interrupt if no delay wanted. - * WARNING: No true transmitter empty check?? - * Set d_wait bit when sending data so interrupt is delayed until - * fifo flushed. (Fix tcdrain() problem) - * - * Revision 1.39 2000/10/04 16:08:02 bjornw - * * Use virt_to_phys etc. for DMA addresses - * * Removed CONFIG_FLUSH_DMA_FAST hacks - * * Indentation fix - * - * Revision 1.38 2000/10/02 12:27:10 mattias - * * added variable used when using fast flush on serial dma. - * (CONFIG_FLUSH_DMA_FAST) - * - * Revision 1.37 2000/09/27 09:44:24 pkj - * Uncomment definition of SERIAL_HANDLE_EARLY_ERRORS. - * - * Revision 1.36 2000/09/20 13:12:52 johana - * Support for CONFIG_ETRAX_SERIAL_RX_TIMEOUT_TICKS: - * Number of timer ticks between flush of receive fifo (1 tick = 10ms). - * Try 0-3 for low latency applications. Approx 5 for high load - * applications (e.g. PPP). Maybe this should be more adaptive some day... - * - * Revision 1.35 2000/09/20 10:36:08 johana - * Typo in get_lsr_info() - * - * Revision 1.34 2000/09/20 10:29:59 johana - * Let rs_chars_in_buffer() check fifo content as well. - * get_lsr_info() might work now (not tested). - * Easier to change the port to debug. - * - * Revision 1.33 2000/09/13 07:52:11 torbjore - * Support RS485 - * - * Revision 1.32 2000/08/31 14:45:37 bjornw - * After sending a break we need to reset the transmit DMA channel - * - * Revision 1.31 2000/06/21 12:13:29 johana - * Fixed wait for all chars sent when closing port. - * (Used to always take 1 second!) - * Added shadows for directions of status/ctrl signals. - * - * Revision 1.30 2000/05/29 16:27:55 bjornw - * Simulator ifdef moved a bit - * - * Revision 1.29 2000/05/09 09:40:30 mattias - * * Added description of dma registers used in timeout_interrupt - * * Removed old code - * - * Revision 1.28 2000/05/08 16:38:58 mattias - * * Bugfix for flushing fifo in timeout_interrupt - * Problem occurs when bluetooth stack waits for a small number of bytes - * containing an event acknowledging free buffers in bluetooth HW - * As before, data was stuck in fifo until more data came on uart and - * flushed it up to the stack. - * - * Revision 1.27 2000/05/02 09:52:28 jonasd - * Added fix for peculiar etrax behaviour when eop is forced on an empty - * fifo. This is used when flashing the IRMA chip. Disabled by default. - * - * Revision 1.26 2000/03/29 15:32:02 bjornw - * 2.0.34 updates - * - * Revision 1.25 2000/02/16 16:59:36 bjornw - * * Receive DMA directly into the flip-buffer, eliminating an intermediary - * receive buffer and a memcpy. Will avoid some overruns. - * * Error message on debug port if an overrun or flip buffer overrun occurs. - * * Just use the first byte in the flag flip buffer for errors. - * * Check for timeout on the serial ports only each 5/100 s, not 1/100. - * - * Revision 1.24 2000/02/09 18:02:28 bjornw - * * Clear serial errors (overrun, framing, parity) correctly. Before, the - * receiver would get stuck if an error occurred and we did not restart - * the input DMA. - * * Cosmetics (indentation, some code made into inlines) - * * Some more debug options - * * Actually shut down the serial port (DMA irq, DMA reset, receiver stop) - * when the last open is closed. Corresponding fixes in startup(). - * * rs_close() "tx FIFO wait" code moved into right place, bug & -> && fixed - * and make a special case out of port 1 (R_DMA_CHx_STATUS is broken for that) - * * e100_disable_rx/enable_rx just disables/enables the receiver, not RTS - * - * Revision 1.23 2000/01/24 17:46:19 johana - * Wait for flush of DMA/FIFO when closing port. - * - * Revision 1.22 2000/01/20 18:10:23 johana - * Added TIOCMGET ioctl to return modem status. - * Implemented modem status/control that works with the extra signals - * (DTR, DSR, RI,CD) as well. - * 3 different modes supported: - * ser0 on PB (Bundy), ser1 on PB (Lisa) and ser2 on PA (Bundy) - * Fixed DEF_TX value that caused the serial transmitter pin (txd) to go to 0 when - * closing the last filehandle, NASTY!. - * Added break generation, not tested though! - * Use IRQF_SHARED when request_irq() for ser2 and ser3 (shared with) par0 and par1. - * You can't use them at the same time (yet..), but you can hopefully switch - * between ser2/par0, ser3/par1 with the same kernel config. - * Replaced some magic constants with defines - * - * */ static char *serial_version = "$Revision: 1.25 $"; @@ -446,6 +30,7 @@ static char *serial_version = "$Revision: 1.25 $"; #include <asm/io.h> #include <asm/irq.h> +#include <asm/dma.h> #include <asm/system.h> #include <linux/delay.h> @@ -454,8 +39,9 @@ static char *serial_version = "$Revision: 1.25 $"; /* non-arch dependent serial structures are in linux/serial.h */ #include <linux/serial.h> /* while we keep our own stuff (struct e100_serial) in a local .h file */ -#include "serial.h" +#include "crisv10.h" #include <asm/fasttimer.h> +#include <asm/arch/io_interface_mux.h> #ifdef CONFIG_ETRAX_SERIAL_FAST_TIMER #ifndef CONFIG_ETRAX_FAST_TIMER @@ -504,18 +90,6 @@ struct tty_driver *serial_driver; from eLinux */ #define SERIAL_HANDLE_EARLY_ERRORS -/* Defined and used in n_tty.c, but we need it here as well */ -#define TTY_THRESHOLD_THROTTLE 128 - -/* Due to buffersizes and threshold values, our SERIAL_DESCR_BUF_SIZE - * must not be to high or flow control won't work if we leave it to the tty - * layer so we have our own throttling in flush_to_flip - * TTY_FLIPBUF_SIZE=512, - * TTY_THRESHOLD_THROTTLE/UNTHROTTLE=128 - * BUF_SIZE can't be > 128 - */ -#define CRIS_BUF_SIZE 512 - /* Currently 16 descriptors x 128 bytes = 2048 bytes */ #define SERIAL_DESCR_BUF_SIZE 256 @@ -588,13 +162,13 @@ unsigned long timer_data_to_ns(unsigned long timer_data); static void change_speed(struct e100_serial *info); static void rs_throttle(struct tty_struct * tty); static void rs_wait_until_sent(struct tty_struct *tty, int timeout); -static int rs_write(struct tty_struct * tty, int from_user, - const unsigned char *buf, int count); +static int rs_write(struct tty_struct *tty, + const unsigned char *buf, int count); #ifdef CONFIG_ETRAX_RS485 -static int e100_write_rs485(struct tty_struct * tty, int from_user, - const unsigned char *buf, int count); +static int e100_write_rs485(struct tty_struct *tty, + const unsigned char *buf, int count); #endif -static int get_lsr_info(struct e100_serial * info, unsigned int *value); +static int get_lsr_info(struct e100_serial *info, unsigned int *value); #define DEF_BAUD 115200 /* 115.2 kbit/s */ @@ -679,20 +253,39 @@ static struct e100_serial rs_table[] = { .rx_ctrl = DEF_RX, .tx_ctrl = DEF_TX, .iseteop = 2, + .dma_owner = dma_ser0, + .io_if = if_serial_0, #ifdef CONFIG_ETRAX_SERIAL_PORT0 .enabled = 1, #ifdef CONFIG_ETRAX_SERIAL_PORT0_DMA6_OUT .dma_out_enabled = 1, + .dma_out_nbr = SER0_TX_DMA_NBR, + .dma_out_irq_nbr = SER0_DMA_TX_IRQ_NBR, + .dma_out_irq_flags = IRQF_DISABLED, + .dma_out_irq_description = "serial 0 dma tr", #else .dma_out_enabled = 0, + .dma_out_nbr = UINT_MAX, + .dma_out_irq_nbr = 0, + .dma_out_irq_flags = 0, + .dma_out_irq_description = NULL, #endif #ifdef CONFIG_ETRAX_SERIAL_PORT0_DMA7_IN .dma_in_enabled = 1, + .dma_in_nbr = SER0_RX_DMA_NBR, + .dma_in_irq_nbr = SER0_DMA_RX_IRQ_NBR, + .dma_in_irq_flags = IRQF_DISABLED, + .dma_in_irq_description = "serial 0 dma rec", #else - .dma_in_enabled = 0 + .dma_in_enabled = 0, + .dma_in_nbr = UINT_MAX, + .dma_in_irq_nbr = 0, + .dma_in_irq_flags = 0, + .dma_in_irq_description = NULL, #endif #else .enabled = 0, + .io_if_description = NULL, .dma_out_enabled = 0, .dma_in_enabled = 0 #endif @@ -714,20 +307,42 @@ static struct e100_serial rs_table[] = { .rx_ctrl = DEF_RX, .tx_ctrl = DEF_TX, .iseteop = 3, + .dma_owner = dma_ser1, + .io_if = if_serial_1, #ifdef CONFIG_ETRAX_SERIAL_PORT1 .enabled = 1, + .io_if_description = "ser1", #ifdef CONFIG_ETRAX_SERIAL_PORT1_DMA8_OUT .dma_out_enabled = 1, + .dma_out_nbr = SER1_TX_DMA_NBR, + .dma_out_irq_nbr = SER1_DMA_TX_IRQ_NBR, + .dma_out_irq_flags = IRQF_DISABLED, + .dma_out_irq_description = "serial 1 dma tr", #else .dma_out_enabled = 0, + .dma_out_nbr = UINT_MAX, + .dma_out_irq_nbr = 0, + .dma_out_irq_flags = 0, + .dma_out_irq_description = NULL, #endif #ifdef CONFIG_ETRAX_SERIAL_PORT1_DMA9_IN .dma_in_enabled = 1, + .dma_in_nbr = SER1_RX_DMA_NBR, + .dma_in_irq_nbr = SER1_DMA_RX_IRQ_NBR, + .dma_in_irq_flags = IRQF_DISABLED, + .dma_in_irq_description = "serial 1 dma rec", #else - .dma_in_enabled = 0 + .dma_in_enabled = 0, + .dma_in_enabled = 0, + .dma_in_nbr = UINT_MAX, + .dma_in_irq_nbr = 0, + .dma_in_irq_flags = 0, + .dma_in_irq_description = NULL, #endif #else .enabled = 0, + .io_if_description = NULL, + .dma_in_irq_nbr = 0, .dma_out_enabled = 0, .dma_in_enabled = 0 #endif @@ -748,20 +363,40 @@ static struct e100_serial rs_table[] = { .rx_ctrl = DEF_RX, .tx_ctrl = DEF_TX, .iseteop = 0, + .dma_owner = dma_ser2, + .io_if = if_serial_2, #ifdef CONFIG_ETRAX_SERIAL_PORT2 .enabled = 1, + .io_if_description = "ser2", #ifdef CONFIG_ETRAX_SERIAL_PORT2_DMA2_OUT .dma_out_enabled = 1, + .dma_out_nbr = SER2_TX_DMA_NBR, + .dma_out_irq_nbr = SER2_DMA_TX_IRQ_NBR, + .dma_out_irq_flags = IRQF_DISABLED, + .dma_out_irq_description = "serial 2 dma tr", #else .dma_out_enabled = 0, + .dma_out_nbr = UINT_MAX, + .dma_out_irq_nbr = 0, + .dma_out_irq_flags = 0, + .dma_out_irq_description = NULL, #endif #ifdef CONFIG_ETRAX_SERIAL_PORT2_DMA3_IN .dma_in_enabled = 1, + .dma_in_nbr = SER2_RX_DMA_NBR, + .dma_in_irq_nbr = SER2_DMA_RX_IRQ_NBR, + .dma_in_irq_flags = IRQF_DISABLED, + .dma_in_irq_description = "serial 2 dma rec", #else - .dma_in_enabled = 0 + .dma_in_enabled = 0, + .dma_in_nbr = UINT_MAX, + .dma_in_irq_nbr = 0, + .dma_in_irq_flags = 0, + .dma_in_irq_description = NULL, #endif #else .enabled = 0, + .io_if_description = NULL, .dma_out_enabled = 0, .dma_in_enabled = 0 #endif @@ -782,20 +417,40 @@ static struct e100_serial rs_table[] = { .rx_ctrl = DEF_RX, .tx_ctrl = DEF_TX, .iseteop = 1, + .dma_owner = dma_ser3, + .io_if = if_serial_3, #ifdef CONFIG_ETRAX_SERIAL_PORT3 .enabled = 1, + .io_if_description = "ser3", #ifdef CONFIG_ETRAX_SERIAL_PORT3_DMA4_OUT .dma_out_enabled = 1, + .dma_out_nbr = SER3_TX_DMA_NBR, + .dma_out_irq_nbr = SER3_DMA_TX_IRQ_NBR, + .dma_out_irq_flags = IRQF_DISABLED, + .dma_out_irq_description = "serial 3 dma tr", #else .dma_out_enabled = 0, + .dma_out_nbr = UINT_MAX, + .dma_out_irq_nbr = 0, + .dma_out_irq_flags = 0, + .dma_out_irq_description = NULL, #endif #ifdef CONFIG_ETRAX_SERIAL_PORT3_DMA5_IN .dma_in_enabled = 1, + .dma_in_nbr = SER3_RX_DMA_NBR, + .dma_in_irq_nbr = SER3_DMA_RX_IRQ_NBR, + .dma_in_irq_flags = IRQF_DISABLED, + .dma_in_irq_description = "serial 3 dma rec", #else - .dma_in_enabled = 0 + .dma_in_enabled = 0, + .dma_in_nbr = UINT_MAX, + .dma_in_irq_nbr = 0, + .dma_in_irq_flags = 0, + .dma_in_irq_description = NULL #endif #else .enabled = 0, + .io_if_description = NULL, .dma_out_enabled = 0, .dma_in_enabled = 0 #endif @@ -1416,12 +1071,11 @@ e100_dtr(struct e100_serial *info, int set) { unsigned long flags; - save_flags(flags); - cli(); + local_irq_save(flags); *e100_modem_pins[info->line].dtr_shadow &= ~mask; *e100_modem_pins[info->line].dtr_shadow |= (set ? 0 : mask); *e100_modem_pins[info->line].dtr_port = *e100_modem_pins[info->line].dtr_shadow; - restore_flags(flags); + local_irq_restore(flags); } #ifdef SERIAL_DEBUG_IO @@ -1440,12 +1094,11 @@ e100_rts(struct e100_serial *info, int set) { #ifndef CONFIG_SVINTO_SIM unsigned long flags; - save_flags(flags); - cli(); + local_irq_save(flags); info->rx_ctrl &= ~E100_RTS_MASK; info->rx_ctrl |= (set ? 0 : E100_RTS_MASK); /* RTS is active low */ info->port[REG_REC_CTRL] = info->rx_ctrl; - restore_flags(flags); + local_irq_restore(flags); #ifdef SERIAL_DEBUG_IO printk("ser%i rts %i\n", info->line, set); #endif @@ -1463,12 +1116,11 @@ e100_ri_out(struct e100_serial *info, int set) unsigned char mask = e100_modem_pins[info->line].ri_mask; unsigned long flags; - save_flags(flags); - cli(); + local_irq_save(flags); *e100_modem_pins[info->line].ri_shadow &= ~mask; *e100_modem_pins[info->line].ri_shadow |= (set ? 0 : mask); *e100_modem_pins[info->line].ri_port = *e100_modem_pins[info->line].ri_shadow; - restore_flags(flags); + local_irq_restore(flags); } #endif } @@ -1481,12 +1133,11 @@ e100_cd_out(struct e100_serial *info, int set) unsigned char mask = e100_modem_pins[info->line].cd_mask; unsigned long flags; - save_flags(flags); - cli(); + local_irq_save(flags); *e100_modem_pins[info->line].cd_shadow &= ~mask; *e100_modem_pins[info->line].cd_shadow |= (set ? 0 : mask); *e100_modem_pins[info->line].cd_port = *e100_modem_pins[info->line].cd_shadow; - restore_flags(flags); + local_irq_restore(flags); } #endif } @@ -1560,8 +1211,7 @@ static void e100_disable_txdma_channel(struct e100_serial *info) /* Disable output DMA channel for the serial port in question * ( set to something other then serialX) */ - save_flags(flags); - cli(); + local_irq_save(flags); DFLOW(DEBUG_LOG(info->line, "disable_txdma_channel %i\n", info->line)); if (info->line == 0) { if ((genconfig_shadow & IO_MASK(R_GEN_CONFIG, dma6)) == @@ -1589,7 +1239,7 @@ static void e100_disable_txdma_channel(struct e100_serial *info) } } *R_GEN_CONFIG = genconfig_shadow; - restore_flags(flags); + local_irq_restore(flags); } @@ -1597,8 +1247,7 @@ static void e100_enable_txdma_channel(struct e100_serial *info) { unsigned long flags; - save_flags(flags); - cli(); + local_irq_save(flags); DFLOW(DEBUG_LOG(info->line, "enable_txdma_channel %i\n", info->line)); /* Enable output DMA channel for the serial port in question */ if (info->line == 0) { @@ -1615,7 +1264,7 @@ static void e100_enable_txdma_channel(struct e100_serial *info) genconfig_shadow |= IO_STATE(R_GEN_CONFIG, dma4, serial3); } *R_GEN_CONFIG = genconfig_shadow; - restore_flags(flags); + local_irq_restore(flags); } static void e100_disable_rxdma_channel(struct e100_serial *info) @@ -1625,8 +1274,7 @@ static void e100_disable_rxdma_channel(struct e100_serial *info) /* Disable input DMA channel for the serial port in question * ( set to something other then serialX) */ - save_flags(flags); - cli(); + local_irq_save(flags); if (info->line == 0) { if ((genconfig_shadow & IO_MASK(R_GEN_CONFIG, dma7)) == IO_STATE(R_GEN_CONFIG, dma7, serial0)) { @@ -1653,7 +1301,7 @@ static void e100_disable_rxdma_channel(struct e100_serial *info) } } *R_GEN_CONFIG = genconfig_shadow; - restore_flags(flags); + local_irq_restore(flags); } @@ -1661,8 +1309,7 @@ static void e100_enable_rxdma_channel(struct e100_serial *info) { unsigned long flags; - save_flags(flags); - cli(); + local_irq_save(flags); /* Enable input DMA channel for the serial port in question */ if (info->line == 0) { genconfig_shadow &= ~IO_MASK(R_GEN_CONFIG, dma7); @@ -1678,7 +1325,7 @@ static void e100_enable_rxdma_channel(struct e100_serial *info) genconfig_shadow |= IO_STATE(R_GEN_CONFIG, dma5, serial3); } *R_GEN_CONFIG = genconfig_shadow; - restore_flags(flags); + local_irq_restore(flags); } #ifdef SERIAL_HANDLE_EARLY_ERRORS @@ -1785,7 +1432,7 @@ e100_enable_rs485(struct tty_struct *tty,struct rs485_control *r) } static int -e100_write_rs485(struct tty_struct *tty, int from_user, +e100_write_rs485(struct tty_struct *tty, const unsigned char *buf, int count) { struct e100_serial * info = (struct e100_serial *)tty->driver_data; @@ -1798,7 +1445,7 @@ e100_write_rs485(struct tty_struct *tty, int from_user, */ info->rs485.enabled = 1; /* rs_write now deals with RS485 if enabled */ - count = rs_write(tty, from_user, buf, count); + count = rs_write(tty, buf, count); info->rs485.enabled = old_enabled; return count; } @@ -1836,7 +1483,7 @@ rs_stop(struct tty_struct *tty) unsigned long flags; unsigned long xoff; - save_flags(flags); cli(); + local_irq_save(flags); DFLOW(DEBUG_LOG(info->line, "XOFF rs_stop xmit %i\n", CIRC_CNT(info->xmit.head, info->xmit.tail,SERIAL_XMIT_SIZE))); @@ -1848,7 +1495,7 @@ rs_stop(struct tty_struct *tty) } *((unsigned long *)&info->port[REG_XOFF]) = xoff; - restore_flags(flags); + local_irq_restore(flags); } } @@ -1860,7 +1507,7 @@ rs_start(struct tty_struct *tty) unsigned long flags; unsigned long xoff; - save_flags(flags); cli(); + local_irq_save(flags); DFLOW(DEBUG_LOG(info->line, "XOFF rs_start xmit %i\n", CIRC_CNT(info->xmit.head, info->xmit.tail,SERIAL_XMIT_SIZE))); @@ -1875,7 +1522,7 @@ rs_start(struct tty_struct *tty) info->xmit.head != info->xmit.tail && info->xmit.buf) e100_enable_serial_tx_ready_irq(info); - restore_flags(flags); + local_irq_restore(flags); } } @@ -2055,8 +1702,7 @@ static int serial_fast_timer_expired = 0; static void flush_timeout_function(unsigned long data); #define START_FLUSH_FAST_TIMER_TIME(info, string, usec) {\ unsigned long timer_flags; \ - save_flags(timer_flags); \ - cli(); \ + local_irq_save(timer_flags); \ if (fast_timers[info->line].function == NULL) { \ serial_fast_timer_started++; \ TIMERD(DEBUG_LOG(info->line, "start_timer %i ", info->line)); \ @@ -2070,7 +1716,7 @@ static void flush_timeout_function(unsigned long data); else { \ TIMERD(DEBUG_LOG(info->line, "timer %i already running\n", info->line)); \ } \ - restore_flags(timer_flags); \ + local_irq_restore(timer_flags); \ } #define START_FLUSH_FAST_TIMER(info, string) START_FLUSH_FAST_TIMER_TIME(info, string, info->flush_time_usec) @@ -2099,8 +1745,7 @@ append_recv_buffer(struct e100_serial *info, struct etrax_recv_buffer *buffer) { unsigned long flags; - save_flags(flags); - cli(); + local_irq_save(flags); if (!info->first_recv_buffer) info->first_recv_buffer = buffer; @@ -2113,7 +1758,7 @@ append_recv_buffer(struct e100_serial *info, struct etrax_recv_buffer *buffer) if (info->recv_cnt > info->max_recv_cnt) info->max_recv_cnt = info->recv_cnt; - restore_flags(flags); + local_irq_restore(flags); } static int @@ -2133,11 +1778,7 @@ add_char_and_flag(struct e100_serial *info, unsigned char data, unsigned char fl info->icount.rx++; } else { struct tty_struct *tty = info->tty; - *tty->flip.char_buf_ptr = data; - *tty->flip.flag_buf_ptr = flag; - tty->flip.flag_buf_ptr++; - tty->flip.char_buf_ptr++; - tty->flip.count++; + tty_insert_flip_char(tty, data, flag); info->icount.rx++; } @@ -2322,7 +1963,6 @@ start_receive(struct e100_serial *info) */ return; #endif - info->tty->flip.count = 0; if (info->uses_dma_in) { /* reset the input dma channel to be sure it works */ @@ -2484,32 +2124,20 @@ static void flush_to_flip_buffer(struct e100_serial *info) { struct tty_struct *tty; struct etrax_recv_buffer *buffer; - unsigned int length; unsigned long flags; - int max_flip_size; - - if (!info->first_recv_buffer) - return; - save_flags(flags); - cli(); + local_irq_save(flags); + tty = info->tty; - if (!(tty = info->tty)) { - restore_flags(flags); + if (!tty) { + local_irq_restore(flags); return; } while ((buffer = info->first_recv_buffer) != NULL) { unsigned int count = buffer->length; - count = tty_buffer_request_room(tty, count); - if (count == 0) /* Throttle ?? */ - break; - - if (count > 1) - tty_insert_flip_strings(tty, buffer->buffer, count - 1); - tty_insert_flip_char(tty, buffer->buffer[count-1], buffer->error); - + tty_insert_flip_string(tty, buffer->buffer, count); info->recv_cnt -= count; if (count == buffer->length) { @@ -2525,18 +2153,9 @@ static void flush_to_flip_buffer(struct e100_serial *info) if (!info->first_recv_buffer) info->last_recv_buffer = NULL; - restore_flags(flags); - - DFLIP( - if (1) { - DEBUG_LOG(info->line, "*** rxtot %i\n", info->icount.rx); - DEBUG_LOG(info->line, "ldisc %lu\n", tty->ldisc.chars_in_buffer(tty)); - DEBUG_LOG(info->line, "room %lu\n", tty->ldisc.receive_room(tty)); - } + local_irq_restore(flags); - ); - - /* this includes a check for low-latency */ + /* This includes a check for low-latency */ tty_flip_buffer_push(tty); } @@ -2679,21 +2298,7 @@ struct e100_serial * handle_ser_rx_interrupt_no_dma(struct e100_serial *info) printk("!NO TTY!\n"); return info; } - if (tty->flip.count >= CRIS_BUF_SIZE - TTY_THRESHOLD_THROTTLE) { - /* check TTY_THROTTLED first so it indicates our state */ - if (!test_and_set_bit(TTY_THROTTLED, &tty->flags)) { - DFLOW(DEBUG_LOG(info->line, "rs_throttle flip.count: %i\n", tty->flip.count)); - rs_throttle(tty); - } - } - if (tty->flip.count >= CRIS_BUF_SIZE) { - DEBUG_LOG(info->line, "force FLIP! %i\n", tty->flip.count); - tty->flip.work.func((void *) tty); - if (tty->flip.count >= CRIS_BUF_SIZE) { - DEBUG_LOG(info->line, "FLIP FULL! %i\n", tty->flip.count); - return info; /* if TTY_DONT_FLIP is set */ - } - } + /* Read data and status at the same time */ data_read = *((unsigned long *)&info->port[REG_DATA_STATUS32]); more_data: @@ -2746,27 +2351,26 @@ more_data: DEBUG_LOG(info->line, "EBRK %i\n", info->break_detected_cnt); info->errorcode = ERRCODE_INSERT_BREAK; } else { + unsigned char data = IO_EXTRACT(R_SERIAL0_READ, + data_in, data_read); + char flag = TTY_NORMAL; if (info->errorcode == ERRCODE_INSERT_BREAK) { - info->icount.brk++; - *tty->flip.char_buf_ptr = 0; - *tty->flip.flag_buf_ptr = TTY_BREAK; - tty->flip.flag_buf_ptr++; - tty->flip.char_buf_ptr++; - tty->flip.count++; + struct tty_struct *tty = info->tty; + tty_insert_flip_char(tty, 0, flag); info->icount.rx++; } - *tty->flip.char_buf_ptr = IO_EXTRACT(R_SERIAL0_READ, data_in, data_read); if (data_read & IO_MASK(R_SERIAL0_READ, par_err)) { info->icount.parity++; - *tty->flip.flag_buf_ptr = TTY_PARITY; + flag = TTY_PARITY; } else if (data_read & IO_MASK(R_SERIAL0_READ, overrun)) { info->icount.overrun++; - *tty->flip.flag_buf_ptr = TTY_OVERRUN; + flag = TTY_OVERRUN; } else if (data_read & IO_MASK(R_SERIAL0_READ, framing_err)) { info->icount.frame++; - *tty->flip.flag_buf_ptr = TTY_FRAME; + flag = TTY_FRAME; } + tty_insert_flip_char(tty, data, flag); info->errorcode = 0; } info->break_detected_cnt = 0; @@ -2782,16 +2386,14 @@ more_data: log_int(rdpc(), 0, 0); } ); - *tty->flip.char_buf_ptr = IO_EXTRACT(R_SERIAL0_READ, data_in, data_read); - *tty->flip.flag_buf_ptr = 0; + tty_insert_flip_char(tty, + IO_EXTRACT(R_SERIAL0_READ, data_in, data_read), + TTY_NORMAL); } else { DEBUG_LOG(info->line, "ser_rx int but no data_avail %08lX\n", data_read); } - tty->flip.flag_buf_ptr++; - tty->flip.char_buf_ptr++; - tty->flip.count++; info->icount.rx++; data_read = *((unsigned long *)&info->port[REG_DATA_STATUS32]); if (data_read & IO_MASK(R_SERIAL0_READ, data_avail)) { @@ -2929,7 +2531,7 @@ static void handle_ser_tx_interrupt(struct e100_serial *info) if (info->x_char) { unsigned char rstat; DFLOW(DEBUG_LOG(info->line, "tx_int: xchar 0x%02X\n", info->x_char)); - save_flags(flags); cli(); + local_irq_save(flags); rstat = info->port[REG_STATUS]; DFLOW(DEBUG_LOG(info->line, "stat %x\n", rstat)); @@ -2938,7 +2540,7 @@ static void handle_ser_tx_interrupt(struct e100_serial *info) info->x_char = 0; /* We must enable since it is disabled in ser_interrupt */ e100_enable_serial_tx_ready_irq(info); - restore_flags(flags); + local_irq_restore(flags); return; } if (info->uses_dma_out) { @@ -2946,7 +2548,7 @@ static void handle_ser_tx_interrupt(struct e100_serial *info) int i; /* We only use normal tx interrupt when sending x_char */ DFLOW(DEBUG_LOG(info->line, "tx_int: xchar sent\n", 0)); - save_flags(flags); cli(); + local_irq_save(flags); rstat = info->port[REG_STATUS]; DFLOW(DEBUG_LOG(info->line, "stat %x\n", rstat)); e100_disable_serial_tx_ready_irq(info); @@ -2959,7 +2561,7 @@ static void handle_ser_tx_interrupt(struct e100_serial *info) nop(); *info->ocmdadr = IO_STATE(R_DMA_CH6_CMD, cmd, continue); - restore_flags(flags); + local_irq_restore(flags); return; } /* Normal char-by-char interrupt */ @@ -2973,7 +2575,7 @@ static void handle_ser_tx_interrupt(struct e100_serial *info) } DINTR2(DEBUG_LOG(info->line, "tx_int %c\n", info->xmit.buf[info->xmit.tail])); /* Send a byte, rs485 timing is critical so turn of ints */ - save_flags(flags); cli(); + local_irq_save(flags); info->port[REG_TR_DATA] = info->xmit.buf[info->xmit.tail]; info->xmit.tail = (info->xmit.tail + 1) & (SERIAL_XMIT_SIZE-1); info->icount.tx++; @@ -2997,7 +2599,7 @@ static void handle_ser_tx_interrupt(struct e100_serial *info) /* We must enable since it is disabled in ser_interrupt */ e100_enable_serial_tx_ready_irq(info); } - restore_flags(flags); + local_irq_restore(flags); if (CIRC_CNT(info->xmit.head, info->xmit.tail, @@ -3022,7 +2624,7 @@ ser_interrupt(int irq, void *dev_id) int handled = 0; static volatile unsigned long reentered_ready_mask = 0; - save_flags(flags); cli(); + local_irq_save(flags); irq_mask1_rd = *R_IRQ_MASK1_RD; /* First handle all rx interrupts with ints disabled */ info = rs_table; @@ -3067,7 +2669,7 @@ ser_interrupt(int irq, void *dev_id) /* Unblock the serial interrupt */ *R_VECT_MASK_SET = IO_STATE(R_VECT_MASK_SET, serial, set); - sti(); + local_irq_enable(); ready_mask = (1 << (8+1+2*0)); /* ser0 tr_ready */ info = rs_table; for (i = 0; i < NR_PORTS; i++) { @@ -3080,11 +2682,11 @@ ser_interrupt(int irq, void *dev_id) ready_mask <<= 2; } /* handle_ser_tx_interrupt enables tr_ready interrupts */ - cli(); + local_irq_disable(); /* Handle reentered TX interrupt */ irq_mask1_rd = reentered_ready_mask; } - cli(); + local_irq_disable(); tx_started = 0; } else { unsigned long ready_mask; @@ -3100,7 +2702,7 @@ ser_interrupt(int irq, void *dev_id) } } - restore_flags(flags); + local_irq_restore(flags); return IRQ_RETVAL(handled); } /* ser_interrupt */ #endif @@ -3121,11 +2723,13 @@ ser_interrupt(int irq, void *dev_id) * them using rs_sched_event(), and they get done here. */ static void -do_softint(void *private_) +do_softint(struct work_struct *work) { - struct e100_serial *info = (struct e100_serial *) private_; + struct e100_serial *info; struct tty_struct *tty; + info = container_of(work, struct e100_serial, work); + tty = info->tty; if (!tty) return; @@ -3145,13 +2749,12 @@ startup(struct e100_serial * info) if (!xmit_page) return -ENOMEM; - save_flags(flags); - cli(); + local_irq_save(flags); /* if it was already initialized, skip this */ if (info->flags & ASYNC_INITIALIZED) { - restore_flags(flags); + local_irq_restore(flags); free_page(xmit_page); return 0; } @@ -3277,7 +2880,7 @@ startup(struct e100_serial * info) info->flags |= ASYNC_INITIALIZED; - restore_flags(flags); + local_irq_restore(flags); return 0; } @@ -3328,8 +2931,7 @@ shutdown(struct e100_serial * info) info->irq); #endif - save_flags(flags); - cli(); /* Disable interrupts */ + local_irq_save(flags); if (info->xmit.buf) { free_page((unsigned long)info->xmit.buf); @@ -3353,7 +2955,7 @@ shutdown(struct e100_serial * info) set_bit(TTY_IO_ERROR, &info->tty->flags); info->flags &= ~ASYNC_INITIALIZED; - restore_flags(flags); + local_irq_restore(flags); } @@ -3411,7 +3013,6 @@ change_speed(struct e100_serial *info) DBAUD(printk("using external baudrate: %lu\n", CONFIG_ETRAX_EXTERN_PB6CLK_FREQ/8)); info->baud = CONFIG_ETRAX_EXTERN_PB6CLK_FREQ/8; } - } #endif else { @@ -3445,8 +3046,7 @@ change_speed(struct e100_serial *info) #ifndef CONFIG_SVINTO_SIM /* start with default settings and then fill in changes */ - save_flags(flags); - cli(); + local_irq_save(flags); /* 8 bit, no/even parity */ info->rx_ctrl &= ~(IO_MASK(R_SERIAL0_REC_CTRL, rec_bitnr) | IO_MASK(R_SERIAL0_REC_CTRL, rec_par_en) | @@ -3510,7 +3110,7 @@ change_speed(struct e100_serial *info) } *((unsigned long *)&info->port[REG_XOFF]) = xoff; - restore_flags(flags); + local_irq_restore(flags); #endif /* !CONFIG_SVINTO_SIM */ update_char_time(info); @@ -3538,13 +3138,12 @@ rs_flush_chars(struct tty_struct *tty) /* this protection might not exactly be necessary here */ - save_flags(flags); - cli(); + local_irq_save(flags); start_transmit(info); - restore_flags(flags); + local_irq_restore(flags); } -static int rs_raw_write(struct tty_struct * tty, int from_user, +static int rs_raw_write(struct tty_struct *tty, const unsigned char *buf, int count) { int c, ret = 0; @@ -3567,53 +3166,19 @@ static int rs_raw_write(struct tty_struct * tty, int from_user, SIMCOUT(buf, count); return count; #endif - save_flags(flags); + local_save_flags(flags); DFLOW(DEBUG_LOG(info->line, "write count %i ", count)); DFLOW(DEBUG_LOG(info->line, "ldisc %i\n", tty->ldisc.chars_in_buffer(tty))); - /* the cli/restore_flags pairs below are needed because the - * DMA interrupt handler moves the info->xmit values. the memcpy - * needs to be in the critical region unfortunately, because we - * need to read xmit values, memcpy, write xmit values in one - * atomic operation... this could perhaps be avoided by more clever - * design. + /* The local_irq_disable/restore_flags pairs below are needed + * because the DMA interrupt handler moves the info->xmit values. + * the memcpy needs to be in the critical region unfortunately, + * because we need to read xmit values, memcpy, write xmit values + * in one atomic operation... this could perhaps be avoided by + * more clever design. */ - if (from_user) { - mutex_lock(&tmp_buf_mutex); - while (1) { - int c1; - c = CIRC_SPACE_TO_END(info->xmit.head, - info->xmit.tail, - SERIAL_XMIT_SIZE); - if (count < c) - c = count; - if (c <= 0) - break; - - c -= copy_from_user(tmp_buf, buf, c); - if (!c) { - if (!ret) - ret = -EFAULT; - break; - } - cli(); - c1 = CIRC_SPACE_TO_END(info->xmit.head, - info->xmit.tail, - SERIAL_XMIT_SIZE); - if (c1 < c) - c = c1; - memcpy(info->xmit.buf + info->xmit.head, tmp_buf, c); - info->xmit.head = ((info->xmit.head + c) & - (SERIAL_XMIT_SIZE-1)); - restore_flags(flags); - buf += c; - count -= c; - ret += c; - } - mutex_unlock(&tmp_buf_mutex); - } else { - cli(); + local_irq_disable(); while (count) { c = CIRC_SPACE_TO_END(info->xmit.head, info->xmit.tail, @@ -3631,8 +3196,7 @@ static int rs_raw_write(struct tty_struct * tty, int from_user, count -= c; ret += c; } - restore_flags(flags); - } + local_irq_restore(flags); /* enable transmitter if not running, unless the tty is stopped * this does not need IRQ protection since if tr_running == 0 @@ -3651,7 +3215,7 @@ static int rs_raw_write(struct tty_struct * tty, int from_user, } /* raw_raw_write() */ static int -rs_write(struct tty_struct * tty, int from_user, +rs_write(struct tty_struct *tty, const unsigned char *buf, int count) { #if defined(CONFIG_ETRAX_RS485) @@ -3678,7 +3242,7 @@ rs_write(struct tty_struct * tty, int from_user, } #endif /* CONFIG_ETRAX_RS485 */ - count = rs_raw_write(tty, from_user, buf, count); + count = rs_raw_write(tty, buf, count); #if defined(CONFIG_ETRAX_RS485) if (info->rs485.enabled) @@ -3746,10 +3310,9 @@ rs_flush_buffer(struct tty_struct *tty) struct e100_serial *info = (struct e100_serial *)tty->driver_data; unsigned long flags; - save_flags(flags); - cli(); + local_irq_save(flags); info->xmit.head = info->xmit.tail = 0; - restore_flags(flags); + local_irq_restore(flags); tty_wakeup(tty); } @@ -3767,7 +3330,7 @@ static void rs_send_xchar(struct tty_struct *tty, char ch) { struct e100_serial *info = (struct e100_serial *)tty->driver_data; unsigned long flags; - save_flags(flags); cli(); + local_irq_save(flags); if (info->uses_dma_out) { /* Put the DMA on hold and disable the channel */ *info->ocmdadr = IO_STATE(R_DMA_CH6_CMD, cmd, hold); @@ -3784,7 +3347,7 @@ static void rs_send_xchar(struct tty_struct *tty, char ch) DFLOW(DEBUG_LOG(info->line, "rs_send_xchar 0x%02X\n", ch)); info->x_char = ch; e100_enable_serial_tx_ready_irq(info); - restore_flags(flags); + local_irq_restore(flags); } /* @@ -3996,21 +3559,61 @@ char *get_control_state_str(int MLines, char *s) } #endif +static void +rs_break(struct tty_struct *tty, int break_state) +{ + struct e100_serial *info = (struct e100_serial *)tty->driver_data; + unsigned long flags; + + if (!info->port) + return; + + local_irq_save(flags); + if (break_state == -1) { + /* Go to manual mode and set the txd pin to 0 */ + /* Clear bit 7 (txd) and 6 (tr_enable) */ + info->tx_ctrl &= 0x3F; + } else { + /* Set bit 7 (txd) and 6 (tr_enable) */ + info->tx_ctrl |= (0x80 | 0x40); + } + info->port[REG_TR_CTRL] = info->tx_ctrl; + local_irq_restore(flags); +} + static int -get_modem_info(struct e100_serial * info, unsigned int *value) +rs_tiocmset(struct tty_struct *tty, struct file *file, + unsigned int set, unsigned int clear) { - unsigned int result; - /* Polarity isn't verified */ -#if 0 /*def SERIAL_DEBUG_IO */ + struct e100_serial *info = (struct e100_serial *)tty->driver_data; - printk("get_modem_info: RTS: %i DTR: %i CD: %i RI: %i DSR: %i CTS: %i\n", - E100_RTS_GET(info), - E100_DTR_GET(info), - E100_CD_GET(info), - E100_RI_GET(info), - E100_DSR_GET(info), - E100_CTS_GET(info)); -#endif + if (clear & TIOCM_RTS) + e100_rts(info, 0); + if (clear & TIOCM_DTR) + e100_dtr(info, 0); + /* Handle FEMALE behaviour */ + if (clear & TIOCM_RI) + e100_ri_out(info, 0); + if (clear & TIOCM_CD) + e100_cd_out(info, 0); + + if (set & TIOCM_RTS) + e100_rts(info, 1); + if (set & TIOCM_DTR) + e100_dtr(info, 1); + /* Handle FEMALE behaviour */ + if (set & TIOCM_RI) + e100_ri_out(info, 1); + if (set & TIOCM_CD) + e100_cd_out(info, 1); + return 0; +} + +static int +rs_tiocmget(struct tty_struct *tty, struct file *file) +{ + struct e100_serial *info = (struct e100_serial *)tty->driver_data; + unsigned int result; result = (!E100_RTS_GET(info) ? TIOCM_RTS : 0) @@ -4021,95 +3624,20 @@ get_modem_info(struct e100_serial * info, unsigned int *value) | (!E100_CTS_GET(info) ? TIOCM_CTS : 0); #ifdef SERIAL_DEBUG_IO - printk("e100ser: modem state: %i 0x%08X\n", result, result); + printk(KERN_DEBUG "ser%i: modem state: %i 0x%08X\n", + info->line, result, result); { char s[100]; get_control_state_str(result, s); - printk("state: %s\n", s); + printk(KERN_DEBUG "state: %s\n", s); } #endif - if (copy_to_user(value, &result, sizeof(int))) - return -EFAULT; - return 0; -} + return result; - -static int -set_modem_info(struct e100_serial * info, unsigned int cmd, - unsigned int *value) -{ - unsigned int arg; - - if (copy_from_user(&arg, value, sizeof(int))) - return -EFAULT; - - switch (cmd) { - case TIOCMBIS: - if (arg & TIOCM_RTS) { - e100_rts(info, 1); - } - if (arg & TIOCM_DTR) { - e100_dtr(info, 1); - } - /* Handle FEMALE behaviour */ - if (arg & TIOCM_RI) { - e100_ri_out(info, 1); - } - if (arg & TIOCM_CD) { - e100_cd_out(info, 1); - } - break; - case TIOCMBIC: - if (arg & TIOCM_RTS) { - e100_rts(info, 0); - } - if (arg & TIOCM_DTR) { - e100_dtr(info, 0); - } - /* Handle FEMALE behaviour */ - if (arg & TIOCM_RI) { - e100_ri_out(info, 0); - } - if (arg & TIOCM_CD) { - e100_cd_out(info, 0); - } - break; - case TIOCMSET: - e100_rts(info, arg & TIOCM_RTS); - e100_dtr(info, arg & TIOCM_DTR); - /* Handle FEMALE behaviour */ - e100_ri_out(info, arg & TIOCM_RI); - e100_cd_out(info, arg & TIOCM_CD); - break; - default: - return -EINVAL; - } - return 0; } -static void -rs_break(struct tty_struct *tty, int break_state) -{ - struct e100_serial * info = (struct e100_serial *)tty->driver_data; - unsigned long flags; - - if (!info->port) - return; - - save_flags(flags); - cli(); - if (break_state == -1) { - /* Go to manual mode and set the txd pin to 0 */ - info->tx_ctrl &= 0x3F; /* Clear bit 7 (txd) and 6 (tr_enable) */ - } else { - info->tx_ctrl |= (0x80 | 0x40); /* Set bit 7 (txd) and 6 (tr_enable) */ - } - info->port[REG_TR_CTRL] = info->tx_ctrl; - restore_flags(flags); -} - static int rs_ioctl(struct tty_struct *tty, struct file * file, unsigned int cmd, unsigned long arg) @@ -4124,49 +3652,45 @@ rs_ioctl(struct tty_struct *tty, struct file * file, } switch (cmd) { - case TIOCMGET: - return get_modem_info(info, (unsigned int *) arg); - case TIOCMBIS: - case TIOCMBIC: - case TIOCMSET: - return set_modem_info(info, cmd, (unsigned int *) arg); - case TIOCGSERIAL: - return get_serial_info(info, - (struct serial_struct *) arg); - case TIOCSSERIAL: - return set_serial_info(info, - (struct serial_struct *) arg); - case TIOCSERGETLSR: /* Get line status register */ - return get_lsr_info(info, (unsigned int *) arg); - - case TIOCSERGSTRUCT: - if (copy_to_user((struct e100_serial *) arg, - info, sizeof(struct e100_serial))) - return -EFAULT; - return 0; + case TIOCGSERIAL: + return get_serial_info(info, + (struct serial_struct *) arg); + case TIOCSSERIAL: + return set_serial_info(info, + (struct serial_struct *) arg); + case TIOCSERGETLSR: /* Get line status register */ + return get_lsr_info(info, (unsigned int *) arg); + + case TIOCSERGSTRUCT: + if (copy_to_user((struct e100_serial *) arg, + info, sizeof(struct e100_serial))) + return -EFAULT; + return 0; #if defined(CONFIG_ETRAX_RS485) - case TIOCSERSETRS485: - { - struct rs485_control rs485ctrl; - if (copy_from_user(&rs485ctrl, (struct rs485_control*)arg, sizeof(rs485ctrl))) - return -EFAULT; + case TIOCSERSETRS485: + { + struct rs485_control rs485ctrl; + if (copy_from_user(&rs485ctrl, (struct rs485_control *)arg, + sizeof(rs485ctrl))) + return -EFAULT; - return e100_enable_rs485(tty, &rs485ctrl); - } + return e100_enable_rs485(tty, &rs485ctrl); + } - case TIOCSERWRRS485: - { - struct rs485_write rs485wr; - if (copy_from_user(&rs485wr, (struct rs485_write*)arg, sizeof(rs485wr))) - return -EFAULT; + case TIOCSERWRRS485: + { + struct rs485_write rs485wr; + if (copy_from_user(&rs485wr, (struct rs485_write *)arg, + sizeof(rs485wr))) + return -EFAULT; - return e100_write_rs485(tty, 1, rs485wr.outc, rs485wr.outc_size); - } + return e100_write_rs485(tty, rs485wr.outc, rs485wr.outc_size); + } #endif - default: - return -ENOIOCTLCMD; + default: + return -ENOIOCTLCMD; } return 0; } @@ -4191,46 +3715,6 @@ rs_set_termios(struct tty_struct *tty, struct ktermios *old_termios) } -/* In debugport.c - register a console write function that uses the normal - * serial driver - */ -typedef int (*debugport_write_function)(int i, const char *buf, unsigned int len); - -extern debugport_write_function debug_write_function; - -static int rs_debug_write_function(int i, const char *buf, unsigned int len) -{ - int cnt; - int written = 0; - struct tty_struct *tty; - static int recurse_cnt = 0; - - tty = rs_table[i].tty; - if (tty) { - unsigned long flags; - if (recurse_cnt > 5) /* We skip this debug output */ - return 1; - - local_irq_save(flags); - recurse_cnt++; - local_irq_restore(flags); - do { - cnt = rs_write(tty, 0, buf + written, len); - if (cnt >= 0) { - written += cnt; - buf += cnt; - len -= cnt; - } else - len = cnt; - } while(len > 0); - local_irq_save(flags); - recurse_cnt--; - local_irq_restore(flags); - return 1; - } - return 0; -} - /* * ------------------------------------------------------------ * rs_close() @@ -4252,11 +3736,10 @@ rs_close(struct tty_struct *tty, struct file * filp) /* interrupts are disabled for this entire function */ - save_flags(flags); - cli(); + local_irq_save(flags); if (tty_hung_up_p(filp)) { - restore_flags(flags); + local_irq_restore(flags); return; } @@ -4283,7 +3766,7 @@ rs_close(struct tty_struct *tty, struct file * filp) info->count = 0; } if (info->count) { - restore_flags(flags); + local_irq_restore(flags); return; } info->flags |= ASYNC_CLOSING; @@ -4337,7 +3820,7 @@ rs_close(struct tty_struct *tty, struct file * filp) } info->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING); wake_up_interruptible(&info->close_wait); - restore_flags(flags); + local_irq_restore(flags); /* port closed */ @@ -4359,6 +3842,28 @@ rs_close(struct tty_struct *tty, struct file * filp) #endif } #endif + + /* + * Release any allocated DMA irq's. + */ + if (info->dma_in_enabled) { + free_irq(info->dma_in_irq_nbr, info); + cris_free_dma(info->dma_in_nbr, info->dma_in_irq_description); + info->uses_dma_in = 0; +#ifdef SERIAL_DEBUG_OPEN + printk(KERN_DEBUG "DMA irq '%s' freed\n", + info->dma_in_irq_description); +#endif + } + if (info->dma_out_enabled) { + free_irq(info->dma_out_irq_nbr, info); + cris_free_dma(info->dma_out_nbr, info->dma_out_irq_description); + info->uses_dma_out = 0; +#ifdef SERIAL_DEBUG_OPEN + printk(KERN_DEBUG "DMA irq '%s' freed\n", + info->dma_out_irq_description); +#endif + } } /* @@ -4433,8 +3938,8 @@ block_til_ready(struct tty_struct *tty, struct file * filp, */ if (tty_hung_up_p(filp) || (info->flags & ASYNC_CLOSING)) { - if (info->flags & ASYNC_CLOSING) - interruptible_sleep_on(&info->close_wait); + wait_event_interruptible(info->close_wait, + !(info->flags & ASYNC_CLOSING)); #ifdef SERIAL_DO_RESTART if (info->flags & ASYNC_HUP_NOTIFY) return -EAGAIN; @@ -4472,21 +3977,19 @@ block_til_ready(struct tty_struct *tty, struct file * filp, printk("block_til_ready before block: ttyS%d, count = %d\n", info->line, info->count); #endif - save_flags(flags); - cli(); + local_irq_save(flags); if (!tty_hung_up_p(filp)) { extra_count++; info->count--; } - restore_flags(flags); + local_irq_restore(flags); info->blocked_open++; while (1) { - save_flags(flags); - cli(); + local_irq_save(flags); /* assert RTS and DTR */ e100_rts(info, 1); e100_dtr(info, 1); - restore_flags(flags); + local_irq_restore(flags); set_current_state(TASK_INTERRUPTIBLE); if (tty_hung_up_p(filp) || !(info->flags & ASYNC_INITIALIZED)) { @@ -4528,6 +4031,19 @@ block_til_ready(struct tty_struct *tty, struct file * filp, return 0; } +static void +deinit_port(struct e100_serial *info) +{ + if (info->dma_out_enabled) { + cris_free_dma(info->dma_out_nbr, info->dma_out_irq_description); + free_irq(info->dma_out_irq_nbr, info); + } + if (info->dma_in_enabled) { + cris_free_dma(info->dma_in_nbr, info->dma_in_irq_description); + free_irq(info->dma_in_irq_nbr, info); + } +} + /* * This routine is called whenever a serial port is opened. * It performs the serial-specific initialization for the tty structure. @@ -4538,9 +4054,9 @@ rs_open(struct tty_struct *tty, struct file * filp) struct e100_serial *info; int retval, line; unsigned long page; + int allocated_resources = 0; /* find which port we want to open */ - line = tty->index; if (line < 0 || line >= NR_PORTS) @@ -4580,8 +4096,8 @@ rs_open(struct tty_struct *tty, struct file * filp) */ if (tty_hung_up_p(filp) || (info->flags & ASYNC_CLOSING)) { - if (info->flags & ASYNC_CLOSING) - interruptible_sleep_on(&info->close_wait); + wait_event_interruptible(info->close_wait, + !(info->flags & ASYNC_CLOSING)); #ifdef SERIAL_DO_RESTART return ((info->flags & ASYNC_HUP_NOTIFY) ? -EAGAIN : -ERESTARTSYS); @@ -4591,12 +4107,85 @@ rs_open(struct tty_struct *tty, struct file * filp) } /* + * If DMA is enabled try to allocate the irq's. + */ + if (info->count == 1) { + allocated_resources = 1; + if (info->dma_in_enabled) { + if (request_irq(info->dma_in_irq_nbr, + rec_interrupt, + info->dma_in_irq_flags, + info->dma_in_irq_description, + info)) { + printk(KERN_WARNING "DMA irq '%s' busy; " + "falling back to non-DMA mode\n", + info->dma_in_irq_description); + /* Make sure we never try to use DMA in */ + /* for the port again. */ + info->dma_in_enabled = 0; + } else if (cris_request_dma(info->dma_in_nbr, + info->dma_in_irq_description, + DMA_VERBOSE_ON_ERROR, + info->dma_owner)) { + free_irq(info->dma_in_irq_nbr, info); + printk(KERN_WARNING "DMA '%s' busy; " + "falling back to non-DMA mode\n", + info->dma_in_irq_description); + /* Make sure we never try to use DMA in */ + /* for the port again. */ + info->dma_in_enabled = 0; + } +#ifdef SERIAL_DEBUG_OPEN + else + printk(KERN_DEBUG "DMA irq '%s' allocated\n", + info->dma_in_irq_description); +#endif + } + if (info->dma_out_enabled) { + if (request_irq(info->dma_out_irq_nbr, + tr_interrupt, + info->dma_out_irq_flags, + info->dma_out_irq_description, + info)) { + printk(KERN_WARNING "DMA irq '%s' busy; " + "falling back to non-DMA mode\n", + info->dma_out_irq_description); + /* Make sure we never try to use DMA out */ + /* for the port again. */ + info->dma_out_enabled = 0; + } else if (cris_request_dma(info->dma_out_nbr, + info->dma_out_irq_description, + DMA_VERBOSE_ON_ERROR, + info->dma_owner)) { + free_irq(info->dma_out_irq_nbr, info); + printk(KERN_WARNING "DMA '%s' busy; " + "falling back to non-DMA mode\n", + info->dma_out_irq_description); + /* Make sure we never try to use DMA out */ + /* for the port again. */ + info->dma_out_enabled = 0; + } +#ifdef SERIAL_DEBUG_OPEN + else + printk(KERN_DEBUG "DMA irq '%s' allocated\n", + info->dma_out_irq_description); +#endif + } + } + + /* * Start up the serial port */ retval = startup(info); - if (retval) + if (retval) { + if (allocated_resources) + deinit_port(info); + + /* FIXME Decrease count info->count here too? */ return retval; + } + retval = block_til_ready(tty, filp, info); if (retval) { @@ -4604,6 +4193,9 @@ rs_open(struct tty_struct *tty, struct file * filp) printk("rs_open returning after block_til_ready with %d\n", retval); #endif + if (allocated_resources) + deinit_port(info); + return retval; } @@ -4793,6 +4385,8 @@ static const struct tty_operations rs_ops = { .send_xchar = rs_send_xchar, .wait_until_sent = rs_wait_until_sent, .read_proc = rs_read_proc, + .tiocmget = rs_tiocmget, + .tiocmset = rs_tiocmset }; static int __init @@ -4810,9 +4404,27 @@ rs_init(void) /* Setup the timed flush handler system */ #if !defined(CONFIG_ETRAX_SERIAL_FAST_TIMER) - init_timer(&flush_timer); - flush_timer.function = timed_flush_handler; - mod_timer(&flush_timer, jiffies + CONFIG_ETRAX_SERIAL_RX_TIMEOUT_TICKS); + setup_timer(&flush_timer, timed_flush_handler, 0); + mod_timer(&flush_timer, jiffies + 5); +#endif + +#if defined(CONFIG_ETRAX_RS485) +#if defined(CONFIG_ETRAX_RS485_ON_PA) + if (cris_io_interface_allocate_pins(if_ser0, 'a', rs485_pa_bit, + rs485_pa_bit)) { + printk(KERN_CRIT "ETRAX100LX serial: Could not allocate " + "RS485 pin\n"); + return -EBUSY; + } +#endif +#if defined(CONFIG_ETRAX_RS485_ON_PORT_G) + if (cris_io_interface_allocate_pins(if_ser0, 'g', rs485_pa_bit, + rs485_port_g_bit)) { + printk(KERN_CRIT "ETRAX100LX serial: Could not allocate " + "RS485 pin\n"); + return -EBUSY; + } +#endif #endif /* Initialize the tty_driver structure */ @@ -4839,6 +4451,16 @@ rs_init(void) /* do some initializing for the separate ports */ for (i = 0, info = rs_table; i < NR_PORTS; i++,info++) { + if (info->enabled) { + if (cris_request_io_interface(info->io_if, + info->io_if_description)) { + printk(KERN_CRIT "ETRAX100LX async serial: " + "Could not allocate IO pins for " + "%s, port %d\n", + info->io_if_description, i); + info->enabled = 0; + } + } info->uses_dma_in = 0; info->uses_dma_out = 0; info->line = i; @@ -4872,7 +4494,7 @@ rs_init(void) info->rs485.delay_rts_before_send = 0; info->rs485.enabled = 0; #endif - INIT_WORK(&info->work, do_softint, info); + INIT_WORK(&info->work, do_softint); if (info->enabled) { printk(KERN_INFO "%s%d at 0x%x is a builtin UART with DMA\n", @@ -4890,64 +4512,17 @@ rs_init(void) #endif #ifndef CONFIG_SVINTO_SIM +#ifndef CONFIG_ETRAX_KGDB /* Not needed in simulator. May only complicate stuff. */ /* hook the irq's for DMA channel 6 and 7, serial output and input, and some more... */ - if (request_irq(SERIAL_IRQ_NBR, ser_interrupt, IRQF_SHARED | IRQF_DISABLED, "serial ", NULL)) - panic("irq8"); - -#ifdef CONFIG_ETRAX_SERIAL_PORT0 -#ifdef CONFIG_ETRAX_SERIAL_PORT0_DMA6_OUT - if (request_irq(SER0_DMA_TX_IRQ_NBR, tr_interrupt, IRQF_DISABLED, "serial 0 dma tr", NULL)) - panic("irq22"); -#endif -#ifdef CONFIG_ETRAX_SERIAL_PORT0_DMA7_IN - if (request_irq(SER0_DMA_RX_IRQ_NBR, rec_interrupt, IRQF_DISABLED, "serial 0 dma rec", NULL)) - panic("irq23"); -#endif -#endif - -#ifdef CONFIG_ETRAX_SERIAL_PORT1 -#ifdef CONFIG_ETRAX_SERIAL_PORT1_DMA8_OUT - if (request_irq(SER1_DMA_TX_IRQ_NBR, tr_interrupt, IRQF_DISABLED, "serial 1 dma tr", NULL)) - panic("irq24"); -#endif -#ifdef CONFIG_ETRAX_SERIAL_PORT1_DMA9_IN - if (request_irq(SER1_DMA_RX_IRQ_NBR, rec_interrupt, IRQF_DISABLED, "serial 1 dma rec", NULL)) - panic("irq25"); -#endif -#endif -#ifdef CONFIG_ETRAX_SERIAL_PORT2 - /* DMA Shared with par0 (and SCSI0 and ATA) */ -#ifdef CONFIG_ETRAX_SERIAL_PORT2_DMA2_OUT - if (request_irq(SER2_DMA_TX_IRQ_NBR, tr_interrupt, IRQF_SHARED | IRQF_DISABLED, "serial 2 dma tr", NULL)) - panic("irq18"); -#endif -#ifdef CONFIG_ETRAX_SERIAL_PORT2_DMA3_IN - if (request_irq(SER2_DMA_RX_IRQ_NBR, rec_interrupt, IRQF_SHARED | IRQF_DISABLED, "serial 2 dma rec", NULL)) - panic("irq19"); -#endif -#endif -#ifdef CONFIG_ETRAX_SERIAL_PORT3 - /* DMA Shared with par1 (and SCSI1 and Extern DMA 0) */ -#ifdef CONFIG_ETRAX_SERIAL_PORT3_DMA4_OUT - if (request_irq(SER3_DMA_TX_IRQ_NBR, tr_interrupt, IRQF_SHARED | IRQF_DISABLED, "serial 3 dma tr", NULL)) - panic("irq20"); -#endif -#ifdef CONFIG_ETRAX_SERIAL_PORT3_DMA5_IN - if (request_irq(SER3_DMA_RX_IRQ_NBR, rec_interrupt, IRQF_SHARED | IRQF_DISABLED, "serial 3 dma rec", NULL)) - panic("irq21"); -#endif -#endif + if (request_irq(SERIAL_IRQ_NBR, ser_interrupt, + IRQF_SHARED | IRQF_DISABLED, "serial ", driver)) + panic("%s: Failed to request irq8", __FUNCTION__); -#ifdef CONFIG_ETRAX_SERIAL_FLUSH_DMA_FAST - if (request_irq(TIMER1_IRQ_NBR, timeout_interrupt, IRQF_SHARED | IRQF_DISABLED, - "fast serial dma timeout", NULL)) { - printk(KERN_CRIT "err: timer1 irq\n"); - } #endif #endif /* CONFIG_SVINTO_SIM */ - debug_write_function = rs_debug_write_function; + return 0; } diff --git a/drivers/serial/crisv10.h b/drivers/serial/crisv10.h new file mode 100644 index 0000000..ccd0f32 --- /dev/null +++ b/drivers/serial/crisv10.h @@ -0,0 +1,146 @@ +/* + * serial.h: Arch-dep definitions for the Etrax100 serial driver. + * + * Copyright (C) 1998-2007 Axis Communications AB + */ + +#ifndef _ETRAX_SERIAL_H +#define _ETRAX_SERIAL_H + +#include <linux/circ_buf.h> +#include <asm/termios.h> +#include <asm/dma.h> +#include <asm/arch/io_interface_mux.h> + +/* Software state per channel */ + +#ifdef __KERNEL__ +/* + * This is our internal structure for each serial port's state. + * + * Many fields are paralleled by the structure used by the serial_struct + * structure. + * + * For definitions of the flags field, see tty.h + */ + +#define SERIAL_RECV_DESCRIPTORS 8 + +struct etrax_recv_buffer { + struct etrax_recv_buffer *next; + unsigned short length; + unsigned char error; + unsigned char pad; + + unsigned char buffer[0]; +}; + +struct e100_serial { + int baud; + volatile u8 *port; /* R_SERIALx_CTRL */ + u32 irq; /* bitnr in R_IRQ_MASK2 for dmaX_descr */ + + /* Output registers */ + volatile u8 *oclrintradr; /* adr to R_DMA_CHx_CLR_INTR */ + volatile u32 *ofirstadr; /* adr to R_DMA_CHx_FIRST */ + volatile u8 *ocmdadr; /* adr to R_DMA_CHx_CMD */ + const volatile u8 *ostatusadr; /* adr to R_DMA_CHx_STATUS */ + + /* Input registers */ + volatile u8 *iclrintradr; /* adr to R_DMA_CHx_CLR_INTR */ + volatile u32 *ifirstadr; /* adr to R_DMA_CHx_FIRST */ + volatile u8 *icmdadr; /* adr to R_DMA_CHx_CMD */ + volatile u32 *idescradr; /* adr to R_DMA_CHx_DESCR */ + + int flags; /* defined in tty.h */ + + u8 rx_ctrl; /* shadow for R_SERIALx_REC_CTRL */ + u8 tx_ctrl; /* shadow for R_SERIALx_TR_CTRL */ + u8 iseteop; /* bit number for R_SET_EOP for the input dma */ + int enabled; /* Set to 1 if the port is enabled in HW config */ + + u8 dma_out_enabled; /* Set to 1 if DMA should be used */ + u8 dma_in_enabled; /* Set to 1 if DMA should be used */ + + /* end of fields defined in rs_table[] in .c-file */ + int dma_owner; + unsigned int dma_in_nbr; + unsigned int dma_out_nbr; + unsigned int dma_in_irq_nbr; + unsigned int dma_out_irq_nbr; + unsigned long dma_in_irq_flags; + unsigned long dma_out_irq_flags; + char *dma_in_irq_description; + char *dma_out_irq_description; + + enum cris_io_interface io_if; + char *io_if_description; + + u8 uses_dma_in; /* Set to 1 if DMA is used */ + u8 uses_dma_out; /* Set to 1 if DMA is used */ + u8 forced_eop; /* a fifo eop has been forced */ + int baud_base; /* For special baudrates */ + int custom_divisor; /* For special baudrates */ + struct etrax_dma_descr tr_descr; + struct etrax_dma_descr rec_descr[SERIAL_RECV_DESCRIPTORS]; + int cur_rec_descr; + + volatile int tr_running; /* 1 if output is running */ + + struct tty_struct *tty; + int read_status_mask; + int ignore_status_mask; + int x_char; /* xon/xoff character */ + int close_delay; + unsigned short closing_wait; + unsigned short closing_wait2; + unsigned long event; + unsigned long last_active; + int line; + int type; /* PORT_ETRAX */ + int count; /* # of fd on device */ + int blocked_open; /* # of blocked opens */ + struct circ_buf xmit; + struct etrax_recv_buffer *first_recv_buffer; + struct etrax_recv_buffer *last_recv_buffer; + unsigned int recv_cnt; + unsigned int max_recv_cnt; + + struct work_struct work; + struct async_icount icount; /* error-statistics etc.*/ + struct ktermios normal_termios; + struct ktermios callout_termios; + wait_queue_head_t open_wait; + wait_queue_head_t close_wait; + + unsigned long char_time_usec; /* The time for 1 char, in usecs */ + unsigned long flush_time_usec; /* How often we should flush */ + unsigned long last_tx_active_usec; /* Last tx usec in the jiffies */ + unsigned long last_tx_active; /* Last tx time in jiffies */ + unsigned long last_rx_active_usec; /* Last rx usec in the jiffies */ + unsigned long last_rx_active; /* Last rx time in jiffies */ + + int break_detected_cnt; + int errorcode; + +#ifdef CONFIG_ETRAX_RS485 + struct rs485_control rs485; /* RS-485 support */ +#endif +}; + +/* this PORT is not in the standard serial.h. it's not actually used for + * anything since we only have one type of async serial-port anyway in this + * system. + */ + +#define PORT_ETRAX 1 + +/* + * Events are used to schedule things to happen at timer-interrupt + * time, instead of at rs interrupt time. + */ +#define RS_EVENT_WRITE_WAKEUP 0 + +#endif /* __KERNEL__ */ + +#endif /* !_ETRAX_SERIAL_H */ diff --git a/drivers/serial/ip22zilog.c b/drivers/serial/ip22zilog.c index f3257f7..9c95bc0 100644 --- a/drivers/serial/ip22zilog.c +++ b/drivers/serial/ip22zilog.c @@ -45,8 +45,6 @@ #include "ip22zilog.h" -void ip22_do_break(void); - /* * On IP22 we need to delay after register accesses but we do not need to * flush writes. @@ -81,12 +79,9 @@ struct uart_ip22zilog_port { #define IP22ZILOG_FLAG_REGS_HELD 0x00000040 #define IP22ZILOG_FLAG_TX_STOPPED 0x00000080 #define IP22ZILOG_FLAG_TX_ACTIVE 0x00000100 +#define IP22ZILOG_FLAG_RESET_DONE 0x00000200 - unsigned int cflag; - - /* L1-A keyboard break state. */ - int kbd_id; - int l1_down; + unsigned int tty_break; unsigned char parity_mask; unsigned char prev_status; @@ -250,13 +245,26 @@ static void ip22zilog_maybe_update_regs(struct uart_ip22zilog_port *up, } } -static void ip22zilog_receive_chars(struct uart_ip22zilog_port *up, - struct zilog_channel *channel) +#define Rx_BRK 0x0100 /* BREAK event software flag. */ +#define Rx_SYS 0x0200 /* SysRq event software flag. */ + +static struct tty_struct *ip22zilog_receive_chars(struct uart_ip22zilog_port *up, + struct zilog_channel *channel) { - struct tty_struct *tty = up->port.info->tty; /* XXX info==NULL? */ + struct tty_struct *tty; + unsigned char ch, flag; + unsigned int r1; + + tty = NULL; + if (up->port.info != NULL && + up->port.info->tty != NULL) + tty = up->port.info->tty; - while (1) { - unsigned char ch, r1, flag; + for (;;) { + ch = readb(&channel->control); + ZSDELAY(); + if (!(ch & Rx_CH_AV)) + break; r1 = read_zsreg(channel, R1); if (r1 & (PAR_ERR | Rx_OVR | CRC_ERR)) { @@ -265,43 +273,26 @@ static void ip22zilog_receive_chars(struct uart_ip22zilog_port *up, ZS_WSYNC(channel); } - ch = readb(&channel->control); - ZSDELAY(); - - /* This funny hack depends upon BRK_ABRT not interfering - * with the other bits we care about in R1. - */ - if (ch & BRK_ABRT) - r1 |= BRK_ABRT; - ch = readb(&channel->data); ZSDELAY(); ch &= up->parity_mask; - if (ZS_IS_CONS(up) && (r1 & BRK_ABRT)) { - /* Wait for BREAK to deassert to avoid potentially - * confusing the PROM. - */ - while (1) { - ch = readb(&channel->control); - ZSDELAY(); - if (!(ch & BRK_ABRT)) - break; - } - ip22_do_break(); - return; - } + /* Handle the null char got when BREAK is removed. */ + if (!ch) + r1 |= up->tty_break; /* A real serial line, record the character and status. */ flag = TTY_NORMAL; up->port.icount.rx++; - if (r1 & (BRK_ABRT | PAR_ERR | Rx_OVR | CRC_ERR)) { - if (r1 & BRK_ABRT) { - r1 &= ~(PAR_ERR | CRC_ERR); + if (r1 & (PAR_ERR | Rx_OVR | CRC_ERR | Rx_SYS | Rx_BRK)) { + up->tty_break = 0; + + if (r1 & (Rx_SYS | Rx_BRK)) { up->port.icount.brk++; - if (uart_handle_break(&up->port)) - goto next_char; + if (r1 & Rx_SYS) + continue; + r1 &= ~(PAR_ERR | CRC_ERR); } else if (r1 & PAR_ERR) up->port.icount.parity++; @@ -310,30 +301,21 @@ static void ip22zilog_receive_chars(struct uart_ip22zilog_port *up, if (r1 & Rx_OVR) up->port.icount.overrun++; r1 &= up->port.read_status_mask; - if (r1 & BRK_ABRT) + if (r1 & Rx_BRK) flag = TTY_BREAK; else if (r1 & PAR_ERR) flag = TTY_PARITY; else if (r1 & CRC_ERR) flag = TTY_FRAME; } - if (uart_handle_sysrq_char(&up->port, ch)) - goto next_char; - if (up->port.ignore_status_mask == 0xff || - (r1 & up->port.ignore_status_mask) == 0) - tty_insert_flip_char(tty, ch, flag); + if (uart_handle_sysrq_char(&up->port, ch)) + continue; - if (r1 & Rx_OVR) - tty_insert_flip_char(tty, 0, TTY_OVERRUN); - next_char: - ch = readb(&channel->control); - ZSDELAY(); - if (!(ch & Rx_CH_AV)) - break; + if (tty) + uart_insert_char(&up->port, r1, Rx_OVR, ch, flag); } - - tty_flip_buffer_push(tty); + return tty; } static void ip22zilog_status_handle(struct uart_ip22zilog_port *up, @@ -348,6 +330,15 @@ static void ip22zilog_status_handle(struct uart_ip22zilog_port *up, ZSDELAY(); ZS_WSYNC(channel); + if (up->curregs[R15] & BRKIE) { + if ((status & BRK_ABRT) && !(up->prev_status & BRK_ABRT)) { + if (uart_handle_break(&up->port)) + up->tty_break = Rx_SYS; + else + up->tty_break = Rx_BRK; + } + } + if (ZS_WANTS_MODEM_STATUS(up)) { if (status & SYNC) up->port.icount.dsr++; @@ -356,10 +347,10 @@ static void ip22zilog_status_handle(struct uart_ip22zilog_port *up, * But it does not tell us which bit has changed, we have to keep * track of this ourselves. */ - if ((status & DCD) ^ up->prev_status) + if ((status ^ up->prev_status) ^ DCD) uart_handle_dcd_change(&up->port, (status & DCD)); - if ((status & CTS) ^ up->prev_status) + if ((status ^ up->prev_status) ^ CTS) uart_handle_cts_change(&up->port, (status & CTS)); @@ -447,19 +438,21 @@ static irqreturn_t ip22zilog_interrupt(int irq, void *dev_id) while (up) { struct zilog_channel *channel = ZILOG_CHANNEL_FROM_PORT(&up->port); + struct tty_struct *tty; unsigned char r3; spin_lock(&up->port.lock); r3 = read_zsreg(channel, R3); /* Channel A */ + tty = NULL; if (r3 & (CHAEXT | CHATxIP | CHARxIP)) { writeb(RES_H_IUS, &channel->control); ZSDELAY(); ZS_WSYNC(channel); if (r3 & CHARxIP) - ip22zilog_receive_chars(up, channel); + tty = ip22zilog_receive_chars(up, channel); if (r3 & CHAEXT) ip22zilog_status_handle(up, channel); if (r3 & CHATxIP) @@ -467,18 +460,22 @@ static irqreturn_t ip22zilog_interrupt(int irq, void *dev_id) } spin_unlock(&up->port.lock); + if (tty) + tty_flip_buffer_push(tty); + /* Channel B */ up = up->next; channel = ZILOG_CHANNEL_FROM_PORT(&up->port); spin_lock(&up->port.lock); + tty = NULL; if (r3 & (CHBEXT | CHBTxIP | CHBRxIP)) { writeb(RES_H_IUS, &channel->control); ZSDELAY(); ZS_WSYNC(channel); if (r3 & CHBRxIP) - ip22zilog_receive_chars(up, channel); + tty = ip22zilog_receive_chars(up, channel); if (r3 & CHBEXT) ip22zilog_status_handle(up, channel); if (r3 & CHBTxIP) @@ -486,6 +483,9 @@ static irqreturn_t ip22zilog_interrupt(int irq, void *dev_id) } spin_unlock(&up->port.lock); + if (tty) + tty_flip_buffer_push(tty); + up = up->next; } @@ -681,11 +681,46 @@ static void ip22zilog_break_ctl(struct uart_port *port, int break_state) spin_unlock_irqrestore(&port->lock, flags); } +static void __ip22zilog_reset(struct uart_ip22zilog_port *up) +{ + struct zilog_channel *channel; + int i; + + if (up->flags & IP22ZILOG_FLAG_RESET_DONE) + return; + + /* Let pending transmits finish. */ + channel = ZILOG_CHANNEL_FROM_PORT(&up->port); + for (i = 0; i < 1000; i++) { + unsigned char stat = read_zsreg(channel, R1); + if (stat & ALL_SNT) + break; + udelay(100); + } + + if (!ZS_IS_CHANNEL_A(up)) { + up++; + channel = ZILOG_CHANNEL_FROM_PORT(&up->port); + } + write_zsreg(channel, R9, FHWRES); + ZSDELAY_LONG(); + (void) read_zsreg(channel, R0); + + up->flags |= IP22ZILOG_FLAG_RESET_DONE; + up->next->flags |= IP22ZILOG_FLAG_RESET_DONE; +} + static void __ip22zilog_startup(struct uart_ip22zilog_port *up) { struct zilog_channel *channel; channel = ZILOG_CHANNEL_FROM_PORT(&up->port); + + __ip22zilog_reset(up); + + __load_zsregs(channel, up->curregs); + /* set master interrupt enable */ + write_zsreg(channel, R9, up->curregs[R9]); up->prev_status = readb(&channel->control); /* Enable receiver and transmitter. */ @@ -859,8 +894,6 @@ ip22zilog_set_termios(struct uart_port *port, struct ktermios *termios, else up->flags &= ~IP22ZILOG_FLAG_MODEM_STATUS; - up->cflag = termios->c_cflag; - ip22zilog_maybe_update_regs(up, ZILOG_CHANNEL_FROM_PORT(port)); uart_update_timeout(port, termios->c_cflag, baud); @@ -992,74 +1025,29 @@ ip22zilog_console_write(struct console *con, const char *s, unsigned int count) spin_unlock_irqrestore(&up->port.lock, flags); } -void -ip22serial_console_termios(struct console *con, char *options) -{ - int baud = 9600, bits = 8, cflag; - int parity = 'n'; - int flow = 'n'; - - if (options) - uart_parse_options(options, &baud, &parity, &bits, &flow); - - cflag = CREAD | HUPCL | CLOCAL; - - switch (baud) { - case 150: cflag |= B150; break; - case 300: cflag |= B300; break; - case 600: cflag |= B600; break; - case 1200: cflag |= B1200; break; - case 2400: cflag |= B2400; break; - case 4800: cflag |= B4800; break; - case 9600: cflag |= B9600; break; - case 19200: cflag |= B19200; break; - case 38400: cflag |= B38400; break; - default: baud = 9600; cflag |= B9600; break; - } - - con->cflag = cflag | CS8; /* 8N1 */ - - uart_update_timeout(&ip22zilog_port_table[con->index].port, cflag, baud); -} - static int __init ip22zilog_console_setup(struct console *con, char *options) { struct uart_ip22zilog_port *up = &ip22zilog_port_table[con->index]; unsigned long flags; - int baud, brg; - - printk("Console: ttyS%d (IP22-Zilog)\n", con->index); + int baud = 9600, bits = 8; + int parity = 'n'; + int flow = 'n'; - /* Get firmware console settings. */ - ip22serial_console_termios(con, options); + up->flags |= IP22ZILOG_FLAG_IS_CONS; - /* Firmware console speed is limited to 150-->38400 baud so - * this hackish cflag thing is OK. - */ - switch (con->cflag & CBAUD) { - case B150: baud = 150; break; - case B300: baud = 300; break; - case B600: baud = 600; break; - case B1200: baud = 1200; break; - case B2400: baud = 2400; break; - case B4800: baud = 4800; break; - default: case B9600: baud = 9600; break; - case B19200: baud = 19200; break; - case B38400: baud = 38400; break; - }; - - brg = BPS_TO_BRG(baud, ZS_CLOCK / ZS_CLOCK_DIVISOR); + printk(KERN_INFO "Console: ttyS%d (IP22-Zilog)\n", con->index); spin_lock_irqsave(&up->port.lock, flags); - up->curregs[R15] = BRKIE; - ip22zilog_convert_to_zs(up, con->cflag, 0, brg); + up->curregs[R15] |= BRKIE; __ip22zilog_startup(up); spin_unlock_irqrestore(&up->port.lock, flags); - return 0; + if (options) + uart_parse_options(options, &baud, &parity, &bits, &flow); + return uart_set_options(&up->port, con, baud, parity, bits, flow); } static struct uart_driver ip22zilog_reg; @@ -1140,25 +1128,10 @@ static void __init ip22zilog_prepare(void) up[(chip * 2) + 1].port.line = (chip * 2) + 1; up[(chip * 2) + 1].flags |= IP22ZILOG_FLAG_IS_CHANNEL_A; } -} - -static void __init ip22zilog_init_hw(void) -{ - int i; - - for (i = 0; i < NUM_CHANNELS; i++) { - struct uart_ip22zilog_port *up = &ip22zilog_port_table[i]; - struct zilog_channel *channel = ZILOG_CHANNEL_FROM_PORT(&up->port); - unsigned long flags; - int baud, brg; - spin_lock_irqsave(&up->port.lock, flags); - - if (ZS_IS_CHANNEL_A(up)) { - write_zsreg(channel, R9, FHWRES); - ZSDELAY_LONG(); - (void) read_zsreg(channel, R0); - } + for (channel = 0; channel < NUM_CHANNELS; channel++) { + struct uart_ip22zilog_port *up = &ip22zilog_port_table[channel]; + int brg; /* Normal serial TTY. */ up->parity_mask = 0xff; @@ -1169,16 +1142,10 @@ static void __init ip22zilog_init_hw(void) up->curregs[R9] = NV | MIE; up->curregs[R10] = NRZ; up->curregs[R11] = TCBR | RCBR; - baud = 9600; - brg = BPS_TO_BRG(baud, ZS_CLOCK / ZS_CLOCK_DIVISOR); + brg = BPS_TO_BRG(9600, ZS_CLOCK / ZS_CLOCK_DIVISOR); up->curregs[R12] = (brg & 0xff); up->curregs[R13] = (brg >> 8) & 0xff; up->curregs[R14] = BRENAB; - __load_zsregs(channel, up->curregs); - /* set master interrupt enable */ - write_zsreg(channel, R9, up->curregs[R9]); - - spin_unlock_irqrestore(&up->port.lock, flags); } } @@ -1195,8 +1162,6 @@ static int __init ip22zilog_ports_init(void) panic("IP22-Zilog: Unable to register zs interrupt handler.\n"); } - ip22zilog_init_hw(); - ret = uart_register_driver(&ip22zilog_reg); if (ret == 0) { int i; diff --git a/drivers/serial/pxa.c b/drivers/serial/pxa.c index af3a011..352fcb8 100644 --- a/drivers/serial/pxa.c +++ b/drivers/serial/pxa.c @@ -585,11 +585,11 @@ serial_pxa_type(struct uart_port *port) return up->name; } -#ifdef CONFIG_SERIAL_PXA_CONSOLE - static struct uart_pxa_port *serial_pxa_ports[4]; static struct uart_driver serial_pxa_reg; +#ifdef CONFIG_SERIAL_PXA_CONSOLE + #define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE) /* diff --git a/drivers/serial/sh-sci.h b/drivers/serial/sh-sci.h index e89ae29..d24621c 100644 --- a/drivers/serial/sh-sci.h +++ b/drivers/serial/sh-sci.h @@ -77,7 +77,6 @@ # define SCIF_ONLY #elif defined(CONFIG_CPU_SUBTYPE_SH7710) || defined(CONFIG_CPU_SUBTYPE_SH7712) # define SCSPTR0 0xA4400000 /* 16 bit SCIF */ -# define SCI_NPORTS 2 # define SCIF_ORER 0x0001 /* overrun error bit */ # define PACR 0xa4050100 # define PBCR 0xa4050102 @@ -102,12 +101,6 @@ # define SCIF_ORER 0x0001 /* overrun error bit */ # define SCSCR_INIT(port) 0x38 /* TIE=0,RIE=0,TE=1,RE=1,REIE=1 */ # define SCIF_ONLY -#elif defined(CONFIG_CPU_SUBTYPE_ST40STB1) -# define SCSPTR1 0xffe00020 /* 16 bit SCIF */ -# define SCSPTR2 0xffe80020 /* 16 bit SCIF */ -# define SCIF_ORER 0x0001 /* overrun error bit */ -# define SCSCR_INIT(port) 0x38 /* TIE=0,RIE=0,TE=1,RE=1,REIE=1 */ -# define SCIF_ONLY #elif defined(CONFIG_CPU_SUBTYPE_SH5_101) || defined(CONFIG_CPU_SUBTYPE_SH5_103) # include <asm/hardware.h> # define SCIF_BASE_ADDR 0x01030000 @@ -116,8 +109,7 @@ # define SCIF_LSR2_OFFS 0x0000024 # define SCSPTR2 ((port->mapbase)+SCIF_PTR2_OFFS) /* 16 bit SCIF */ # define SCLSR2 ((port->mapbase)+SCIF_LSR2_OFFS) /* 16 bit SCIF */ -# define SCSCR_INIT(port) 0x38 /* TIE=0,RIE=0, - TE=1,RE=1,REIE=1 */ +# define SCSCR_INIT(port) 0x38 /* TIE=0,RIE=0, TE=1,RE=1,REIE=1 */ # define SCIF_ONLY #elif defined(CONFIG_H83007) || defined(CONFIG_H83068) # define SCSCR_INIT(port) 0x30 /* TIE=0,RIE=0,TE=1,RE=1 */ @@ -577,15 +569,6 @@ static inline int sci_rxd_in(struct uart_port *port) return ctrl_inb(SCPDR0) & 0x0001 ? 1 : 0; /* SCIF0 */ return 1; } -#elif defined(CONFIG_CPU_SUBTYPE_ST40STB1) -static inline int sci_rxd_in(struct uart_port *port) -{ - if (port->mapbase == 0xffe00000) - return ctrl_inw(SCSPTR1)&0x0001 ? 1 : 0; /* SCIF */ - else - return ctrl_inw(SCSPTR2)&0x0001 ? 1 : 0; /* SCIF */ - -} #elif defined(CONFIG_CPU_SUBTYPE_SH5_101) || defined(CONFIG_CPU_SUBTYPE_SH5_103) static inline int sci_rxd_in(struct uart_port *port) { diff --git a/drivers/serial/uartlite.c b/drivers/serial/uartlite.c index dfef83f..a85f2d3 100644 --- a/drivers/serial/uartlite.c +++ b/drivers/serial/uartlite.c @@ -329,12 +329,14 @@ static struct uart_ops ulite_ops = { static void ulite_console_wait_tx(struct uart_port *port) { int i; + u8 val; - /* wait up to 10ms for the character(s) to be sent */ - for (i = 0; i < 10000; i++) { - if (readb(port->membase + ULITE_STATUS) & ULITE_STATUS_TXEMPTY) + /* Spin waiting for TX fifo to have space available */ + for (i = 0; i < 100000; i++) { + val = readb(port->membase + ULITE_STATUS); + if ((val & ULITE_STATUS_TXFULL) == 0) break; - udelay(1); + cpu_relax(); } } diff --git a/drivers/sh/superhyway/superhyway.c b/drivers/sh/superhyway/superhyway.c index 7d873b3..4d0282b 100644 --- a/drivers/sh/superhyway/superhyway.c +++ b/drivers/sh/superhyway/superhyway.c @@ -107,16 +107,17 @@ int superhyway_add_devices(struct superhyway_bus *bus, static int __init superhyway_init(void) { struct superhyway_bus *bus; - int ret = 0; + int ret; - device_register(&superhyway_bus_device); + ret = device_register(&superhyway_bus_device); + if (unlikely(ret)) + return ret; for (bus = superhyway_channels; bus->ops; bus++) ret |= superhyway_scan_bus(bus); return ret; } - postcore_initcall(superhyway_init); static const struct superhyway_device_id * diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index a77ede5..abf0504 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig @@ -61,7 +61,7 @@ config SPI_ATMEL config SPI_BFIN tristate "SPI controller driver for ADI Blackfin5xx" - depends on SPI_MASTER && BFIN + depends on SPI_MASTER && BLACKFIN help This is the SPI controller master driver for Blackfin 5xx processor. diff --git a/drivers/spi/atmel_spi.c b/drivers/spi/atmel_spi.c index 0d342dc..ff6a14b 100644 --- a/drivers/spi/atmel_spi.c +++ b/drivers/spi/atmel_spi.c @@ -497,7 +497,7 @@ static int atmel_spi_setup(struct spi_device *spi) /* chipselect must have been muxed as GPIO (e.g. in board setup) */ npcs_pin = (unsigned int)spi->controller_data; if (!spi->controller_state) { - ret = gpio_request(npcs_pin, "spi_npcs"); + ret = gpio_request(npcs_pin, spi->dev.bus_id); if (ret) return ret; spi->controller_state = (void *)npcs_pin; diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index 89769ce..b31f443 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -457,10 +457,11 @@ done: EXPORT_SYMBOL_GPL(spi_register_master); -static int __unregister(struct device *dev, void *unused) +static int __unregister(struct device *dev, void *master_dev) { /* note: before about 2.6.14-rc1 this would corrupt memory: */ - spi_unregister_device(to_spi_device(dev)); + if (dev != master_dev) + spi_unregister_device(to_spi_device(dev)); return 0; } @@ -478,7 +479,8 @@ void spi_unregister_master(struct spi_master *master) { int dummy; - dummy = device_for_each_child(master->dev.parent, NULL, __unregister); + dummy = device_for_each_child(master->dev.parent, &master->dev, + __unregister); device_unregister(&master->dev); } EXPORT_SYMBOL_GPL(spi_unregister_master); diff --git a/drivers/spi/spi_s3c24xx_gpio.c b/drivers/spi/spi_s3c24xx_gpio.c index 0fa25e2..109d82c 100644 --- a/drivers/spi/spi_s3c24xx_gpio.c +++ b/drivers/spi/spi_s3c24xx_gpio.c @@ -96,6 +96,7 @@ static void s3c2410_spigpio_chipselect(struct spi_device *dev, int value) static int s3c2410_spigpio_probe(struct platform_device *dev) { + struct s3c2410_spigpio_info *info; struct spi_master *master; struct s3c2410_spigpio *sp; int ret; @@ -113,10 +114,11 @@ static int s3c2410_spigpio_probe(struct platform_device *dev) platform_set_drvdata(dev, sp); /* copy in the plkatform data */ - sp->info = dev->dev.platform_data; + info = sp->info = dev->dev.platform_data; /* setup spi bitbang adaptor */ sp->bitbang.master = spi_master_get(master); + sp->bitbang.master->bus_num = info->bus_num; sp->bitbang.chipselect = s3c2410_spigpio_chipselect; sp->bitbang.txrx_word[SPI_MODE_0] = s3c2410_spigpio_txrx_mode0; @@ -124,13 +126,18 @@ static int s3c2410_spigpio_probe(struct platform_device *dev) sp->bitbang.txrx_word[SPI_MODE_2] = s3c2410_spigpio_txrx_mode2; sp->bitbang.txrx_word[SPI_MODE_3] = s3c2410_spigpio_txrx_mode3; - /* set state of spi pins */ - s3c2410_gpio_setpin(sp->info->pin_clk, 0); - s3c2410_gpio_setpin(sp->info->pin_mosi, 0); + /* set state of spi pins, always assume that the clock is + * available, but do check the MOSI and MISO. */ + s3c2410_gpio_setpin(info->pin_clk, 0); + s3c2410_gpio_cfgpin(info->pin_clk, S3C2410_GPIO_OUTPUT); - s3c2410_gpio_cfgpin(sp->info->pin_clk, S3C2410_GPIO_OUTPUT); - s3c2410_gpio_cfgpin(sp->info->pin_mosi, S3C2410_GPIO_OUTPUT); - s3c2410_gpio_cfgpin(sp->info->pin_miso, S3C2410_GPIO_INPUT); + if (info->pin_mosi < S3C2410_GPH10) { + s3c2410_gpio_setpin(info->pin_mosi, 0); + s3c2410_gpio_cfgpin(info->pin_mosi, S3C2410_GPIO_OUTPUT); + } + + if (info->pin_miso != S3C2410_GPA0 && info->pin_miso < S3C2410_GPH10) + s3c2410_gpio_cfgpin(info->pin_miso, S3C2410_GPIO_INPUT); ret = spi_bitbang_start(&sp->bitbang); if (ret) diff --git a/drivers/spi/spi_txx9.c b/drivers/spi/spi_txx9.c index cc5094f..363ac8e 100644 --- a/drivers/spi/spi_txx9.c +++ b/drivers/spi/spi_txx9.c @@ -24,6 +24,7 @@ #include <linux/spi/spi.h> #include <linux/err.h> #include <linux/clk.h> +#include <linux/io.h> #include <asm/gpio.h> @@ -74,7 +75,6 @@ struct txx9spi { struct list_head queue; wait_queue_head_t waitq; void __iomem *membase; - int irq; int baseclk; struct clk *clk; u32 max_speed_hz, min_speed_hz; @@ -350,12 +350,12 @@ static int __init txx9spi_probe(struct platform_device *dev) struct resource *res; int ret = -ENODEV; u32 mcr; + int irq; master = spi_alloc_master(&dev->dev, sizeof(*c)); if (!master) return ret; c = spi_master_get_devdata(master); - c->irq = -1; platform_set_drvdata(dev, master); INIT_WORK(&c->work, txx9spi_work); @@ -381,32 +381,36 @@ static int __init txx9spi_probe(struct platform_device *dev) res = platform_get_resource(dev, IORESOURCE_MEM, 0); if (!res) - goto exit; - c->membase = ioremap(res->start, res->end - res->start + 1); + goto exit_busy; + if (!devm_request_mem_region(&dev->dev, + res->start, res->end - res->start + 1, + "spi_txx9")) + goto exit_busy; + c->membase = devm_ioremap(&dev->dev, + res->start, res->end - res->start + 1); if (!c->membase) - goto exit; + goto exit_busy; /* enter config mode */ mcr = txx9spi_rd(c, TXx9_SPMCR); mcr &= ~(TXx9_SPMCR_OPMODE | TXx9_SPMCR_SPSTP | TXx9_SPMCR_BCLR); txx9spi_wr(c, mcr | TXx9_SPMCR_CONFIG | TXx9_SPMCR_BCLR, TXx9_SPMCR); - c->irq = platform_get_irq(dev, 0); - if (c->irq < 0) - goto exit; - ret = request_irq(c->irq, txx9spi_interrupt, 0, dev->name, c); - if (ret) { - c->irq = -1; + irq = platform_get_irq(dev, 0); + if (irq < 0) + goto exit_busy; + ret = devm_request_irq(&dev->dev, irq, txx9spi_interrupt, 0, + "spi_txx9", c); + if (ret) goto exit; - } c->workqueue = create_singlethread_workqueue(master->dev.parent->bus_id); if (!c->workqueue) - goto exit; + goto exit_busy; c->last_chipselect = -1; dev_info(&dev->dev, "at %#llx, irq %d, %dMHz\n", - (unsigned long long)res->start, c->irq, + (unsigned long long)res->start, irq, (c->baseclk + 500000) / 1000000); master->bus_num = dev->id; @@ -418,13 +422,11 @@ static int __init txx9spi_probe(struct platform_device *dev) if (ret) goto exit; return 0; +exit_busy: + ret = -EBUSY; exit: if (c->workqueue) destroy_workqueue(c->workqueue); - if (c->irq >= 0) - free_irq(c->irq, c); - if (c->membase) - iounmap(c->membase); if (c->clk) { clk_disable(c->clk); clk_put(c->clk); @@ -442,8 +444,6 @@ static int __exit txx9spi_remove(struct platform_device *dev) spi_unregister_master(master); platform_set_drvdata(dev, NULL); destroy_workqueue(c->workqueue); - free_irq(c->irq, c); - iounmap(c->membase); clk_disable(c->clk); clk_put(c->clk); spi_master_put(master); diff --git a/drivers/spi/tle62x0.c b/drivers/spi/tle62x0.c index 6da58ca..455991f 100644 --- a/drivers/spi/tle62x0.c +++ b/drivers/spi/tle62x0.c @@ -107,8 +107,11 @@ static ssize_t tle62x0_status_show(struct device *dev, mutex_lock(&st->lock); ret = tle62x0_read(st); - dev_dbg(dev, "tle62x0_read() returned %d\n", ret); + if (ret < 0) { + mutex_unlock(&st->lock); + return ret; + } for (ptr = 0; ptr < (st->nr_gpio * 2)/8; ptr += 1) { fault <<= 8; diff --git a/drivers/ssb/main.c b/drivers/ssb/main.c index c12a741..85a2054 100644 --- a/drivers/ssb/main.c +++ b/drivers/ssb/main.c @@ -440,6 +440,7 @@ static int ssb_devices_register(struct ssb_bus *bus) break; case SSB_BUSTYPE_PCMCIA: #ifdef CONFIG_SSB_PCMCIAHOST + sdev->irq = bus->host_pcmcia->irq.AssignedIRQ; dev->parent = &bus->host_pcmcia->dev; #endif break; @@ -1147,7 +1148,10 @@ static int __init ssb_modinit(void) return err; } -subsys_initcall(ssb_modinit); +/* ssb must be initialized after PCI but before the ssb drivers. + * That means we must use some initcall between subsys_initcall + * and device_initcall. */ +fs_initcall(ssb_modinit); static void __exit ssb_modexit(void) { diff --git a/drivers/ssb/pcmcia.c b/drivers/ssb/pcmcia.c index b6abee8..bb44a76 100644 --- a/drivers/ssb/pcmcia.c +++ b/drivers/ssb/pcmcia.c @@ -63,17 +63,17 @@ int ssb_pcmcia_switch_coreidx(struct ssb_bus *bus, err = pcmcia_access_configuration_register(pdev, ®); if (err != CS_SUCCESS) goto error; - read_addr |= (reg.Value & 0xF) << 12; + read_addr |= ((u32)(reg.Value & 0x0F)) << 12; reg.Offset = 0x30; err = pcmcia_access_configuration_register(pdev, ®); if (err != CS_SUCCESS) goto error; - read_addr |= reg.Value << 16; + read_addr |= ((u32)reg.Value) << 16; reg.Offset = 0x32; err = pcmcia_access_configuration_register(pdev, ®); if (err != CS_SUCCESS) goto error; - read_addr |= reg.Value << 24; + read_addr |= ((u32)reg.Value) << 24; cur_core = (read_addr - SSB_ENUM_BASE) / SSB_CORE_SIZE; if (cur_core == coreidx) @@ -152,28 +152,29 @@ error: goto out_unlock; } -/* These are the main device register access functions. - * do_select_core is inline to have the likely hotpath inline. - * All unlikely codepaths are out-of-line. */ -static inline int do_select_core(struct ssb_bus *bus, - struct ssb_device *dev, - u16 *offset) +static int select_core_and_segment(struct ssb_device *dev, + u16 *offset) { + struct ssb_bus *bus = dev->bus; int err; - u8 need_seg = (*offset >= 0x800) ? 1 : 0; + u8 need_segment; + + if (*offset >= 0x800) { + *offset -= 0x800; + need_segment = 1; + } else + need_segment = 0; if (unlikely(dev != bus->mapped_device)) { err = ssb_pcmcia_switch_core(bus, dev); if (unlikely(err)) return err; } - if (unlikely(need_seg != bus->mapped_pcmcia_seg)) { - err = ssb_pcmcia_switch_segment(bus, need_seg); + if (unlikely(need_segment != bus->mapped_pcmcia_seg)) { + err = ssb_pcmcia_switch_segment(bus, need_segment); if (unlikely(err)) return err; } - if (need_seg == 1) - *offset -= 0x800; return 0; } @@ -181,32 +182,31 @@ static inline int do_select_core(struct ssb_bus *bus, static u16 ssb_pcmcia_read16(struct ssb_device *dev, u16 offset) { struct ssb_bus *bus = dev->bus; - u16 x; - if (unlikely(do_select_core(bus, dev, &offset))) + if (unlikely(select_core_and_segment(dev, &offset))) return 0xFFFF; - x = readw(bus->mmio + offset); - return x; + return readw(bus->mmio + offset); } static u32 ssb_pcmcia_read32(struct ssb_device *dev, u16 offset) { struct ssb_bus *bus = dev->bus; - u32 x; + u32 lo, hi; - if (unlikely(do_select_core(bus, dev, &offset))) + if (unlikely(select_core_and_segment(dev, &offset))) return 0xFFFFFFFF; - x = readl(bus->mmio + offset); + lo = readw(bus->mmio + offset); + hi = readw(bus->mmio + offset + 2); - return x; + return (lo | (hi << 16)); } static void ssb_pcmcia_write16(struct ssb_device *dev, u16 offset, u16 value) { struct ssb_bus *bus = dev->bus; - if (unlikely(do_select_core(bus, dev, &offset))) + if (unlikely(select_core_and_segment(dev, &offset))) return; writew(value, bus->mmio + offset); } @@ -215,12 +215,12 @@ static void ssb_pcmcia_write32(struct ssb_device *dev, u16 offset, u32 value) { struct ssb_bus *bus = dev->bus; - if (unlikely(do_select_core(bus, dev, &offset))) + if (unlikely(select_core_and_segment(dev, &offset))) return; - readw(bus->mmio + offset); - writew(value >> 16, bus->mmio + offset + 2); - readw(bus->mmio + offset); - writew(value, bus->mmio + offset); + writeb((value & 0xFF000000) >> 24, bus->mmio + offset + 3); + writeb((value & 0x00FF0000) >> 16, bus->mmio + offset + 2); + writeb((value & 0x0000FF00) >> 8, bus->mmio + offset + 1); + writeb((value & 0x000000FF) >> 0, bus->mmio + offset + 0); } /* Not "static", as it's used in main.c */ diff --git a/drivers/usb/README b/drivers/usb/README index 3c84341..284f46b 100644 --- a/drivers/usb/README +++ b/drivers/usb/README @@ -39,12 +39,12 @@ first subdirectory in the list below that it fits into. image/ - This is for still image drivers, like scanners or digital cameras. -input/ - This is for any driver that uses the input subsystem, +../input/ - This is for any driver that uses the input subsystem, like keyboard, mice, touchscreens, tablets, etc. -media/ - This is for multimedia drivers, like video cameras, +../media/ - This is for multimedia drivers, like video cameras, radios, and any other drivers that talk to the v4l subsystem. -net/ - This is for network drivers. +../net/ - This is for network drivers. serial/ - This is for USB to serial drivers. storage/ - This is for USB mass-storage drivers. class/ - This is for all USB device drivers that do not fit diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c index 8586817..c51f8e9 100644 --- a/drivers/usb/core/driver.c +++ b/drivers/usb/core/driver.c @@ -585,9 +585,6 @@ static int usb_uevent(struct device *dev, struct kobj_uevent_env *env) { struct usb_device *usb_dev; - if (!dev) - return -ENODEV; - /* driver is often null here; dev_dbg() would oops */ pr_debug ("usb %s: uevent\n", dev->bus_id); @@ -631,14 +628,6 @@ static int usb_uevent(struct device *dev, struct kobj_uevent_env *env) usb_dev->descriptor.bDeviceProtocol)) return -ENOMEM; - if (add_uevent_var(env, "BUSNUM=%03d", - usb_dev->bus->busnum)) - return -ENOMEM; - - if (add_uevent_var(env, "DEVNUM=%03d", - usb_dev->devnum)) - return -ENOMEM; - return 0; } diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index fea8256..d5ed3fa 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c @@ -1311,8 +1311,8 @@ void usb_hcd_flush_endpoint(struct usb_device *udev, hcd = bus_to_hcd(udev->bus); /* No more submits can occur */ -rescan: spin_lock_irq(&hcd_urb_list_lock); +rescan: list_for_each_entry (urb, &ep->urb_list, urb_list) { int is_in; @@ -1345,6 +1345,7 @@ rescan: usb_put_urb (urb); /* list contents may have changed */ + spin_lock(&hcd_urb_list_lock); goto rescan; } spin_unlock_irq(&hcd_urb_list_lock); diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 036c3de..13b326a 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -335,7 +335,7 @@ static void kick_khubd(struct usb_hub *hub) to_usb_interface(hub->intfdev)->pm_usage_cnt = 1; spin_lock_irqsave(&hub_event_lock, flags); - if (!hub->disconnected & list_empty(&hub->event_list)) { + if (!hub->disconnected && list_empty(&hub->event_list)) { list_add_tail(&hub->event_list, &hub_event_list); wake_up(&khubd_wait); } diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c index 316a746..fcd40ec 100644 --- a/drivers/usb/core/message.c +++ b/drivers/usb/core/message.c @@ -1172,7 +1172,6 @@ int usb_set_interface(struct usb_device *dev, int interface, int alternate) struct usb_host_interface *alt; int ret; int manual = 0; - int changed; if (dev->state == USB_STATE_SUSPENDED) return -EHOSTUNREACH; @@ -1212,8 +1211,7 @@ int usb_set_interface(struct usb_device *dev, int interface, int alternate) */ /* prevent submissions using previous endpoint settings */ - changed = (iface->cur_altsetting != alt); - if (changed && device_is_registered(&iface->dev)) + if (iface->cur_altsetting != alt && device_is_registered(&iface->dev)) usb_remove_sysfs_intf_files(iface); usb_disable_interface(dev, iface); @@ -1250,7 +1248,7 @@ int usb_set_interface(struct usb_device *dev, int interface, int alternate) * (Likewise, EP0 never "halts" on well designed devices.) */ usb_enable_interface(dev, iface); - if (changed && device_is_registered(&iface->dev)) + if (device_is_registered(&iface->dev)) usb_create_sysfs_intf_files(iface); return 0; @@ -1348,34 +1346,10 @@ static int usb_if_uevent(struct device *dev, struct kobj_uevent_env *env) struct usb_interface *intf; struct usb_host_interface *alt; - if (!dev) - return -ENODEV; - - /* driver is often null here; dev_dbg() would oops */ - pr_debug ("usb %s: uevent\n", dev->bus_id); - intf = to_usb_interface(dev); usb_dev = interface_to_usbdev(intf); alt = intf->cur_altsetting; -#ifdef CONFIG_USB_DEVICEFS - if (add_uevent_var(env, "DEVICE=/proc/bus/usb/%03d/%03d", - usb_dev->bus->busnum, usb_dev->devnum)) - return -ENOMEM; -#endif - - if (add_uevent_var(env, "PRODUCT=%x/%x/%x", - le16_to_cpu(usb_dev->descriptor.idVendor), - le16_to_cpu(usb_dev->descriptor.idProduct), - le16_to_cpu(usb_dev->descriptor.bcdDevice))) - return -ENOMEM; - - if (add_uevent_var(env, "TYPE=%d/%d/%d", - usb_dev->descriptor.bDeviceClass, - usb_dev->descriptor.bDeviceSubClass, - usb_dev->descriptor.bDeviceProtocol)) - return -ENOMEM; - if (add_uevent_var(env, "INTERFACE=%d/%d/%d", alt->desc.bInterfaceClass, alt->desc.bInterfaceSubClass, @@ -1641,12 +1615,6 @@ free_interfaces: intf->dev.bus_id, ret); continue; } - - /* The driver's probe method can call usb_set_interface(), - * which would mean the interface's sysfs files are already - * created. Just in case, we'll remove them first. - */ - usb_remove_sysfs_intf_files(intf); usb_create_sysfs_intf_files(intf); } diff --git a/drivers/usb/core/sysfs.c b/drivers/usb/core/sysfs.c index b04afd0..32bd130 100644 --- a/drivers/usb/core/sysfs.c +++ b/drivers/usb/core/sysfs.c @@ -735,6 +735,8 @@ int usb_create_sysfs_intf_files(struct usb_interface *intf) struct usb_host_interface *alt = intf->cur_altsetting; int retval; + if (intf->sysfs_files_created) + return 0; retval = sysfs_create_group(&dev->kobj, &intf_attr_grp); if (retval) return retval; @@ -746,6 +748,7 @@ int usb_create_sysfs_intf_files(struct usb_interface *intf) if (intf->intf_assoc) retval = sysfs_create_group(&dev->kobj, &intf_assoc_attr_grp); usb_create_intf_ep_files(intf, udev); + intf->sysfs_files_created = 1; return 0; } @@ -753,8 +756,11 @@ void usb_remove_sysfs_intf_files(struct usb_interface *intf) { struct device *dev = &intf->dev; + if (!intf->sysfs_files_created) + return; usb_remove_intf_ep_files(intf); device_remove_file(dev, &dev_attr_interface); sysfs_remove_group(&dev->kobj, &intf_attr_grp); sysfs_remove_group(&intf->dev.kobj, &intf_assoc_attr_grp); + intf->sysfs_files_created = 0; } diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c index c4a6f10..8f14237 100644 --- a/drivers/usb/core/usb.c +++ b/drivers/usb/core/usb.c @@ -192,9 +192,34 @@ static void usb_release_dev(struct device *dev) kfree(udev); } +#ifdef CONFIG_HOTPLUG +static int usb_dev_uevent(struct device *dev, struct kobj_uevent_env *env) +{ + struct usb_device *usb_dev; + + usb_dev = to_usb_device(dev); + + if (add_uevent_var(env, "BUSNUM=%03d", usb_dev->bus->busnum)) + return -ENOMEM; + + if (add_uevent_var(env, "DEVNUM=%03d", usb_dev->devnum)) + return -ENOMEM; + + return 0; +} + +#else + +static int usb_dev_uevent(struct device *dev, struct kobj_uevent_env *env) +{ + return -ENODEV; +} +#endif /* CONFIG_HOTPLUG */ + struct device_type usb_device_type = { .name = "usb_device", .release = usb_release_dev, + .uevent = usb_dev_uevent, }; #ifdef CONFIG_PM diff --git a/drivers/usb/gadget/omap_udc.c b/drivers/usb/gadget/omap_udc.c index 87c4f50..d377154 100644 --- a/drivers/usb/gadget/omap_udc.c +++ b/drivers/usb/gadget/omap_udc.c @@ -1241,14 +1241,14 @@ static void pullup_enable(struct omap_udc *udc) udc->gadget.dev.parent->power.power_state = PMSG_ON; udc->gadget.dev.power.power_state = PMSG_ON; UDC_SYSCON1_REG |= UDC_PULLUP_EN; - if (!gadget_is_otg(udc->gadget) && !cpu_is_omap15xx()) + if (!gadget_is_otg(&udc->gadget) && !cpu_is_omap15xx()) OTG_CTRL_REG |= OTG_BSESSVLD; UDC_IRQ_EN_REG = UDC_DS_CHG_IE; } static void pullup_disable(struct omap_udc *udc) { - if (!gadget_is_otg(udc->gadget) && !cpu_is_omap15xx()) + if (!gadget_is_otg(&udc->gadget) && !cpu_is_omap15xx()) OTG_CTRL_REG &= ~OTG_BSESSVLD; UDC_IRQ_EN_REG = UDC_DS_CHG_IE; UDC_SYSCON1_REG &= ~UDC_PULLUP_EN; @@ -1386,7 +1386,7 @@ static void update_otg(struct omap_udc *udc) { u16 devstat; - if (!gadget_is_otg(udc->gadget)) + if (!gadget_is_otg(&udc->gadget)) return; if (OTG_CTRL_REG & OTG_ID) diff --git a/drivers/usb/gadget/s3c2410_udc.c b/drivers/usb/gadget/s3c2410_udc.c index e3e90f8..4ce050c 100644 --- a/drivers/usb/gadget/s3c2410_udc.c +++ b/drivers/usb/gadget/s3c2410_udc.c @@ -52,10 +52,10 @@ #include <asm/arch/irqs.h> #include <asm/arch/hardware.h> -#include <asm/arch/regs-clock.h> #include <asm/arch/regs-gpio.h> -#include <asm/arch/regs-udc.h> -#include <asm/arch/udc.h> + +#include <asm/plat-s3c24xx/regs-udc.h> +#include <asm/plat-s3c24xx/udc.h> #include <asm/mach-types.h> @@ -1511,7 +1511,11 @@ static irqreturn_t s3c2410_udc_vbus_irq(int irq, void *_dev) unsigned int value; dprintk(DEBUG_NORMAL, "%s()\n", __func__); + + /* some cpus cannot read from an line configured to IRQ! */ + s3c2410_gpio_cfgpin(udc_info->vbus_pin, S3C2410_GPIO_INPUT); value = s3c2410_gpio_getpin(udc_info->vbus_pin); + s3c2410_gpio_cfgpin(udc_info->vbus_pin, S3C2410_GPIO_SFN2); if (udc_info->vbus_pin_inverted) value = !value; @@ -1872,9 +1876,9 @@ static int s3c2410_udc_probe(struct platform_device *pdev) if (udc_info && udc_info->vbus_pin > 0) { irq = s3c2410_gpio_getirq(udc_info->vbus_pin); retval = request_irq(irq, s3c2410_udc_vbus_irq, - IRQF_DISABLED | IRQF_TRIGGER_RISING - | IRQF_TRIGGER_FALLING, - gadget_name, udc); + IRQF_DISABLED | IRQF_TRIGGER_RISING + | IRQF_TRIGGER_FALLING | IRQF_SHARED, + gadget_name, udc); if (retval != 0) { dev_err(dev, "can't get vbus irq %i, err %d\n", diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig index 177e78e..49a91c5e 100644 --- a/drivers/usb/host/Kconfig +++ b/drivers/usb/host/Kconfig @@ -156,7 +156,7 @@ config USB_OHCI_HCD_PCI config USB_OHCI_HCD_SSB bool "OHCI support for Broadcom SSB OHCI core" - depends on USB_OHCI_HCD && (SSB = y || SSB = CONFIG_USB_OHCI_HCD) && EXPERIMENTAL + depends on USB_OHCI_HCD && (SSB = y || SSB = USB_OHCI_HCD) && EXPERIMENTAL default n ---help--- Support for the Sonics Silicon Backplane (SSB) attached diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index c151444..5f2d74e 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c @@ -575,12 +575,15 @@ static int ehci_run (struct usb_hcd *hcd) * from the companions to the EHCI controller. If any of the * companions are in the middle of a port reset at the time, it * could cause trouble. Write-locking ehci_cf_port_reset_rwsem - * guarantees that no resets are in progress. + * guarantees that no resets are in progress. After we set CF, + * a short delay lets the hardware catch up; new resets shouldn't + * be started before the port switching actions could complete. */ down_write(&ehci_cf_port_reset_rwsem); hcd->state = HC_STATE_RUNNING; ehci_writel(ehci, FLAG_CF, &ehci->regs->configured_flag); ehci_readl(ehci, &ehci->regs->command); /* unblock posted writes */ + msleep(5); up_write(&ehci_cf_port_reset_rwsem); temp = HC_VERSION(ehci_readl(ehci, &ehci->caps->hc_capbase)); diff --git a/drivers/usb/image/microtek.c b/drivers/usb/image/microtek.c index 91e999c..bc207e3 100644 --- a/drivers/usb/image/microtek.c +++ b/drivers/usb/image/microtek.c @@ -819,7 +819,7 @@ static int mts_usb_probe(struct usb_interface *intf, goto out_kfree2; new_desc->host->hostdata[0] = (unsigned long)new_desc; - if (scsi_add_host(new_desc->host, NULL)) { + if (scsi_add_host(new_desc->host, &dev->dev)) { err_retval = -EIO; goto out_host_put; } diff --git a/drivers/usb/misc/adutux.c b/drivers/usb/misc/adutux.c index c567aa7..5a2c44e 100644 --- a/drivers/usb/misc/adutux.c +++ b/drivers/usb/misc/adutux.c @@ -79,12 +79,22 @@ MODULE_DEVICE_TABLE(usb, device_table); #define COMMAND_TIMEOUT (2*HZ) /* 60 second timeout for a command */ +/* + * The locking scheme is a vanilla 3-lock: + * adu_device.buflock: A spinlock, covers what IRQs touch. + * adutux_mutex: A Static lock to cover open_count. It would also cover + * any globals, but we don't have them in 2.6. + * adu_device.mtx: A mutex to hold across sleepers like copy_from_user. + * It covers all of adu_device, except the open_count + * and what .buflock covers. + */ + /* Structure to hold all of our device specific stuff */ struct adu_device { - struct mutex mtx; /* locks this structure */ + struct mutex mtx; struct usb_device* udev; /* save off the usb device pointer */ struct usb_interface* interface; - unsigned char minor; /* the starting minor number for this device */ + unsigned int minor; /* the starting minor number for this device */ char serial_number[8]; int open_count; /* number of times this port has been opened */ @@ -107,8 +117,11 @@ struct adu_device { char* interrupt_out_buffer; struct usb_endpoint_descriptor* interrupt_out_endpoint; struct urb* interrupt_out_urb; + int out_urb_finished; }; +static DEFINE_MUTEX(adutux_mutex); + static struct usb_driver adu_driver; static void adu_debug_data(int level, const char *function, int size, @@ -132,27 +145,31 @@ static void adu_debug_data(int level, const char *function, int size, */ static void adu_abort_transfers(struct adu_device *dev) { - dbg(2," %s : enter", __FUNCTION__); + unsigned long flags; - if (dev == NULL) { - dbg(1," %s : dev is null", __FUNCTION__); - goto exit; - } + dbg(2," %s : enter", __FUNCTION__); if (dev->udev == NULL) { dbg(1," %s : udev is null", __FUNCTION__); goto exit; } - dbg(2," %s : udev state %d", __FUNCTION__, dev->udev->state); - if (dev->udev->state == USB_STATE_NOTATTACHED) { - dbg(1," %s : udev is not attached", __FUNCTION__); - goto exit; - } - /* shutdown transfer */ - usb_unlink_urb(dev->interrupt_in_urb); - usb_unlink_urb(dev->interrupt_out_urb); + + /* XXX Anchor these instead */ + spin_lock_irqsave(&dev->buflock, flags); + if (!dev->read_urb_finished) { + spin_unlock_irqrestore(&dev->buflock, flags); + usb_kill_urb(dev->interrupt_in_urb); + } else + spin_unlock_irqrestore(&dev->buflock, flags); + + spin_lock_irqsave(&dev->buflock, flags); + if (!dev->out_urb_finished) { + spin_unlock_irqrestore(&dev->buflock, flags); + usb_kill_urb(dev->interrupt_out_urb); + } else + spin_unlock_irqrestore(&dev->buflock, flags); exit: dbg(2," %s : leave", __FUNCTION__); @@ -162,8 +179,6 @@ static void adu_delete(struct adu_device *dev) { dbg(2, "%s enter", __FUNCTION__); - adu_abort_transfers(dev); - /* free data structures */ usb_free_urb(dev->interrupt_in_urb); usb_free_urb(dev->interrupt_out_urb); @@ -239,7 +254,10 @@ static void adu_interrupt_out_callback(struct urb *urb) goto exit; } - wake_up_interruptible(&dev->write_wait); + spin_lock(&dev->buflock); + dev->out_urb_finished = 1; + wake_up(&dev->write_wait); + spin_unlock(&dev->buflock); exit: adu_debug_data(5, __FUNCTION__, urb->actual_length, @@ -252,12 +270,17 @@ static int adu_open(struct inode *inode, struct file *file) struct adu_device *dev = NULL; struct usb_interface *interface; int subminor; - int retval = 0; + int retval; dbg(2,"%s : enter", __FUNCTION__); subminor = iminor(inode); + if ((retval = mutex_lock_interruptible(&adutux_mutex))) { + dbg(2, "%s : mutex lock failed", __FUNCTION__); + goto exit_no_lock; + } + interface = usb_find_interface(&adu_driver, subminor); if (!interface) { err("%s - error, can't find device for minor %d", @@ -267,54 +290,54 @@ static int adu_open(struct inode *inode, struct file *file) } dev = usb_get_intfdata(interface); - if (!dev) { + if (!dev || !dev->udev) { retval = -ENODEV; goto exit_no_device; } - /* lock this device */ - if ((retval = mutex_lock_interruptible(&dev->mtx))) { - dbg(2, "%s : mutex lock failed", __FUNCTION__); + /* check that nobody else is using the device */ + if (dev->open_count) { + retval = -EBUSY; goto exit_no_device; } - /* increment our usage count for the device */ ++dev->open_count; dbg(2,"%s : open count %d", __FUNCTION__, dev->open_count); /* save device in the file's private structure */ file->private_data = dev; - if (dev->open_count == 1) { - /* initialize in direction */ - dev->read_buffer_length = 0; + /* initialize in direction */ + dev->read_buffer_length = 0; - /* fixup first read by having urb waiting for it */ - usb_fill_int_urb(dev->interrupt_in_urb,dev->udev, - usb_rcvintpipe(dev->udev, - dev->interrupt_in_endpoint->bEndpointAddress), - dev->interrupt_in_buffer, - le16_to_cpu(dev->interrupt_in_endpoint->wMaxPacketSize), - adu_interrupt_in_callback, dev, - dev->interrupt_in_endpoint->bInterval); - /* dev->interrupt_in_urb->transfer_flags |= URB_ASYNC_UNLINK; */ - dev->read_urb_finished = 0; - retval = usb_submit_urb(dev->interrupt_in_urb, GFP_KERNEL); - if (retval) - --dev->open_count; - } - mutex_unlock(&dev->mtx); + /* fixup first read by having urb waiting for it */ + usb_fill_int_urb(dev->interrupt_in_urb,dev->udev, + usb_rcvintpipe(dev->udev, + dev->interrupt_in_endpoint->bEndpointAddress), + dev->interrupt_in_buffer, + le16_to_cpu(dev->interrupt_in_endpoint->wMaxPacketSize), + adu_interrupt_in_callback, dev, + dev->interrupt_in_endpoint->bInterval); + dev->read_urb_finished = 0; + if (usb_submit_urb(dev->interrupt_in_urb, GFP_KERNEL)) + dev->read_urb_finished = 1; + /* we ignore failure */ + /* end of fixup for first read */ + + /* initialize out direction */ + dev->out_urb_finished = 1; + + retval = 0; exit_no_device: + mutex_unlock(&adutux_mutex); +exit_no_lock: dbg(2,"%s : leave, return value %d ", __FUNCTION__, retval); - return retval; } -static int adu_release_internal(struct adu_device *dev) +static void adu_release_internal(struct adu_device *dev) { - int retval = 0; - dbg(2," %s : enter", __FUNCTION__); /* decrement our usage count for the device */ @@ -326,12 +349,11 @@ static int adu_release_internal(struct adu_device *dev) } dbg(2," %s : leave", __FUNCTION__); - return retval; } static int adu_release(struct inode *inode, struct file *file) { - struct adu_device *dev = NULL; + struct adu_device *dev; int retval = 0; dbg(2," %s : enter", __FUNCTION__); @@ -343,15 +365,13 @@ static int adu_release(struct inode *inode, struct file *file) } dev = file->private_data; - if (dev == NULL) { dbg(1," %s : object is NULL", __FUNCTION__); retval = -ENODEV; goto exit; } - /* lock our device */ - mutex_lock(&dev->mtx); /* not interruptible */ + mutex_lock(&adutux_mutex); /* not interruptible */ if (dev->open_count <= 0) { dbg(1," %s : device not opened", __FUNCTION__); @@ -359,19 +379,15 @@ static int adu_release(struct inode *inode, struct file *file) goto exit; } + adu_release_internal(dev); if (dev->udev == NULL) { /* the device was unplugged before the file was released */ - mutex_unlock(&dev->mtx); - adu_delete(dev); - dev = NULL; - } else { - /* do the work */ - retval = adu_release_internal(dev); + if (!dev->open_count) /* ... and we're the last user */ + adu_delete(dev); } exit: - if (dev) - mutex_unlock(&dev->mtx); + mutex_unlock(&adutux_mutex); dbg(2," %s : leave, return value %d", __FUNCTION__, retval); return retval; } @@ -393,12 +409,12 @@ static ssize_t adu_read(struct file *file, __user char *buffer, size_t count, dev = file->private_data; dbg(2," %s : dev=%p", __FUNCTION__, dev); - /* lock this object */ + if (mutex_lock_interruptible(&dev->mtx)) return -ERESTARTSYS; /* verify that the device wasn't unplugged */ - if (dev->udev == NULL || dev->minor == 0) { + if (dev->udev == NULL) { retval = -ENODEV; err("No device or device unplugged %d", retval); goto exit; @@ -452,7 +468,7 @@ static ssize_t adu_read(struct file *file, __user char *buffer, size_t count, should_submit = 1; } else { /* even the primary was empty - we may need to do IO */ - if (dev->interrupt_in_urb->status == -EINPROGRESS) { + if (!dev->read_urb_finished) { /* somebody is doing IO */ spin_unlock_irqrestore(&dev->buflock, flags); dbg(2," %s : submitted already", __FUNCTION__); @@ -460,6 +476,7 @@ static ssize_t adu_read(struct file *file, __user char *buffer, size_t count, /* we must initiate input */ dbg(2," %s : initiate input", __FUNCTION__); dev->read_urb_finished = 0; + spin_unlock_irqrestore(&dev->buflock, flags); usb_fill_int_urb(dev->interrupt_in_urb,dev->udev, usb_rcvintpipe(dev->udev, @@ -469,15 +486,12 @@ static ssize_t adu_read(struct file *file, __user char *buffer, size_t count, adu_interrupt_in_callback, dev, dev->interrupt_in_endpoint->bInterval); - retval = usb_submit_urb(dev->interrupt_in_urb, GFP_ATOMIC); - if (!retval) { - spin_unlock_irqrestore(&dev->buflock, flags); - dbg(2," %s : submitted OK", __FUNCTION__); - } else { + retval = usb_submit_urb(dev->interrupt_in_urb, GFP_KERNEL); + if (retval) { + dev->read_urb_finished = 1; if (retval == -ENOMEM) { retval = bytes_read ? bytes_read : -ENOMEM; } - spin_unlock_irqrestore(&dev->buflock, flags); dbg(2," %s : submit failed", __FUNCTION__); goto exit; } @@ -486,10 +500,14 @@ static ssize_t adu_read(struct file *file, __user char *buffer, size_t count, /* we wait for I/O to complete */ set_current_state(TASK_INTERRUPTIBLE); add_wait_queue(&dev->read_wait, &wait); - if (!dev->read_urb_finished) + spin_lock_irqsave(&dev->buflock, flags); + if (!dev->read_urb_finished) { + spin_unlock_irqrestore(&dev->buflock, flags); timeout = schedule_timeout(COMMAND_TIMEOUT); - else + } else { + spin_unlock_irqrestore(&dev->buflock, flags); set_current_state(TASK_RUNNING); + } remove_wait_queue(&dev->read_wait, &wait); if (timeout <= 0) { @@ -509,19 +527,23 @@ static ssize_t adu_read(struct file *file, __user char *buffer, size_t count, retval = bytes_read; /* if the primary buffer is empty then use it */ - if (should_submit && !dev->interrupt_in_urb->status==-EINPROGRESS) { + spin_lock_irqsave(&dev->buflock, flags); + if (should_submit && dev->read_urb_finished) { + dev->read_urb_finished = 0; + spin_unlock_irqrestore(&dev->buflock, flags); usb_fill_int_urb(dev->interrupt_in_urb,dev->udev, usb_rcvintpipe(dev->udev, dev->interrupt_in_endpoint->bEndpointAddress), - dev->interrupt_in_buffer, - le16_to_cpu(dev->interrupt_in_endpoint->wMaxPacketSize), - adu_interrupt_in_callback, - dev, - dev->interrupt_in_endpoint->bInterval); - /* dev->interrupt_in_urb->transfer_flags |= URB_ASYNC_UNLINK; */ - dev->read_urb_finished = 0; - usb_submit_urb(dev->interrupt_in_urb, GFP_KERNEL); + dev->interrupt_in_buffer, + le16_to_cpu(dev->interrupt_in_endpoint->wMaxPacketSize), + adu_interrupt_in_callback, + dev, + dev->interrupt_in_endpoint->bInterval); + if (usb_submit_urb(dev->interrupt_in_urb, GFP_KERNEL) != 0) + dev->read_urb_finished = 1; /* we ignore failure */ + } else { + spin_unlock_irqrestore(&dev->buflock, flags); } exit: @@ -535,24 +557,24 @@ exit: static ssize_t adu_write(struct file *file, const __user char *buffer, size_t count, loff_t *ppos) { + DECLARE_WAITQUEUE(waita, current); struct adu_device *dev; size_t bytes_written = 0; size_t bytes_to_write; size_t buffer_size; + unsigned long flags; int retval; - int timeout = 0; dbg(2," %s : enter, count = %Zd", __FUNCTION__, count); dev = file->private_data; - /* lock this object */ retval = mutex_lock_interruptible(&dev->mtx); if (retval) goto exit_nolock; /* verify that the device wasn't unplugged */ - if (dev->udev == NULL || dev->minor == 0) { + if (dev->udev == NULL) { retval = -ENODEV; err("No device or device unplugged %d", retval); goto exit; @@ -564,42 +586,37 @@ static ssize_t adu_write(struct file *file, const __user char *buffer, goto exit; } - while (count > 0) { - if (dev->interrupt_out_urb->status == -EINPROGRESS) { - timeout = COMMAND_TIMEOUT; + add_wait_queue(&dev->write_wait, &waita); + set_current_state(TASK_INTERRUPTIBLE); + spin_lock_irqsave(&dev->buflock, flags); + if (!dev->out_urb_finished) { + spin_unlock_irqrestore(&dev->buflock, flags); - while (timeout > 0) { - if (signal_pending(current)) { + mutex_unlock(&dev->mtx); + if (signal_pending(current)) { dbg(1," %s : interrupted", __FUNCTION__); + set_current_state(TASK_RUNNING); retval = -EINTR; - goto exit; + goto exit_onqueue; } - mutex_unlock(&dev->mtx); - timeout = interruptible_sleep_on_timeout(&dev->write_wait, timeout); + if (schedule_timeout(COMMAND_TIMEOUT) == 0) { + dbg(1, "%s - command timed out.", __FUNCTION__); + retval = -ETIMEDOUT; + goto exit_onqueue; + } + remove_wait_queue(&dev->write_wait, &waita); retval = mutex_lock_interruptible(&dev->mtx); if (retval) { retval = bytes_written ? bytes_written : retval; goto exit_nolock; } - if (timeout > 0) { - break; - } - dbg(1," %s : interrupted timeout: %d", __FUNCTION__, timeout); - } - - - dbg(1," %s : final timeout: %d", __FUNCTION__, timeout); - - if (timeout == 0) { - dbg(1, "%s - command timed out.", __FUNCTION__); - retval = -ETIMEDOUT; - goto exit; - } - - dbg(4," %s : in progress, count = %Zd", __FUNCTION__, count); + dbg(4," %s : in progress, count = %Zd", __FUNCTION__, count); } else { + spin_unlock_irqrestore(&dev->buflock, flags); + set_current_state(TASK_RUNNING); + remove_wait_queue(&dev->write_wait, &waita); dbg(4," %s : sending, count = %Zd", __FUNCTION__, count); /* write the data into interrupt_out_buffer from userspace */ @@ -622,11 +639,12 @@ static ssize_t adu_write(struct file *file, const __user char *buffer, bytes_to_write, adu_interrupt_out_callback, dev, - dev->interrupt_in_endpoint->bInterval); - /* dev->interrupt_in_urb->transfer_flags |= URB_ASYNC_UNLINK; */ + dev->interrupt_out_endpoint->bInterval); dev->interrupt_out_urb->actual_length = bytes_to_write; + dev->out_urb_finished = 0; retval = usb_submit_urb(dev->interrupt_out_urb, GFP_KERNEL); if (retval < 0) { + dev->out_urb_finished = 1; err("Couldn't submit interrupt_out_urb %d", retval); goto exit; } @@ -637,16 +655,17 @@ static ssize_t adu_write(struct file *file, const __user char *buffer, bytes_written += bytes_to_write; } } - - retval = bytes_written; + mutex_unlock(&dev->mtx); + return bytes_written; exit: - /* unlock the device */ mutex_unlock(&dev->mtx); exit_nolock: - dbg(2," %s : leave, return value %d", __FUNCTION__, retval); + return retval; +exit_onqueue: + remove_wait_queue(&dev->write_wait, &waita); return retval; } @@ -831,25 +850,22 @@ static void adu_disconnect(struct usb_interface *interface) dbg(2," %s : enter", __FUNCTION__); dev = usb_get_intfdata(interface); - usb_set_intfdata(interface, NULL); + mutex_lock(&dev->mtx); /* not interruptible */ + dev->udev = NULL; /* poison */ minor = dev->minor; - - /* give back our minor */ usb_deregister_dev(interface, &adu_class); - dev->minor = 0; + mutex_unlock(&dev->mtx); - mutex_lock(&dev->mtx); /* not interruptible */ + mutex_lock(&adutux_mutex); + usb_set_intfdata(interface, NULL); /* if the device is not opened, then we clean up right now */ dbg(2," %s : open count %d", __FUNCTION__, dev->open_count); - if (!dev->open_count) { - mutex_unlock(&dev->mtx); + if (!dev->open_count) adu_delete(dev); - } else { - dev->udev = NULL; - mutex_unlock(&dev->mtx); - } + + mutex_unlock(&adutux_mutex); dev_info(&interface->dev, "ADU device adutux%d now disconnected\n", (minor - ADU_MINOR_BASE)); diff --git a/drivers/usb/misc/usbled.c b/drivers/usb/misc/usbled.c index 49c5c5c..06cb719 100644 --- a/drivers/usb/misc/usbled.c +++ b/drivers/usb/misc/usbled.c @@ -144,12 +144,14 @@ static void led_disconnect(struct usb_interface *interface) struct usb_led *dev; dev = usb_get_intfdata (interface); - usb_set_intfdata (interface, NULL); device_remove_file(&interface->dev, &dev_attr_blue); device_remove_file(&interface->dev, &dev_attr_red); device_remove_file(&interface->dev, &dev_attr_green); + /* first remove the files, then set the pointer to NULL */ + usb_set_intfdata (interface, NULL); + usb_put_dev(dev->udev); kfree(dev); diff --git a/drivers/usb/serial/generic.c b/drivers/usb/serial/generic.c index 9eb4a65..d415311 100644 --- a/drivers/usb/serial/generic.c +++ b/drivers/usb/serial/generic.c @@ -327,6 +327,7 @@ void usb_serial_generic_read_bulk_callback (struct urb *urb) struct usb_serial_port *port = (struct usb_serial_port *)urb->context; unsigned char *data = urb->transfer_buffer; int status = urb->status; + unsigned long flags; dbg("%s - port %d", __FUNCTION__, port->number); @@ -339,11 +340,11 @@ void usb_serial_generic_read_bulk_callback (struct urb *urb) usb_serial_debug_data(debug, &port->dev, __FUNCTION__, urb->actual_length, data); /* Throttle the device if requested by tty */ - spin_lock(&port->lock); + spin_lock_irqsave(&port->lock, flags); if (!(port->throttled = port->throttle_req)) /* Handle data and continue reading from device */ flush_and_resubmit_read_urb(port); - spin_unlock(&port->lock); + spin_unlock_irqrestore(&port->lock, flags); } EXPORT_SYMBOL_GPL(usb_serial_generic_read_bulk_callback); diff --git a/drivers/usb/serial/keyspan.c b/drivers/usb/serial/keyspan.c index 6bfdba6..feba967 100644 --- a/drivers/usb/serial/keyspan.c +++ b/drivers/usb/serial/keyspan.c @@ -1227,8 +1227,8 @@ static int keyspan_open (struct usb_serial_port *port, struct file *filp) s_priv = usb_get_serial_data(serial); p_priv = usb_get_serial_port_data(port); d_details = p_priv->device_details; - - dbg("%s - port%d.", __FUNCTION__, port->number); + + dbg("%s - port%d.", __FUNCTION__, port->number); /* Set some sane defaults */ p_priv->rts_state = 1; @@ -1249,7 +1249,7 @@ static int keyspan_open (struct usb_serial_port *port, struct file *filp) urb->dev = serial->dev; /* make sure endpoint data toggle is synchronized with the device */ - + usb_clear_halt(urb->dev, urb->pipe); if ((err = usb_submit_urb(urb, GFP_KERNEL)) != 0) { @@ -1265,7 +1265,7 @@ static int keyspan_open (struct usb_serial_port *port, struct file *filp) /* usb_settoggle(urb->dev, usb_pipeendpoint(urb->pipe), usb_pipeout(urb->pipe), 0); */ } - /* get the terminal config for the setup message now so we don't + /* get the terminal config for the setup message now so we don't * need to send 2 of them */ cflag = port->tty->termios->c_cflag; @@ -1274,7 +1274,7 @@ static int keyspan_open (struct usb_serial_port *port, struct file *filp) /* Baud rate calculation takes baud rate as an integer so other rates can be generated if desired. */ baud_rate = tty_get_baud_rate(port->tty); - /* If no match or invalid, leave as default */ + /* If no match or invalid, leave as default */ if (baud_rate >= 0 && d_details->calculate_baud_rate(baud_rate, d_details->baudclk, NULL, NULL, NULL, device_port) == KEYSPAN_BAUD_RATE_OK) { diff --git a/drivers/usb/serial/mos7840.c b/drivers/usb/serial/mos7840.c index a5ced7e..c29c912 100644 --- a/drivers/usb/serial/mos7840.c +++ b/drivers/usb/serial/mos7840.c @@ -2711,7 +2711,7 @@ static int mos7840_startup(struct usb_serial *serial) status = mos7840_set_reg_sync(serial->port[0], ZLP_REG5, Data); if (status < 0) { dbg("Writing ZLP_REG5 failed status-0x%x\n", status); - return -1; + goto error; } else dbg("ZLP_REG5 Writing success status%d\n", status); diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c index 2cd3f1d..cf8add9 100644 --- a/drivers/usb/serial/pl2303.c +++ b/drivers/usb/serial/pl2303.c @@ -86,6 +86,7 @@ static struct usb_device_id id_table [] = { { USB_DEVICE(ALCOR_VENDOR_ID, ALCOR_PRODUCT_ID) }, { USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_ID) }, { USB_DEVICE(WS002IN_VENDOR_ID, WS002IN_PRODUCT_ID) }, + { USB_DEVICE(COREGA_VENDOR_ID, COREGA_PRODUCT_ID) }, { } /* Terminating entry */ }; diff --git a/drivers/usb/serial/pl2303.h b/drivers/usb/serial/pl2303.h index ed603e3..d31f5d2 100644 --- a/drivers/usb/serial/pl2303.h +++ b/drivers/usb/serial/pl2303.h @@ -104,3 +104,6 @@ #define WS002IN_VENDOR_ID 0x11f6 #define WS002IN_PRODUCT_ID 0x2001 +/* Corega CG-USBRS232R Serial Adapter */ +#define COREGA_VENDOR_ID 0x07aa +#define COREGA_PRODUCT_ID 0x002a diff --git a/drivers/usb/serial/sierra.c b/drivers/usb/serial/sierra.c index 833f6e1..605ebcc 100644 --- a/drivers/usb/serial/sierra.c +++ b/drivers/usb/serial/sierra.c @@ -136,6 +136,8 @@ static struct usb_device_id id_table_3port [] = { { USB_DEVICE(0x0f30, 0x1b1d) }, /* Sierra Wireless MC5720 */ { USB_DEVICE(0x1199, 0x0218) }, /* Sierra Wireless MC5720 */ { USB_DEVICE(0x1199, 0x0020) }, /* Sierra Wireless MC5725 */ + { USB_DEVICE(0x1199, 0x0220) }, /* Sierra Wireless MC5725 */ + { USB_DEVICE(0x1199, 0x0220) }, /* Sierra Wireless MC5725 */ { USB_DEVICE(0x1199, 0x0019) }, /* Sierra Wireless AirCard 595 */ { USB_DEVICE(0x1199, 0x0021) }, /* Sierra Wireless AirCard 597E */ { USB_DEVICE(0x1199, 0x0120) }, /* Sierra Wireless USB Dongle 595U*/ diff --git a/drivers/usb/storage/scsiglue.c b/drivers/usb/storage/scsiglue.c index 1ba19ea..836a34a 100644 --- a/drivers/usb/storage/scsiglue.c +++ b/drivers/usb/storage/scsiglue.c @@ -177,6 +177,10 @@ static int slave_configure(struct scsi_device *sdev) * is an occasional series of retries that will all fail. */ sdev->retry_hwerror = 1; + /* USB disks should allow restart. Some drives spin down + * automatically, requiring a START-STOP UNIT command. */ + sdev->allow_restart = 1; + } else { /* Non-disk-type devices don't need to blacklist any pages diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index 22ab238..2c27721 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h @@ -342,11 +342,11 @@ UNUSUAL_DEV( 0x04b0, 0x040d, 0x0100, 0x0100, US_FL_FIX_CAPACITY), /* Reported by Graber and Mike Pagano <mpagano-kernel@mpagano.com> */ -UNUSUAL_DEV( 0x04b0, 0x040f, 0x0200, 0x0200, - "NIKON", - "NIKON DSC D200", - US_SC_DEVICE, US_PR_DEVICE, NULL, - US_FL_FIX_CAPACITY), +UNUSUAL_DEV( 0x04b0, 0x040f, 0x0100, 0x0200, + "NIKON", + "NIKON DSC D200", + US_SC_DEVICE, US_PR_DEVICE, NULL, + US_FL_FIX_CAPACITY), /* Reported by Emil Larsson <emil@swip.net> */ UNUSUAL_DEV( 0x04b0, 0x0411, 0x0100, 0x0101, @@ -731,6 +731,13 @@ UNUSUAL_DEV( 0x0584, 0x0008, 0x0102, 0x0102, US_SC_SCSI, US_PR_ALAUDA, init_alauda, 0 ), #endif +/* Reported by RTE <raszilki@yandex.ru> */ +UNUSUAL_DEV( 0x058f, 0x6387, 0x0141, 0x0141, + "JetFlash", + "TS1GJF2A/120", + US_SC_DEVICE, US_PR_DEVICE, NULL, + US_FL_MAX_SECTORS_64 ), + /* Fabrizio Fellini <fello@libero.it> */ UNUSUAL_DEV( 0x0595, 0x4343, 0x0000, 0x2210, "Fujifilm", diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index cc4b60f..5b3dbcf 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig @@ -503,7 +503,7 @@ config FB_VALKYRIE config FB_CT65550 bool "Chips 65550 display support" - depends on (FB = y) && PPC32 + depends on (FB = y) && PPC32 && PCI select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT @@ -641,6 +641,17 @@ config FB_VESA You will get a boot time penguin logo at no additional cost. Please read <file:Documentation/fb/vesafb.txt>. If unsure, say Y. +config FB_EFI + bool "EFI-based Framebuffer Support" + depends on (FB = y) && X86 + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + help + This is the EFI frame buffer device driver. If the firmware on + your platform is UEFI2.0, select Y to add support for + Graphics Output Protocol for early console messages to appear. + config FB_IMAC bool "Intel-based Macintosh Framebuffer Support" depends on (FB = y) && X86 && EFI diff --git a/drivers/video/Makefile b/drivers/video/Makefile index 59d6c45..83e02b3 100644 --- a/drivers/video/Makefile +++ b/drivers/video/Makefile @@ -118,6 +118,7 @@ obj-$(CONFIG_FB_OMAP) += omap/ obj-$(CONFIG_FB_UVESA) += uvesafb.o obj-$(CONFIG_FB_VESA) += vesafb.o obj-$(CONFIG_FB_IMAC) += imacfb.o +obj-$(CONFIG_FB_EFI) += efifb.o obj-$(CONFIG_FB_VGA16) += vga16fb.o obj-$(CONFIG_FB_OF) += offb.o obj-$(CONFIG_FB_BF54X_LQ043) += bf54x-lq043fb.o diff --git a/drivers/video/atmel_lcdfb.c b/drivers/video/atmel_lcdfb.c index 235b618..11a3a22 100644 --- a/drivers/video/atmel_lcdfb.c +++ b/drivers/video/atmel_lcdfb.c @@ -268,6 +268,10 @@ static int atmel_lcdfb_set_par(struct fb_info *info) /* Turn off the LCD controller and the DMA controller */ lcdc_writel(sinfo, ATMEL_LCDC_PWRCON, sinfo->guard_time << ATMEL_LCDC_GUARDT_OFFSET); + /* Wait for the LCDC core to become idle */ + while (lcdc_readl(sinfo, ATMEL_LCDC_PWRCON) & ATMEL_LCDC_BUSY) + msleep(10); + lcdc_writel(sinfo, ATMEL_LCDC_DMACON, 0); if (info->var.bits_per_pixel == 1) diff --git a/drivers/video/aty/radeon_base.c b/drivers/video/aty/radeon_base.c index 1e32b3d..62867cb 100644 --- a/drivers/video/aty/radeon_base.c +++ b/drivers/video/aty/radeon_base.c @@ -202,6 +202,7 @@ static struct pci_device_id radeonfb_pci_table[] = { CHIP_DEF(PCI_CHIP_RV380_3154, RV380, CHIP_HAS_CRTC2 | CHIP_IS_MOBILITY), CHIP_DEF(PCI_CHIP_RV370_5B60, RV380, CHIP_HAS_CRTC2), CHIP_DEF(PCI_CHIP_RV370_5B62, RV380, CHIP_HAS_CRTC2), + CHIP_DEF(PCI_CHIP_RV370_5B63, RV380, CHIP_HAS_CRTC2), CHIP_DEF(PCI_CHIP_RV370_5B64, RV380, CHIP_HAS_CRTC2), CHIP_DEF(PCI_CHIP_RV370_5B65, RV380, CHIP_HAS_CRTC2), CHIP_DEF(PCI_CHIP_RV370_5460, RV380, CHIP_HAS_CRTC2 | CHIP_IS_MOBILITY), diff --git a/drivers/video/console/Kconfig b/drivers/video/console/Kconfig index 267422f..b87ed37 100644 --- a/drivers/video/console/Kconfig +++ b/drivers/video/console/Kconfig @@ -6,7 +6,7 @@ menu "Console display driver support" config VGA_CONSOLE bool "VGA text console" if EMBEDDED || !X86 - depends on !ARCH_ACORN && !ARCH_EBSA110 && !4xx && !8xx && !SPARC && !M68K && !PARISC && !FRV && !ARCH_VERSATILE && !SUPERH && !BFIN + depends on !ARCH_ACORN && !ARCH_EBSA110 && !4xx && !8xx && !SPARC && !M68K && !PARISC && !FRV && !ARCH_VERSATILE && !SUPERH && !BLACKFIN default y help Saying Y here will allow you to use Linux in text mode through a diff --git a/drivers/video/cyber2000fb.c b/drivers/video/cyber2000fb.c index 5fb8675..d0e4cb6 100644 --- a/drivers/video/cyber2000fb.c +++ b/drivers/video/cyber2000fb.c @@ -874,6 +874,8 @@ static int cyber2000fb_set_par(struct fb_info *info) default: BUG(); } + break; + case 24:/* TRUECOLOUR, 16m */ hw.co_pixfmt = CO_PIXFMT_24BPP; hw.width *= 3; diff --git a/drivers/video/efifb.c b/drivers/video/efifb.c new file mode 100644 index 0000000..bd779ae --- /dev/null +++ b/drivers/video/efifb.c @@ -0,0 +1,232 @@ +/* + * Framebuffer driver for EFI/UEFI based system + * + * (c) 2006 Edgar Hucek <gimli@dark-green.com> + * Original efi driver written by Gerd Knorr <kraxel@goldbach.in-berlin.de> + * + */ + +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/errno.h> +#include <linux/fb.h> +#include <linux/platform_device.h> +#include <linux/screen_info.h> + +#include <video/vga.h> + +static struct fb_var_screeninfo efifb_defined __initdata = { + .activate = FB_ACTIVATE_NOW, + .height = -1, + .width = -1, + .right_margin = 32, + .upper_margin = 16, + .lower_margin = 4, + .vsync_len = 4, + .vmode = FB_VMODE_NONINTERLACED, +}; + +static struct fb_fix_screeninfo efifb_fix __initdata = { + .id = "EFI VGA", + .type = FB_TYPE_PACKED_PIXELS, + .accel = FB_ACCEL_NONE, + .visual = FB_VISUAL_TRUECOLOR, +}; + +static int efifb_setcolreg(unsigned regno, unsigned red, unsigned green, + unsigned blue, unsigned transp, + struct fb_info *info) +{ + /* + * Set a single color register. The values supplied are + * already rounded down to the hardware's capabilities + * (according to the entries in the `var' structure). Return + * != 0 for invalid regno. + */ + + if (regno >= info->cmap.len) + return 1; + + if (regno < 16) { + red >>= 8; + green >>= 8; + blue >>= 8; + ((u32 *)(info->pseudo_palette))[regno] = + (red << info->var.red.offset) | + (green << info->var.green.offset) | + (blue << info->var.blue.offset); + } + return 0; +} + +static struct fb_ops efifb_ops = { + .owner = THIS_MODULE, + .fb_setcolreg = efifb_setcolreg, + .fb_fillrect = cfb_fillrect, + .fb_copyarea = cfb_copyarea, + .fb_imageblit = cfb_imageblit, +}; + +static int __init efifb_probe(struct platform_device *dev) +{ + struct fb_info *info; + int err; + unsigned int size_vmode; + unsigned int size_remap; + unsigned int size_total; + + efifb_fix.smem_start = screen_info.lfb_base; + efifb_defined.bits_per_pixel = screen_info.lfb_depth; + efifb_defined.xres = screen_info.lfb_width; + efifb_defined.yres = screen_info.lfb_height; + efifb_fix.line_length = screen_info.lfb_linelength; + + /* size_vmode -- that is the amount of memory needed for the + * used video mode, i.e. the minimum amount of + * memory we need. */ + size_vmode = efifb_defined.yres * efifb_fix.line_length; + + /* size_total -- all video memory we have. Used for + * entries, ressource allocation and bounds + * checking. */ + size_total = screen_info.lfb_size; + if (size_total < size_vmode) + size_total = size_vmode; + + /* size_remap -- the amount of video memory we are going to + * use for efifb. With modern cards it is no + * option to simply use size_total as that + * wastes plenty of kernel address space. */ + size_remap = size_vmode * 2; + if (size_remap < size_vmode) + size_remap = size_vmode; + if (size_remap > size_total) + size_remap = size_total; + efifb_fix.smem_len = size_remap; + + if (!request_mem_region(efifb_fix.smem_start, size_total, "efifb")) + /* We cannot make this fatal. Sometimes this comes from magic + spaces our resource handlers simply don't know about */ + printk(KERN_WARNING + "efifb: cannot reserve video memory at 0x%lx\n", + efifb_fix.smem_start); + + info = framebuffer_alloc(sizeof(u32) * 16, &dev->dev); + if (!info) { + err = -ENOMEM; + goto err_release_mem; + } + info->pseudo_palette = info->par; + info->par = NULL; + + info->screen_base = ioremap(efifb_fix.smem_start, efifb_fix.smem_len); + if (!info->screen_base) { + printk(KERN_ERR "efifb: abort, cannot ioremap video memory " + "0x%x @ 0x%lx\n", + efifb_fix.smem_len, efifb_fix.smem_start); + err = -EIO; + goto err_unmap; + } + + printk(KERN_INFO "efifb: framebuffer at 0x%lx, mapped to 0x%p, " + "using %dk, total %dk\n", + efifb_fix.smem_start, info->screen_base, + size_remap/1024, size_total/1024); + printk(KERN_INFO "efifb: mode is %dx%dx%d, linelength=%d, pages=%d\n", + efifb_defined.xres, efifb_defined.yres, + efifb_defined.bits_per_pixel, efifb_fix.line_length, + screen_info.pages); + + efifb_defined.xres_virtual = efifb_defined.xres; + efifb_defined.yres_virtual = efifb_fix.smem_len / + efifb_fix.line_length; + printk(KERN_INFO "efifb: scrolling: redraw\n"); + efifb_defined.yres_virtual = efifb_defined.yres; + + /* some dummy values for timing to make fbset happy */ + efifb_defined.pixclock = 10000000 / efifb_defined.xres * + 1000 / efifb_defined.yres; + efifb_defined.left_margin = (efifb_defined.xres / 8) & 0xf8; + efifb_defined.hsync_len = (efifb_defined.xres / 8) & 0xf8; + + efifb_defined.red.offset = screen_info.red_pos; + efifb_defined.red.length = screen_info.red_size; + efifb_defined.green.offset = screen_info.green_pos; + efifb_defined.green.length = screen_info.green_size; + efifb_defined.blue.offset = screen_info.blue_pos; + efifb_defined.blue.length = screen_info.blue_size; + efifb_defined.transp.offset = screen_info.rsvd_pos; + efifb_defined.transp.length = screen_info.rsvd_size; + + printk(KERN_INFO "efifb: %s: " + "size=%d:%d:%d:%d, shift=%d:%d:%d:%d\n", + "Truecolor", + screen_info.rsvd_size, + screen_info.red_size, + screen_info.green_size, + screen_info.blue_size, + screen_info.rsvd_pos, + screen_info.red_pos, + screen_info.green_pos, + screen_info.blue_pos); + + efifb_fix.ypanstep = 0; + efifb_fix.ywrapstep = 0; + + info->fbops = &efifb_ops; + info->var = efifb_defined; + info->fix = efifb_fix; + info->flags = FBINFO_FLAG_DEFAULT; + + if (fb_alloc_cmap(&info->cmap, 256, 0) < 0) { + err = -ENOMEM; + goto err_unmap; + } + if (register_framebuffer(info) < 0) { + err = -EINVAL; + goto err_fb_dealoc; + } + printk(KERN_INFO "fb%d: %s frame buffer device\n", + info->node, info->fix.id); + return 0; + +err_fb_dealoc: + fb_dealloc_cmap(&info->cmap); +err_unmap: + iounmap(info->screen_base); + framebuffer_release(info); +err_release_mem: + release_mem_region(efifb_fix.smem_start, size_total); + return err; +} + +static struct platform_driver efifb_driver = { + .probe = efifb_probe, + .driver = { + .name = "efifb", + }, +}; + +static struct platform_device efifb_device = { + .name = "efifb", +}; + +static int __init efifb_init(void) +{ + int ret; + + if (screen_info.orig_video_isVGA != VIDEO_TYPE_EFI) + return -ENODEV; + + ret = platform_driver_register(&efifb_driver); + + if (!ret) { + ret = platform_device_register(&efifb_device); + if (ret) + platform_driver_unregister(&efifb_driver); + } + return ret; +} +module_init(efifb_init); + +MODULE_LICENSE("GPL"); diff --git a/drivers/video/fb_ddc.c b/drivers/video/fb_ddc.c index f836137..a0df632 100644 --- a/drivers/video/fb_ddc.c +++ b/drivers/video/fb_ddc.c @@ -56,13 +56,12 @@ unsigned char *fb_ddc_read(struct i2c_adapter *adapter) int i, j; algo_data->setscl(algo_data->data, 1); - algo_data->setscl(algo_data->data, 0); for (i = 0; i < 3; i++) { /* For some old monitors we need the * following process to initialize/stop DDC */ - algo_data->setsda(algo_data->data, 0); + algo_data->setsda(algo_data->data, 1); msleep(13); algo_data->setscl(algo_data->data, 1); @@ -97,14 +96,15 @@ unsigned char *fb_ddc_read(struct i2c_adapter *adapter) algo_data->setsda(algo_data->data, 1); msleep(15); algo_data->setscl(algo_data->data, 0); + algo_data->setsda(algo_data->data, 0); if (edid) break; } /* Release the DDC lines when done or the Apple Cinema HD display * will switch off */ - algo_data->setsda(algo_data->data, 0); - algo_data->setscl(algo_data->data, 0); + algo_data->setsda(algo_data->data, 1); + algo_data->setscl(algo_data->data, 1); return edid; } diff --git a/drivers/video/gbefb.c b/drivers/video/gbefb.c index b9b572b..2e552d5 100644 --- a/drivers/video/gbefb.c +++ b/drivers/video/gbefb.c @@ -183,8 +183,8 @@ static struct fb_videomode default_mode_LCD __initdata = { .vmode = FB_VMODE_NONINTERLACED, }; -struct fb_videomode *default_mode = &default_mode_CRT; -struct fb_var_screeninfo *default_var = &default_var_CRT; +struct fb_videomode *default_mode __initdata = &default_mode_CRT; +struct fb_var_screeninfo *default_var __initdata = &default_var_CRT; static int flat_panel_enabled = 0; diff --git a/drivers/video/geode/lxfb.h b/drivers/video/geode/lxfb.h index 6c227f9..ca13c48 100644 --- a/drivers/video/geode/lxfb.h +++ b/drivers/video/geode/lxfb.h @@ -33,7 +33,7 @@ void lx_set_palette_reg(struct fb_info *, unsigned int, unsigned int, #define MSR_LX_GLD_CONFIG 0x48002001 #define MSR_LX_GLCP_DOTPLL 0x4c000015 -#define MSR_LX_DF_PADSEL 0x48000011 +#define MSR_LX_DF_PADSEL 0x48002011 #define MSR_LX_DC_SPARE 0x80000011 #define MSR_LX_DF_GLCONFIG 0x48002001 diff --git a/drivers/video/imacfb.c b/drivers/video/imacfb.c index 6455fd2..9366ef2 100644 --- a/drivers/video/imacfb.c +++ b/drivers/video/imacfb.c @@ -234,10 +234,6 @@ static int __init imacfb_probe(struct platform_device *dev) size_remap = size_total; imacfb_fix.smem_len = size_remap; -#ifndef __i386__ - screen_info.imacpm_seg = 0; -#endif - if (!request_mem_region(imacfb_fix.smem_start, size_total, "imacfb")) { printk(KERN_WARNING "imacfb: cannot reserve video memory at 0x%lx\n", diff --git a/drivers/video/ps3fb.c b/drivers/video/ps3fb.c index b3463dd..9c56c49 100644 --- a/drivers/video/ps3fb.c +++ b/drivers/video/ps3fb.c @@ -51,7 +51,6 @@ #define L1GPU_DISPLAY_SYNC_HSYNC 1 #define L1GPU_DISPLAY_SYNC_VSYNC 2 -#define DDR_SIZE (0) /* used no ddr */ #define GPU_CMD_BUF_SIZE (64 * 1024) #define GPU_IOIF (0x0d000000UL) #define GPU_ALIGN_UP(x) _ALIGN_UP((x), 64) @@ -727,7 +726,7 @@ static int ps3fb_blank(int blank, struct fb_info *info) static int ps3fb_get_vblank(struct fb_vblank *vblank) { - memset(vblank, 0, sizeof(&vblank)); + memset(vblank, 0, sizeof(*vblank)); vblank->flags = FB_VBLANK_HAVE_VSYNC; return 0; } @@ -1060,6 +1059,7 @@ static int __devinit ps3fb_probe(struct ps3_system_bus_device *dev) u64 xdr_lpar; int status, res_index; struct task_struct *task; + unsigned long max_ps3fb_size; status = ps3_open_hv_device(dev); if (status) { @@ -1085,8 +1085,15 @@ static int __devinit ps3fb_probe(struct ps3_system_bus_device *dev) ps3fb_set_sync(&dev->core); + max_ps3fb_size = _ALIGN_UP(GPU_IOIF, 256*1024*1024) - GPU_IOIF; + if (ps3fb_videomemory.size > max_ps3fb_size) { + dev_info(&dev->core, "Limiting ps3fb mem size to %lu bytes\n", + max_ps3fb_size); + ps3fb_videomemory.size = max_ps3fb_size; + } + /* get gpu context handle */ - status = lv1_gpu_memory_allocate(DDR_SIZE, 0, 0, 0, 0, + status = lv1_gpu_memory_allocate(ps3fb_videomemory.size, 0, 0, 0, 0, &ps3fb.memory_handle, &ddr_lpar); if (status) { dev_err(&dev->core, "%s: lv1_gpu_memory_allocate failed: %d\n", diff --git a/drivers/video/s1d13xxxfb.c b/drivers/video/s1d13xxxfb.c index a5333c1..b829dc7 100644 --- a/drivers/video/s1d13xxxfb.c +++ b/drivers/video/s1d13xxxfb.c @@ -540,7 +540,7 @@ s1d13xxxfb_probe(struct platform_device *pdev) int ret = 0; u8 revision; - dbg("probe called: device is %p\n", dev); + dbg("probe called: device is %p\n", pdev); printk(KERN_INFO "Epson S1D13XXX FB Driver\n"); @@ -753,8 +753,11 @@ static struct platform_driver s1d13xxxfb_driver = { static int __init s1d13xxxfb_init(void) { + +#ifndef MODULE if (fb_get_options("s1d13xxxfb", NULL)) return -ENODEV; +#endif return platform_driver_register(&s1d13xxxfb_driver); } diff --git a/drivers/video/sis/sis_main.c b/drivers/video/sis/sis_main.c index bc7d236..37bd24b 100644 --- a/drivers/video/sis/sis_main.c +++ b/drivers/video/sis/sis_main.c @@ -1248,7 +1248,6 @@ sisfb_do_set_var(struct fb_var_screeninfo *var, int isactive, struct fb_info *in if(found_mode) { ivideo->sisfb_mode_idx = sisfb_validate_mode(ivideo, ivideo->sisfb_mode_idx, ivideo->currentvbflags); - ivideo->mode_no = sisbios_mode[ivideo->sisfb_mode_idx].mode_no[ivideo->mni]; } else { ivideo->sisfb_mode_idx = -1; } @@ -1260,6 +1259,8 @@ sisfb_do_set_var(struct fb_var_screeninfo *var, int isactive, struct fb_info *in return -EINVAL; } + ivideo->mode_no = sisbios_mode[ivideo->sisfb_mode_idx].mode_no[ivideo->mni]; + if(sisfb_search_refresh_rate(ivideo, ivideo->refresh_rate, ivideo->sisfb_mode_idx) == 0) { ivideo->rate_idx = sisbios_mode[ivideo->sisfb_mode_idx].rate_idx; ivideo->refresh_rate = 60; diff --git a/drivers/video/uvesafb.c b/drivers/video/uvesafb.c index b983d26..d1d6c0f 100644 --- a/drivers/video/uvesafb.c +++ b/drivers/video/uvesafb.c @@ -926,8 +926,10 @@ static int uvesafb_setpalette(struct uvesafb_pal_entry *entries, int count, int start, struct fb_info *info) { struct uvesafb_ktask *task; +#ifdef CONFIG_X86 struct uvesafb_par *par = info->par; int i = par->mode_idx; +#endif int err = 0; /* @@ -1103,11 +1105,11 @@ static int uvesafb_pan_display(struct fb_var_screeninfo *var, static int uvesafb_blank(int blank, struct fb_info *info) { - struct uvesafb_par *par = info->par; struct uvesafb_ktask *task; int err = 1; - #ifdef CONFIG_X86 + struct uvesafb_par *par = info->par; + if (par->vbe_ib.capabilities & VBE_CAP_VGACOMPAT) { int loop = 10000; u8 seq = 0, crtc17 = 0; diff --git a/drivers/virtio/virtio.c b/drivers/virtio/virtio.c index 15d7787..69d7ea0 100644 --- a/drivers/virtio/virtio.c +++ b/drivers/virtio/virtio.c @@ -96,10 +96,23 @@ static int virtio_dev_probe(struct device *_d) return err; } +static int virtio_dev_remove(struct device *_d) +{ + struct virtio_device *dev = container_of(_d,struct virtio_device,dev); + struct virtio_driver *drv = container_of(dev->dev.driver, + struct virtio_driver, driver); + + dev->config->set_status(dev, dev->config->get_status(dev) + & ~VIRTIO_CONFIG_S_DRIVER); + drv->remove(dev); + return 0; +} + int register_virtio_driver(struct virtio_driver *driver) { driver->driver.bus = &virtio_bus; driver->driver.probe = virtio_dev_probe; + driver->driver.remove = virtio_dev_remove; return driver_register(&driver->driver); } EXPORT_SYMBOL_GPL(register_virtio_driver); diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c index 0e4baca..1dc04b6 100644 --- a/drivers/virtio/virtio_ring.c +++ b/drivers/virtio/virtio_ring.c @@ -53,7 +53,7 @@ struct vring_virtqueue unsigned int num_added; /* Last used index we've seen. */ - unsigned int last_used_idx; + u16 last_used_idx; /* How to notify other side. FIXME: commonalize hcalls! */ void (*notify)(struct virtqueue *vq); @@ -277,11 +277,17 @@ struct virtqueue *vring_new_virtqueue(unsigned int num, struct vring_virtqueue *vq; unsigned int i; + /* We assume num is a power of 2. */ + if (num & (num - 1)) { + dev_warn(&vdev->dev, "Bad virtqueue length %u\n", num); + return NULL; + } + vq = kmalloc(sizeof(*vq) + sizeof(void *)*num, GFP_KERNEL); if (!vq) return NULL; - vring_init(&vq->vring, num, pages); + vring_init(&vq->vring, num, pages, PAGE_SIZE); vq->vq.callback = callback; vq->vq.vdev = vdev; vq->vq.vq_ops = &vring_vq_ops; diff --git a/drivers/w1/masters/ds2490.c b/drivers/w1/masters/ds2490.c index 299e274..b63b5e0 100644 --- a/drivers/w1/masters/ds2490.c +++ b/drivers/w1/masters/ds2490.c @@ -233,7 +233,7 @@ static int ds_recv_status_nodump(struct ds_device *dev, struct ds_status *st, { int count, err; - memset(st, 0, sizeof(st)); + memset(st, 0, sizeof(*st)); count = 0; err = usb_bulk_msg(dev->udev, usb_rcvbulkpipe(dev->udev, dev->ep[EP_STATUS]), buf, size, &count, 100); diff --git a/drivers/zorro/zorro-driver.c b/drivers/zorro/zorro-driver.c index 067c07b..e6c4390 100644 --- a/drivers/zorro/zorro-driver.c +++ b/drivers/zorro/zorro-driver.c @@ -60,6 +60,20 @@ static int zorro_device_probe(struct device *dev) } +static int zorro_device_remove(struct device *dev) +{ + struct zorro_dev *z = to_zorro_dev(dev); + struct zorro_driver *drv = to_zorro_driver(dev->driver); + + if (drv) { + if (drv->remove) + drv->remove(z); + z->driver = NULL; + } + return 0; +} + + /** * zorro_register_driver - register a new Zorro driver * @drv: the driver structure to register @@ -128,6 +142,7 @@ struct bus_type zorro_bus_type = { .name = "zorro", .match = zorro_bus_match, .probe = zorro_device_probe, + .remove = zorro_device_remove, }; @@ -459,6 +459,15 @@ config OCFS2_DEBUG_MASKLOG This option will enlarge your kernel, but it allows debugging of ocfs2 filesystem issues. +config OCFS2_DEBUG_FS + bool "OCFS2 expensive checks" + depends on OCFS2_FS + default n + help + This option will enable expensive consistency checks. Enable + this option for debugging only as it is likely to decrease + performance of the filesystem. + config MINIX_FS tristate "Minix fs support" help @@ -2007,7 +2016,7 @@ config CIFS_EXPERIMENTAL config CIFS_UPCALL bool "Kerberos/SPNEGO advanced session setup (EXPERIMENTAL)" depends on CIFS_EXPERIMENTAL - depends on CONNECTOR + depends on KEYS help Enables an upcall mechanism for CIFS which will be used to contact userspace helper utilities to provide SPNEGO packaged Kerberos diff --git a/fs/bfs/bfs.h b/fs/bfs/bfs.h index 130f6c6..ac7a8b1 100644 --- a/fs/bfs/bfs.h +++ b/fs/bfs/bfs.h @@ -14,8 +14,6 @@ struct bfs_sb_info { unsigned long si_blocks; unsigned long si_freeb; unsigned long si_freei; - unsigned long si_lf_ioff; - unsigned long si_lf_sblk; unsigned long si_lf_eblk; unsigned long si_lasti; unsigned long * si_imap; @@ -39,7 +37,7 @@ static inline struct bfs_sb_info *BFS_SB(struct super_block *sb) static inline struct bfs_inode_info *BFS_I(struct inode *inode) { - return list_entry(inode, struct bfs_inode_info, vfs_inode); + return container_of(inode, struct bfs_inode_info, vfs_inode); } diff --git a/fs/bfs/dir.c b/fs/bfs/dir.c index 097f149..1fd056d 100644 --- a/fs/bfs/dir.c +++ b/fs/bfs/dir.c @@ -21,29 +21,32 @@ #define dprintf(x...) #endif -static int bfs_add_entry(struct inode * dir, const unsigned char * name, int namelen, int ino); -static struct buffer_head * bfs_find_entry(struct inode * dir, - const unsigned char * name, int namelen, struct bfs_dirent ** res_dir); +static int bfs_add_entry(struct inode *dir, const unsigned char *name, + int namelen, int ino); +static struct buffer_head *bfs_find_entry(struct inode *dir, + const unsigned char *name, int namelen, + struct bfs_dirent **res_dir); -static int bfs_readdir(struct file * f, void * dirent, filldir_t filldir) +static int bfs_readdir(struct file *f, void *dirent, filldir_t filldir) { - struct inode * dir = f->f_path.dentry->d_inode; - struct buffer_head * bh; - struct bfs_dirent * de; + struct inode *dir = f->f_path.dentry->d_inode; + struct buffer_head *bh; + struct bfs_dirent *de; unsigned int offset; int block; lock_kernel(); - if (f->f_pos & (BFS_DIRENT_SIZE-1)) { - printf("Bad f_pos=%08lx for %s:%08lx\n", (unsigned long)f->f_pos, - dir->i_sb->s_id, dir->i_ino); + if (f->f_pos & (BFS_DIRENT_SIZE - 1)) { + printf("Bad f_pos=%08lx for %s:%08lx\n", + (unsigned long)f->f_pos, + dir->i_sb->s_id, dir->i_ino); unlock_kernel(); return -EBADF; } while (f->f_pos < dir->i_size) { - offset = f->f_pos & (BFS_BSIZE-1); + offset = f->f_pos & (BFS_BSIZE - 1); block = BFS_I(dir)->i_sblock + (f->f_pos >> BFS_BSIZE_BITS); bh = sb_bread(dir->i_sb, block); if (!bh) { @@ -54,7 +57,9 @@ static int bfs_readdir(struct file * f, void * dirent, filldir_t filldir) de = (struct bfs_dirent *)(bh->b_data + offset); if (de->ino) { int size = strnlen(de->name, BFS_NAMELEN); - if (filldir(dirent, de->name, size, f->f_pos, le16_to_cpu(de->ino), DT_UNKNOWN) < 0) { + if (filldir(dirent, de->name, size, f->f_pos, + le16_to_cpu(de->ino), + DT_UNKNOWN) < 0) { brelse(bh); unlock_kernel(); return 0; @@ -62,7 +67,7 @@ static int bfs_readdir(struct file * f, void * dirent, filldir_t filldir) } offset += BFS_DIRENT_SIZE; f->f_pos += BFS_DIRENT_SIZE; - } while (offset < BFS_BSIZE && f->f_pos < dir->i_size); + } while ((offset < BFS_BSIZE) && (f->f_pos < dir->i_size)); brelse(bh); } @@ -78,13 +83,13 @@ const struct file_operations bfs_dir_operations = { extern void dump_imap(const char *, struct super_block *); -static int bfs_create(struct inode * dir, struct dentry * dentry, int mode, - struct nameidata *nd) +static int bfs_create(struct inode *dir, struct dentry *dentry, int mode, + struct nameidata *nd) { int err; - struct inode * inode; - struct super_block * s = dir->i_sb; - struct bfs_sb_info * info = BFS_SB(s); + struct inode *inode; + struct super_block *s = dir->i_sb; + struct bfs_sb_info *info = BFS_SB(s); unsigned long ino; inode = new_inode(s); @@ -97,7 +102,7 @@ static int bfs_create(struct inode * dir, struct dentry * dentry, int mode, iput(inode); return -ENOSPC; } - set_bit(ino, info->si_imap); + set_bit(ino, info->si_imap); info->si_freei--; inode->i_uid = current->fsuid; inode->i_gid = (dir->i_mode & S_ISGID) ? dir->i_gid : current->fsgid; @@ -113,9 +118,10 @@ static int bfs_create(struct inode * dir, struct dentry * dentry, int mode, BFS_I(inode)->i_eblock = 0; insert_inode_hash(inode); mark_inode_dirty(inode); - dump_imap("create",s); + dump_imap("create", s); - err = bfs_add_entry(dir, dentry->d_name.name, dentry->d_name.len, inode->i_ino); + err = bfs_add_entry(dir, dentry->d_name.name, dentry->d_name.len, + inode->i_ino); if (err) { inode_dec_link_count(inode); iput(inode); @@ -127,11 +133,12 @@ static int bfs_create(struct inode * dir, struct dentry * dentry, int mode, return 0; } -static struct dentry * bfs_lookup(struct inode * dir, struct dentry * dentry, struct nameidata *nd) +static struct dentry *bfs_lookup(struct inode *dir, struct dentry *dentry, + struct nameidata *nd) { - struct inode * inode = NULL; - struct buffer_head * bh; - struct bfs_dirent * de; + struct inode *inode = NULL; + struct buffer_head *bh; + struct bfs_dirent *de; if (dentry->d_name.len > BFS_NAMELEN) return ERR_PTR(-ENAMETOOLONG); @@ -152,13 +159,15 @@ static struct dentry * bfs_lookup(struct inode * dir, struct dentry * dentry, st return NULL; } -static int bfs_link(struct dentry * old, struct inode * dir, struct dentry * new) +static int bfs_link(struct dentry *old, struct inode *dir, + struct dentry *new) { - struct inode * inode = old->d_inode; + struct inode *inode = old->d_inode; int err; lock_kernel(); - err = bfs_add_entry(dir, new->d_name.name, new->d_name.len, inode->i_ino); + err = bfs_add_entry(dir, new->d_name.name, new->d_name.len, + inode->i_ino); if (err) { unlock_kernel(); return err; @@ -172,23 +181,23 @@ static int bfs_link(struct dentry * old, struct inode * dir, struct dentry * new return 0; } - -static int bfs_unlink(struct inode * dir, struct dentry * dentry) +static int bfs_unlink(struct inode *dir, struct dentry *dentry) { int error = -ENOENT; - struct inode * inode; - struct buffer_head * bh; - struct bfs_dirent * de; + struct inode *inode; + struct buffer_head *bh; + struct bfs_dirent *de; inode = dentry->d_inode; lock_kernel(); bh = bfs_find_entry(dir, dentry->d_name.name, dentry->d_name.len, &de); - if (!bh || le16_to_cpu(de->ino) != inode->i_ino) + if (!bh || (le16_to_cpu(de->ino) != inode->i_ino)) goto out_brelse; if (!inode->i_nlink) { - printf("unlinking non-existent file %s:%lu (nlink=%d)\n", inode->i_sb->s_id, - inode->i_ino, inode->i_nlink); + printf("unlinking non-existent file %s:%lu (nlink=%d)\n", + inode->i_sb->s_id, inode->i_ino, + inode->i_nlink); inode->i_nlink = 1; } de->ino = 0; @@ -205,12 +214,12 @@ out_brelse: return error; } -static int bfs_rename(struct inode * old_dir, struct dentry * old_dentry, - struct inode * new_dir, struct dentry * new_dentry) +static int bfs_rename(struct inode *old_dir, struct dentry *old_dentry, + struct inode *new_dir, struct dentry *new_dentry) { - struct inode * old_inode, * new_inode; - struct buffer_head * old_bh, * new_bh; - struct bfs_dirent * old_de, * new_de; + struct inode *old_inode, *new_inode; + struct buffer_head *old_bh, *new_bh; + struct bfs_dirent *old_de, *new_de; int error = -ENOENT; old_bh = new_bh = NULL; @@ -223,7 +232,7 @@ static int bfs_rename(struct inode * old_dir, struct dentry * old_dentry, old_dentry->d_name.name, old_dentry->d_name.len, &old_de); - if (!old_bh || le16_to_cpu(old_de->ino) != old_inode->i_ino) + if (!old_bh || (le16_to_cpu(old_de->ino) != old_inode->i_ino)) goto end_rename; error = -EPERM; @@ -239,7 +248,8 @@ static int bfs_rename(struct inode * old_dir, struct dentry * old_dentry, if (!new_bh) { error = bfs_add_entry(new_dir, new_dentry->d_name.name, - new_dentry->d_name.len, old_inode->i_ino); + new_dentry->d_name.len, + old_inode->i_ino); if (error) goto end_rename; } @@ -268,11 +278,12 @@ const struct inode_operations bfs_dir_inops = { .rename = bfs_rename, }; -static int bfs_add_entry(struct inode * dir, const unsigned char * name, int namelen, int ino) +static int bfs_add_entry(struct inode *dir, const unsigned char *name, + int namelen, int ino) { - struct buffer_head * bh; - struct bfs_dirent * de; - int block, sblock, eblock, off, eoff; + struct buffer_head *bh; + struct bfs_dirent *de; + int block, sblock, eblock, off, pos; int i; dprintf("name=%s, namelen=%d\n", name, namelen); @@ -284,27 +295,24 @@ static int bfs_add_entry(struct inode * dir, const unsigned char * name, int nam sblock = BFS_I(dir)->i_sblock; eblock = BFS_I(dir)->i_eblock; - eoff = dir->i_size % BFS_BSIZE; - for (block=sblock; block<=eblock; block++) { + for (block = sblock; block <= eblock; block++) { bh = sb_bread(dir->i_sb, block); - if(!bh) + if (!bh) return -ENOSPC; - for (off=0; off<BFS_BSIZE; off+=BFS_DIRENT_SIZE) { + for (off = 0; off < BFS_BSIZE; off += BFS_DIRENT_SIZE) { de = (struct bfs_dirent *)(bh->b_data + off); - if (block==eblock && off>=eoff) { - /* Do not read/interpret the garbage in the end of eblock. */ - de->ino = 0; - } if (!de->ino) { - if ((block-sblock)*BFS_BSIZE + off >= dir->i_size) { + pos = (block - sblock) * BFS_BSIZE + off; + if (pos >= dir->i_size) { dir->i_size += BFS_DIRENT_SIZE; dir->i_ctime = CURRENT_TIME_SEC; } dir->i_mtime = CURRENT_TIME_SEC; mark_inode_dirty(dir); de->ino = cpu_to_le16((u16)ino); - for (i=0; i<BFS_NAMELEN; i++) - de->name[i] = (i < namelen) ? name[i] : 0; + for (i = 0; i < BFS_NAMELEN; i++) + de->name[i] = + (i < namelen) ? name[i] : 0; mark_buffer_dirty(bh); brelse(bh); return 0; @@ -315,25 +323,26 @@ static int bfs_add_entry(struct inode * dir, const unsigned char * name, int nam return -ENOSPC; } -static inline int bfs_namecmp(int len, const unsigned char * name, const char * buffer) +static inline int bfs_namecmp(int len, const unsigned char *name, + const char *buffer) { - if (len < BFS_NAMELEN && buffer[len]) + if ((len < BFS_NAMELEN) && buffer[len]) return 0; return !memcmp(name, buffer, len); } -static struct buffer_head * bfs_find_entry(struct inode * dir, - const unsigned char * name, int namelen, struct bfs_dirent ** res_dir) +static struct buffer_head *bfs_find_entry(struct inode *dir, + const unsigned char *name, int namelen, + struct bfs_dirent **res_dir) { - unsigned long block, offset; - struct buffer_head * bh; - struct bfs_dirent * de; + unsigned long block = 0, offset = 0; + struct buffer_head *bh = NULL; + struct bfs_dirent *de; *res_dir = NULL; if (namelen > BFS_NAMELEN) return NULL; - bh = NULL; - block = offset = 0; + while (block * BFS_BSIZE + offset < dir->i_size) { if (!bh) { bh = sb_bread(dir->i_sb, BFS_I(dir)->i_sblock + block); @@ -344,7 +353,8 @@ static struct buffer_head * bfs_find_entry(struct inode * dir, } de = (struct bfs_dirent *)(bh->b_data + offset); offset += BFS_DIRENT_SIZE; - if (le16_to_cpu(de->ino) && bfs_namecmp(namelen, name, de->name)) { + if (le16_to_cpu(de->ino) && + bfs_namecmp(namelen, name, de->name)) { *res_dir = de; return bh; } diff --git a/fs/bfs/file.c b/fs/bfs/file.c index 911b4cc..b11e63e 100644 --- a/fs/bfs/file.c +++ b/fs/bfs/file.c @@ -2,6 +2,11 @@ * fs/bfs/file.c * BFS file operations. * Copyright (C) 1999,2000 Tigran Aivazian <tigran@veritas.com> + * + * Make the file block allocation algorithm understand the size + * of the underlying block device. + * Copyright (C) 2007 Dmitri Vorobiev <dmitri.vorobiev@gmail.com> + * */ #include <linux/fs.h> @@ -27,7 +32,8 @@ const struct file_operations bfs_file_operations = { .splice_read = generic_file_splice_read, }; -static int bfs_move_block(unsigned long from, unsigned long to, struct super_block *sb) +static int bfs_move_block(unsigned long from, unsigned long to, + struct super_block *sb) { struct buffer_head *bh, *new; @@ -43,21 +49,22 @@ static int bfs_move_block(unsigned long from, unsigned long to, struct super_blo } static int bfs_move_blocks(struct super_block *sb, unsigned long start, - unsigned long end, unsigned long where) + unsigned long end, unsigned long where) { unsigned long i; dprintf("%08lx-%08lx->%08lx\n", start, end, where); for (i = start; i <= end; i++) if(bfs_move_block(i, where + i, sb)) { - dprintf("failed to move block %08lx -> %08lx\n", i, where + i); + dprintf("failed to move block %08lx -> %08lx\n", i, + where + i); return -EIO; } return 0; } -static int bfs_get_block(struct inode * inode, sector_t block, - struct buffer_head * bh_result, int create) +static int bfs_get_block(struct inode *inode, sector_t block, + struct buffer_head *bh_result, int create) { unsigned long phys; int err; @@ -66,9 +73,6 @@ static int bfs_get_block(struct inode * inode, sector_t block, struct bfs_inode_info *bi = BFS_I(inode); struct buffer_head *sbh = info->si_sbh; - if (block > info->si_blocks) - return -EIO; - phys = bi->i_sblock + block; if (!create) { if (phys <= bi->i_eblock) { @@ -79,21 +83,29 @@ static int bfs_get_block(struct inode * inode, sector_t block, return 0; } - /* if the file is not empty and the requested block is within the range - of blocks allocated for this file, we can grant it */ - if (inode->i_size && phys <= bi->i_eblock) { + /* + * If the file is not empty and the requested block is within the + * range of blocks allocated for this file, we can grant it. + */ + if (bi->i_sblock && (phys <= bi->i_eblock)) { dprintf("c=%d, b=%08lx, phys=%08lx (interim block granted)\n", create, (unsigned long)block, phys); map_bh(bh_result, sb, phys); return 0; } - /* the rest has to be protected against itself */ + /* The file will be extended, so let's see if there is enough space. */ + if (phys >= info->si_blocks) + return -ENOSPC; + + /* The rest has to be protected against itself. */ lock_kernel(); - /* if the last data block for this file is the last allocated - block, we can extend the file trivially, without moving it - anywhere */ + /* + * If the last data block for this file is the last allocated + * block, we can extend the file trivially, without moving it + * anywhere. + */ if (bi->i_eblock == info->si_lf_eblk) { dprintf("c=%d, b=%08lx, phys=%08lx (simple extension)\n", create, (unsigned long)block, phys); @@ -106,13 +118,19 @@ static int bfs_get_block(struct inode * inode, sector_t block, goto out; } - /* Ok, we have to move this entire file to the next free block */ + /* Ok, we have to move this entire file to the next free block. */ phys = info->si_lf_eblk + 1; - if (bi->i_sblock) { /* if data starts on block 0 then there is no data */ + if (phys + block >= info->si_blocks) { + err = -ENOSPC; + goto out; + } + + if (bi->i_sblock) { err = bfs_move_blocks(inode->i_sb, bi->i_sblock, - bi->i_eblock, phys); + bi->i_eblock, phys); if (err) { - dprintf("failed to move ino=%08lx -> fs corruption\n", inode->i_ino); + dprintf("failed to move ino=%08lx -> fs corruption\n", + inode->i_ino); goto out; } } else @@ -124,8 +142,10 @@ static int bfs_get_block(struct inode * inode, sector_t block, phys += block; info->si_lf_eblk = bi->i_eblock = phys; - /* this assumes nothing can write the inode back while we are here - * and thus update inode->i_blocks! (XXX)*/ + /* + * This assumes nothing can write the inode back while we are here + * and thus update inode->i_blocks! (XXX) + */ info->si_freeb -= bi->i_eblock - bi->i_sblock + 1 - inode->i_blocks; mark_inode_dirty(inode); mark_buffer_dirty(sbh); diff --git a/fs/bfs/inode.c b/fs/bfs/inode.c index 7bd9c2b..294c41b 100644 --- a/fs/bfs/inode.c +++ b/fs/bfs/inode.c @@ -30,25 +30,26 @@ MODULE_LICENSE("GPL"); #define dprintf(x...) #endif -void dump_imap(const char *prefix, struct super_block * s); +void dump_imap(const char *prefix, struct super_block *s); -static void bfs_read_inode(struct inode * inode) +static void bfs_read_inode(struct inode *inode) { unsigned long ino = inode->i_ino; - struct bfs_inode * di; - struct buffer_head * bh; + struct bfs_inode *di; + struct buffer_head *bh; int block, off; - if (ino < BFS_ROOT_INO || ino > BFS_SB(inode->i_sb)->si_lasti) { + if ((ino < BFS_ROOT_INO) || (ino > BFS_SB(inode->i_sb)->si_lasti)) { printf("Bad inode number %s:%08lx\n", inode->i_sb->s_id, ino); make_bad_inode(inode); return; } - block = (ino - BFS_ROOT_INO)/BFS_INODES_PER_BLOCK + 1; + block = (ino - BFS_ROOT_INO) / BFS_INODES_PER_BLOCK + 1; bh = sb_bread(inode->i_sb, block); if (!bh) { - printf("Unable to read inode %s:%08lx\n", inode->i_sb->s_id, ino); + printf("Unable to read inode %s:%08lx\n", inode->i_sb->s_id, + ino); make_bad_inode(inode); return; } @@ -56,7 +57,7 @@ static void bfs_read_inode(struct inode * inode) off = (ino - BFS_ROOT_INO) % BFS_INODES_PER_BLOCK; di = (struct bfs_inode *)bh->b_data + off; - inode->i_mode = 0x0000FFFF & le32_to_cpu(di->i_mode); + inode->i_mode = 0x0000FFFF & le32_to_cpu(di->i_mode); if (le32_to_cpu(di->i_vtype) == BFS_VDIR) { inode->i_mode |= S_IFDIR; inode->i_op = &bfs_dir_inops; @@ -70,48 +71,48 @@ static void bfs_read_inode(struct inode * inode) BFS_I(inode)->i_sblock = le32_to_cpu(di->i_sblock); BFS_I(inode)->i_eblock = le32_to_cpu(di->i_eblock); + BFS_I(inode)->i_dsk_ino = le16_to_cpu(di->i_ino); inode->i_uid = le32_to_cpu(di->i_uid); inode->i_gid = le32_to_cpu(di->i_gid); inode->i_nlink = le32_to_cpu(di->i_nlink); inode->i_size = BFS_FILESIZE(di); inode->i_blocks = BFS_FILEBLOCKS(di); - if (inode->i_size || inode->i_blocks) dprintf("Registered inode with %lld size, %ld blocks\n", inode->i_size, inode->i_blocks); inode->i_atime.tv_sec = le32_to_cpu(di->i_atime); inode->i_mtime.tv_sec = le32_to_cpu(di->i_mtime); inode->i_ctime.tv_sec = le32_to_cpu(di->i_ctime); inode->i_atime.tv_nsec = 0; inode->i_mtime.tv_nsec = 0; inode->i_ctime.tv_nsec = 0; - BFS_I(inode)->i_dsk_ino = le16_to_cpu(di->i_ino); /* can be 0 so we store a copy */ brelse(bh); } -static int bfs_write_inode(struct inode * inode, int unused) +static int bfs_write_inode(struct inode *inode, int unused) { unsigned int ino = (u16)inode->i_ino; unsigned long i_sblock; - struct bfs_inode * di; - struct buffer_head * bh; + struct bfs_inode *di; + struct buffer_head *bh; int block, off; dprintf("ino=%08x\n", ino); - if (ino < BFS_ROOT_INO || ino > BFS_SB(inode->i_sb)->si_lasti) { + if ((ino < BFS_ROOT_INO) || (ino > BFS_SB(inode->i_sb)->si_lasti)) { printf("Bad inode number %s:%08x\n", inode->i_sb->s_id, ino); return -EIO; } lock_kernel(); - block = (ino - BFS_ROOT_INO)/BFS_INODES_PER_BLOCK + 1; + block = (ino - BFS_ROOT_INO) / BFS_INODES_PER_BLOCK + 1; bh = sb_bread(inode->i_sb, block); if (!bh) { - printf("Unable to read inode %s:%08x\n", inode->i_sb->s_id, ino); + printf("Unable to read inode %s:%08x\n", + inode->i_sb->s_id, ino); unlock_kernel(); return -EIO; } - off = (ino - BFS_ROOT_INO)%BFS_INODES_PER_BLOCK; + off = (ino - BFS_ROOT_INO) % BFS_INODES_PER_BLOCK; di = (struct bfs_inode *)bh->b_data + off; if (ino == BFS_ROOT_INO) @@ -133,27 +134,26 @@ static int bfs_write_inode(struct inode * inode, int unused) di->i_eoffset = cpu_to_le32(i_sblock * BFS_BSIZE + inode->i_size - 1); mark_buffer_dirty(bh); - dprintf("Written ino=%d into %d:%d\n",le16_to_cpu(di->i_ino),block,off); brelse(bh); unlock_kernel(); return 0; } -static void bfs_delete_inode(struct inode * inode) +static void bfs_delete_inode(struct inode *inode) { unsigned long ino = inode->i_ino; - struct bfs_inode * di; - struct buffer_head * bh; + struct bfs_inode *di; + struct buffer_head *bh; int block, off; - struct super_block * s = inode->i_sb; - struct bfs_sb_info * info = BFS_SB(s); - struct bfs_inode_info * bi = BFS_I(inode); + struct super_block *s = inode->i_sb; + struct bfs_sb_info *info = BFS_SB(s); + struct bfs_inode_info *bi = BFS_I(inode); dprintf("ino=%08lx\n", ino); truncate_inode_pages(&inode->i_data, 0); - if (ino < BFS_ROOT_INO || ino > info->si_lasti) { + if ((ino < BFS_ROOT_INO) || (ino > info->si_lasti)) { printf("invalid ino=%08lx\n", ino); return; } @@ -162,31 +162,35 @@ static void bfs_delete_inode(struct inode * inode) inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME_SEC; lock_kernel(); mark_inode_dirty(inode); - block = (ino - BFS_ROOT_INO)/BFS_INODES_PER_BLOCK + 1; + + block = (ino - BFS_ROOT_INO) / BFS_INODES_PER_BLOCK + 1; bh = sb_bread(s, block); if (!bh) { - printf("Unable to read inode %s:%08lx\n", inode->i_sb->s_id, ino); + printf("Unable to read inode %s:%08lx\n", + inode->i_sb->s_id, ino); unlock_kernel(); return; } - off = (ino - BFS_ROOT_INO)%BFS_INODES_PER_BLOCK; - di = (struct bfs_inode *) bh->b_data + off; + off = (ino - BFS_ROOT_INO) % BFS_INODES_PER_BLOCK; + di = (struct bfs_inode *)bh->b_data + off; + memset((void *)di, 0, sizeof(struct bfs_inode)); + mark_buffer_dirty(bh); + brelse(bh); + if (bi->i_dsk_ino) { - info->si_freeb += 1 + bi->i_eblock - bi->i_sblock; + info->si_freeb += BFS_FILEBLOCKS(bi); info->si_freei++; clear_bit(ino, info->si_imap); dump_imap("delete_inode", s); } - di->i_ino = 0; - di->i_sblock = 0; - mark_buffer_dirty(bh); - brelse(bh); - /* if this was the last file, make the previous - block "last files last block" even if there is no real file there, - saves us 1 gap */ - if (info->si_lf_eblk == BFS_I(inode)->i_eblock) { - info->si_lf_eblk = BFS_I(inode)->i_sblock - 1; + /* + * If this was the last file, make the previous block + * "last block of the last file" even if there is no + * real file there, saves us 1 gap. + */ + if (info->si_lf_eblk == bi->i_eblock) { + info->si_lf_eblk = bi->i_sblock - 1; mark_buffer_dirty(info->si_sbh); } unlock_kernel(); @@ -228,7 +232,7 @@ static void bfs_write_super(struct super_block *s) unlock_kernel(); } -static struct kmem_cache * bfs_inode_cachep; +static struct kmem_cache *bfs_inode_cachep; static struct inode *bfs_alloc_inode(struct super_block *sb) { @@ -279,7 +283,7 @@ static const struct super_operations bfs_sops = { .statfs = bfs_statfs, }; -void dump_imap(const char *prefix, struct super_block * s) +void dump_imap(const char *prefix, struct super_block *s) { #ifdef DEBUG int i; @@ -287,25 +291,26 @@ void dump_imap(const char *prefix, struct super_block * s) if (!tmpbuf) return; - for (i=BFS_SB(s)->si_lasti; i>=0; i--) { - if (i > PAGE_SIZE-100) break; + for (i = BFS_SB(s)->si_lasti; i >= 0; i--) { + if (i > PAGE_SIZE - 100) break; if (test_bit(i, BFS_SB(s)->si_imap)) strcat(tmpbuf, "1"); else strcat(tmpbuf, "0"); } - printk(KERN_ERR "BFS-fs: %s: lasti=%08lx <%s>\n", prefix, BFS_SB(s)->si_lasti, tmpbuf); + printf("BFS-fs: %s: lasti=%08lx <%s>\n", + prefix, BFS_SB(s)->si_lasti, tmpbuf); free_page((unsigned long)tmpbuf); #endif } static int bfs_fill_super(struct super_block *s, void *data, int silent) { - struct buffer_head * bh; - struct bfs_super_block * bfs_sb; - struct inode * inode; + struct buffer_head *bh; + struct bfs_super_block *bfs_sb; + struct inode *inode; unsigned i, imap_len; - struct bfs_sb_info * info; + struct bfs_sb_info *info; info = kzalloc(sizeof(*info), GFP_KERNEL); if (!info) @@ -329,14 +334,14 @@ static int bfs_fill_super(struct super_block *s, void *data, int silent) s->s_magic = BFS_MAGIC; info->si_sbh = bh; - info->si_lasti = (le32_to_cpu(bfs_sb->s_start) - BFS_BSIZE)/sizeof(struct bfs_inode) - + BFS_ROOT_INO - 1; - - imap_len = info->si_lasti/8 + 1; + info->si_lasti = (le32_to_cpu(bfs_sb->s_start) - BFS_BSIZE) / + sizeof(struct bfs_inode) + + BFS_ROOT_INO - 1; + imap_len = (info->si_lasti / 8) + 1; info->si_imap = kzalloc(imap_len, GFP_KERNEL); if (!info->si_imap) goto out; - for (i=0; i<BFS_ROOT_INO; i++) + for (i = 0; i < BFS_ROOT_INO; i++) set_bit(i, info->si_imap); s->s_op = &bfs_sops; @@ -352,16 +357,15 @@ static int bfs_fill_super(struct super_block *s, void *data, int silent) goto out; } - info->si_blocks = (le32_to_cpu(bfs_sb->s_end) + 1)>>BFS_BSIZE_BITS; /* for statfs(2) */ - info->si_freeb = (le32_to_cpu(bfs_sb->s_end) + 1 - le32_to_cpu(bfs_sb->s_start))>>BFS_BSIZE_BITS; + info->si_blocks = (le32_to_cpu(bfs_sb->s_end) + 1) >> BFS_BSIZE_BITS; + info->si_freeb = (le32_to_cpu(bfs_sb->s_end) + 1 + - le32_to_cpu(bfs_sb->s_start)) >> BFS_BSIZE_BITS; info->si_freei = 0; info->si_lf_eblk = 0; - info->si_lf_sblk = 0; - info->si_lf_ioff = 0; bh = NULL; - for (i=BFS_ROOT_INO; i<=info->si_lasti; i++) { + for (i = BFS_ROOT_INO; i <= info->si_lasti; i++) { struct bfs_inode *di; - int block = (i - BFS_ROOT_INO)/BFS_INODES_PER_BLOCK + 1; + int block = (i - BFS_ROOT_INO) / BFS_INODES_PER_BLOCK + 1; int off = (i - BFS_ROOT_INO) % BFS_INODES_PER_BLOCK; unsigned long sblock, eblock; @@ -384,11 +388,8 @@ static int bfs_fill_super(struct super_block *s, void *data, int silent) sblock = le32_to_cpu(di->i_sblock); eblock = le32_to_cpu(di->i_eblock); - if (eblock > info->si_lf_eblk) { + if (eblock > info->si_lf_eblk) info->si_lf_eblk = eblock; - info->si_lf_sblk = sblock; - info->si_lf_ioff = BFS_INO2OFF(i); - } } brelse(bh); if (!(s->s_flags & MS_RDONLY)) { diff --git a/fs/cifs/CHANGES b/fs/cifs/CHANGES index 3d41916..a609599 100644 --- a/fs/cifs/CHANGES +++ b/fs/cifs/CHANGES @@ -1,3 +1,10 @@ +Version 1.52 +------------ +Fix oops on second mount to server when null auth is used. +Enable experimental Kerberos support. Return writebehind errors on flush +and sync so that events like out of disk space get reported properly on +cached files. + Version 1.51 ------------ Fix memory leak in statfs when mounted to very old servers (e.g. @@ -12,7 +19,12 @@ leak that causes cifsd not to stop and rmmod to fail to cleanup cifs_request_buffers pool. Fix problem with POSIX Open/Mkdir on bigendian architectures. Fix possible memory corruption when EAGAIN returned on kern_recvmsg. Return better error if server -requires packet signing but client has disabled it. +requires packet signing but client has disabled it. When mounted +with cifsacl mount option - mode bits are approximated based +on the contents of the ACL of the file or directory. When cifs +mount helper is missing convert make sure that UNC name +has backslash (not forward slash) between ip address of server +and the share name. Version 1.50 ------------ diff --git a/fs/cifs/Makefile b/fs/cifs/Makefile index ff6ba8d..45e42fb 100644 --- a/fs/cifs/Makefile +++ b/fs/cifs/Makefile @@ -3,4 +3,9 @@ # obj-$(CONFIG_CIFS) += cifs.o -cifs-objs := cifsfs.o cifssmb.o cifs_debug.o connect.o dir.o file.o inode.o link.o misc.o netmisc.o smbdes.o smbencrypt.o transport.o asn1.o md4.o md5.o cifs_unicode.o nterr.o xattr.o cifsencrypt.o fcntl.o readdir.o ioctl.o sess.o export.o cifsacl.o +cifs-y := cifsfs.o cifssmb.o cifs_debug.o connect.o dir.o file.o inode.o \ + link.o misc.o netmisc.o smbdes.o smbencrypt.o transport.o asn1.o \ + md4.o md5.o cifs_unicode.o nterr.o xattr.o cifsencrypt.o fcntl.o \ + readdir.o ioctl.o sess.o export.o cifsacl.o + +cifs-$(CONFIG_CIFS_UPCALL) += cifs_spnego.o diff --git a/fs/cifs/README b/fs/cifs/README index b806b11..bf11329 100644 --- a/fs/cifs/README +++ b/fs/cifs/README @@ -225,12 +225,9 @@ If no password is provided, mount.cifs will prompt for password entry Restrictions ============ -Servers must support the NTLM SMB dialect (which is the most recent, supported -by Samba and Windows NT version 4, 2000 and XP and many other SMB/CIFS servers) Servers must support either "pure-TCP" (port 445 TCP/IP CIFS connections) or RFC -1001/1002 support for "Netbios-Over-TCP/IP." Neither of these is likely to be a -problem as most servers support this. IPv6 support is planned for the future, -and is almost complete. +1001/1002 support for "Netbios-Over-TCP/IP." This is not likely to be a +problem as most servers support this. Valid filenames differ between Windows and Linux. Windows typically restricts filenames which contain certain reserved characters (e.g.the character : @@ -458,6 +455,8 @@ A partial list of the supported mount options follows: byte range locks). remount remount the share (often used to change from ro to rw mounts or vice versa) + cifsacl Report mode bits (e.g. on stat) based on the Windows ACL for + the file. (EXPERIMENTAL) servern Specify the server 's netbios name (RFC1001 name) to use when attempting to setup a session to the server. This is This is needed for mounting to some older servers (such @@ -584,8 +583,8 @@ Experimental When set to 1 used to enable certain experimental performance enhancement was disabled when signing turned on in case buffer was modified just before it was sent, also this flag will - be used to use the new experimental sessionsetup - code). + be used to use the new experimental directory change + notification code). These experimental features and tracing can be enabled by changing flags in /proc/fs/cifs (after the cifs module has been installed or built into the @@ -608,7 +607,8 @@ the start of smb requests and responses can be enabled via: Two other experimental features are under development. To test these requires enabling CONFIG_CIFS_EXPERIMENTAL - ipv6 enablement + cifsacl support needed to retrieve approximated mode bits based on + the contents on the CIFS ACL. DNOTIFY fcntl: needed for support of directory change notification and perhaps later for file leases) @@ -625,10 +625,7 @@ that they represent all for that share, not just those for which the server returned success. Also note that "cat /proc/fs/cifs/DebugData" will display information about -the active sessions and the shares that are mounted. Note: NTLMv2 enablement -will not work since its implementation is not quite complete yet. Do not alter -the ExtendedSecurity configuration value unless you are doing specific testing. -Enabling extended security works to Windows 2000 Workstations and XP but not to -Windows 2000 server or Samba since it does not usually send "raw NTLMSSP" -(instead it sends NTLMSSP encapsulated in SPNEGO/GSSAPI, which support is not -complete in the CIFS VFS yet). +the active sessions and the shares that are mounted. +Enabling Kerberos (extended security) works when CONFIG_CIFS_EXPERIMENTAL is enabled +but requires a user space helper (from the Samba project). NTLM and NTLMv2 and +LANMAN support do not require this helpr. diff --git a/fs/cifs/TODO b/fs/cifs/TODO index 29d4b27..a8852c2 100644 --- a/fs/cifs/TODO +++ b/fs/cifs/TODO @@ -16,7 +16,7 @@ SecurityDescriptors c) Better pam/winbind integration (e.g. to handle uid mapping better) -d) Kerberos/SPNEGO session setup support - (started) +d) Verify that Kerberos signing works e) Cleanup now unneeded SessSetup code in fs/cifs/connect.c and add back in NTLMSSP code if any servers diff --git a/fs/cifs/asn1.c b/fs/cifs/asn1.c index 2a01f3e..bcda2c6 100644 --- a/fs/cifs/asn1.c +++ b/fs/cifs/asn1.c @@ -77,8 +77,12 @@ #define SPNEGO_OID_LEN 7 #define NTLMSSP_OID_LEN 10 +#define KRB5_OID_LEN 7 +#define MSKRB5_OID_LEN 7 static unsigned long SPNEGO_OID[7] = { 1, 3, 6, 1, 5, 5, 2 }; static unsigned long NTLMSSP_OID[10] = { 1, 3, 6, 1, 4, 1, 311, 2, 2, 10 }; +static unsigned long KRB5_OID[7] = { 1, 2, 840, 113554, 1, 2, 2 }; +static unsigned long MSKRB5_OID[7] = { 1, 2, 840, 48018, 1, 2, 2 }; /* * ASN.1 context. @@ -457,6 +461,7 @@ decode_negTokenInit(unsigned char *security_blob, int length, unsigned long *oid = NULL; unsigned int cls, con, tag, oidlen, rc; int use_ntlmssp = FALSE; + int use_kerberos = FALSE; *secType = NTLM; /* BB eventually make Kerberos or NLTMSSP the default*/ @@ -545,18 +550,28 @@ decode_negTokenInit(unsigned char *security_blob, int length, return 0; } if ((tag == ASN1_OJI) && (con == ASN1_PRI)) { - rc = asn1_oid_decode(&ctx, end, &oid, &oidlen); - if (rc) { + if (asn1_oid_decode(&ctx, end, &oid, &oidlen)) { + cFYI(1, ("OID len = %d oid = 0x%lx 0x%lx " "0x%lx 0x%lx", oidlen, *oid, *(oid + 1), *(oid + 2), *(oid + 3))); - rc = compare_oid(oid, oidlen, - NTLMSSP_OID, NTLMSSP_OID_LEN); - kfree(oid); - if (rc) + + if (compare_oid(oid, oidlen, + MSKRB5_OID, + MSKRB5_OID_LEN)) + use_kerberos = TRUE; + else if (compare_oid(oid, oidlen, + KRB5_OID, + KRB5_OID_LEN)) + use_kerberos = TRUE; + else if (compare_oid(oid, oidlen, + NTLMSSP_OID, + NTLMSSP_OID_LEN)) use_ntlmssp = TRUE; + + kfree(oid); } } else { cFYI(1, ("Should be an oid what is going on?")); @@ -609,12 +624,10 @@ decode_negTokenInit(unsigned char *security_blob, int length, ctx.pointer)); /* is this UTF-8 or ASCII? */ } - /* if (use_kerberos) - *secType = Kerberos - else */ - if (use_ntlmssp) { + if (use_kerberos) + *secType = Kerberos; + else if (use_ntlmssp) *secType = NTLMSSP; - } return 1; } diff --git a/fs/cifs/cifs_spnego.c b/fs/cifs/cifs_spnego.c new file mode 100644 index 0000000..1529d2b --- /dev/null +++ b/fs/cifs/cifs_spnego.c @@ -0,0 +1,134 @@ +/* + * fs/cifs/cifs_spnego.c -- SPNEGO upcall management for CIFS + * + * Copyright (c) 2007 Red Hat, Inc. + * Author(s): Jeff Layton (jlayton@redhat.com) + * + * This library is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See + * the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include <linux/list.h> +#include <linux/string.h> +#include <keys/user-type.h> +#include <linux/key-type.h> +#include "cifsglob.h" +#include "cifs_spnego.h" +#include "cifs_debug.h" + +/* create a new cifs key */ +static int +cifs_spnego_key_instantiate(struct key *key, const void *data, size_t datalen) +{ + char *payload; + int ret; + + ret = -ENOMEM; + payload = kmalloc(datalen, GFP_KERNEL); + if (!payload) + goto error; + + /* attach the data */ + memcpy(payload, data, datalen); + rcu_assign_pointer(key->payload.data, payload); + ret = 0; + +error: + return ret; +} + +static void +cifs_spnego_key_destroy(struct key *key) +{ + kfree(key->payload.data); +} + + +/* + * keytype for CIFS spnego keys + */ +struct key_type cifs_spnego_key_type = { + .name = "cifs.spnego", + .instantiate = cifs_spnego_key_instantiate, + .match = user_match, + .destroy = cifs_spnego_key_destroy, + .describe = user_describe, +}; + +#define MAX_VER_STR_LEN 9 /* length of longest version string e.g. + strlen(";ver=0xFF") */ +#define MAX_MECH_STR_LEN 13 /* length of longest security mechanism name, eg + in future could have strlen(";sec=ntlmsspi") */ +#define MAX_IPV6_ADDR_LEN 42 /* eg FEDC:BA98:7654:3210:FEDC:BA98:7654:3210/60 */ +/* get a key struct with a SPNEGO security blob, suitable for session setup */ +struct key * +cifs_get_spnego_key(struct cifsSesInfo *sesInfo) +{ + struct TCP_Server_Info *server = sesInfo->server; + char *description, *dp; + size_t desc_len; + struct key *spnego_key; + const char *hostname = server->hostname; + + /* BB: come up with better scheme for determining length */ + /* length of fields (with semicolons): ver=0xyz ipv4= ipaddress host= + hostname sec=mechanism uid=0x uid */ + desc_len = MAX_VER_STR_LEN + 5 + MAX_IPV6_ADDR_LEN + 1 + 6 + + strlen(hostname) + MAX_MECH_STR_LEN + 8 + (sizeof(uid_t) * 2); + spnego_key = ERR_PTR(-ENOMEM); + description = kzalloc(desc_len, GFP_KERNEL); + if (description == NULL) + goto out; + + dp = description; + /* start with version and hostname portion of UNC string */ + spnego_key = ERR_PTR(-EINVAL); + sprintf(dp, "ver=0x%x;host=%s;", CIFS_SPNEGO_UPCALL_VERSION, + hostname); + dp = description + strlen(description); + + /* add the server address */ + if (server->addr.sockAddr.sin_family == AF_INET) + sprintf(dp, "ip4=" NIPQUAD_FMT, + NIPQUAD(server->addr.sockAddr.sin_addr)); + else if (server->addr.sockAddr.sin_family == AF_INET6) + sprintf(dp, "ip6=" NIP6_SEQFMT, + NIP6(server->addr.sockAddr6.sin6_addr)); + else + goto out; + + dp = description + strlen(description); + + /* for now, only sec=krb5 is valid */ + if (server->secType == Kerberos) + sprintf(dp, ";sec=krb5"); + else + goto out; + + dp = description + strlen(description); + sprintf(dp, ";uid=0x%x", sesInfo->linux_uid); + + cFYI(1, ("key description = %s", description)); + spnego_key = request_key(&cifs_spnego_key_type, description, ""); + + if (cifsFYI && !IS_ERR(spnego_key)) { + struct cifs_spnego_msg *msg = spnego_key->payload.data; + cifs_dump_mem("SPNEGO reply blob:", msg->data, + msg->secblob_len + msg->sesskey_len); + } + +out: + kfree(description); + return spnego_key; +} diff --git a/fs/cifs/cifs_spnego.h b/fs/cifs/cifs_spnego.h new file mode 100644 index 0000000..05a34b1 --- /dev/null +++ b/fs/cifs/cifs_spnego.h @@ -0,0 +1,47 @@ +/* + * fs/cifs/cifs_spnego.h -- SPNEGO upcall management for CIFS + * + * Copyright (c) 2007 Red Hat, Inc. + * Author(s): Jeff Layton (jlayton@redhat.com) + * Steve French (sfrench@us.ibm.com) + * + * This library is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See + * the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _CIFS_SPNEGO_H +#define _CIFS_SPNEGO_H + +#define CIFS_SPNEGO_UPCALL_VERSION 1 + +/* + * The version field should always be set to CIFS_SPNEGO_UPCALL_VERSION. + * The flags field is for future use. The request-key callout should set + * sesskey_len and secblob_len, and then concatenate the SessKey+SecBlob + * and stuff it in the data field. + */ +struct cifs_spnego_msg { + uint32_t version; + uint32_t flags; + uint32_t sesskey_len; + uint32_t secblob_len; + uint8_t data[1]; +}; + +#ifdef __KERNEL__ +extern struct key_type cifs_spnego_key_type; +extern struct key *cifs_get_spnego_key(struct cifsSesInfo *sesInfo); +#endif /* KERNEL */ + +#endif /* _CIFS_SPNEGO_H */ diff --git a/fs/cifs/cifsacl.c b/fs/cifs/cifsacl.c index e8e5635..f02fdef 100644 --- a/fs/cifs/cifsacl.c +++ b/fs/cifs/cifsacl.c @@ -38,13 +38,13 @@ static struct cifs_wksid wksidarr[NUM_WK_SIDS] = { {{1, 1, {0, 0, 0, 0, 0, 5}, {cpu_to_le32(18), 0, 0, 0, 0} }, "sys"}, {{1, 2, {0, 0, 0, 0, 0, 5}, {cpu_to_le32(32), cpu_to_le32(544), 0, 0, 0} }, "root"}, {{1, 2, {0, 0, 0, 0, 0, 5}, {cpu_to_le32(32), cpu_to_le32(545), 0, 0, 0} }, "users"}, - {{1, 2, {0, 0, 0, 0, 0, 5}, {cpu_to_le32(32), cpu_to_le32(546), 0, 0, 0} }, "guest"} -}; + {{1, 2, {0, 0, 0, 0, 0, 5}, {cpu_to_le32(32), cpu_to_le32(546), 0, 0, 0} }, "guest"} } +; /* security id for everyone */ -static const struct cifs_sid sid_everyone = - {1, 1, {0, 0, 0, 0, 0, 0}, {} }; +static const struct cifs_sid sid_everyone = { + 1, 1, {0, 0, 0, 0, 0, 1}, {0} }; /* group users */ static const struct cifs_sid sid_user = {1, 2 , {0, 0, 0, 0, 0, 5}, {} }; @@ -97,7 +97,7 @@ int match_sid(struct cifs_sid *ctsid) /* if the two SIDs (roughly equivalent to a UUID for a user or group) are the same returns 1, if they do not match returns 0 */ -int compare_sids(struct cifs_sid *ctsid, struct cifs_sid *cwsid) +int compare_sids(const struct cifs_sid *ctsid, const struct cifs_sid *cwsid) { int i; int num_subauth, num_sat, num_saw; @@ -129,70 +129,153 @@ int compare_sids(struct cifs_sid *ctsid, struct cifs_sid *cwsid) return (1); /* sids compare/match */ } +/* + change posix mode to reflect permissions + pmode is the existing mode (we only want to overwrite part of this + bits to set can be: S_IRWXU, S_IRWXG or S_IRWXO ie 00700 or 00070 or 00007 +*/ +static void access_flags_to_mode(__u32 ace_flags, int type, umode_t *pmode, + umode_t *pbits_to_set) +{ + /* the order of ACEs is important. The canonical order is to begin with + DENY entries followed by ALLOW, otherwise an allow entry could be + encountered first, making the subsequent deny entry like "dead code" + which would be superflous since Windows stops when a match is made + for the operation you are trying to perform for your user */ + + /* For deny ACEs we change the mask so that subsequent allow access + control entries do not turn on the bits we are denying */ + if (type == ACCESS_DENIED) { + if (ace_flags & GENERIC_ALL) { + *pbits_to_set &= ~S_IRWXUGO; + } + if ((ace_flags & GENERIC_WRITE) || + ((ace_flags & FILE_WRITE_RIGHTS) == FILE_WRITE_RIGHTS)) + *pbits_to_set &= ~S_IWUGO; + if ((ace_flags & GENERIC_READ) || + ((ace_flags & FILE_READ_RIGHTS) == FILE_READ_RIGHTS)) + *pbits_to_set &= ~S_IRUGO; + if ((ace_flags & GENERIC_EXECUTE) || + ((ace_flags & FILE_EXEC_RIGHTS) == FILE_EXEC_RIGHTS)) + *pbits_to_set &= ~S_IXUGO; + return; + } else if (type != ACCESS_ALLOWED) { + cERROR(1, ("unknown access control type %d", type)); + return; + } + /* else ACCESS_ALLOWED type */ + + if (ace_flags & GENERIC_ALL) { + *pmode |= (S_IRWXUGO & (*pbits_to_set)); +#ifdef CONFIG_CIFS_DEBUG2 + cFYI(1, ("all perms")); +#endif + return; + } + if ((ace_flags & GENERIC_WRITE) || + ((ace_flags & FILE_WRITE_RIGHTS) == FILE_WRITE_RIGHTS)) + *pmode |= (S_IWUGO & (*pbits_to_set)); + if ((ace_flags & GENERIC_READ) || + ((ace_flags & FILE_READ_RIGHTS) == FILE_READ_RIGHTS)) + *pmode |= (S_IRUGO & (*pbits_to_set)); + if ((ace_flags & GENERIC_EXECUTE) || + ((ace_flags & FILE_EXEC_RIGHTS) == FILE_EXEC_RIGHTS)) + *pmode |= (S_IXUGO & (*pbits_to_set)); -static void parse_ace(struct cifs_ace *pace, char *end_of_acl) +#ifdef CONFIG_CIFS_DEBUG2 + cFYI(1, ("access flags 0x%x mode now 0x%x", ace_flags, *pmode)); +#endif + return; +} + +/* + Generate access flags to reflect permissions mode is the existing mode. + This function is called for every ACE in the DACL whose SID matches + with either owner or group or everyone. +*/ + +static void mode_to_access_flags(umode_t mode, umode_t bits_to_use, + __u32 *pace_flags) +{ + /* reset access mask */ + *pace_flags = 0x0; + + /* bits to use are either S_IRWXU or S_IRWXG or S_IRWXO */ + mode &= bits_to_use; + + /* check for R/W/X UGO since we do not know whose flags + is this but we have cleared all the bits sans RWX for + either user or group or other as per bits_to_use */ + if (mode & S_IRUGO) + *pace_flags |= SET_FILE_READ_RIGHTS; + if (mode & S_IWUGO) + *pace_flags |= SET_FILE_WRITE_RIGHTS; + if (mode & S_IXUGO) + *pace_flags |= SET_FILE_EXEC_RIGHTS; + +#ifdef CONFIG_CIFS_DEBUG2 + cFYI(1, ("mode: 0x%x, access flags now 0x%x", mode, *pace_flags)); +#endif + return; +} + + +#ifdef CONFIG_CIFS_DEBUG2 +static void dump_ace(struct cifs_ace *pace, char *end_of_acl) { int num_subauth; /* validate that we do not go past end of acl */ - /* XXX this if statement can be removed - if (end_of_acl < (char *)pace + sizeof(struct cifs_ace)) { + if (le16_to_cpu(pace->size) < 16) { + cERROR(1, ("ACE too small, %d", le16_to_cpu(pace->size))); + return; + } + + if (end_of_acl < (char *)pace + le16_to_cpu(pace->size)) { cERROR(1, ("ACL too small to parse ACE")); return; - } */ + } - num_subauth = pace->num_subauth; + num_subauth = pace->sid.num_subauth; if (num_subauth) { -#ifdef CONFIG_CIFS_DEBUG2 int i; - cFYI(1, ("ACE revision %d num_subauth %d", - pace->revision, pace->num_subauth)); + cFYI(1, ("ACE revision %d num_auth %d type %d flags %d size %d", + pace->sid.revision, pace->sid.num_subauth, pace->type, + pace->flags, pace->size)); for (i = 0; i < num_subauth; ++i) { cFYI(1, ("ACE sub_auth[%d]: 0x%x", i, - le32_to_cpu(pace->sub_auth[i]))); + le32_to_cpu(pace->sid.sub_auth[i]))); } /* BB add length check to make sure that we do not have huge num auths and therefore go off the end */ - - cFYI(1, ("RID %d", le32_to_cpu(pace->sub_auth[num_subauth-1]))); -#endif } return; } - -static void parse_ntace(struct cifs_ntace *pntace, char *end_of_acl) -{ - /* validate that we do not go past end of acl */ - if (end_of_acl < (char *)pntace + sizeof(struct cifs_ntace)) { - cERROR(1, ("ACL too small to parse NT ACE")); - return; - } - -#ifdef CONFIG_CIFS_DEBUG2 - cFYI(1, ("NTACE type %d flags 0x%x size %d, access Req 0x%x", - pntace->type, pntace->flags, pntace->size, - pntace->access_req)); #endif - return; -} - static void parse_dacl(struct cifs_acl *pdacl, char *end_of_acl, - struct cifs_sid *pownersid, struct cifs_sid *pgrpsid) + struct cifs_sid *pownersid, struct cifs_sid *pgrpsid, + struct inode *inode) { int i; int num_aces = 0; int acl_size; char *acl_base; - struct cifs_ntace **ppntace; struct cifs_ace **ppace; /* BB need to add parm so we can store the SID BB */ + if (!pdacl) { + /* no DACL in the security descriptor, set + all the permissions for user/group/other */ + inode->i_mode |= S_IRWXUGO; + return; + } + /* validate that we do not go past end of acl */ if (end_of_acl < (char *)pdacl + le16_to_cpu(pdacl->size)) { cERROR(1, ("ACL too small to parse DACL")); @@ -205,50 +288,57 @@ static void parse_dacl(struct cifs_acl *pdacl, char *end_of_acl, le32_to_cpu(pdacl->num_aces))); #endif + /* reset rwx permissions for user/group/other. + Also, if num_aces is 0 i.e. DACL has no ACEs, + user/group/other have no permissions */ + inode->i_mode &= ~(S_IRWXUGO); + acl_base = (char *)pdacl; acl_size = sizeof(struct cifs_acl); num_aces = le32_to_cpu(pdacl->num_aces); if (num_aces > 0) { - ppntace = kmalloc(num_aces * sizeof(struct cifs_ntace *), - GFP_KERNEL); + umode_t user_mask = S_IRWXU; + umode_t group_mask = S_IRWXG; + umode_t other_mask = S_IRWXO; + ppace = kmalloc(num_aces * sizeof(struct cifs_ace *), GFP_KERNEL); /* cifscred->cecount = pdacl->num_aces; - cifscred->ntaces = kmalloc(num_aces * - sizeof(struct cifs_ntace *), GFP_KERNEL); cifscred->aces = kmalloc(num_aces * sizeof(struct cifs_ace *), GFP_KERNEL);*/ for (i = 0; i < num_aces; ++i) { - ppntace[i] = (struct cifs_ntace *) - (acl_base + acl_size); - ppace[i] = (struct cifs_ace *) ((char *)ppntace[i] + - sizeof(struct cifs_ntace)); - - parse_ntace(ppntace[i], end_of_acl); - if (end_of_acl < ((char *)ppace[i] + - (le16_to_cpu(ppntace[i]->size) - - sizeof(struct cifs_ntace)))) { - cERROR(1, ("ACL too small to parse ACE")); - break; - } else - parse_ace(ppace[i], end_of_acl); - -/* memcpy((void *)(&(cifscred->ntaces[i])), - (void *)ppntace[i], - sizeof(struct cifs_ntace)); - memcpy((void *)(&(cifscred->aces[i])), + ppace[i] = (struct cifs_ace *) (acl_base + acl_size); +#ifdef CONFIG_CIFS_DEBUG2 + dump_ace(ppace[i], end_of_acl); +#endif + if (compare_sids(&(ppace[i]->sid), pownersid)) + access_flags_to_mode(ppace[i]->access_req, + ppace[i]->type, + &(inode->i_mode), + &user_mask); + if (compare_sids(&(ppace[i]->sid), pgrpsid)) + access_flags_to_mode(ppace[i]->access_req, + ppace[i]->type, + &(inode->i_mode), + &group_mask); + if (compare_sids(&(ppace[i]->sid), &sid_everyone)) + access_flags_to_mode(ppace[i]->access_req, + ppace[i]->type, + &(inode->i_mode), + &other_mask); + +/* memcpy((void *)(&(cifscred->aces[i])), (void *)ppace[i], sizeof(struct cifs_ace)); */ - acl_base = (char *)ppntace[i]; - acl_size = le16_to_cpu(ppntace[i]->size); + acl_base = (char *)ppace[i]; + acl_size = le16_to_cpu(ppace[i]->size); } kfree(ppace); - kfree(ppntace); } return; @@ -257,20 +347,20 @@ static void parse_dacl(struct cifs_acl *pdacl, char *end_of_acl, static int parse_sid(struct cifs_sid *psid, char *end_of_acl) { - /* BB need to add parm so we can store the SID BB */ - /* validate that we do not go past end of acl */ - if (end_of_acl < (char *)psid + sizeof(struct cifs_sid)) { - cERROR(1, ("ACL too small to parse SID")); + /* validate that we do not go past end of ACL - sid must be at least 8 + bytes long (assuming no sub-auths - e.g. the null SID */ + if (end_of_acl < (char *)psid + 8) { + cERROR(1, ("ACL too small to parse SID %p", psid)); return -EINVAL; } if (psid->num_subauth) { #ifdef CONFIG_CIFS_DEBUG2 int i; - cFYI(1, ("SID revision %d num_auth %d First subauth 0x%x", - psid->revision, psid->num_subauth, psid->sub_auth[0])); + cFYI(1, ("SID revision %d num_auth %d", + psid->revision, psid->num_subauth)); for (i = 0; i < psid->num_subauth; i++) { cFYI(1, ("SID sub_auth[%d]: 0x%x ", i, @@ -289,27 +379,32 @@ static int parse_sid(struct cifs_sid *psid, char *end_of_acl) /* Convert CIFS ACL to POSIX form */ -int parse_sec_desc(struct cifs_ntsd *pntsd, int acl_len) +static int parse_sec_desc(struct cifs_ntsd *pntsd, int acl_len, + struct inode *inode) { int rc; struct cifs_sid *owner_sid_ptr, *group_sid_ptr; struct cifs_acl *dacl_ptr; /* no need for SACL ptr */ char *end_of_acl = ((char *)pntsd) + acl_len; + __u32 dacloffset; + + if ((inode == NULL) || (pntsd == NULL)) + return -EIO; owner_sid_ptr = (struct cifs_sid *)((char *)pntsd + le32_to_cpu(pntsd->osidoffset)); group_sid_ptr = (struct cifs_sid *)((char *)pntsd + le32_to_cpu(pntsd->gsidoffset)); - dacl_ptr = (struct cifs_acl *)((char *)pntsd + - le32_to_cpu(pntsd->dacloffset)); + dacloffset = le32_to_cpu(pntsd->dacloffset); + dacl_ptr = (struct cifs_acl *)((char *)pntsd + dacloffset); #ifdef CONFIG_CIFS_DEBUG2 cFYI(1, ("revision %d type 0x%x ooffset 0x%x goffset 0x%x " "sacloffset 0x%x dacloffset 0x%x", pntsd->revision, pntsd->type, le32_to_cpu(pntsd->osidoffset), le32_to_cpu(pntsd->gsidoffset), - le32_to_cpu(pntsd->sacloffset), - le32_to_cpu(pntsd->dacloffset))); + le32_to_cpu(pntsd->sacloffset), dacloffset)); #endif +/* cifs_dump_mem("owner_sid: ", owner_sid_ptr, 64); */ rc = parse_sid(owner_sid_ptr, end_of_acl); if (rc) return rc; @@ -318,16 +413,120 @@ int parse_sec_desc(struct cifs_ntsd *pntsd, int acl_len) if (rc) return rc; - parse_dacl(dacl_ptr, end_of_acl, owner_sid_ptr, group_sid_ptr); + if (dacloffset) + parse_dacl(dacl_ptr, end_of_acl, owner_sid_ptr, + group_sid_ptr, inode); + else + cFYI(1, ("no ACL")); /* BB grant all or default perms? */ /* cifscred->uid = owner_sid_ptr->rid; cifscred->gid = group_sid_ptr->rid; memcpy((void *)(&(cifscred->osid)), (void *)owner_sid_ptr, - sizeof (struct cifs_sid)); + sizeof(struct cifs_sid)); memcpy((void *)(&(cifscred->gsid)), (void *)group_sid_ptr, - sizeof (struct cifs_sid)); */ + sizeof(struct cifs_sid)); */ return (0); } + + +/* Retrieve an ACL from the server */ +static struct cifs_ntsd *get_cifs_acl(u32 *pacllen, struct inode *inode, + const char *path) +{ + struct cifsFileInfo *open_file; + int unlock_file = FALSE; + int xid; + int rc = -EIO; + __u16 fid; + struct super_block *sb; + struct cifs_sb_info *cifs_sb; + struct cifs_ntsd *pntsd = NULL; + + cFYI(1, ("get mode from ACL for %s", path)); + + if (inode == NULL) + return NULL; + + xid = GetXid(); + open_file = find_readable_file(CIFS_I(inode)); + sb = inode->i_sb; + if (sb == NULL) { + FreeXid(xid); + return NULL; + } + cifs_sb = CIFS_SB(sb); + + if (open_file) { + unlock_file = TRUE; + fid = open_file->netfid; + } else { + int oplock = FALSE; + /* open file */ + rc = CIFSSMBOpen(xid, cifs_sb->tcon, path, FILE_OPEN, + READ_CONTROL, 0, &fid, &oplock, NULL, + cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & + CIFS_MOUNT_MAP_SPECIAL_CHR); + if (rc != 0) { + cERROR(1, ("Unable to open file to get ACL")); + FreeXid(xid); + return NULL; + } + } + + rc = CIFSSMBGetCIFSACL(xid, cifs_sb->tcon, fid, &pntsd, pacllen); + cFYI(1, ("GetCIFSACL rc = %d ACL len %d", rc, *pacllen)); + if (unlock_file == TRUE) + atomic_dec(&open_file->wrtPending); + else + CIFSSMBClose(xid, cifs_sb->tcon, fid); + + FreeXid(xid); + return pntsd; +} + +/* Translate the CIFS ACL (simlar to NTFS ACL) for a file into mode bits */ +void acl_to_uid_mode(struct inode *inode, const char *path) +{ + struct cifs_ntsd *pntsd = NULL; + u32 acllen = 0; + int rc = 0; + +#ifdef CONFIG_CIFS_DEBUG2 + cFYI(1, ("converting ACL to mode for %s", path)); +#endif + pntsd = get_cifs_acl(&acllen, inode, path); + + /* if we can retrieve the ACL, now parse Access Control Entries, ACEs */ + if (pntsd) + rc = parse_sec_desc(pntsd, acllen, inode); + if (rc) + cFYI(1, ("parse sec desc failed rc = %d", rc)); + + kfree(pntsd); + return; +} + +/* Convert mode bits to an ACL so we can update the ACL on the server */ +int mode_to_acl(struct inode *inode, const char *path) +{ + int rc = 0; + __u32 acllen = 0; + struct cifs_ntsd *pntsd = NULL; + + cFYI(1, ("set ACL from mode for %s", path)); + + /* Get the security descriptor */ + pntsd = get_cifs_acl(&acllen, inode, path); + + /* Add/Modify the three ACEs for owner, group, everyone + while retaining the other ACEs */ + + /* Set the security descriptor */ + + + kfree(pntsd); + return rc; +} #endif /* CONFIG_CIFS_EXPERIMENTAL */ diff --git a/fs/cifs/cifsacl.h b/fs/cifs/cifsacl.h index 420f878..93a7c34 100644 --- a/fs/cifs/cifsacl.h +++ b/fs/cifs/cifsacl.h @@ -35,6 +35,9 @@ #define UBITSHIFT 6 #define GBITSHIFT 3 +#define ACCESS_ALLOWED 0 +#define ACCESS_DENIED 1 + struct cifs_ntsd { __le16 revision; /* revision level */ __le16 type; @@ -48,7 +51,7 @@ struct cifs_sid { __u8 revision; /* revision level */ __u8 num_subauth; __u8 authority[6]; - __le32 sub_auth[5]; /* sub_auth[num_subauth] */ /* BB FIXME endianness BB */ + __le32 sub_auth[5]; /* sub_auth[num_subauth] */ } __attribute__((packed)); struct cifs_acl { @@ -57,18 +60,12 @@ struct cifs_acl { __le32 num_aces; } __attribute__((packed)); -struct cifs_ntace { /* first part of ACE which contains perms */ +struct cifs_ace { __u8 type; __u8 flags; __le16 size; __le32 access_req; -} __attribute__((packed)); - -struct cifs_ace { /* last part of ACE which includes user info */ - __u8 revision; /* revision level */ - __u8 num_subauth; - __u8 authority[6]; - __le32 sub_auth[5]; + struct cifs_sid sid; /* ie UUID of user or group who gets these perms */ } __attribute__((packed)); struct cifs_wksid { @@ -79,7 +76,7 @@ struct cifs_wksid { #ifdef CONFIG_CIFS_EXPERIMENTAL extern int match_sid(struct cifs_sid *); -extern int compare_sids(struct cifs_sid *, struct cifs_sid *); +extern int compare_sids(const struct cifs_sid *, const struct cifs_sid *); #endif /* CONFIG_CIFS_EXPERIMENTAL */ diff --git a/fs/cifs/cifsencrypt.c b/fs/cifs/cifsencrypt.c index 632070b..4ff8939 100644 --- a/fs/cifs/cifsencrypt.c +++ b/fs/cifs/cifsencrypt.c @@ -99,15 +99,16 @@ static int cifs_calc_signature2(const struct kvec *iov, int n_vec, MD5Init(&context); MD5Update(&context, (char *)&key->data, key->len); for (i = 0; i < n_vec; i++) { + if (iov[i].iov_len == 0) + continue; if (iov[i].iov_base == NULL) { cERROR(1, ("null iovec entry")); return -EIO; - } else if (iov[i].iov_len == 0) - break; /* bail out if we are sent nothing to sign */ + } /* The first entry includes a length field (which does not get signed that occupies the first 4 bytes before the header */ if (i == 0) { - if (iov[0].iov_len <= 8 ) /* cmd field at offset 9 */ + if (iov[0].iov_len <= 8) /* cmd field at offset 9 */ break; /* nothing to sign or corrupt header */ MD5Update(&context, iov[0].iov_base+4, iov[0].iov_len-4); @@ -122,7 +123,7 @@ static int cifs_calc_signature2(const struct kvec *iov, int n_vec, int cifs_sign_smb2(struct kvec *iov, int n_vec, struct TCP_Server_Info *server, - __u32 * pexpected_response_sequence_number) + __u32 *pexpected_response_sequence_number) { int rc = 0; char smb_signature[20]; diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index a6fbea5..093beaa 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c @@ -43,6 +43,8 @@ #include "cifs_debug.h" #include "cifs_fs_sb.h" #include <linux/mm.h> +#include <linux/key-type.h> +#include "cifs_spnego.h" #define CIFS_MAGIC_NUMBER 0xFF534D42 /* the first four bytes of SMB PDUs */ #ifdef CONFIG_CIFS_QUOTA @@ -264,6 +266,7 @@ cifs_alloc_inode(struct super_block *sb) cifs_inode->cifsAttrs = 0x20; /* default */ atomic_set(&cifs_inode->inUse, 0); cifs_inode->time = 0; + cifs_inode->write_behind_rc = 0; /* Until the file is open and we have gotten oplock info back from the server, can not assume caching of file data or metadata */ @@ -850,7 +853,7 @@ static int cifs_oplock_thread(void *dummyarg) struct cifsTconInfo *pTcon; struct inode *inode; __u16 netfid; - int rc; + int rc, waitrc = 0; set_freezable(); do { @@ -882,9 +885,11 @@ static int cifs_oplock_thread(void *dummyarg) filemap_fdatawrite(inode->i_mapping); if (CIFS_I(inode)->clientCanCacheRead == 0) { - filemap_fdatawait(inode->i_mapping); + waitrc = filemap_fdatawait(inode->i_mapping); invalidate_remote_inode(inode); } + if (rc == 0) + rc = waitrc; } else rc = 0; /* mutex_unlock(&inode->i_mutex);*/ @@ -1005,12 +1010,16 @@ init_cifs(void) rc = register_filesystem(&cifs_fs_type); if (rc) goto out_destroy_request_bufs; - +#ifdef CONFIG_CIFS_UPCALL + rc = register_key_type(&cifs_spnego_key_type); + if (rc) + goto out_unregister_filesystem; +#endif oplockThread = kthread_run(cifs_oplock_thread, NULL, "cifsoplockd"); if (IS_ERR(oplockThread)) { rc = PTR_ERR(oplockThread); cERROR(1, ("error %d create oplock thread", rc)); - goto out_unregister_filesystem; + goto out_unregister_key_type; } dnotifyThread = kthread_run(cifs_dnotify_thread, NULL, "cifsdnotifyd"); @@ -1024,7 +1033,11 @@ init_cifs(void) out_stop_oplock_thread: kthread_stop(oplockThread); + out_unregister_key_type: +#ifdef CONFIG_CIFS_UPCALL + unregister_key_type(&cifs_spnego_key_type); out_unregister_filesystem: +#endif unregister_filesystem(&cifs_fs_type); out_destroy_request_bufs: cifs_destroy_request_bufs(); @@ -1046,6 +1059,9 @@ exit_cifs(void) #ifdef CONFIG_PROC_FS cifs_proc_clean(); #endif +#ifdef CONFIG_CIFS_UPCALL + unregister_key_type(&cifs_spnego_key_type); +#endif unregister_filesystem(&cifs_fs_type); cifs_destroy_inodecache(); cifs_destroy_mids(); diff --git a/fs/cifs/cifsfs.h b/fs/cifs/cifsfs.h index 5574ba3..2a21dc6 100644 --- a/fs/cifs/cifsfs.h +++ b/fs/cifs/cifsfs.h @@ -106,5 +106,5 @@ extern int cifs_ioctl(struct inode *inode, struct file *filep, extern const struct export_operations cifs_export_ops; #endif /* EXPERIMENTAL */ -#define CIFS_VERSION "1.51" +#define CIFS_VERSION "1.52" #endif /* _CIFSFS_H */ diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h index 87f51f2..1fde219 100644 --- a/fs/cifs/cifsglob.h +++ b/fs/cifs/cifsglob.h @@ -110,6 +110,7 @@ struct mac_key { unsigned int len; union { char ntlm[CIFS_SESS_KEY_SIZE + 16]; + char krb5[CIFS_SESS_KEY_SIZE + 16]; /* BB: length correct? */ struct { char key[16]; struct ntlmv2_resp resp; @@ -139,6 +140,7 @@ struct TCP_Server_Info { /* 15 character server name + 0x20 16th byte indicating type = srv */ char server_RFC1001_name[SERVER_NAME_LEN_WITH_NULL]; char unicode_server_Name[SERVER_NAME_LEN_WITH_NULL * 2]; + char *hostname; /* hostname portion of UNC string */ struct socket *ssocket; union { struct sockaddr_in sockAddr; @@ -471,6 +473,17 @@ struct dir_notify_req { #define CIFS_LARGE_BUFFER 2 #define CIFS_IOVEC 4 /* array of response buffers */ +/* Type of Request to SendReceive2 */ +#define CIFS_STD_OP 0 /* normal request timeout */ +#define CIFS_LONG_OP 1 /* long op (up to 45 sec, oplock time) */ +#define CIFS_VLONG_OP 2 /* sloow op - can take up to 180 seconds */ +#define CIFS_BLOCKING_OP 4 /* operation can block */ +#define CIFS_ASYNC_OP 8 /* do not wait for response */ +#define CIFS_TIMEOUT_MASK 0x00F /* only one of 5 above set in req */ +#define CIFS_LOG_ERROR 0x010 /* log NT STATUS if non-zero */ +#define CIFS_LARGE_BUF_OP 0x020 /* large request buffer */ +#define CIFS_NO_RESP 0x040 /* no response buffer required */ + /* Security Flags: indicate type of session setup needed */ #define CIFSSEC_MAY_SIGN 0x00001 #define CIFSSEC_MAY_NTLM 0x00002 diff --git a/fs/cifs/cifspdu.h b/fs/cifs/cifspdu.h index c41ff74..dbe6b84 100644 --- a/fs/cifs/cifspdu.h +++ b/fs/cifs/cifspdu.h @@ -220,6 +220,23 @@ | FILE_WRITE_EA | FILE_WRITE_ATTRIBUTES) #define FILE_EXEC_RIGHTS (FILE_EXECUTE) +#define SET_FILE_READ_RIGHTS (FILE_READ_DATA | FILE_READ_EA | FILE_WRITE_EA \ + | FILE_READ_ATTRIBUTES \ + | FILE_WRITE_ATTRIBUTES \ + | DELETE | READ_CONTROL | WRITE_DAC \ + | WRITE_OWNER | SYNCHRONIZE) +#define SET_FILE_WRITE_RIGHTS (FILE_WRITE_DATA | FILE_APPEND_DATA \ + | FILE_READ_EA | FILE_WRITE_EA \ + | FILE_DELETE_CHILD | FILE_READ_ATTRIBUTES \ + | FILE_WRITE_ATTRIBUTES \ + | DELETE | READ_CONTROL | WRITE_DAC \ + | WRITE_OWNER | SYNCHRONIZE) +#define SET_FILE_EXEC_RIGHTS (FILE_READ_EA | FILE_WRITE_EA | FILE_EXECUTE \ + | FILE_READ_ATTRIBUTES \ + | FILE_WRITE_ATTRIBUTES \ + | DELETE | READ_CONTROL | WRITE_DAC \ + | WRITE_OWNER | SYNCHRONIZE) + /* * Invalid readdir handle @@ -1211,6 +1228,29 @@ typedef struct smb_com_transaction_qsec_req { __le32 AclFlags; } __attribute__((packed)) QUERY_SEC_DESC_REQ; + +typedef struct smb_com_transaction_ssec_req { + struct smb_hdr hdr; /* wct = 19 */ + __u8 MaxSetupCount; + __u16 Reserved; + __le32 TotalParameterCount; + __le32 TotalDataCount; + __le32 MaxParameterCount; + __le32 MaxDataCount; + __le32 ParameterCount; + __le32 ParameterOffset; + __le32 DataCount; + __le32 DataOffset; + __u8 SetupCount; /* no setup words follow subcommand */ + /* SNIA spec incorrectly included spurious pad here */ + __le16 SubCommand; /* 3 = SET_SECURITY_DESC */ + __le16 ByteCount; /* bcc = 3 + 8 */ + __u8 Pad[3]; + __u16 Fid; + __u16 Reserved2; + __le32 AclFlags; +} __attribute__((packed)) SET_SEC_DESC_REQ; + typedef struct smb_com_transaction_change_notify_req { struct smb_hdr hdr; /* wct = 23 */ __u8 MaxSetupCount; diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h index 1a88366..8350eec 100644 --- a/fs/cifs/cifsproto.h +++ b/fs/cifs/cifsproto.h @@ -48,10 +48,11 @@ extern int SendReceive(const unsigned int /* xid */ , struct cifsSesInfo *, struct smb_hdr * /* input */ , struct smb_hdr * /* out */ , int * /* bytes returned */ , const int long_op); +extern int SendReceiveNoRsp(const unsigned int xid, struct cifsSesInfo *ses, + struct smb_hdr *in_buf, int flags); extern int SendReceive2(const unsigned int /* xid */ , struct cifsSesInfo *, struct kvec *, int /* nvec to send */, - int * /* type of buf returned */ , const int long_op, - const int logError /* whether to log status code*/ ); + int * /* type of buf returned */ , const int flags); extern int SendReceiveBlockingLock(const unsigned int /* xid */ , struct cifsTconInfo *, struct smb_hdr * /* input */ , @@ -61,6 +62,9 @@ extern int checkSMB(struct smb_hdr *smb, __u16 mid, unsigned int length); extern int is_valid_oplock_break(struct smb_hdr *smb, struct TCP_Server_Info *); extern int is_size_safe_to_change(struct cifsInodeInfo *, __u64 eof); extern struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *); +#ifdef CONFIG_CIFS_EXPERIMENTAL +extern struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *); +#endif extern unsigned int smbCalcSize(struct smb_hdr *ptr); extern unsigned int smbCalcSize_LE(struct smb_hdr *ptr); extern int decode_negTokenInit(unsigned char *security_blob, int length, @@ -92,6 +96,8 @@ extern int cifs_get_inode_info(struct inode **pinode, extern int cifs_get_inode_info_unix(struct inode **pinode, const unsigned char *search_path, struct super_block *sb, int xid); +extern void acl_to_uid_mode(struct inode *inode, const char *search_path); +extern int mode_to_acl(struct inode *inode, const char *path); extern int cifs_mount(struct super_block *, struct cifs_sb_info *, char *, const char *); @@ -241,15 +247,15 @@ extern int CIFSSMBQueryReparseLinkInfo(const int xid, extern int CIFSSMBOpen(const int xid, struct cifsTconInfo *tcon, const char *fileName, const int disposition, const int access_flags, const int omode, - __u16 * netfid, int *pOplock, FILE_ALL_INFO *, + __u16 *netfid, int *pOplock, FILE_ALL_INFO *, const struct nls_table *nls_codepage, int remap); extern int SMBLegacyOpen(const int xid, struct cifsTconInfo *tcon, const char *fileName, const int disposition, const int access_flags, const int omode, - __u16 * netfid, int *pOplock, FILE_ALL_INFO *, + __u16 *netfid, int *pOplock, FILE_ALL_INFO *, const struct nls_table *nls_codepage, int remap); extern int CIFSPOSIXCreate(const int xid, struct cifsTconInfo *tcon, - u32 posix_flags, __u64 mode, __u16 * netfid, + u32 posix_flags, __u64 mode, __u16 *netfid, FILE_UNIX_BASIC_INFO *pRetData, __u32 *pOplock, const char *name, const struct nls_table *nls_codepage, int remap); @@ -270,7 +276,7 @@ extern int CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon, const __u64 offset, unsigned int *nbytes, struct kvec *iov, const int nvec, const int long_op); extern int CIFSGetSrvInodeNumber(const int xid, struct cifsTconInfo *tcon, - const unsigned char *searchName, __u64 * inode_number, + const unsigned char *searchName, __u64 *inode_number, const struct nls_table *nls_codepage, int remap_special_chars); extern int cifs_convertUCSpath(char *target, const __le16 *source, int maxlen, @@ -311,7 +317,6 @@ extern void setup_ntlmv2_rsp(struct cifsSesInfo *, char *, #ifdef CONFIG_CIFS_WEAK_PW_HASH extern void calc_lanman_hash(struct cifsSesInfo *ses, char *lnm_session_key); #endif /* CIFS_WEAK_PW_HASH */ -extern int parse_sec_desc(struct cifs_ntsd *, int); extern int CIFSSMBCopy(int xid, struct cifsTconInfo *source_tcon, const char *fromName, @@ -336,8 +341,7 @@ extern int CIFSSMBSetEA(const int xid, struct cifsTconInfo *tcon, const void *ea_value, const __u16 ea_value_len, const struct nls_table *nls_codepage, int remap_special_chars); extern int CIFSSMBGetCIFSACL(const int xid, struct cifsTconInfo *tcon, - __u16 fid, char *acl_inf, const int buflen, - const int acl_type /* ACCESS vs. DEFAULT */); + __u16 fid, struct cifs_ntsd **acl_inf, __u32 *buflen); extern int CIFSSMBGetPosixACL(const int xid, struct cifsTconInfo *tcon, const unsigned char *searchName, char *acl_inf, const int buflen, const int acl_type, @@ -347,5 +351,5 @@ extern int CIFSSMBSetPosixACL(const int xid, struct cifsTconInfo *tcon, const char *local_acl, const int buflen, const int acl_type, const struct nls_table *nls_codepage, int remap_special_chars); extern int CIFSGetExtAttr(const int xid, struct cifsTconInfo *tcon, - const int netfid, __u64 * pExtAttrBits, __u64 *pMask); + const int netfid, __u64 *pExtAttrBits, __u64 *pMask); #endif /* _CIFSPROTO_H */ diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index f0d9a48..9e8a6be 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c @@ -647,8 +647,7 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses) count - 16, &server->secType); if (rc == 1) { - /* BB Need to fill struct for sessetup here */ - rc = -EOPNOTSUPP; + rc = 0; } else { rc = -EINVAL; } @@ -699,9 +698,7 @@ int CIFSSMBTDis(const int xid, struct cifsTconInfo *tcon) { struct smb_hdr *smb_buffer; - struct smb_hdr *smb_buffer_response; /* BB removeme BB */ int rc = 0; - int length; cFYI(1, ("In tree disconnect")); /* @@ -738,16 +735,12 @@ CIFSSMBTDis(const int xid, struct cifsTconInfo *tcon) if (rc) { up(&tcon->tconSem); return rc; - } else { - smb_buffer_response = smb_buffer; /* BB removeme BB */ } - rc = SendReceive(xid, tcon->ses, smb_buffer, smb_buffer_response, - &length, 0); + + rc = SendReceiveNoRsp(xid, tcon->ses, smb_buffer, 0); if (rc) cFYI(1, ("Tree disconnect failed %d", rc)); - if (smb_buffer) - cifs_small_buf_release(smb_buffer); up(&tcon->tconSem); /* No need to return error on this operation if tid invalidated and @@ -761,10 +754,8 @@ CIFSSMBTDis(const int xid, struct cifsTconInfo *tcon) int CIFSSMBLogoff(const int xid, struct cifsSesInfo *ses) { - struct smb_hdr *smb_buffer_response; LOGOFF_ANDX_REQ *pSMB; int rc = 0; - int length; cFYI(1, ("In SMBLogoff for session disconnect")); if (ses) @@ -783,8 +774,6 @@ CIFSSMBLogoff(const int xid, struct cifsSesInfo *ses) return rc; } - smb_buffer_response = (struct smb_hdr *)pSMB; /* BB removeme BB */ - if (ses->server) { pSMB->hdr.Mid = GetNextMid(ses->server); @@ -796,8 +785,7 @@ CIFSSMBLogoff(const int xid, struct cifsSesInfo *ses) pSMB->hdr.Uid = ses->Suid; pSMB->AndXCommand = 0xFF; - rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB, - smb_buffer_response, &length, 0); + rc = SendReceiveNoRsp(xid, ses, (struct smb_hdr *) pSMB, 0); if (ses->server) { atomic_dec(&ses->server->socketUseCount); if (atomic_read(&ses->server->socketUseCount) == 0) { @@ -808,7 +796,6 @@ CIFSSMBLogoff(const int xid, struct cifsSesInfo *ses) } } up(&ses->sesSem); - cifs_small_buf_release(pSMB); /* if session dead then we do not need to do ulogoff, since server closed smb session, no sense reporting @@ -1256,7 +1243,7 @@ OldOpenRetry: pSMB->ByteCount = cpu_to_le16(count); /* long_op set to 1 to allow for oplock break timeouts */ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, - (struct smb_hdr *) pSMBr, &bytes_returned, 1); + (struct smb_hdr *)pSMBr, &bytes_returned, CIFS_LONG_OP); cifs_stats_inc(&tcon->num_opens); if (rc) { cFYI(1, ("Error in Open = %d", rc)); @@ -1369,7 +1356,7 @@ openRetry: pSMB->ByteCount = cpu_to_le16(count); /* long_op set to 1 to allow for oplock break timeouts */ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, - (struct smb_hdr *) pSMBr, &bytes_returned, 1); + (struct smb_hdr *)pSMBr, &bytes_returned, CIFS_LONG_OP); cifs_stats_inc(&tcon->num_opens); if (rc) { cFYI(1, ("Error in Open = %d", rc)); @@ -1447,7 +1434,7 @@ CIFSSMBRead(const int xid, struct cifsTconInfo *tcon, const int netfid, iov[0].iov_base = (char *)pSMB; iov[0].iov_len = pSMB->hdr.smb_buf_length + 4; rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovecs */, - &resp_buf_type, 0 /* not long op */, 1 /* log err */ ); + &resp_buf_type, CIFS_STD_OP | CIFS_LOG_ERROR); cifs_stats_inc(&tcon->num_reads); pSMBr = (READ_RSP *)iov[0].iov_base; if (rc) { @@ -1666,7 +1653,7 @@ CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon, rc = SendReceive2(xid, tcon->ses, iov, n_vec + 1, &resp_buf_type, - long_op, 0 /* do not log STATUS code */ ); + long_op); cifs_stats_inc(&tcon->num_writes); if (rc) { cFYI(1, ("Send error Write2 = %d", rc)); @@ -1708,7 +1695,7 @@ CIFSSMBLock(const int xid, struct cifsTconInfo *tcon, int timeout = 0; __u16 count; - cFYI(1, ("In CIFSSMBLock - timeout %d numLock %d", waitFlag, numLock)); + cFYI(1, ("CIFSSMBLock timeout %d numLock %d", waitFlag, numLock)); rc = small_smb_init(SMB_COM_LOCKING_ANDX, 8, tcon, (void **) &pSMB); if (rc) @@ -1717,10 +1704,10 @@ CIFSSMBLock(const int xid, struct cifsTconInfo *tcon, pSMBr = (LOCK_RSP *)pSMB; /* BB removeme BB */ if (lockType == LOCKING_ANDX_OPLOCK_RELEASE) { - timeout = -1; /* no response expected */ + timeout = CIFS_ASYNC_OP; /* no response expected */ pSMB->Timeout = 0; } else if (waitFlag == TRUE) { - timeout = 3; /* blocking operation, no timeout */ + timeout = CIFS_BLOCKING_OP; /* blocking operation, no timeout */ pSMB->Timeout = cpu_to_le32(-1);/* blocking - do not time out */ } else { pSMB->Timeout = 0; @@ -1750,15 +1737,16 @@ CIFSSMBLock(const int xid, struct cifsTconInfo *tcon, if (waitFlag) { rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB, (struct smb_hdr *) pSMBr, &bytes_returned); + cifs_small_buf_release(pSMB); } else { - rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, - (struct smb_hdr *) pSMBr, &bytes_returned, timeout); + rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *)pSMB, + timeout); + /* SMB buffer freed by function above */ } cifs_stats_inc(&tcon->num_locks); if (rc) { cFYI(1, ("Send error in Lock = %d", rc)); } - cifs_small_buf_release(pSMB); /* Note: On -EAGAIN error only caller can retry on handle based calls since file handle passed in no longer valid */ @@ -1777,7 +1765,9 @@ CIFSSMBPosixLock(const int xid, struct cifsTconInfo *tcon, int rc = 0; int timeout = 0; int bytes_returned = 0; + int resp_buf_type = 0; __u16 params, param_offset, offset, byte_count, count; + struct kvec iov[1]; cFYI(1, ("Posix Lock")); @@ -1819,7 +1809,7 @@ CIFSSMBPosixLock(const int xid, struct cifsTconInfo *tcon, parm_data->lock_type = cpu_to_le16(lock_type); if (waitFlag) { - timeout = 3; /* blocking operation, no timeout */ + timeout = CIFS_BLOCKING_OP; /* blocking operation, no timeout */ parm_data->lock_flags = cpu_to_le16(1); pSMB->Timeout = cpu_to_le32(-1); } else @@ -1839,8 +1829,13 @@ CIFSSMBPosixLock(const int xid, struct cifsTconInfo *tcon, rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB, (struct smb_hdr *) pSMBr, &bytes_returned); } else { - rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, - (struct smb_hdr *) pSMBr, &bytes_returned, timeout); + iov[0].iov_base = (char *)pSMB; + iov[0].iov_len = pSMB->hdr.smb_buf_length + 4; + rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovecs */, + &resp_buf_type, timeout); + pSMB = NULL; /* request buf already freed by SendReceive2. Do + not try to free it twice below on exit */ + pSMBr = (struct smb_com_transaction2_sfi_rsp *)iov[0].iov_base; } if (rc) { @@ -1875,6 +1870,11 @@ plk_err_exit: if (pSMB) cifs_small_buf_release(pSMB); + if (resp_buf_type == CIFS_SMALL_BUFFER) + cifs_small_buf_release(iov[0].iov_base); + else if (resp_buf_type == CIFS_LARGE_BUFFER) + cifs_buf_release(iov[0].iov_base); + /* Note: On -EAGAIN error only caller can retry on handle based calls since file handle passed in no longer valid */ @@ -1887,8 +1887,6 @@ CIFSSMBClose(const int xid, struct cifsTconInfo *tcon, int smb_file_id) { int rc = 0; CLOSE_REQ *pSMB = NULL; - CLOSE_RSP *pSMBr = NULL; - int bytes_returned; cFYI(1, ("In CIFSSMBClose")); /* do not retry on dead session on close */ @@ -1898,13 +1896,10 @@ CIFSSMBClose(const int xid, struct cifsTconInfo *tcon, int smb_file_id) if (rc) return rc; - pSMBr = (CLOSE_RSP *)pSMB; /* BB removeme BB */ - pSMB->FileID = (__u16) smb_file_id; pSMB->LastWriteTime = 0xFFFFFFFF; pSMB->ByteCount = 0; - rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, - (struct smb_hdr *) pSMBr, &bytes_returned, 0); + rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0); cifs_stats_inc(&tcon->num_closes); if (rc) { if (rc != -EINTR) { @@ -1913,8 +1908,6 @@ CIFSSMBClose(const int xid, struct cifsTconInfo *tcon, int smb_file_id) } } - cifs_small_buf_release(pSMB); - /* Since session is dead, file will be closed on server already */ if (rc == -EAGAIN) rc = 0; @@ -2486,6 +2479,7 @@ querySymLinkRetry: return rc; } +#ifdef CONFIG_CIFS_EXPERIMENTAL /* Initialize NT TRANSACT SMB into small smb request buffer. This assumes that all NT TRANSACTS that we init here have total parm and data under about 400 bytes (to fit in small cifs @@ -2494,7 +2488,7 @@ querySymLinkRetry: MaxSetupCount (size of returned setup area) and MaxParameterCount (returned parms size) must be set by caller */ static int -smb_init_ntransact(const __u16 sub_command, const int setup_count, +smb_init_nttransact(const __u16 sub_command, const int setup_count, const int parm_len, struct cifsTconInfo *tcon, void **ret_buf) { @@ -2525,12 +2519,15 @@ smb_init_ntransact(const __u16 sub_command, const int setup_count, static int validate_ntransact(char *buf, char **ppparm, char **ppdata, - int *pdatalen, int *pparmlen) + __u32 *pparmlen, __u32 *pdatalen) { char *end_of_smb; __u32 data_count, data_offset, parm_count, parm_offset; struct smb_com_ntransact_rsp *pSMBr; + *pdatalen = 0; + *pparmlen = 0; + if (buf == NULL) return -EINVAL; @@ -2567,8 +2564,11 @@ validate_ntransact(char *buf, char **ppparm, char **ppdata, cFYI(1, ("parm count and data count larger than SMB")); return -EINVAL; } + *pdatalen = data_count; + *pparmlen = parm_count; return 0; } +#endif /* CIFS_EXPERIMENTAL */ int CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon, @@ -3067,8 +3067,7 @@ GetExtAttrOut: /* Get Security Descriptor (by handle) from remote server for a file or dir */ int CIFSSMBGetCIFSACL(const int xid, struct cifsTconInfo *tcon, __u16 fid, - /* BB fix up return info */ char *acl_inf, const int buflen, - const int acl_type) + struct cifs_ntsd **acl_inf, __u32 *pbuflen) { int rc = 0; int buf_type = 0; @@ -3077,7 +3076,10 @@ CIFSSMBGetCIFSACL(const int xid, struct cifsTconInfo *tcon, __u16 fid, cFYI(1, ("GetCifsACL")); - rc = smb_init_ntransact(NT_TRANSACT_QUERY_SECURITY_DESC, 0, + *pbuflen = 0; + *acl_inf = NULL; + + rc = smb_init_nttransact(NT_TRANSACT_QUERY_SECURITY_DESC, 0, 8 /* parm len */, tcon, (void **) &pSMB); if (rc) return rc; @@ -3094,39 +3096,57 @@ CIFSSMBGetCIFSACL(const int xid, struct cifsTconInfo *tcon, __u16 fid, iov[0].iov_len = pSMB->hdr.smb_buf_length + 4; rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovec */, &buf_type, - 0 /* not long op */, 0 /* do not log STATUS codes */ ); + CIFS_STD_OP); cifs_stats_inc(&tcon->num_acl_get); if (rc) { cFYI(1, ("Send error in QuerySecDesc = %d", rc)); } else { /* decode response */ - struct cifs_ntsd *psec_desc; __le32 * parm; - int parm_len; - int data_len; - int acl_len; + __u32 parm_len; + __u32 acl_len; struct smb_com_ntransact_rsp *pSMBr; + char *pdata; /* validate_nttransact */ rc = validate_ntransact(iov[0].iov_base, (char **)&parm, - (char **)&psec_desc, - &parm_len, &data_len); + &pdata, &parm_len, pbuflen); if (rc) goto qsec_out; pSMBr = (struct smb_com_ntransact_rsp *)iov[0].iov_base; - cFYI(1, ("smb %p parm %p data %p", pSMBr, parm, psec_desc)); + cFYI(1, ("smb %p parm %p data %p", pSMBr, parm, *acl_inf)); if (le32_to_cpu(pSMBr->ParameterCount) != 4) { rc = -EIO; /* bad smb */ + *pbuflen = 0; goto qsec_out; } /* BB check that data area is minimum length and as big as acl_len */ acl_len = le32_to_cpu(*parm); - /* BB check if (acl_len > bufsize) */ + if (acl_len != *pbuflen) { + cERROR(1, ("acl length %d does not match %d", + acl_len, *pbuflen)); + if (*pbuflen > acl_len) + *pbuflen = acl_len; + } - parse_sec_desc(psec_desc, acl_len); + /* check if buffer is big enough for the acl + header followed by the smallest SID */ + if ((*pbuflen < sizeof(struct cifs_ntsd) + 8) || + (*pbuflen >= 64 * 1024)) { + cERROR(1, ("bad acl length %d", *pbuflen)); + rc = -EINVAL; + *pbuflen = 0; + } else { + *acl_inf = kmalloc(*pbuflen, GFP_KERNEL); + if (*acl_inf == NULL) { + *pbuflen = 0; + rc = -ENOMEM; + } + memcpy(*acl_inf, pdata, *pbuflen); + } } qsec_out: if (buf_type == CIFS_SMALL_BUFFER) @@ -3381,7 +3401,7 @@ UnixQPathInfoRetry: memcpy((char *) pFindData, (char *) &pSMBr->hdr.Protocol + data_offset, - sizeof (FILE_UNIX_BASIC_INFO)); + sizeof(FILE_UNIX_BASIC_INFO)); } } cifs_buf_release(pSMB); @@ -3649,7 +3669,7 @@ int CIFSFindNext(const int xid, struct cifsTconInfo *tcon, pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_NEXT); pSMB->SearchHandle = searchHandle; /* always kept as le */ pSMB->SearchCount = - cpu_to_le16(CIFSMaxBufSize / sizeof (FILE_UNIX_INFO)); + cpu_to_le16(CIFSMaxBufSize / sizeof(FILE_UNIX_INFO)); pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level); pSMB->ResumeKey = psrch_inf->resume_key; pSMB->SearchFlags = @@ -3737,8 +3757,6 @@ CIFSFindClose(const int xid, struct cifsTconInfo *tcon, { int rc = 0; FINDCLOSE_REQ *pSMB = NULL; - CLOSE_RSP *pSMBr = NULL; /* BB removeme BB */ - int bytes_returned; cFYI(1, ("In CIFSSMBFindClose")); rc = small_smb_init(SMB_COM_FIND_CLOSE2, 1, tcon, (void **)&pSMB); @@ -3750,16 +3768,13 @@ CIFSFindClose(const int xid, struct cifsTconInfo *tcon, if (rc) return rc; - pSMBr = (CLOSE_RSP *)pSMB; /* BB removeme BB */ pSMB->FileID = searchHandle; pSMB->ByteCount = 0; - rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, - (struct smb_hdr *) pSMBr, &bytes_returned, 0); + rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0); if (rc) { cERROR(1, ("Send error in FindClose = %d", rc)); } cifs_stats_inc(&tcon->num_fclose); - cifs_small_buf_release(pSMB); /* Since session is dead, search handle closed on server already */ if (rc == -EAGAIN) @@ -4331,7 +4346,7 @@ QFSDeviceRetry: } else { /* decode response */ rc = validate_t2((struct smb_t2_rsp *)pSMBr); - if (rc || (pSMBr->ByteCount < sizeof (FILE_SYSTEM_DEVICE_INFO))) + if (rc || (pSMBr->ByteCount < sizeof(FILE_SYSTEM_DEVICE_INFO))) rc = -EIO; /* bad smb */ else { __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset); @@ -4681,11 +4696,9 @@ CIFSSMBSetFileSize(const int xid, struct cifsTconInfo *tcon, __u64 size, __u16 fid, __u32 pid_of_opener, int SetAllocation) { struct smb_com_transaction2_sfi_req *pSMB = NULL; - struct smb_com_transaction2_sfi_rsp *pSMBr = NULL; char *data_offset; struct file_end_of_file_info *parm_data; int rc = 0; - int bytes_returned = 0; __u16 params, param_offset, offset, byte_count, count; cFYI(1, ("SetFileSize (via SetFileInfo) %lld", @@ -4695,8 +4708,6 @@ CIFSSMBSetFileSize(const int xid, struct cifsTconInfo *tcon, __u64 size, if (rc) return rc; - pSMBr = (struct smb_com_transaction2_sfi_rsp *)pSMB; - pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener); pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16)); @@ -4747,17 +4758,13 @@ CIFSSMBSetFileSize(const int xid, struct cifsTconInfo *tcon, __u64 size, pSMB->Reserved4 = 0; pSMB->hdr.smb_buf_length += byte_count; pSMB->ByteCount = cpu_to_le16(byte_count); - rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, - (struct smb_hdr *) pSMBr, &bytes_returned, 0); + rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0); if (rc) { cFYI(1, ("Send error in SetFileInfo (SetFileSize) = %d", rc)); } - if (pSMB) - cifs_small_buf_release(pSMB); - /* Note: On -EAGAIN error only caller can retry on handle based calls since file handle passed in no longer valid */ @@ -4775,10 +4782,8 @@ CIFSSMBSetFileTimes(const int xid, struct cifsTconInfo *tcon, const FILE_BASIC_INFO *data, __u16 fid) { struct smb_com_transaction2_sfi_req *pSMB = NULL; - struct smb_com_transaction2_sfi_rsp *pSMBr = NULL; char *data_offset; int rc = 0; - int bytes_returned = 0; __u16 params, param_offset, offset, byte_count, count; cFYI(1, ("Set Times (via SetFileInfo)")); @@ -4787,8 +4792,6 @@ CIFSSMBSetFileTimes(const int xid, struct cifsTconInfo *tcon, if (rc) return rc; - pSMBr = (struct smb_com_transaction2_sfi_rsp *)pSMB; - /* At this point there is no need to override the current pid with the pid of the opener, but that could change if we someday use an existing handle (rather than opening one on the fly) */ @@ -4828,14 +4831,11 @@ CIFSSMBSetFileTimes(const int xid, struct cifsTconInfo *tcon, pSMB->hdr.smb_buf_length += byte_count; pSMB->ByteCount = cpu_to_le16(byte_count); memcpy(data_offset, data, sizeof(FILE_BASIC_INFO)); - rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, - (struct smb_hdr *) pSMBr, &bytes_returned, 0); + rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0); if (rc) { cFYI(1, ("Send error in Set Time (SetFileInfo) = %d", rc)); } - cifs_small_buf_release(pSMB); - /* Note: On -EAGAIN error only caller can retry on handle based calls since file handle passed in no longer valid */ @@ -5126,7 +5126,8 @@ int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon, pSMB->ByteCount = 0; rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, - (struct smb_hdr *) pSMBr, &bytes_returned, -1); + (struct smb_hdr *)pSMBr, &bytes_returned, + CIFS_ASYNC_OP); if (rc) { cFYI(1, ("Error in Notify = %d", rc)); } else { diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index 19ee11f..fd9147c 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c @@ -160,7 +160,7 @@ cifs_reconnect(struct TCP_Server_Info *server) if (server->ssocket) { cFYI(1, ("State: 0x%x Flags: 0x%lx", server->ssocket->state, server->ssocket->flags)); - server->ssocket->ops->shutdown(server->ssocket, SEND_SHUTDOWN); + kernel_sock_shutdown(server->ssocket, SHUT_WR); cFYI(1, ("Post shutdown state: 0x%x Flags: 0x%lx", server->ssocket->state, server->ssocket->flags)); @@ -438,9 +438,9 @@ incomplete_rcv: csocket = server->ssocket; wake_up(&server->response_q); continue; - } else if (length < 4) { - cFYI(1, ("less than four bytes received (%d bytes)", - length)); + } else if (length < pdu_length) { + cFYI(1, ("requested %d bytes but only got %d bytes", + pdu_length, length)); pdu_length -= length; msleep(1); goto incomplete_rcv; @@ -752,6 +752,7 @@ multi_t2_fnd: } write_unlock(&GlobalSMBSeslock); + kfree(server->hostname); kfree(server); if (length > 0) mempool_resize(cifs_req_poolp, length + cifs_min_rcv, @@ -760,6 +761,34 @@ multi_t2_fnd: return 0; } +/* extract the host portion of the UNC string */ +static char * +extract_hostname(const char *unc) +{ + const char *src; + char *dst, *delim; + unsigned int len; + + /* skip double chars at beginning of string */ + /* BB: check validity of these bytes? */ + src = unc + 2; + + /* delimiter between hostname and sharename is always '\\' now */ + delim = strchr(src, '\\'); + if (!delim) + return ERR_PTR(-EINVAL); + + len = delim - src; + dst = kmalloc((len + 1), GFP_KERNEL); + if (dst == NULL) + return ERR_PTR(-ENOMEM); + + memcpy(dst, src, len); + dst[len] = '\0'; + + return dst; +} + static int cifs_parse_mount_options(char *options, const char *devname, struct smb_vol *vol) @@ -793,7 +822,7 @@ cifs_parse_mount_options(char *options, const char *devname, vol->linux_gid = current->gid; vol->dir_mode = S_IRWXUGO; /* 2767 perms indicate mandatory locking support */ - vol->file_mode = S_IALLUGO & ~(S_ISUID | S_IXGRP); + vol->file_mode = (S_IRWXUGO | S_ISGID) & (~S_IXGRP); /* vol->retry default is 0 (i.e. "soft" limited retry not hard retry) */ vol->rw = TRUE; @@ -1781,16 +1810,13 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, memset(&volume_info, 0, sizeof(struct smb_vol)); if (cifs_parse_mount_options(mount_data, devname, &volume_info)) { - kfree(volume_info.UNC); - kfree(volume_info.password); - kfree(volume_info.prepath); - FreeXid(xid); - return -EINVAL; + rc = -EINVAL; + goto out; } if (volume_info.nullauth) { cFYI(1, ("null user")); - volume_info.username = NULL; + volume_info.username = ""; } else if (volume_info.username) { /* BB fixme parse for domain name here */ cFYI(1, ("Username: %s", volume_info.username)); @@ -1798,11 +1824,8 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, cifserror("No username specified"); /* In userspace mount helper we can get user name from alternate locations such as env variables and files on disk */ - kfree(volume_info.UNC); - kfree(volume_info.password); - kfree(volume_info.prepath); - FreeXid(xid); - return -EINVAL; + rc = -EINVAL; + goto out; } if (volume_info.UNCip && volume_info.UNC) { @@ -1821,11 +1844,8 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, if (rc <= 0) { /* we failed translating address */ - kfree(volume_info.UNC); - kfree(volume_info.password); - kfree(volume_info.prepath); - FreeXid(xid); - return -EINVAL; + rc = -EINVAL; + goto out; } cFYI(1, ("UNC: %s ip: %s", volume_info.UNC, volume_info.UNCip)); @@ -1835,20 +1855,14 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, /* BB using ip addr as server name to connect to the DFS root below */ cERROR(1, ("Connecting to DFS root not implemented yet")); - kfree(volume_info.UNC); - kfree(volume_info.password); - kfree(volume_info.prepath); - FreeXid(xid); - return -EINVAL; + rc = -EINVAL; + goto out; } else /* which servers DFS root would we conect to */ { cERROR(1, ("CIFS mount error: No UNC path (e.g. -o " "unc=//192.168.1.100/public) specified")); - kfree(volume_info.UNC); - kfree(volume_info.password); - kfree(volume_info.prepath); - FreeXid(xid); - return -EINVAL; + rc = -EINVAL; + goto out; } /* this is needed for ASCII cp to Unicode converts */ @@ -1860,11 +1874,8 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, if (cifs_sb->local_nls == NULL) { cERROR(1, ("CIFS mount error: iocharset %s not found", volume_info.iocharset)); - kfree(volume_info.UNC); - kfree(volume_info.password); - kfree(volume_info.prepath); - FreeXid(xid); - return -ELIBACC; + rc = -ELIBACC; + goto out; } } @@ -1878,11 +1889,8 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, &sin_server6.sin6_addr, volume_info.username, &srvTcp); } else { - kfree(volume_info.UNC); - kfree(volume_info.password); - kfree(volume_info.prepath); - FreeXid(xid); - return -EINVAL; + rc = -EINVAL; + goto out; } if (srvTcp) { @@ -1906,22 +1914,14 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, "Aborting operation")); if (csocket != NULL) sock_release(csocket); - kfree(volume_info.UNC); - kfree(volume_info.password); - kfree(volume_info.prepath); - FreeXid(xid); - return rc; + goto out; } srvTcp = kzalloc(sizeof(struct TCP_Server_Info), GFP_KERNEL); if (!srvTcp) { rc = -ENOMEM; sock_release(csocket); - kfree(volume_info.UNC); - kfree(volume_info.password); - kfree(volume_info.prepath); - FreeXid(xid); - return rc; + goto out; } else { memcpy(&srvTcp->addr.sockAddr, &sin_server, sizeof(struct sockaddr_in)); @@ -1929,6 +1929,12 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, /* BB Add code for ipv6 case too */ srvTcp->ssocket = csocket; srvTcp->protocolType = IPV4; + srvTcp->hostname = extract_hostname(volume_info.UNC); + if (IS_ERR(srvTcp->hostname)) { + rc = PTR_ERR(srvTcp->hostname); + sock_release(csocket); + goto out; + } init_waitqueue_head(&srvTcp->response_q); init_waitqueue_head(&srvTcp->request_q); INIT_LIST_HEAD(&srvTcp->pending_mid_q); @@ -1938,16 +1944,13 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, srvTcp->tcpStatus = CifsNew; init_MUTEX(&srvTcp->tcpSem); srvTcp->tsk = kthread_run((void *)(void *)cifs_demultiplex_thread, srvTcp, "cifsd"); - if ( IS_ERR(srvTcp->tsk) ) { + if (IS_ERR(srvTcp->tsk)) { rc = PTR_ERR(srvTcp->tsk); cERROR(1, ("error %d create cifsd thread", rc)); srvTcp->tsk = NULL; sock_release(csocket); - kfree(volume_info.UNC); - kfree(volume_info.password); - kfree(volume_info.prepath); - FreeXid(xid); - return rc; + kfree(srvTcp->hostname); + goto out; } wait_for_completion(&cifsd_complete); rc = 0; @@ -1962,8 +1965,6 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, if (existingCifsSes) { pSesInfo = existingCifsSes; cFYI(1, ("Existing smb sess found")); - kfree(volume_info.password); - /* volume_info.UNC freed at end of function */ } else if (!rc) { cFYI(1, ("Existing smb sess not found")); pSesInfo = sesInfoAlloc(); @@ -1977,8 +1978,11 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, if (!rc) { /* volume_info.password freed at unmount */ - if (volume_info.password) + if (volume_info.password) { pSesInfo->password = volume_info.password; + /* set to NULL to prevent freeing on exit */ + volume_info.password = NULL; + } if (volume_info.username) strncpy(pSesInfo->userName, volume_info.username, @@ -2000,8 +2004,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, up(&pSesInfo->sesSem); if (!rc) atomic_inc(&srvTcp->socketUseCount); - } else - kfree(volume_info.password); + } } /* search for existing tcon to this server share */ @@ -2106,9 +2109,8 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, "", cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); - kfree(volume_info.UNC); - FreeXid(xid); - return -ENODEV; + rc = -ENODEV; + goto out; } else { /* BB Do we need to wrap sesSem around * this TCon call and Unix SetFS as @@ -2231,6 +2233,12 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, (in which case it is not needed anymore) but when new sesion is created the password ptr is put in the new session structure (in which case the password will be freed at unmount time) */ +out: + /* zero out password before freeing */ + if (volume_info.password != NULL) { + memset(volume_info.password, 0, strlen(volume_info.password)); + kfree(volume_info.password); + } kfree(volume_info.UNC); kfree(volume_info.prepath); FreeXid(xid); @@ -2374,7 +2382,7 @@ CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses, pSMB->req_no_secext.ByteCount = cpu_to_le16(count); rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response, - &bytes_returned, 1); + &bytes_returned, CIFS_LONG_OP); if (rc) { /* rc = map_smb_to_linux_error(smb_buffer_response); now done in SendReceive */ } else if ((smb_buffer_response->WordCount == 3) @@ -2678,7 +2686,7 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid, pSMB->req.ByteCount = cpu_to_le16(count); rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response, - &bytes_returned, 1); + &bytes_returned, CIFS_LONG_OP); if (smb_buffer_response->Status.CifsError == cpu_to_le32(NT_STATUS_MORE_PROCESSING_REQUIRED)) @@ -3105,7 +3113,7 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses, pSMB->req.ByteCount = cpu_to_le16(count); rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response, - &bytes_returned, 1); + &bytes_returned, CIFS_LONG_OP); if (rc) { /* rc = map_smb_to_linux_error(smb_buffer_response) done in SendReceive now */ } else if ((smb_buffer_response->WordCount == 3) || @@ -3381,7 +3389,8 @@ CIFSTCon(unsigned int xid, struct cifsSesInfo *ses, pSMB->hdr.smb_buf_length += count; pSMB->ByteCount = cpu_to_le16(count); - rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response, &length, 0); + rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response, &length, + CIFS_STD_OP); /* if (rc) rc = map_smb_to_linux_error(smb_buffer_response); */ /* above now done in SendReceive */ diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c index 793404b..37dc97a 100644 --- a/fs/cifs/dir.c +++ b/fs/cifs/dir.c @@ -593,7 +593,7 @@ static int cifs_ci_compare(struct dentry *dentry, struct qstr *a, * case take precedence. If a is not a negative dentry, this * should have no side effects */ - memcpy((unsigned char *)a->name, b->name, a->len); + memcpy(a->name, b->name, a->len); return 0; } return 1; diff --git a/fs/cifs/file.c b/fs/cifs/file.c index 1e7e4c0..dd26e27 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c @@ -130,7 +130,9 @@ static inline int cifs_open_inode_helper(struct inode *inode, struct file *file, if (file->f_path.dentry->d_inode->i_mapping) { /* BB no need to lock inode until after invalidate since namei code should already have it locked? */ - filemap_write_and_wait(file->f_path.dentry->d_inode->i_mapping); + rc = filemap_write_and_wait(file->f_path.dentry->d_inode->i_mapping); + if (rc != 0) + CIFS_I(file->f_path.dentry->d_inode)->write_behind_rc = rc; } cFYI(1, ("invalidating remote inode since open detected it " "changed")); @@ -425,7 +427,9 @@ reopen_error_exit: pCifsInode = CIFS_I(inode); if (pCifsInode) { if (can_flush) { - filemap_write_and_wait(inode->i_mapping); + rc = filemap_write_and_wait(inode->i_mapping); + if (rc != 0) + CIFS_I(inode)->write_behind_rc = rc; /* temporarily disable caching while we go to server to get inode info */ pCifsInode->clientCanCacheAll = FALSE; @@ -835,9 +839,9 @@ ssize_t cifs_user_write(struct file *file, const char __user *write_data, xid = GetXid(); if (*poffset > file->f_path.dentry->d_inode->i_size) - long_op = 2; /* writes past end of file can take a long time */ + long_op = CIFS_VLONG_OP; /* writes past EOF take long time */ else - long_op = 1; + long_op = CIFS_LONG_OP; for (total_written = 0; write_size > total_written; total_written += bytes_written) { @@ -884,7 +888,7 @@ ssize_t cifs_user_write(struct file *file, const char __user *write_data, } } else *poffset += bytes_written; - long_op = FALSE; /* subsequent writes fast - + long_op = CIFS_STD_OP; /* subsequent writes fast - 15 seconds is plenty */ } @@ -934,9 +938,9 @@ static ssize_t cifs_write(struct file *file, const char *write_data, xid = GetXid(); if (*poffset > file->f_path.dentry->d_inode->i_size) - long_op = 2; /* writes past end of file can take a long time */ + long_op = CIFS_VLONG_OP; /* writes past EOF can be slow */ else - long_op = 1; + long_op = CIFS_LONG_OP; for (total_written = 0; write_size > total_written; total_written += bytes_written) { @@ -1002,7 +1006,7 @@ static ssize_t cifs_write(struct file *file, const char *write_data, } } else *poffset += bytes_written; - long_op = FALSE; /* subsequent writes fast - + long_op = CIFS_STD_OP; /* subsequent writes fast - 15 seconds is plenty */ } @@ -1026,6 +1030,37 @@ static ssize_t cifs_write(struct file *file, const char *write_data, return total_written; } +#ifdef CONFIG_CIFS_EXPERIMENTAL +struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *cifs_inode) +{ + struct cifsFileInfo *open_file = NULL; + + read_lock(&GlobalSMBSeslock); + /* we could simply get the first_list_entry since write-only entries + are always at the end of the list but since the first entry might + have a close pending, we go through the whole list */ + list_for_each_entry(open_file, &cifs_inode->openFileList, flist) { + if (open_file->closePend) + continue; + if (open_file->pfile && ((open_file->pfile->f_flags & O_RDWR) || + (open_file->pfile->f_flags & O_RDONLY))) { + if (!open_file->invalidHandle) { + /* found a good file */ + /* lock it so it will not be closed on us */ + atomic_inc(&open_file->wrtPending); + read_unlock(&GlobalSMBSeslock); + return open_file; + } /* else might as well continue, and look for + another, or simply have the caller reopen it + again rather than trying to fix this handle */ + } else /* write only file */ + break; /* write only files are last so must be done */ + } + read_unlock(&GlobalSMBSeslock); + return NULL; +} +#endif + struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *cifs_inode) { struct cifsFileInfo *open_file; @@ -1056,11 +1091,11 @@ refind_writable: read_unlock(&GlobalSMBSeslock); return open_file; } - + read_unlock(&GlobalSMBSeslock); /* Had to unlock since following call can block */ rc = cifs_reopen_file(open_file->pfile, FALSE); - if (!rc) { + if (!rc) { if (!open_file->closePend) return open_file; else { /* start over in case this was deleted */ @@ -1083,7 +1118,7 @@ refind_writable: /* can not use this handle, no write pending on this one after all */ atomic_dec(&open_file->wrtPending); - + if (open_file->closePend) /* list could have changed */ goto refind_writable; /* else we simply continue to the next entry. Thus @@ -1329,14 +1364,17 @@ retry: open_file->netfid, bytes_to_write, offset, &bytes_written, iov, n_iov, - 1); + CIFS_LONG_OP); atomic_dec(&open_file->wrtPending); if (rc || bytes_written < bytes_to_write) { cERROR(1, ("Write2 ret %d, wrote %d", rc, bytes_written)); /* BB what if continued retry is requested via mount flags? */ - set_bit(AS_EIO, &mapping->flags); + if (rc == -ENOSPC) + set_bit(AS_ENOSPC, &mapping->flags); + else + set_bit(AS_EIO, &mapping->flags); } else { cifs_stats_bytes_written(cifs_sb->tcon, bytes_written); @@ -1468,9 +1506,11 @@ int cifs_fsync(struct file *file, struct dentry *dentry, int datasync) cFYI(1, ("Sync file - name: %s datasync: 0x%x", dentry->d_name.name, datasync)); - rc = filemap_fdatawrite(inode->i_mapping); - if (rc == 0) + rc = filemap_write_and_wait(inode->i_mapping); + if (rc == 0) { + rc = CIFS_I(inode)->write_behind_rc; CIFS_I(inode)->write_behind_rc = 0; + } FreeXid(xid); return rc; } @@ -1522,8 +1562,11 @@ int cifs_flush(struct file *file, fl_owner_t id) filemapfdatawrite appears easier for the time being */ rc = filemap_fdatawrite(inode->i_mapping); - if (!rc) /* reset wb rc if we were able to write out dirty pages */ + /* reset wb rc if we were able to write out dirty pages */ + if (!rc) { + rc = CIFS_I(inode)->write_behind_rc; CIFS_I(inode)->write_behind_rc = 0; + } cFYI(1, ("Flush inode %p file %p rc %d", inode, file, rc)); diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index 5e8b388..e915eb1 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c @@ -289,7 +289,7 @@ static int decode_sfu_inode(struct inode *inode, __u64 size, #define SFBITS_MASK (S_ISVTX | S_ISGID | S_ISUID) /* SETFILEBITS valid bits */ -static int get_sfu_uid_mode(struct inode *inode, +static int get_sfu_mode(struct inode *inode, const unsigned char *path, struct cifs_sb_info *cifs_sb, int xid) { @@ -527,11 +527,16 @@ int cifs_get_inode_info(struct inode **pinode, /* BB fill in uid and gid here? with help from winbind? or retrieve from NTFS stream extended attribute */ +#ifdef CONFIG_CIFS_EXPERIMENTAL + /* fill in 0777 bits from ACL */ + if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) { + cFYI(1, ("Getting mode bits from ACL")); + acl_to_uid_mode(inode, search_path); + } +#endif if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) { - /* fill in uid, gid, mode from server ACL */ - /* BB FIXME this should also take into account the - * default uid specified on mount if present */ - get_sfu_uid_mode(inode, search_path, cifs_sb, xid); + /* fill in remaining high mode bits e.g. SUID, VTX */ + get_sfu_mode(inode, search_path, cifs_sb, xid); } else if (atomic_read(&cifsInfo->inUse) == 0) { inode->i_uid = cifs_sb->mnt_uid; inode->i_gid = cifs_sb->mnt_gid; @@ -1228,7 +1233,7 @@ cifs_rename_exit: int cifs_revalidate(struct dentry *direntry) { int xid; - int rc = 0; + int rc = 0, wbrc = 0; char *full_path; struct cifs_sb_info *cifs_sb; struct cifsInodeInfo *cifsInode; @@ -1328,7 +1333,9 @@ int cifs_revalidate(struct dentry *direntry) if (direntry->d_inode->i_mapping) { /* do we need to lock inode until after invalidate completes below? */ - filemap_fdatawrite(direntry->d_inode->i_mapping); + wbrc = filemap_fdatawrite(direntry->d_inode->i_mapping); + if (wbrc) + CIFS_I(direntry->d_inode)->write_behind_rc = wbrc; } if (invalidate_inode) { /* shrink_dcache not necessary now that cifs dentry ops @@ -1337,7 +1344,9 @@ int cifs_revalidate(struct dentry *direntry) shrink_dcache_parent(direntry); */ if (S_ISREG(direntry->d_inode->i_mode)) { if (direntry->d_inode->i_mapping) - filemap_fdatawait(direntry->d_inode->i_mapping); + wbrc = filemap_fdatawait(direntry->d_inode->i_mapping); + if (wbrc) + CIFS_I(direntry->d_inode)->write_behind_rc = wbrc; /* may eventually have to do this for open files too */ if (list_empty(&(cifsInode->openFileList))) { /* changed on server - flush read ahead pages */ @@ -1480,10 +1489,20 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs) /* BB check if we need to refresh inode from server now ? BB */ - /* need to flush data before changing file size on server */ - filemap_write_and_wait(direntry->d_inode->i_mapping); - if (attrs->ia_valid & ATTR_SIZE) { + /* + Flush data before changing file size on server. If the + flush returns error, store it to report later and continue. + BB: This should be smarter. Why bother flushing pages that + will be truncated anyway? Also, should we error out here if + the flush returns error? + */ + rc = filemap_write_and_wait(direntry->d_inode->i_mapping); + if (rc != 0) { + CIFS_I(direntry->d_inode)->write_behind_rc = rc; + rc = 0; + } + /* To avoid spurious oplock breaks from server, in the case of inodes that we already have open, avoid doing path based setting of file size if we can do it by handle. diff --git a/fs/cifs/md5.c b/fs/cifs/md5.c index e5c3e12..f13f96d 100644 --- a/fs/cifs/md5.c +++ b/fs/cifs/md5.c @@ -276,8 +276,8 @@ hmac_md5_init_rfc2104(unsigned char *key, int key_len, } /* start out by storing key in pads */ - memset(ctx->k_ipad, 0, sizeof (ctx->k_ipad)); - memset(ctx->k_opad, 0, sizeof (ctx->k_opad)); + memset(ctx->k_ipad, 0, sizeof(ctx->k_ipad)); + memset(ctx->k_opad, 0, sizeof(ctx->k_opad)); memcpy(ctx->k_ipad, key, key_len); memcpy(ctx->k_opad, key, key_len); @@ -307,8 +307,8 @@ hmac_md5_init_limK_to_64(const unsigned char *key, int key_len, } /* start out by storing key in pads */ - memset(ctx->k_ipad, 0, sizeof (ctx->k_ipad)); - memset(ctx->k_opad, 0, sizeof (ctx->k_opad)); + memset(ctx->k_ipad, 0, sizeof(ctx->k_ipad)); + memset(ctx->k_opad, 0, sizeof(ctx->k_opad)); memcpy(ctx->k_ipad, key, key_len); memcpy(ctx->k_opad, key, key_len); diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c index 51ec681..15546c2 100644 --- a/fs/cifs/misc.c +++ b/fs/cifs/misc.c @@ -73,7 +73,7 @@ sesInfoAlloc(void) { struct cifsSesInfo *ret_buf; - ret_buf = kzalloc(sizeof (struct cifsSesInfo), GFP_KERNEL); + ret_buf = kzalloc(sizeof(struct cifsSesInfo), GFP_KERNEL); if (ret_buf) { write_lock(&GlobalSMBSeslock); atomic_inc(&sesInfoAllocCount); @@ -109,7 +109,7 @@ struct cifsTconInfo * tconInfoAlloc(void) { struct cifsTconInfo *ret_buf; - ret_buf = kzalloc(sizeof (struct cifsTconInfo), GFP_KERNEL); + ret_buf = kzalloc(sizeof(struct cifsTconInfo), GFP_KERNEL); if (ret_buf) { write_lock(&GlobalSMBSeslock); atomic_inc(&tconInfoAllocCount); @@ -298,7 +298,7 @@ header_assemble(struct smb_hdr *buffer, char smb_command /* command */ , memset(temp, 0, 256); /* bigger than MAX_CIFS_HDR_SIZE */ buffer->smb_buf_length = - (2 * word_count) + sizeof (struct smb_hdr) - + (2 * word_count) + sizeof(struct smb_hdr) - 4 /* RFC 1001 length field does not count */ + 2 /* for bcc field itself */ ; /* Note that this is the only network field that has to be converted @@ -422,8 +422,8 @@ checkSMB(struct smb_hdr *smb, __u16 mid, unsigned int length) __u32 clc_len; /* calculated length */ cFYI(0, ("checkSMB Length: 0x%x, smb_buf_length: 0x%x", length, len)); - if (length < 2 + sizeof (struct smb_hdr)) { - if ((length >= sizeof (struct smb_hdr) - 1) + if (length < 2 + sizeof(struct smb_hdr)) { + if ((length >= sizeof(struct smb_hdr) - 1) && (smb->Status.CifsError != 0)) { smb->WordCount = 0; /* some error cases do not return wct and bcc */ diff --git a/fs/cifs/netmisc.c b/fs/cifs/netmisc.c index f06359c..646e1f0 100644 --- a/fs/cifs/netmisc.c +++ b/fs/cifs/netmisc.c @@ -132,6 +132,34 @@ static const struct smb_to_posix_error mapping_table_ERRHRD[] = { {0, 0} }; + +/* if the mount helper is missing we need to reverse the 1st slash + from '/' to backslash in order to format the UNC properly for + ip address parsing and for tree connect (unless the user + remembered to put the UNC name in properly). Fortunately we do + not have to call this twice (we check for IPv4 addresses + first, so it is already converted by the time we + try IPv6 addresses */ +static int canonicalize_unc(char *cp) +{ + int i; + + for (i = 0; i <= 46 /* INET6_ADDRSTRLEN */ ; i++) { + if (cp[i] == 0) + break; + if (cp[i] == '\\') + break; + if (cp[i] == '/') { +#ifdef CONFIG_CIFS_DEBUG2 + cFYI(1, ("change slash to backslash in malformed UNC")); +#endif + cp[i] = '\\'; + return 1; + } + } + return 0; +} + /* Convert string containing dotted ip address to binary form */ /* returns 0 if invalid address */ @@ -141,11 +169,13 @@ cifs_inet_pton(int address_family, char *cp, void *dst) int ret = 0; /* calculate length by finding first slash or NULL */ - /* BB Should we convert '/' slash to '\' here since it seems already - * done before this */ - if ( address_family == AF_INET ) { - ret = in4_pton(cp, -1 /* len */, dst , '\\', NULL); - } else if ( address_family == AF_INET6 ) { + if (address_family == AF_INET) { + ret = in4_pton(cp, -1 /* len */, dst, '\\', NULL); + if (ret == 0) { + if (canonicalize_unc(cp)) + ret = in4_pton(cp, -1, dst, '\\', NULL); + } + } else if (address_family == AF_INET6) { ret = in6_pton(cp, -1 /* len */, dst , '\\', NULL); } #ifdef CONFIG_CIFS_DEBUG2 @@ -740,7 +770,7 @@ cifs_print_status(__u32 status_code) static void -ntstatus_to_dos(__u32 ntstatus, __u8 * eclass, __u16 * ecode) +ntstatus_to_dos(__u32 ntstatus, __u8 *eclass, __u16 *ecode) { int i; if (ntstatus == 0) { @@ -793,8 +823,8 @@ map_smb_to_linux_error(struct smb_hdr *smb, int logErr) if (smberrclass == ERRDOS) { /* 1 byte field no need to byte reverse */ for (i = 0; i < - sizeof (mapping_table_ERRDOS) / - sizeof (struct smb_to_posix_error); i++) { + sizeof(mapping_table_ERRDOS) / + sizeof(struct smb_to_posix_error); i++) { if (mapping_table_ERRDOS[i].smb_err == 0) break; else if (mapping_table_ERRDOS[i].smb_err == @@ -807,8 +837,8 @@ map_smb_to_linux_error(struct smb_hdr *smb, int logErr) } else if (smberrclass == ERRSRV) { /* server class of error codes */ for (i = 0; i < - sizeof (mapping_table_ERRSRV) / - sizeof (struct smb_to_posix_error); i++) { + sizeof(mapping_table_ERRSRV) / + sizeof(struct smb_to_posix_error); i++) { if (mapping_table_ERRSRV[i].smb_err == 0) break; else if (mapping_table_ERRSRV[i].smb_err == @@ -837,14 +867,14 @@ map_smb_to_linux_error(struct smb_hdr *smb, int logErr) unsigned int smbCalcSize(struct smb_hdr *ptr) { - return (sizeof (struct smb_hdr) + (2 * ptr->WordCount) + + return (sizeof(struct smb_hdr) + (2 * ptr->WordCount) + 2 /* size of the bcc field */ + BCC(ptr)); } unsigned int smbCalcSize_LE(struct smb_hdr *ptr) { - return (sizeof (struct smb_hdr) + (2 * ptr->WordCount) + + return (sizeof(struct smb_hdr) + (2 * ptr->WordCount) + 2 /* size of the bcc field */ + le16_to_cpu(BCC_LE(ptr))); } diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c index 3746580..0f22def 100644 --- a/fs/cifs/readdir.c +++ b/fs/cifs/readdir.c @@ -171,7 +171,13 @@ static void fill_in_inode(struct inode *tmp_inode, int new_buf_type, /* Linux can not store file creation time unfortunately so ignore it */ cifsInfo->cifsAttrs = attr; - cifsInfo->time = jiffies; +#ifdef CONFIG_CIFS_EXPERIMENTAL + if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) { + /* get more accurate mode via ACL - so force inode refresh */ + cifsInfo->time = 0; + } else +#endif /* CONFIG_CIFS_EXPERIMENTAL */ + cifsInfo->time = jiffies; /* treat dos attribute of read-only as read-only mode bit e.g. 555? */ /* 2767 perms - indicate mandatory locking */ @@ -495,7 +501,7 @@ ffirst_retry: static int cifs_unicode_bytelen(char *str) { int len; - __le16 * ustr = (__le16 *)str; + __le16 *ustr = (__le16 *)str; for (len = 0; len <= PATH_MAX; len++) { if (ustr[len] == 0) diff --git a/fs/cifs/sess.c b/fs/cifs/sess.c index 899dc60..d0cb469 100644 --- a/fs/cifs/sess.c +++ b/fs/cifs/sess.c @@ -29,6 +29,7 @@ #include "ntlmssp.h" #include "nterr.h" #include <linux/utsname.h> +#include "cifs_spnego.h" extern void SMBNTencrypt(unsigned char *passwd, unsigned char *c8, unsigned char *p24); @@ -340,11 +341,12 @@ CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, int first_time, SESSION_SETUP_ANDX *pSMB; __u32 capabilities; int count; - int resp_buf_type = 0; - struct kvec iov[2]; + int resp_buf_type; + struct kvec iov[3]; enum securityEnum type; __u16 action; int bytes_remaining; + struct key *spnego_key = NULL; if (ses == NULL) return -EINVAL; @@ -377,24 +379,32 @@ CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, int first_time, capabilities = cifs_ssetup_hdr(ses, pSMB); - /* we will send the SMB in two pieces, - a fixed length beginning part, and a - second part which will include the strings - and rest of bcc area, in order to avoid having - to do a large buffer 17K allocation */ + /* we will send the SMB in three pieces: + a fixed length beginning part, an optional + SPNEGO blob (which can be zero length), and a + last part which will include the strings + and rest of bcc area. This allows us to avoid + a large buffer 17K allocation */ iov[0].iov_base = (char *)pSMB; iov[0].iov_len = smb_buf->smb_buf_length + 4; + /* setting this here allows the code at the end of the function + to free the request buffer if there's an error */ + resp_buf_type = CIFS_SMALL_BUFFER; + /* 2000 big enough to fit max user, domain, NOS name etc. */ str_area = kmalloc(2000, GFP_KERNEL); if (str_area == NULL) { - cifs_small_buf_release(smb_buf); - return -ENOMEM; + rc = -ENOMEM; + goto ssetup_exit; } bcc_ptr = str_area; ses->flags &= ~CIFS_SES_LANMAN; + iov[1].iov_base = NULL; + iov[1].iov_len = 0; + if (type == LANMAN) { #ifdef CONFIG_CIFS_WEAK_PW_HASH char lnm_session_key[CIFS_SESS_KEY_SIZE]; @@ -463,8 +473,8 @@ CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, int first_time, struct ntlmv2_resp */ if (v2_sess_key == NULL) { - cifs_small_buf_release(smb_buf); - return -ENOMEM; + rc = -ENOMEM; + goto ssetup_exit; } pSMB->req_no_secext.Capabilities = cpu_to_le32(capabilities); @@ -499,22 +509,67 @@ CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, int first_time, unicode_ssetup_strings(&bcc_ptr, ses, nls_cp); } else ascii_ssetup_strings(&bcc_ptr, ses, nls_cp); - } else /* NTLMSSP or SPNEGO */ { + } else if (type == Kerberos) { +#ifdef CONFIG_CIFS_UPCALL + struct cifs_spnego_msg *msg; + spnego_key = cifs_get_spnego_key(ses); + if (IS_ERR(spnego_key)) { + rc = PTR_ERR(spnego_key); + spnego_key = NULL; + goto ssetup_exit; + } + + msg = spnego_key->payload.data; + /* bail out if key is too long */ + if (msg->sesskey_len > + sizeof(ses->server->mac_signing_key.data.krb5)) { + cERROR(1, ("Kerberos signing key too long (%u bytes)", + msg->sesskey_len)); + rc = -EOVERFLOW; + goto ssetup_exit; + } + ses->server->mac_signing_key.len = msg->sesskey_len; + memcpy(ses->server->mac_signing_key.data.krb5, msg->data, + msg->sesskey_len); pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC; capabilities |= CAP_EXTENDED_SECURITY; pSMB->req.Capabilities = cpu_to_le32(capabilities); - /* BB set password lengths */ + iov[1].iov_base = msg->data + msg->sesskey_len; + iov[1].iov_len = msg->secblob_len; + pSMB->req.SecurityBlobLength = cpu_to_le16(iov[1].iov_len); + + if (ses->capabilities & CAP_UNICODE) { + /* unicode strings must be word aligned */ + if (iov[0].iov_len % 2) { + *bcc_ptr = 0; + bcc_ptr++; + } + unicode_oslm_strings(&bcc_ptr, nls_cp); + unicode_domain_string(&bcc_ptr, ses, nls_cp); + } else + /* BB: is this right? */ + ascii_ssetup_strings(&bcc_ptr, ses, nls_cp); +#else /* ! CONFIG_CIFS_UPCALL */ + cERROR(1, ("Kerberos negotiated but upcall support disabled!")); + rc = -ENOSYS; + goto ssetup_exit; +#endif /* CONFIG_CIFS_UPCALL */ + } else { + cERROR(1, ("secType %d not supported!", type)); + rc = -ENOSYS; + goto ssetup_exit; } - count = (long) bcc_ptr - (long) str_area; + iov[2].iov_base = str_area; + iov[2].iov_len = (long) bcc_ptr - (long) str_area; + + count = iov[1].iov_len + iov[2].iov_len; smb_buf->smb_buf_length += count; BCC_LE(smb_buf) = cpu_to_le16(count); - iov[1].iov_base = str_area; - iov[1].iov_len = count; - rc = SendReceive2(xid, ses, iov, 2 /* num_iovecs */, &resp_buf_type, - 0 /* not long op */, 1 /* log NT STATUS if any */ ); + rc = SendReceive2(xid, ses, iov, 3 /* num_iovecs */, &resp_buf_type, + CIFS_STD_OP /* not long */ | CIFS_LOG_ERROR); /* SMB request buf freed in SendReceive2 */ cFYI(1, ("ssetup rc from sendrecv2 is %d", rc)); @@ -560,6 +615,8 @@ CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, int first_time, ses, nls_cp); ssetup_exit: + if (spnego_key) + key_put(spnego_key); kfree(str_area); if (resp_buf_type == CIFS_SMALL_BUFFER) { cFYI(1, ("ssetup freeing small buf %p", iov[0].iov_base)); diff --git a/fs/cifs/smbencrypt.c b/fs/cifs/smbencrypt.c index 90542a3..58bbfd9 100644 --- a/fs/cifs/smbencrypt.c +++ b/fs/cifs/smbencrypt.c @@ -80,7 +80,7 @@ SMBencrypt(unsigned char *passwd, unsigned char *c8, unsigned char *p24) /* Routines for Windows NT MD4 Hash functions. */ static int -_my_wcslen(__u16 * str) +_my_wcslen(__u16 *str) { int len = 0; while (*str++ != 0) @@ -96,7 +96,7 @@ _my_wcslen(__u16 * str) */ static int -_my_mbstowcs(__u16 * dst, const unsigned char *src, int len) +_my_mbstowcs(__u16 *dst, const unsigned char *src, int len) { /* BB not a very good conversion routine - change/fix */ int i; __u16 val; @@ -125,9 +125,9 @@ E_md4hash(const unsigned char *passwd, unsigned char *p16) /* Password cannot be longer than 128 characters */ if (passwd) { len = strlen((char *) passwd); - if (len > 128) { + if (len > 128) len = 128; - } + /* Password must be converted to NT unicode */ _my_mbstowcs(wpwd, passwd, len); } else @@ -135,7 +135,7 @@ E_md4hash(const unsigned char *passwd, unsigned char *p16) wpwd[len] = 0; /* Ensure string is null terminated */ /* Calculate length in bytes */ - len = _my_wcslen(wpwd) * sizeof (__u16); + len = _my_wcslen(wpwd) * sizeof(__u16); mdfour(p16, (unsigned char *) wpwd, len); memset(wpwd, 0, 129 * 2); @@ -167,7 +167,7 @@ nt_lm_owf_gen(char *pwd, unsigned char nt_p16[16], unsigned char p16[16]) E_P16((unsigned char *) passwd, (unsigned char *) p16); /* clear out local copy of user's password (just being paranoid). */ - memset(passwd, '\0', sizeof (passwd)); + memset(passwd, '\0', sizeof(passwd)); } #endif @@ -189,8 +189,10 @@ ntv2_owf_gen(const unsigned char owf[16], const char *user_n, return; dom_u = user_u + 1024; - /* push_ucs2(NULL, user_u, user_n, (user_l+1)*2, STR_UNICODE|STR_NOALIGN|STR_TERMINATE|STR_UPPER); - push_ucs2(NULL, dom_u, domain_n, (domain_l+1)*2, STR_UNICODE|STR_NOALIGN|STR_TERMINATE|STR_UPPER); */ + /* push_ucs2(NULL, user_u, user_n, (user_l+1)*2, + STR_UNICODE|STR_NOALIGN|STR_TERMINATE|STR_UPPER); + push_ucs2(NULL, dom_u, domain_n, (domain_l+1)*2, + STR_UNICODE|STR_NOALIGN|STR_TERMINATE|STR_UPPER); */ /* BB user and domain may need to be uppercased */ user_l = cifs_strtoUCS(user_u, user_n, 511, nls_codepage); diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c index 7ed32b3..50b623a 100644 --- a/fs/cifs/transport.c +++ b/fs/cifs/transport.c @@ -308,7 +308,7 @@ smb_send2(struct socket *ssocket, struct kvec *iov, int n_vec, static int wait_for_free_request(struct cifsSesInfo *ses, const int long_op) { - if (long_op == -1) { + if (long_op == CIFS_ASYNC_OP) { /* oplock breaks must not be held up */ atomic_inc(&ses->server->inFlight); } else { @@ -337,7 +337,7 @@ static int wait_for_free_request(struct cifsSesInfo *ses, const int long_op) as they are allowed to block on server */ /* update # of requests on the wire to server */ - if (long_op < 3) + if (long_op != CIFS_BLOCKING_OP) atomic_inc(&ses->server->inFlight); spin_unlock(&GlobalMid_Lock); break; @@ -415,17 +415,48 @@ static int wait_for_response(struct cifsSesInfo *ses, } } + +/* + * + * Send an SMB Request. No response info (other than return code) + * needs to be parsed. + * + * flags indicate the type of request buffer and how long to wait + * and whether to log NT STATUS code (error) before mapping it to POSIX error + * + */ +int +SendReceiveNoRsp(const unsigned int xid, struct cifsSesInfo *ses, + struct smb_hdr *in_buf, int flags) +{ + int rc; + struct kvec iov[1]; + int resp_buf_type; + + iov[0].iov_base = (char *)in_buf; + iov[0].iov_len = in_buf->smb_buf_length + 4; + flags |= CIFS_NO_RESP; + rc = SendReceive2(xid, ses, iov, 1, &resp_buf_type, flags); +#ifdef CONFIG_CIFS_DEBUG2 + cFYI(1, ("SendRcvNoR flags %d rc %d", flags, rc)); +#endif + return rc; +} + int SendReceive2(const unsigned int xid, struct cifsSesInfo *ses, struct kvec *iov, int n_vec, int *pRespBufType /* ret */, - const int long_op, const int logError) + const int flags) { int rc = 0; + int long_op; unsigned int receive_len; unsigned long timeout; struct mid_q_entry *midQ; struct smb_hdr *in_buf = iov[0].iov_base; + long_op = flags & CIFS_TIMEOUT_MASK; + *pRespBufType = CIFS_NO_BUFFER; /* no response buf yet */ if ((ses == NULL) || (ses->server == NULL)) { @@ -483,15 +514,22 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses, if (rc < 0) goto out; - if (long_op == -1) - goto out; - else if (long_op == 2) /* writes past end of file can take loong time */ + if (long_op == CIFS_STD_OP) + timeout = 15 * HZ; + else if (long_op == CIFS_VLONG_OP) /* e.g. slow writes past EOF */ timeout = 180 * HZ; - else if (long_op == 1) + else if (long_op == CIFS_LONG_OP) timeout = 45 * HZ; /* should be greater than servers oplock break timeout (about 43 seconds) */ - else - timeout = 15 * HZ; + else if (long_op == CIFS_ASYNC_OP) + goto out; + else if (long_op == CIFS_BLOCKING_OP) + timeout = 0x7FFFFFFF; /* large, but not so large as to wrap */ + else { + cERROR(1, ("unknown timeout flag %d", long_op)); + rc = -EIO; + goto out; + } /* wait for 15 seconds or until woken up due to response arriving or due to last connection to this server being unmounted */ @@ -566,7 +604,8 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses, } /* BB special case reconnect tid and uid here? */ - rc = map_smb_to_linux_error(midQ->resp_buf, logError); + rc = map_smb_to_linux_error(midQ->resp_buf, + flags & CIFS_LOG_ERROR); /* convert ByteCount if necessary */ if (receive_len >= sizeof(struct smb_hdr) - 4 @@ -574,8 +613,10 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses, (2 * midQ->resp_buf->WordCount) + 2 /* bcc */ ) BCC(midQ->resp_buf) = le16_to_cpu(BCC_LE(midQ->resp_buf)); - midQ->resp_buf = NULL; /* mark it so will not be freed - by DeleteMidQEntry */ + if ((flags & CIFS_NO_RESP) == 0) + midQ->resp_buf = NULL; /* mark it so buf will + not be freed by + DeleteMidQEntry */ } else { rc = -EIO; cFYI(1, ("Bad MID state?")); @@ -663,17 +704,25 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses, if (rc < 0) goto out; - if (long_op == -1) + if (long_op == CIFS_STD_OP) + timeout = 15 * HZ; + /* wait for 15 seconds or until woken up due to response arriving or + due to last connection to this server being unmounted */ + else if (long_op == CIFS_ASYNC_OP) goto out; - else if (long_op == 2) /* writes past end of file can take loong time */ + else if (long_op == CIFS_VLONG_OP) /* writes past EOF can be slow */ timeout = 180 * HZ; - else if (long_op == 1) + else if (long_op == CIFS_LONG_OP) timeout = 45 * HZ; /* should be greater than servers oplock break timeout (about 43 seconds) */ - else - timeout = 15 * HZ; - /* wait for 15 seconds or until woken up due to response arriving or - due to last connection to this server being unmounted */ + else if (long_op == CIFS_BLOCKING_OP) + timeout = 0x7FFFFFFF; /* large but no so large as to wrap */ + else { + cERROR(1, ("unknown timeout flag %d", long_op)); + rc = -EIO; + goto out; + } + if (signal_pending(current)) { /* if signal pending do not hold up user for full smb timeout but we still give response a chance to complete */ @@ -812,7 +861,7 @@ send_lock_cancel(const unsigned int xid, struct cifsTconInfo *tcon, pSMB->hdr.Mid = GetNextMid(ses->server); return SendReceive(xid, ses, in_buf, out_buf, - &bytes_returned, 0); + &bytes_returned, CIFS_STD_OP); } int @@ -844,7 +893,7 @@ SendReceiveBlockingLock(const unsigned int xid, struct cifsTconInfo *tcon, to the same server. We may make this configurable later or use ses->maxReq */ - rc = wait_for_free_request(ses, 3); + rc = wait_for_free_request(ses, CIFS_BLOCKING_OP); if (rc) return rc; diff --git a/fs/cifs/xattr.c b/fs/cifs/xattr.c index 369e838..54e8ef9 100644 --- a/fs/cifs/xattr.c +++ b/fs/cifs/xattr.c @@ -265,7 +265,9 @@ ssize_t cifs_getxattr(struct dentry *direntry, const char *ea_name, else if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) { __u16 fid; int oplock = FALSE; - if (experimEnabled) + struct cifs_ntsd *pacl = NULL; + __u32 buflen = 0; + if (experimEnabled) rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_OPEN, GENERIC_READ, 0, &fid, &oplock, NULL, cifs_sb->local_nls, @@ -273,10 +275,9 @@ ssize_t cifs_getxattr(struct dentry *direntry, const char *ea_name, CIFS_MOUNT_MAP_SPECIAL_CHR); /* else rc is EOPNOTSUPP from above */ - if(rc == 0) { - rc = CIFSSMBGetCIFSACL(xid, pTcon, fid, - ea_value, buf_size, - ACL_TYPE_ACCESS); + if (rc == 0) { + rc = CIFSSMBGetCIFSACL(xid, pTcon, fid, &pacl, + &buflen); CIFSSMBClose(xid, pTcon, fid); } } diff --git a/fs/compat_ioctl.c b/fs/compat_ioctl.c index bd26e4c..e8b7c3a 100644 --- a/fs/compat_ioctl.c +++ b/fs/compat_ioctl.c @@ -1954,6 +1954,12 @@ ULONG_IOCTL(TIOCSCTTY) COMPATIBLE_IOCTL(TIOCGPTN) COMPATIBLE_IOCTL(TIOCSPTLCK) COMPATIBLE_IOCTL(TIOCSERGETLSR) +#ifdef TCGETS2 +COMPATIBLE_IOCTL(TCGETS2) +COMPATIBLE_IOCTL(TCSETS2) +COMPATIBLE_IOCTL(TCSETSW2) +COMPATIBLE_IOCTL(TCSETSF2) +#endif /* Little f */ COMPATIBLE_IOCTL(FIOCLEX) COMPATIBLE_IOCTL(FIONCLEX) diff --git a/fs/dlm/lowcomms.c b/fs/dlm/lowcomms.c index 58bf3f5..e9923ca 100644 --- a/fs/dlm/lowcomms.c +++ b/fs/dlm/lowcomms.c @@ -1062,7 +1062,7 @@ static int sctp_listen_for_all(void) subscribe.sctp_shutdown_event = 1; subscribe.sctp_partial_delivery_event = 1; - result = kernel_setsockopt(sock, SOL_SOCKET, SO_RCVBUF, + result = kernel_setsockopt(sock, SOL_SOCKET, SO_RCVBUFFORCE, (char *)&bufsize, sizeof(bufsize)); if (result) log_print("Error increasing buffer space on socket %d", result); @@ -1454,10 +1454,6 @@ int dlm_lowcomms_start(void) if (!con_cache) goto out; - /* Set some sysctl minima */ - if (sysctl_rmem_max < NEEDED_RMEM) - sysctl_rmem_max = NEEDED_RMEM; - /* Start listening */ if (dlm_config.ci_protocol == 0) error = tcp_listen_for_all(); diff --git a/fs/ecryptfs/read_write.c b/fs/ecryptfs/read_write.c index 2150edf..6b7474a 100644 --- a/fs/ecryptfs/read_write.c +++ b/fs/ecryptfs/read_write.c @@ -87,7 +87,7 @@ int ecryptfs_write_lower_page_segment(struct inode *ecryptfs_inode, loff_t offset; int rc; - offset = ((((off_t)page_for_lower->index) << PAGE_CACHE_SHIFT) + offset = ((((loff_t)page_for_lower->index) << PAGE_CACHE_SHIFT) + offset_in_page); virt = kmap(page_for_lower); rc = ecryptfs_write_lower(ecryptfs_inode, virt, offset, size); @@ -1692,7 +1692,10 @@ int do_coredump(long signr, int exit_code, struct pt_regs * regs) if (!binfmt || !binfmt->core_dump) goto fail; down_write(&mm->mmap_sem); - if (!get_dumpable(mm)) { + /* + * If another thread got here first, or we are not dumpable, bail out. + */ + if (mm->core_waiters || !get_dumpable(mm)) { up_write(&mm->mmap_sem); goto fail; } @@ -1706,7 +1709,6 @@ int do_coredump(long signr, int exit_code, struct pt_regs * regs) flag = O_EXCL; /* Stop rewrite attacks */ current->fsuid = 0; /* Dump root private */ } - set_dumpable(mm, 0); retval = coredump_wait(exit_code); if (retval < 0) @@ -1778,6 +1780,12 @@ int do_coredump(long signr, int exit_code, struct pt_regs * regs) but keep the previous behaviour for now. */ if (!ispipe && !S_ISREG(inode->i_mode)) goto close_fail; + /* + * Dont allow local users get cute and trick others to coredump + * into their pre-created files: + */ + if (inode->i_uid != current->fsuid) + goto close_fail; if (!file->f_op) goto close_fail; if (!file->f_op->write) diff --git a/fs/ext2/balloc.c b/fs/ext2/balloc.c index 18a42de..377ad17 100644 --- a/fs/ext2/balloc.c +++ b/fs/ext2/balloc.c @@ -69,14 +69,6 @@ struct ext2_group_desc * ext2_get_group_desc(struct super_block * sb, return desc + offset; } -static inline int -block_in_use(unsigned long block, struct super_block *sb, unsigned char *map) -{ - return ext2_test_bit ((block - - le32_to_cpu(EXT2_SB(sb)->s_es->s_first_data_block)) % - EXT2_BLOCKS_PER_GROUP(sb), map); -} - /* * Read the bitmap for a given block_group, reading into the specified * slot in the superblock's bitmap cache. @@ -86,51 +78,20 @@ block_in_use(unsigned long block, struct super_block *sb, unsigned char *map) static struct buffer_head * read_block_bitmap(struct super_block *sb, unsigned int block_group) { - int i; struct ext2_group_desc * desc; struct buffer_head * bh = NULL; - unsigned int bitmap_blk; - + desc = ext2_get_group_desc (sb, block_group, NULL); if (!desc) - return NULL; - bitmap_blk = le32_to_cpu(desc->bg_block_bitmap); - bh = sb_bread(sb, bitmap_blk); + goto error_out; + bh = sb_bread(sb, le32_to_cpu(desc->bg_block_bitmap)); if (!bh) - ext2_error (sb, __FUNCTION__, + ext2_error (sb, "read_block_bitmap", "Cannot read block bitmap - " "block_group = %d, block_bitmap = %u", block_group, le32_to_cpu(desc->bg_block_bitmap)); - - /* check whether block bitmap block number is set */ - if (!block_in_use(bitmap_blk, sb, bh->b_data)) { - /* bad block bitmap */ - goto error_out; - } - /* check whether the inode bitmap block number is set */ - bitmap_blk = le32_to_cpu(desc->bg_inode_bitmap); - if (!block_in_use(bitmap_blk, sb, bh->b_data)) { - /* bad block bitmap */ - goto error_out; - } - /* check whether the inode table block number is set */ - bitmap_blk = le32_to_cpu(desc->bg_inode_table); - for (i = 0; i < EXT2_SB(sb)->s_itb_per_group; i++, bitmap_blk++) { - if (!block_in_use(bitmap_blk, sb, bh->b_data)) { - /* bad block bitmap */ - goto error_out; - } - } - - return bh; - error_out: - brelse(bh); - ext2_error(sb, __FUNCTION__, - "Invalid block bitmap - " - "block_group = %d, block = %u", - block_group, bitmap_blk); - return NULL; + return bh; } static void release_blocks(struct super_block *sb, int count) @@ -1461,7 +1422,6 @@ unsigned long ext2_count_free_blocks (struct super_block * sb) #endif } - static inline int test_root(int a, int b) { int num = b; diff --git a/fs/ext2/ext2.h b/fs/ext2/ext2.h index 7730388..c87ae29 100644 --- a/fs/ext2/ext2.h +++ b/fs/ext2/ext2.h @@ -178,3 +178,10 @@ extern const struct inode_operations ext2_special_inode_operations; /* symlink.c */ extern const struct inode_operations ext2_fast_symlink_inode_operations; extern const struct inode_operations ext2_symlink_inode_operations; + +static inline ext2_fsblk_t +ext2_group_first_block_no(struct super_block *sb, unsigned long group_no) +{ + return group_no * (ext2_fsblk_t)EXT2_BLOCKS_PER_GROUP(sb) + + le32_to_cpu(EXT2_SB(sb)->s_es->s_first_data_block); +} diff --git a/fs/ext2/ioctl.c b/fs/ext2/ioctl.c index c2324d5..320b2cb 100644 --- a/fs/ext2/ioctl.c +++ b/fs/ext2/ioctl.c @@ -47,6 +47,11 @@ int ext2_ioctl (struct inode * inode, struct file * filp, unsigned int cmd, flags &= ~EXT2_DIRSYNC_FL; mutex_lock(&inode->i_mutex); + /* Is it quota file? Do not allow user to mess with it */ + if (IS_NOQUOTA(inode)) { + mutex_unlock(&inode->i_mutex); + return -EPERM; + } oldflags = ei->i_flags; /* diff --git a/fs/ext3/balloc.c b/fs/ext3/balloc.c index 7a87d15..a8ba7e8 100644 --- a/fs/ext3/balloc.c +++ b/fs/ext3/balloc.c @@ -80,14 +80,6 @@ struct ext3_group_desc * ext3_get_group_desc(struct super_block * sb, return desc + offset; } -static inline int -block_in_use(ext3_fsblk_t block, struct super_block *sb, unsigned char *map) -{ - return ext3_test_bit ((block - - le32_to_cpu(EXT3_SB(sb)->s_es->s_first_data_block)) % - EXT3_BLOCKS_PER_GROUP(sb), map); -} - /** * read_block_bitmap() * @sb: super block @@ -101,51 +93,20 @@ block_in_use(ext3_fsblk_t block, struct super_block *sb, unsigned char *map) static struct buffer_head * read_block_bitmap(struct super_block *sb, unsigned int block_group) { - int i; struct ext3_group_desc * desc; struct buffer_head * bh = NULL; - ext3_fsblk_t bitmap_blk; desc = ext3_get_group_desc (sb, block_group, NULL); if (!desc) - return NULL; - bitmap_blk = le32_to_cpu(desc->bg_block_bitmap); - bh = sb_bread(sb, bitmap_blk); + goto error_out; + bh = sb_bread(sb, le32_to_cpu(desc->bg_block_bitmap)); if (!bh) - ext3_error (sb, __FUNCTION__, + ext3_error (sb, "read_block_bitmap", "Cannot read block bitmap - " "block_group = %d, block_bitmap = %u", block_group, le32_to_cpu(desc->bg_block_bitmap)); - - /* check whether block bitmap block number is set */ - if (!block_in_use(bitmap_blk, sb, bh->b_data)) { - /* bad block bitmap */ - goto error_out; - } - /* check whether the inode bitmap block number is set */ - bitmap_blk = le32_to_cpu(desc->bg_inode_bitmap); - if (!block_in_use(bitmap_blk, sb, bh->b_data)) { - /* bad block bitmap */ - goto error_out; - } - /* check whether the inode table block number is set */ - bitmap_blk = le32_to_cpu(desc->bg_inode_table); - for (i = 0; i < EXT3_SB(sb)->s_itb_per_group; i++, bitmap_blk++) { - if (!block_in_use(bitmap_blk, sb, bh->b_data)) { - /* bad block bitmap */ - goto error_out; - } - } - - return bh; - error_out: - brelse(bh); - ext3_error(sb, __FUNCTION__, - "Invalid block bitmap - " - "block_group = %d, block = %lu", - block_group, bitmap_blk); - return NULL; + return bh; } /* * The reservation window structure operations @@ -1772,7 +1733,6 @@ ext3_fsblk_t ext3_count_free_blocks(struct super_block *sb) #endif } - static inline int test_root(int a, int b) { int num = b; diff --git a/fs/ext3/dir.c b/fs/ext3/dir.c index c8e4ee3..8ca3bfd 100644 --- a/fs/ext3/dir.c +++ b/fs/ext3/dir.c @@ -67,7 +67,7 @@ int ext3_check_dir_entry (const char * function, struct inode * dir, unsigned long offset) { const char * error_msg = NULL; - const int rlen = le16_to_cpu(de->rec_len); + const int rlen = ext3_rec_len_from_disk(de->rec_len); if (rlen < EXT3_DIR_REC_LEN(1)) error_msg = "rec_len is smaller than minimal"; @@ -173,10 +173,10 @@ revalidate: * least that it is non-zero. A * failure will be detected in the * dirent test below. */ - if (le16_to_cpu(de->rec_len) < + if (ext3_rec_len_from_disk(de->rec_len) < EXT3_DIR_REC_LEN(1)) break; - i += le16_to_cpu(de->rec_len); + i += ext3_rec_len_from_disk(de->rec_len); } offset = i; filp->f_pos = (filp->f_pos & ~(sb->s_blocksize - 1)) @@ -197,7 +197,7 @@ revalidate: ret = stored; goto out; } - offset += le16_to_cpu(de->rec_len); + offset += ext3_rec_len_from_disk(de->rec_len); if (le32_to_cpu(de->inode)) { /* We might block in the next section * if the data destination is @@ -219,7 +219,7 @@ revalidate: goto revalidate; stored ++; } - filp->f_pos += le16_to_cpu(de->rec_len); + filp->f_pos += ext3_rec_len_from_disk(de->rec_len); } offset = 0; brelse (bh); diff --git a/fs/ext3/ioctl.c b/fs/ext3/ioctl.c index 4a2a02c..023a070 100644 --- a/fs/ext3/ioctl.c +++ b/fs/ext3/ioctl.c @@ -51,6 +51,11 @@ int ext3_ioctl (struct inode * inode, struct file * filp, unsigned int cmd, flags &= ~EXT3_DIRSYNC_FL; mutex_lock(&inode->i_mutex); + /* Is it quota file? Do not allow user to mess with it */ + if (IS_NOQUOTA(inode)) { + mutex_unlock(&inode->i_mutex); + return -EPERM; + } oldflags = ei->i_flags; /* The JOURNAL_DATA flag is modifiable only by root */ diff --git a/fs/ext3/namei.c b/fs/ext3/namei.c index ec8170a..4ab6f76 100644 --- a/fs/ext3/namei.c +++ b/fs/ext3/namei.c @@ -177,6 +177,16 @@ static int ext3_dx_add_entry(handle_t *handle, struct dentry *dentry, struct inode *inode); /* + * p is at least 6 bytes before the end of page + */ +static inline struct ext3_dir_entry_2 * +ext3_next_entry(struct ext3_dir_entry_2 *p) +{ + return (struct ext3_dir_entry_2 *)((char *)p + + ext3_rec_len_from_disk(p->rec_len)); +} + +/* * Future: use high four bits of block for coalesce-on-delete flags * Mask them off for now. */ @@ -280,7 +290,7 @@ static struct stats dx_show_leaf(struct dx_hash_info *hinfo, struct ext3_dir_ent space += EXT3_DIR_REC_LEN(de->name_len); names++; } - de = (struct ext3_dir_entry_2 *) ((char *) de + le16_to_cpu(de->rec_len)); + de = ext3_next_entry(de); } printk("(%i)\n", names); return (struct stats) { names, space, 1 }; @@ -547,14 +557,6 @@ static int ext3_htree_next_block(struct inode *dir, __u32 hash, /* - * p is at least 6 bytes before the end of page - */ -static inline struct ext3_dir_entry_2 *ext3_next_entry(struct ext3_dir_entry_2 *p) -{ - return (struct ext3_dir_entry_2 *)((char*)p + le16_to_cpu(p->rec_len)); -} - -/* * This function fills a red-black tree with information from a * directory block. It returns the number directory entries loaded * into the tree. If there is an error it is returned in err. @@ -720,7 +722,7 @@ static int dx_make_map (struct ext3_dir_entry_2 *de, int size, cond_resched(); } /* XXX: do we need to check rec_len == 0 case? -Chris */ - de = (struct ext3_dir_entry_2 *) ((char *) de + le16_to_cpu(de->rec_len)); + de = ext3_next_entry(de); } return count; } @@ -822,7 +824,7 @@ static inline int search_dirblock(struct buffer_head * bh, return 1; } /* prevent looping on a bad block */ - de_len = le16_to_cpu(de->rec_len); + de_len = ext3_rec_len_from_disk(de->rec_len); if (de_len <= 0) return -1; offset += de_len; @@ -1130,7 +1132,7 @@ dx_move_dirents(char *from, char *to, struct dx_map_entry *map, int count) rec_len = EXT3_DIR_REC_LEN(de->name_len); memcpy (to, de, rec_len); ((struct ext3_dir_entry_2 *) to)->rec_len = - cpu_to_le16(rec_len); + ext3_rec_len_to_disk(rec_len); de->inode = 0; map++; to += rec_len; @@ -1149,13 +1151,12 @@ static struct ext3_dir_entry_2* dx_pack_dirents(char *base, int size) prev = to = de; while ((char*)de < base + size) { - next = (struct ext3_dir_entry_2 *) ((char *) de + - le16_to_cpu(de->rec_len)); + next = ext3_next_entry(de); if (de->inode && de->name_len) { rec_len = EXT3_DIR_REC_LEN(de->name_len); if (de > to) memmove(to, de, rec_len); - to->rec_len = cpu_to_le16(rec_len); + to->rec_len = ext3_rec_len_to_disk(rec_len); prev = to; to = (struct ext3_dir_entry_2 *) (((char *) to) + rec_len); } @@ -1229,8 +1230,8 @@ static struct ext3_dir_entry_2 *do_split(handle_t *handle, struct inode *dir, /* Fancy dance to stay within two buffers */ de2 = dx_move_dirents(data1, data2, map + split, count - split); de = dx_pack_dirents(data1,blocksize); - de->rec_len = cpu_to_le16(data1 + blocksize - (char *) de); - de2->rec_len = cpu_to_le16(data2 + blocksize - (char *) de2); + de->rec_len = ext3_rec_len_to_disk(data1 + blocksize - (char *) de); + de2->rec_len = ext3_rec_len_to_disk(data2 + blocksize - (char *) de2); dxtrace(dx_show_leaf (hinfo, (struct ext3_dir_entry_2 *) data1, blocksize, 1)); dxtrace(dx_show_leaf (hinfo, (struct ext3_dir_entry_2 *) data2, blocksize, 1)); @@ -1300,7 +1301,7 @@ static int add_dirent_to_buf(handle_t *handle, struct dentry *dentry, return -EEXIST; } nlen = EXT3_DIR_REC_LEN(de->name_len); - rlen = le16_to_cpu(de->rec_len); + rlen = ext3_rec_len_from_disk(de->rec_len); if ((de->inode? rlen - nlen: rlen) >= reclen) break; de = (struct ext3_dir_entry_2 *)((char *)de + rlen); @@ -1319,11 +1320,11 @@ static int add_dirent_to_buf(handle_t *handle, struct dentry *dentry, /* By now the buffer is marked for journaling */ nlen = EXT3_DIR_REC_LEN(de->name_len); - rlen = le16_to_cpu(de->rec_len); + rlen = ext3_rec_len_from_disk(de->rec_len); if (de->inode) { struct ext3_dir_entry_2 *de1 = (struct ext3_dir_entry_2 *)((char *)de + nlen); - de1->rec_len = cpu_to_le16(rlen - nlen); - de->rec_len = cpu_to_le16(nlen); + de1->rec_len = ext3_rec_len_to_disk(rlen - nlen); + de->rec_len = ext3_rec_len_to_disk(nlen); de = de1; } de->file_type = EXT3_FT_UNKNOWN; @@ -1400,17 +1401,18 @@ static int make_indexed_dir(handle_t *handle, struct dentry *dentry, /* The 0th block becomes the root, move the dirents out */ fde = &root->dotdot; - de = (struct ext3_dir_entry_2 *)((char *)fde + le16_to_cpu(fde->rec_len)); + de = (struct ext3_dir_entry_2 *)((char *)fde + + ext3_rec_len_from_disk(fde->rec_len)); len = ((char *) root) + blocksize - (char *) de; memcpy (data1, de, len); de = (struct ext3_dir_entry_2 *) data1; top = data1 + len; - while ((char *)(de2=(void*)de+le16_to_cpu(de->rec_len)) < top) + while ((char *)(de2 = ext3_next_entry(de)) < top) de = de2; - de->rec_len = cpu_to_le16(data1 + blocksize - (char *) de); + de->rec_len = ext3_rec_len_to_disk(data1 + blocksize - (char *) de); /* Initialize the root; the dot dirents already exist */ de = (struct ext3_dir_entry_2 *) (&root->dotdot); - de->rec_len = cpu_to_le16(blocksize - EXT3_DIR_REC_LEN(2)); + de->rec_len = ext3_rec_len_to_disk(blocksize - EXT3_DIR_REC_LEN(2)); memset (&root->info, 0, sizeof(root->info)); root->info.info_length = sizeof(root->info); root->info.hash_version = EXT3_SB(dir->i_sb)->s_def_hash_version; @@ -1490,7 +1492,7 @@ static int ext3_add_entry (handle_t *handle, struct dentry *dentry, return retval; de = (struct ext3_dir_entry_2 *) bh->b_data; de->inode = 0; - de->rec_len = cpu_to_le16(blocksize); + de->rec_len = ext3_rec_len_to_disk(blocksize); return add_dirent_to_buf(handle, dentry, inode, de, bh); } @@ -1553,7 +1555,7 @@ static int ext3_dx_add_entry(handle_t *handle, struct dentry *dentry, goto cleanup; node2 = (struct dx_node *)(bh2->b_data); entries2 = node2->entries; - node2->fake.rec_len = cpu_to_le16(sb->s_blocksize); + node2->fake.rec_len = ext3_rec_len_to_disk(sb->s_blocksize); node2->fake.inode = 0; BUFFER_TRACE(frame->bh, "get_write_access"); err = ext3_journal_get_write_access(handle, frame->bh); @@ -1651,9 +1653,9 @@ static int ext3_delete_entry (handle_t *handle, BUFFER_TRACE(bh, "get_write_access"); ext3_journal_get_write_access(handle, bh); if (pde) - pde->rec_len = - cpu_to_le16(le16_to_cpu(pde->rec_len) + - le16_to_cpu(de->rec_len)); + pde->rec_len = ext3_rec_len_to_disk( + ext3_rec_len_from_disk(pde->rec_len) + + ext3_rec_len_from_disk(de->rec_len)); else de->inode = 0; dir->i_version++; @@ -1661,10 +1663,9 @@ static int ext3_delete_entry (handle_t *handle, ext3_journal_dirty_metadata(handle, bh); return 0; } - i += le16_to_cpu(de->rec_len); + i += ext3_rec_len_from_disk(de->rec_len); pde = de; - de = (struct ext3_dir_entry_2 *) - ((char *) de + le16_to_cpu(de->rec_len)); + de = ext3_next_entry(de); } return -ENOENT; } @@ -1798,13 +1799,13 @@ retry: de = (struct ext3_dir_entry_2 *) dir_block->b_data; de->inode = cpu_to_le32(inode->i_ino); de->name_len = 1; - de->rec_len = cpu_to_le16(EXT3_DIR_REC_LEN(de->name_len)); + de->rec_len = ext3_rec_len_to_disk(EXT3_DIR_REC_LEN(de->name_len)); strcpy (de->name, "."); ext3_set_de_type(dir->i_sb, de, S_IFDIR); - de = (struct ext3_dir_entry_2 *) - ((char *) de + le16_to_cpu(de->rec_len)); + de = ext3_next_entry(de); de->inode = cpu_to_le32(dir->i_ino); - de->rec_len = cpu_to_le16(inode->i_sb->s_blocksize-EXT3_DIR_REC_LEN(1)); + de->rec_len = ext3_rec_len_to_disk(inode->i_sb->s_blocksize - + EXT3_DIR_REC_LEN(1)); de->name_len = 2; strcpy (de->name, ".."); ext3_set_de_type(dir->i_sb, de, S_IFDIR); @@ -1856,8 +1857,7 @@ static int empty_dir (struct inode * inode) return 1; } de = (struct ext3_dir_entry_2 *) bh->b_data; - de1 = (struct ext3_dir_entry_2 *) - ((char *) de + le16_to_cpu(de->rec_len)); + de1 = ext3_next_entry(de); if (le32_to_cpu(de->inode) != inode->i_ino || !le32_to_cpu(de1->inode) || strcmp (".", de->name) || @@ -1868,9 +1868,9 @@ static int empty_dir (struct inode * inode) brelse (bh); return 1; } - offset = le16_to_cpu(de->rec_len) + le16_to_cpu(de1->rec_len); - de = (struct ext3_dir_entry_2 *) - ((char *) de1 + le16_to_cpu(de1->rec_len)); + offset = ext3_rec_len_from_disk(de->rec_len) + + ext3_rec_len_from_disk(de1->rec_len); + de = ext3_next_entry(de1); while (offset < inode->i_size ) { if (!bh || (void *) de >= (void *) (bh->b_data+sb->s_blocksize)) { @@ -1899,9 +1899,8 @@ static int empty_dir (struct inode * inode) brelse (bh); return 0; } - offset += le16_to_cpu(de->rec_len); - de = (struct ext3_dir_entry_2 *) - ((char *) de + le16_to_cpu(de->rec_len)); + offset += ext3_rec_len_from_disk(de->rec_len); + de = ext3_next_entry(de); } brelse (bh); return 1; @@ -2255,8 +2254,7 @@ retry: } #define PARENT_INO(buffer) \ - ((struct ext3_dir_entry_2 *) ((char *) buffer + \ - le16_to_cpu(((struct ext3_dir_entry_2 *) buffer)->rec_len)))->inode + (ext3_next_entry((struct ext3_dir_entry_2 *)(buffer))->inode) /* * Anybody can rename anything with this: the permission checks are left to the diff --git a/fs/ext4/balloc.c b/fs/ext4/balloc.c index e906b65..71ee95e 100644 --- a/fs/ext4/balloc.c +++ b/fs/ext4/balloc.c @@ -189,15 +189,6 @@ struct ext4_group_desc * ext4_get_group_desc(struct super_block * sb, return desc; } -static inline int -block_in_use(ext4_fsblk_t block, struct super_block *sb, unsigned char *map) -{ - ext4_grpblk_t offset; - - ext4_get_group_no_and_offset(sb, block, NULL, &offset); - return ext4_test_bit (offset, map); -} - /** * read_block_bitmap() * @sb: super block @@ -211,7 +202,6 @@ block_in_use(ext4_fsblk_t block, struct super_block *sb, unsigned char *map) struct buffer_head * read_block_bitmap(struct super_block *sb, unsigned int block_group) { - int i; struct ext4_group_desc * desc; struct buffer_head * bh = NULL; ext4_fsblk_t bitmap_blk; @@ -239,38 +229,7 @@ read_block_bitmap(struct super_block *sb, unsigned int block_group) "Cannot read block bitmap - " "block_group = %d, block_bitmap = %llu", block_group, bitmap_blk); - - /* check whether block bitmap block number is set */ - if (!block_in_use(bitmap_blk, sb, bh->b_data)) { - /* bad block bitmap */ - goto error_out; - } - - /* check whether the inode bitmap block number is set */ - bitmap_blk = ext4_inode_bitmap(sb, desc); - if (!block_in_use(bitmap_blk, sb, bh->b_data)) { - /* bad block bitmap */ - goto error_out; - } - /* check whether the inode table block number is set */ - bitmap_blk = ext4_inode_table(sb, desc); - for (i = 0; i < EXT4_SB(sb)->s_itb_per_group; i++, bitmap_blk++) { - if (!block_in_use(bitmap_blk, sb, bh->b_data)) { - /* bad block bitmap */ - goto error_out; - } - } - return bh; - -error_out: - brelse(bh); - ext4_error(sb, __FUNCTION__, - "Invalid block bitmap - " - "block_group = %d, block = %llu", - block_group, bitmap_blk); - return NULL; - } /* * The reservation window structure operations diff --git a/fs/ext4/ioctl.c b/fs/ext4/ioctl.c index c04c7cc..e7f894b 100644 --- a/fs/ext4/ioctl.c +++ b/fs/ext4/ioctl.c @@ -51,6 +51,11 @@ int ext4_ioctl (struct inode * inode, struct file * filp, unsigned int cmd, flags &= ~EXT4_DIRSYNC_FL; mutex_lock(&inode->i_mutex); + /* Is it quota file? Do not allow user to mess with it */ + if (IS_NOQUOTA(inode)) { + mutex_unlock(&inode->i_mutex); + return -EPERM; + } oldflags = ei->i_flags; /* The JOURNAL_DATA flag is modifiable only by root */ diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c index 3763757..80d2f52 100644 --- a/fs/fuse/dir.c +++ b/fs/fuse/dir.c @@ -132,6 +132,21 @@ static void fuse_lookup_init(struct fuse_req *req, struct inode *dir, req->out.args[0].value = outarg; } +static u64 fuse_get_attr_version(struct fuse_conn *fc) +{ + u64 curr_version; + + /* + * The spin lock isn't actually needed on 64bit archs, but we + * don't yet care too much about such optimizations. + */ + spin_lock(&fc->lock); + curr_version = fc->attr_version; + spin_unlock(&fc->lock); + + return curr_version; +} + /* * Check whether the dentry is still valid * @@ -171,9 +186,7 @@ static int fuse_dentry_revalidate(struct dentry *entry, struct nameidata *nd) return 0; } - spin_lock(&fc->lock); - attr_version = fc->attr_version; - spin_unlock(&fc->lock); + attr_version = fuse_get_attr_version(fc); parent = dget_parent(entry); fuse_lookup_init(req, parent->d_inode, entry, &outarg); @@ -264,9 +277,7 @@ static struct dentry *fuse_lookup(struct inode *dir, struct dentry *entry, return ERR_PTR(PTR_ERR(forget_req)); } - spin_lock(&fc->lock); - attr_version = fc->attr_version; - spin_unlock(&fc->lock); + attr_version = fuse_get_attr_version(fc); fuse_lookup_init(req, dir, entry, &outarg); request_send(fc, req); @@ -646,6 +657,9 @@ static int fuse_rename(struct inode *olddir, struct dentry *oldent, err = req->out.h.error; fuse_put_request(fc, req); if (!err) { + /* ctime changes */ + fuse_invalidate_attr(oldent->d_inode); + fuse_invalidate_attr(olddir); if (olddir != newdir) fuse_invalidate_attr(newdir); @@ -733,9 +747,7 @@ static int fuse_do_getattr(struct inode *inode, struct kstat *stat, if (IS_ERR(req)) return PTR_ERR(req); - spin_lock(&fc->lock); - attr_version = fc->attr_version; - spin_unlock(&fc->lock); + attr_version = fuse_get_attr_version(fc); memset(&inarg, 0, sizeof(inarg)); memset(&outarg, 0, sizeof(outarg)); @@ -775,6 +787,31 @@ static int fuse_do_getattr(struct inode *inode, struct kstat *stat, return err; } +int fuse_update_attributes(struct inode *inode, struct kstat *stat, + struct file *file, bool *refreshed) +{ + struct fuse_inode *fi = get_fuse_inode(inode); + int err; + bool r; + + if (fi->i_time < get_jiffies_64()) { + r = true; + err = fuse_do_getattr(inode, stat, file); + } else { + r = false; + err = 0; + if (stat) { + generic_fillattr(inode, stat); + stat->mode = fi->orig_i_mode; + } + } + + if (refreshed != NULL) + *refreshed = r; + + return err; +} + /* * Calling into a user-controlled filesystem gives the filesystem * daemon ptrace-like capabilities over the requester process. This @@ -862,14 +899,9 @@ static int fuse_permission(struct inode *inode, int mask, struct nameidata *nd) */ if ((fc->flags & FUSE_DEFAULT_PERMISSIONS) || ((mask & MAY_EXEC) && S_ISREG(inode->i_mode))) { - struct fuse_inode *fi = get_fuse_inode(inode); - if (fi->i_time < get_jiffies_64()) { - err = fuse_do_getattr(inode, NULL, NULL); - if (err) - return err; - - refreshed = true; - } + err = fuse_update_attributes(inode, NULL, NULL, &refreshed); + if (err) + return err; } if (fc->flags & FUSE_DEFAULT_PERMISSIONS) { @@ -935,7 +967,6 @@ static int fuse_readdir(struct file *file, void *dstbuf, filldir_t filldir) struct page *page; struct inode *inode = file->f_path.dentry->d_inode; struct fuse_conn *fc = get_fuse_conn(inode); - struct fuse_file *ff = file->private_data; struct fuse_req *req; if (is_bad_inode(inode)) @@ -952,7 +983,7 @@ static int fuse_readdir(struct file *file, void *dstbuf, filldir_t filldir) } req->num_pages = 1; req->pages[0] = page; - fuse_read_fill(req, ff, inode, file->f_pos, PAGE_SIZE, FUSE_READDIR); + fuse_read_fill(req, file, inode, file->f_pos, PAGE_SIZE, FUSE_READDIR); request_send(fc, req); nbytes = req->out.args[0].size; err = req->out.h.error; @@ -1173,22 +1204,12 @@ static int fuse_getattr(struct vfsmount *mnt, struct dentry *entry, struct kstat *stat) { struct inode *inode = entry->d_inode; - struct fuse_inode *fi = get_fuse_inode(inode); struct fuse_conn *fc = get_fuse_conn(inode); - int err; if (!fuse_allow_task(fc, current)) return -EACCES; - if (fi->i_time < get_jiffies_64()) - err = fuse_do_getattr(inode, stat, NULL); - else { - err = 0; - generic_fillattr(inode, stat); - stat->mode = fi->orig_i_mode; - } - - return err; + return fuse_update_attributes(inode, stat, NULL, NULL); } static int fuse_setxattr(struct dentry *entry, const char *name, diff --git a/fs/fuse/file.c b/fs/fuse/file.c index 0fcdba9..bb05d22 100644 --- a/fs/fuse/file.c +++ b/fs/fuse/file.c @@ -55,9 +55,10 @@ struct fuse_file *fuse_file_alloc(void) if (!ff->reserved_req) { kfree(ff); ff = NULL; + } else { + INIT_LIST_HEAD(&ff->write_entry); + atomic_set(&ff->count, 0); } - INIT_LIST_HEAD(&ff->write_entry); - atomic_set(&ff->count, 0); } return ff; } @@ -288,14 +289,16 @@ static int fuse_fsync(struct file *file, struct dentry *de, int datasync) return fuse_fsync_common(file, de, datasync, 0); } -void fuse_read_fill(struct fuse_req *req, struct fuse_file *ff, +void fuse_read_fill(struct fuse_req *req, struct file *file, struct inode *inode, loff_t pos, size_t count, int opcode) { struct fuse_read_in *inarg = &req->misc.read_in; + struct fuse_file *ff = file->private_data; inarg->fh = ff->fh; inarg->offset = pos; inarg->size = count; + inarg->flags = file->f_flags; req->in.h.opcode = opcode; req->in.h.nodeid = get_node_id(inode); req->in.numargs = 1; @@ -312,9 +315,8 @@ static size_t fuse_send_read(struct fuse_req *req, struct file *file, fl_owner_t owner) { struct fuse_conn *fc = get_fuse_conn(inode); - struct fuse_file *ff = file->private_data; - fuse_read_fill(req, ff, inode, pos, count, FUSE_READ); + fuse_read_fill(req, file, inode, pos, count, FUSE_READ); if (owner != NULL) { struct fuse_read_in *inarg = &req->misc.read_in; @@ -375,15 +377,16 @@ static void fuse_readpages_end(struct fuse_conn *fc, struct fuse_req *req) fuse_put_request(fc, req); } -static void fuse_send_readpages(struct fuse_req *req, struct fuse_file *ff, +static void fuse_send_readpages(struct fuse_req *req, struct file *file, struct inode *inode) { struct fuse_conn *fc = get_fuse_conn(inode); loff_t pos = page_offset(req->pages[0]); size_t count = req->num_pages << PAGE_CACHE_SHIFT; req->out.page_zeroing = 1; - fuse_read_fill(req, ff, inode, pos, count, FUSE_READ); + fuse_read_fill(req, file, inode, pos, count, FUSE_READ); if (fc->async_read) { + struct fuse_file *ff = file->private_data; req->ff = fuse_file_get(ff); req->end = fuse_readpages_end; request_send_background(fc, req); @@ -395,7 +398,7 @@ static void fuse_send_readpages(struct fuse_req *req, struct fuse_file *ff, struct fuse_fill_data { struct fuse_req *req; - struct fuse_file *ff; + struct file *file; struct inode *inode; }; @@ -410,7 +413,7 @@ static int fuse_readpages_fill(void *_data, struct page *page) (req->num_pages == FUSE_MAX_PAGES_PER_REQ || (req->num_pages + 1) * PAGE_CACHE_SIZE > fc->max_read || req->pages[req->num_pages - 1]->index + 1 != page->index)) { - fuse_send_readpages(req, data->ff, inode); + fuse_send_readpages(req, data->file, inode); data->req = req = fuse_get_req(fc); if (IS_ERR(req)) { unlock_page(page); @@ -434,7 +437,7 @@ static int fuse_readpages(struct file *file, struct address_space *mapping, if (is_bad_inode(inode)) goto out; - data.ff = file->private_data; + data.file = file; data.inode = inode; data.req = fuse_get_req(fc); err = PTR_ERR(data.req); @@ -444,7 +447,7 @@ static int fuse_readpages(struct file *file, struct address_space *mapping, err = read_cache_pages(mapping, pages, fuse_readpages_fill, &data); if (!err) { if (data.req->num_pages) - fuse_send_readpages(data.req, data.ff, inode); + fuse_send_readpages(data.req, file, inode); else fuse_put_request(fc, data.req); } @@ -452,11 +455,31 @@ out: return err; } -static void fuse_write_fill(struct fuse_req *req, struct fuse_file *ff, +static ssize_t fuse_file_aio_read(struct kiocb *iocb, const struct iovec *iov, + unsigned long nr_segs, loff_t pos) +{ + struct inode *inode = iocb->ki_filp->f_mapping->host; + + if (pos + iov_length(iov, nr_segs) > i_size_read(inode)) { + int err; + /* + * If trying to read past EOF, make sure the i_size + * attribute is up-to-date. + */ + err = fuse_update_attributes(inode, NULL, iocb->ki_filp, NULL); + if (err) + return err; + } + + return generic_file_aio_read(iocb, iov, nr_segs, pos); +} + +static void fuse_write_fill(struct fuse_req *req, struct file *file, struct inode *inode, loff_t pos, size_t count, int writepage) { struct fuse_conn *fc = get_fuse_conn(inode); + struct fuse_file *ff = file->private_data; struct fuse_write_in *inarg = &req->misc.write.in; struct fuse_write_out *outarg = &req->misc.write.out; @@ -465,6 +488,7 @@ static void fuse_write_fill(struct fuse_req *req, struct fuse_file *ff, inarg->offset = pos; inarg->size = count; inarg->write_flags = writepage ? FUSE_WRITE_CACHE : 0; + inarg->flags = file->f_flags; req->in.h.opcode = FUSE_WRITE; req->in.h.nodeid = get_node_id(inode); req->in.argpages = 1; @@ -485,7 +509,7 @@ static size_t fuse_send_write(struct fuse_req *req, struct file *file, fl_owner_t owner) { struct fuse_conn *fc = get_fuse_conn(inode); - fuse_write_fill(req, file->private_data, inode, pos, count, 0); + fuse_write_fill(req, file, inode, pos, count, 0); if (owner != NULL) { struct fuse_write_in *inarg = &req->misc.write.in; inarg->write_flags |= FUSE_WRITE_LOCKOWNER; @@ -886,7 +910,7 @@ static sector_t fuse_bmap(struct address_space *mapping, sector_t block) static const struct file_operations fuse_file_operations = { .llseek = generic_file_llseek, .read = do_sync_read, - .aio_read = generic_file_aio_read, + .aio_read = fuse_file_aio_read, .write = do_sync_write, .aio_write = generic_file_aio_write, .mmap = fuse_file_mmap, diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h index 6c5461d..3ab8a30 100644 --- a/fs/fuse/fuse_i.h +++ b/fs/fuse/fuse_i.h @@ -447,7 +447,7 @@ void fuse_send_forget(struct fuse_conn *fc, struct fuse_req *req, /** * Initialize READ or READDIR request */ -void fuse_read_fill(struct fuse_req *req, struct fuse_file *ff, +void fuse_read_fill(struct fuse_req *req, struct file *file, struct inode *inode, loff_t pos, size_t count, int opcode); /** @@ -593,3 +593,6 @@ int fuse_valid_type(int m); int fuse_allow_task(struct fuse_conn *fc, struct task_struct *task); u64 fuse_lock_owner_id(struct fuse_conn *fc, fl_owner_t id); + +int fuse_update_attributes(struct inode *inode, struct kstat *stat, + struct file *file, bool *refreshed); diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c index 9a68d69..84f9f7d 100644 --- a/fs/fuse/inode.c +++ b/fs/fuse/inode.c @@ -56,6 +56,7 @@ static struct inode *fuse_alloc_inode(struct super_block *sb) fi->i_time = 0; fi->nodeid = 0; fi->nlookup = 0; + fi->attr_version = 0; INIT_LIST_HEAD(&fi->write_files); fi->forget_req = fuse_request_alloc(); if (!fi->forget_req) { @@ -562,8 +563,7 @@ static void fuse_send_init(struct fuse_conn *fc, struct fuse_req *req) arg->major = FUSE_KERNEL_VERSION; arg->minor = FUSE_KERNEL_MINOR_VERSION; arg->max_readahead = fc->bdi.ra_pages * PAGE_CACHE_SIZE; - arg->flags |= FUSE_ASYNC_READ | FUSE_POSIX_LOCKS | FUSE_FILE_OPS | - FUSE_ATOMIC_O_TRUNC; + arg->flags |= FUSE_ASYNC_READ | FUSE_POSIX_LOCKS | FUSE_ATOMIC_O_TRUNC; req->in.h.opcode = FUSE_INIT; req->in.numargs = 1; req->in.args[0].size = sizeof(*arg); diff --git a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c index 12aca8e..09ee07f 100644 --- a/fs/hugetlbfs/inode.c +++ b/fs/hugetlbfs/inode.c @@ -364,7 +364,6 @@ static void truncate_hugepages(struct inode *inode, loff_t lstart) ++next; truncate_huge_page(page); unlock_page(page); - hugetlb_put_quota(mapping); freed++; } huge_pagevec_release(&pvec); @@ -859,15 +858,15 @@ out_free: return -ENOMEM; } -int hugetlb_get_quota(struct address_space *mapping) +int hugetlb_get_quota(struct address_space *mapping, long delta) { int ret = 0; struct hugetlbfs_sb_info *sbinfo = HUGETLBFS_SB(mapping->host->i_sb); if (sbinfo->free_blocks > -1) { spin_lock(&sbinfo->stat_lock); - if (sbinfo->free_blocks > 0) - sbinfo->free_blocks--; + if (sbinfo->free_blocks - delta >= 0) + sbinfo->free_blocks -= delta; else ret = -ENOMEM; spin_unlock(&sbinfo->stat_lock); @@ -876,13 +875,13 @@ int hugetlb_get_quota(struct address_space *mapping) return ret; } -void hugetlb_put_quota(struct address_space *mapping) +void hugetlb_put_quota(struct address_space *mapping, long delta) { struct hugetlbfs_sb_info *sbinfo = HUGETLBFS_SB(mapping->host->i_sb); if (sbinfo->free_blocks > -1) { spin_lock(&sbinfo->stat_lock); - sbinfo->free_blocks++; + sbinfo->free_blocks += delta; spin_unlock(&sbinfo->stat_lock); } } diff --git a/fs/ioprio.c b/fs/ioprio.c index d6ff77e..e4e01bc 100644 --- a/fs/ioprio.c +++ b/fs/ioprio.c @@ -78,6 +78,10 @@ asmlinkage long sys_ioprio_set(int which, int who, int ioprio) if (!capable(CAP_SYS_ADMIN)) return -EPERM; break; + case IOPRIO_CLASS_NONE: + if (data) + return -EINVAL; + break; default: return -EINVAL; } diff --git a/fs/jfs/ioctl.c b/fs/jfs/ioctl.c index 3c8663b..dfda12a 100644 --- a/fs/jfs/ioctl.c +++ b/fs/jfs/ioctl.c @@ -79,6 +79,9 @@ int jfs_ioctl(struct inode * inode, struct file * filp, unsigned int cmd, if (!S_ISDIR(inode->i_mode)) flags &= ~JFS_DIRSYNC_FL; + /* Is it quota file? Do not allow user to mess with it */ + if (IS_NOQUOTA(inode)) + return -EPERM; jfs_get_inode_flags(jfs_inode); oldflags = jfs_inode->mode2; diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c index 3533453..f697b5c 100644 --- a/fs/nfs/dir.c +++ b/fs/nfs/dir.c @@ -38,6 +38,7 @@ #include "nfs4_fs.h" #include "delegation.h" #include "iostat.h" +#include "internal.h" /* #define NFS_DEBUG_VERBOSE 1 */ diff --git a/fs/nfs/direct.c b/fs/nfs/direct.c index afcab00..5e8d82f 100644 --- a/fs/nfs/direct.c +++ b/fs/nfs/direct.c @@ -263,17 +263,19 @@ static const struct rpc_call_ops nfs_read_direct_ops = { * handled automatically by nfs_direct_read_result(). Otherwise, if * no requests have been sent, just return an error. */ -static ssize_t nfs_direct_read_schedule(struct nfs_direct_req *dreq, unsigned long user_addr, size_t count, loff_t pos) +static ssize_t nfs_direct_read_schedule_segment(struct nfs_direct_req *dreq, + const struct iovec *iov, + loff_t pos) { struct nfs_open_context *ctx = dreq->ctx; struct inode *inode = ctx->path.dentry->d_inode; + unsigned long user_addr = (unsigned long)iov->iov_base; + size_t count = iov->iov_len; size_t rsize = NFS_SERVER(inode)->rsize; unsigned int pgbase; int result; ssize_t started = 0; - get_dreq(dreq); - do { struct nfs_read_data *data; size_t bytes; @@ -347,15 +349,46 @@ static ssize_t nfs_direct_read_schedule(struct nfs_direct_req *dreq, unsigned lo count -= bytes; } while (count != 0); + if (started) + return started; + return result < 0 ? (ssize_t) result : -EFAULT; +} + +static ssize_t nfs_direct_read_schedule_iovec(struct nfs_direct_req *dreq, + const struct iovec *iov, + unsigned long nr_segs, + loff_t pos) +{ + ssize_t result = -EINVAL; + size_t requested_bytes = 0; + unsigned long seg; + + get_dreq(dreq); + + for (seg = 0; seg < nr_segs; seg++) { + const struct iovec *vec = &iov[seg]; + result = nfs_direct_read_schedule_segment(dreq, vec, pos); + if (result < 0) + break; + requested_bytes += result; + if ((size_t)result < vec->iov_len) + break; + pos += vec->iov_len; + } + if (put_dreq(dreq)) nfs_direct_complete(dreq); - if (started) + if (requested_bytes != 0) return 0; - return result < 0 ? (ssize_t) result : -EFAULT; + + if (result < 0) + return result; + return -EIO; } -static ssize_t nfs_direct_read(struct kiocb *iocb, unsigned long user_addr, size_t count, loff_t pos) +static ssize_t nfs_direct_read(struct kiocb *iocb, const struct iovec *iov, + unsigned long nr_segs, loff_t pos) { ssize_t result = 0; sigset_t oldset; @@ -372,9 +405,8 @@ static ssize_t nfs_direct_read(struct kiocb *iocb, unsigned long user_addr, size if (!is_sync_kiocb(iocb)) dreq->iocb = iocb; - nfs_add_stats(inode, NFSIOS_DIRECTREADBYTES, count); rpc_clnt_sigmask(clnt, &oldset); - result = nfs_direct_read_schedule(dreq, user_addr, count, pos); + result = nfs_direct_read_schedule_iovec(dreq, iov, nr_segs, pos); if (!result) result = nfs_direct_wait(dreq); rpc_clnt_sigunmask(clnt, &oldset); @@ -601,17 +633,19 @@ static const struct rpc_call_ops nfs_write_direct_ops = { * handled automatically by nfs_direct_write_result(). Otherwise, if * no requests have been sent, just return an error. */ -static ssize_t nfs_direct_write_schedule(struct nfs_direct_req *dreq, unsigned long user_addr, size_t count, loff_t pos, int sync) +static ssize_t nfs_direct_write_schedule_segment(struct nfs_direct_req *dreq, + const struct iovec *iov, + loff_t pos, int sync) { struct nfs_open_context *ctx = dreq->ctx; struct inode *inode = ctx->path.dentry->d_inode; + unsigned long user_addr = (unsigned long)iov->iov_base; + size_t count = iov->iov_len; size_t wsize = NFS_SERVER(inode)->wsize; unsigned int pgbase; int result; ssize_t started = 0; - get_dreq(dreq); - do { struct nfs_write_data *data; size_t bytes; @@ -689,15 +723,48 @@ static ssize_t nfs_direct_write_schedule(struct nfs_direct_req *dreq, unsigned l count -= bytes; } while (count != 0); + if (started) + return started; + return result < 0 ? (ssize_t) result : -EFAULT; +} + +static ssize_t nfs_direct_write_schedule_iovec(struct nfs_direct_req *dreq, + const struct iovec *iov, + unsigned long nr_segs, + loff_t pos, int sync) +{ + ssize_t result = 0; + size_t requested_bytes = 0; + unsigned long seg; + + get_dreq(dreq); + + for (seg = 0; seg < nr_segs; seg++) { + const struct iovec *vec = &iov[seg]; + result = nfs_direct_write_schedule_segment(dreq, vec, + pos, sync); + if (result < 0) + break; + requested_bytes += result; + if ((size_t)result < vec->iov_len) + break; + pos += vec->iov_len; + } + if (put_dreq(dreq)) - nfs_direct_write_complete(dreq, inode); + nfs_direct_write_complete(dreq, dreq->inode); - if (started) + if (requested_bytes != 0) return 0; - return result < 0 ? (ssize_t) result : -EFAULT; + + if (result < 0) + return result; + return -EIO; } -static ssize_t nfs_direct_write(struct kiocb *iocb, unsigned long user_addr, size_t count, loff_t pos) +static ssize_t nfs_direct_write(struct kiocb *iocb, const struct iovec *iov, + unsigned long nr_segs, loff_t pos, + size_t count) { ssize_t result = 0; sigset_t oldset; @@ -720,10 +787,8 @@ static ssize_t nfs_direct_write(struct kiocb *iocb, unsigned long user_addr, siz if (!is_sync_kiocb(iocb)) dreq->iocb = iocb; - nfs_add_stats(inode, NFSIOS_DIRECTWRITTENBYTES, count); - rpc_clnt_sigmask(clnt, &oldset); - result = nfs_direct_write_schedule(dreq, user_addr, count, pos, sync); + result = nfs_direct_write_schedule_iovec(dreq, iov, nr_segs, pos, sync); if (!result) result = nfs_direct_wait(dreq); rpc_clnt_sigunmask(clnt, &oldset); @@ -759,21 +824,16 @@ ssize_t nfs_file_direct_read(struct kiocb *iocb, const struct iovec *iov, ssize_t retval = -EINVAL; struct file *file = iocb->ki_filp; struct address_space *mapping = file->f_mapping; - /* XXX: temporary */ - const char __user *buf = iov[0].iov_base; - size_t count = iov[0].iov_len; + size_t count; + + count = iov_length(iov, nr_segs); + nfs_add_stats(mapping->host, NFSIOS_DIRECTREADBYTES, count); - dprintk("nfs: direct read(%s/%s, %lu@%Ld)\n", + dprintk("nfs: direct read(%s/%s, %zd@%Ld)\n", file->f_path.dentry->d_parent->d_name.name, file->f_path.dentry->d_name.name, - (unsigned long) count, (long long) pos); - - if (nr_segs != 1) - goto out; + count, (long long) pos); - retval = -EFAULT; - if (!access_ok(VERIFY_WRITE, buf, count)) - goto out; retval = 0; if (!count) goto out; @@ -782,7 +842,7 @@ ssize_t nfs_file_direct_read(struct kiocb *iocb, const struct iovec *iov, if (retval) goto out; - retval = nfs_direct_read(iocb, (unsigned long) buf, count, pos); + retval = nfs_direct_read(iocb, iov, nr_segs, pos); if (retval > 0) iocb->ki_pos = pos + retval; @@ -821,21 +881,21 @@ ssize_t nfs_file_direct_write(struct kiocb *iocb, const struct iovec *iov, ssize_t retval = -EINVAL; struct file *file = iocb->ki_filp; struct address_space *mapping = file->f_mapping; - /* XXX: temporary */ - const char __user *buf = iov[0].iov_base; - size_t count = iov[0].iov_len; + size_t count; + + count = iov_length(iov, nr_segs); + nfs_add_stats(mapping->host, NFSIOS_DIRECTWRITTENBYTES, count); - dprintk("nfs: direct write(%s/%s, %lu@%Ld)\n", + dfprintk(VFS, "nfs: direct write(%s/%s, %zd@%Ld)\n", file->f_path.dentry->d_parent->d_name.name, file->f_path.dentry->d_name.name, - (unsigned long) count, (long long) pos); - - if (nr_segs != 1) - goto out; + count, (long long) pos); retval = generic_write_checks(file, &pos, &count, 0); if (retval) goto out; + if (!count) + goto out; /* return 0 */ retval = -EINVAL; if ((ssize_t) count < 0) @@ -844,15 +904,11 @@ ssize_t nfs_file_direct_write(struct kiocb *iocb, const struct iovec *iov, if (!count) goto out; - retval = -EFAULT; - if (!access_ok(VERIFY_READ, buf, count)) - goto out; - retval = nfs_sync_mapping(mapping); if (retval) goto out; - retval = nfs_direct_write(iocb, (unsigned long) buf, count, pos); + retval = nfs_direct_write(iocb, iov, nr_segs, pos, count); if (retval > 0) iocb->ki_pos = pos + retval; diff --git a/fs/nfs/getroot.c b/fs/nfs/getroot.c index 522e5ad..0ee4384 100644 --- a/fs/nfs/getroot.c +++ b/fs/nfs/getroot.c @@ -43,6 +43,25 @@ #define NFSDBG_FACILITY NFSDBG_CLIENT /* + * Set the superblock root dentry. + * Note that this function frees the inode in case of error. + */ +static int nfs_superblock_set_dummy_root(struct super_block *sb, struct inode *inode) +{ + /* The mntroot acts as the dummy root dentry for this superblock */ + if (sb->s_root == NULL) { + sb->s_root = d_alloc_root(inode); + if (sb->s_root == NULL) { + iput(inode); + return -ENOMEM; + } + /* Circumvent igrab(): we know the inode is not being freed */ + atomic_inc(&inode->i_count); + } + return 0; +} + +/* * get an NFS2/NFS3 root dentry from the root filehandle */ struct dentry *nfs_get_root(struct super_block *sb, struct nfs_fh *mntfh) @@ -54,33 +73,6 @@ struct dentry *nfs_get_root(struct super_block *sb, struct nfs_fh *mntfh) struct inode *inode; int error; - /* create a dummy root dentry with dummy inode for this superblock */ - if (!sb->s_root) { - struct nfs_fh dummyfh; - struct dentry *root; - struct inode *iroot; - - memset(&dummyfh, 0, sizeof(dummyfh)); - memset(&fattr, 0, sizeof(fattr)); - nfs_fattr_init(&fattr); - fattr.valid = NFS_ATTR_FATTR; - fattr.type = NFDIR; - fattr.mode = S_IFDIR | S_IRUSR | S_IWUSR; - fattr.nlink = 2; - - iroot = nfs_fhget(sb, &dummyfh, &fattr); - if (IS_ERR(iroot)) - return ERR_PTR(PTR_ERR(iroot)); - - root = d_alloc_root(iroot); - if (!root) { - iput(iroot); - return ERR_PTR(-ENOMEM); - } - - sb->s_root = root; - } - /* get the actual root for this mount */ fsinfo.fattr = &fattr; @@ -96,6 +88,10 @@ struct dentry *nfs_get_root(struct super_block *sb, struct nfs_fh *mntfh) return ERR_PTR(PTR_ERR(inode)); } + error = nfs_superblock_set_dummy_root(sb, inode); + if (error != 0) + return ERR_PTR(error); + /* root dentries normally start off anonymous and get spliced in later * if the dentry tree reaches them; however if the dentry already * exists, we'll pick it up at this point and use it as the root @@ -241,33 +237,6 @@ struct dentry *nfs4_get_root(struct super_block *sb, struct nfs_fh *mntfh) dprintk("--> nfs4_get_root()\n"); - /* create a dummy root dentry with dummy inode for this superblock */ - if (!sb->s_root) { - struct nfs_fh dummyfh; - struct dentry *root; - struct inode *iroot; - - memset(&dummyfh, 0, sizeof(dummyfh)); - memset(&fattr, 0, sizeof(fattr)); - nfs_fattr_init(&fattr); - fattr.valid = NFS_ATTR_FATTR; - fattr.type = NFDIR; - fattr.mode = S_IFDIR | S_IRUSR | S_IWUSR; - fattr.nlink = 2; - - iroot = nfs_fhget(sb, &dummyfh, &fattr); - if (IS_ERR(iroot)) - return ERR_PTR(PTR_ERR(iroot)); - - root = d_alloc_root(iroot); - if (!root) { - iput(iroot); - return ERR_PTR(-ENOMEM); - } - - sb->s_root = root; - } - /* get the info about the server and filesystem */ error = nfs4_server_capabilities(server, mntfh); if (error < 0) { @@ -289,6 +258,10 @@ struct dentry *nfs4_get_root(struct super_block *sb, struct nfs_fh *mntfh) return ERR_PTR(PTR_ERR(inode)); } + error = nfs_superblock_set_dummy_root(sb, inode); + if (error != 0) + return ERR_PTR(error); + /* root dentries normally start off anonymous and get spliced in later * if the dentry tree reaches them; however if the dentry already * exists, we'll pick it up at this point and use it as the root diff --git a/fs/nfs/super.c b/fs/nfs/super.c index fa517ae..2426e71 100644 --- a/fs/nfs/super.c +++ b/fs/nfs/super.c @@ -1054,10 +1054,11 @@ static int nfs_validate_mount_data(void *options, { struct nfs_mount_data *data = (struct nfs_mount_data *)options; + memset(args, 0, sizeof(*args)); + if (data == NULL) goto out_no_data; - memset(args, 0, sizeof(*args)); args->flags = (NFS_MOUNT_VER3 | NFS_MOUNT_TCP); args->rsize = NFS_MAX_FILE_IO_SIZE; args->wsize = NFS_MAX_FILE_IO_SIZE; @@ -1474,6 +1475,11 @@ static int nfs_xdev_get_sb(struct file_system_type *fs_type, int flags, error = PTR_ERR(mntroot); goto error_splat_super; } + if (mntroot->d_inode->i_op != &nfs_dir_inode_operations) { + dput(mntroot); + error = -ESTALE; + goto error_splat_super; + } s->s_flags |= MS_ACTIVE; mnt->mnt_sb = s; @@ -1531,10 +1537,11 @@ static int nfs4_validate_mount_data(void *options, struct nfs4_mount_data *data = (struct nfs4_mount_data *)options; char *c; + memset(args, 0, sizeof(*args)); + if (data == NULL) goto out_no_data; - memset(args, 0, sizeof(*args)); args->rsize = NFS_MAX_FILE_IO_SIZE; args->wsize = NFS_MAX_FILE_IO_SIZE; args->timeo = 600; diff --git a/fs/nfs/write.c b/fs/nfs/write.c index 89527a4..51cc1bd 100644 --- a/fs/nfs/write.c +++ b/fs/nfs/write.c @@ -1436,7 +1436,8 @@ out: return ret; } -int nfs_wb_page_priority(struct inode *inode, struct page *page, int how) +static int nfs_wb_page_priority(struct inode *inode, struct page *page, + int how) { loff_t range_start = page_offset(page); loff_t range_end = range_start + (loff_t)(PAGE_CACHE_SIZE - 1); diff --git a/fs/nfsd/nfs2acl.c b/fs/nfsd/nfs2acl.c index b617428..0e5fa11 100644 --- a/fs/nfsd/nfs2acl.c +++ b/fs/nfsd/nfs2acl.c @@ -41,7 +41,7 @@ static __be32 nfsacld_proc_getacl(struct svc_rqst * rqstp, fh = fh_copy(&resp->fh, &argp->fh); if ((nfserr = fh_verify(rqstp, &resp->fh, 0, MAY_NOP))) - RETURN_STATUS(nfserr_inval); + RETURN_STATUS(nfserr); if (argp->mask & ~(NFS_ACL|NFS_ACLCNT|NFS_DFACL|NFS_DFACLCNT)) RETURN_STATUS(nfserr_inval); diff --git a/fs/nfsd/nfs3acl.c b/fs/nfsd/nfs3acl.c index 3e3f2de..b647f2f 100644 --- a/fs/nfsd/nfs3acl.c +++ b/fs/nfsd/nfs3acl.c @@ -37,7 +37,7 @@ static __be32 nfsd3_proc_getacl(struct svc_rqst * rqstp, fh = fh_copy(&resp->fh, &argp->fh); if ((nfserr = fh_verify(rqstp, &resp->fh, 0, MAY_NOP))) - RETURN_STATUS(nfserr_inval); + RETURN_STATUS(nfserr); if (argp->mask & ~(NFS_ACL|NFS_ACLCNT|NFS_DFACL|NFS_DFACLCNT)) RETURN_STATUS(nfserr_inval); diff --git a/fs/nfsd/nfsfh.c b/fs/nfsd/nfsfh.c index 4f712e9..468f17a 100644 --- a/fs/nfsd/nfsfh.c +++ b/fs/nfsd/nfsfh.c @@ -95,6 +95,22 @@ nfsd_mode_check(struct svc_rqst *rqstp, umode_t mode, int type) return 0; } +static __be32 nfsd_setuser_and_check_port(struct svc_rqst *rqstp, + struct svc_export *exp) +{ + /* Check if the request originated from a secure port. */ + if (!rqstp->rq_secure && EX_SECURE(exp)) { + char buf[RPC_MAX_ADDRBUFLEN]; + dprintk(KERN_WARNING + "nfsd: request from insecure port %s!\n", + svc_print_addr(rqstp, buf, sizeof(buf))); + return nfserr_perm; + } + + /* Set user creds for this exportpoint */ + return nfserrno(nfsd_setuser(rqstp, exp)); +} + /* * Perform sanity checks on the dentry in a client's file handle. * @@ -167,18 +183,7 @@ fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, int access) goto out; } - /* Check if the request originated from a secure port. */ - error = nfserr_perm; - if (!rqstp->rq_secure && EX_SECURE(exp)) { - char buf[RPC_MAX_ADDRBUFLEN]; - printk(KERN_WARNING - "nfsd: request from insecure port %s!\n", - svc_print_addr(rqstp, buf, sizeof(buf))); - goto out; - } - - /* Set user creds for this exportpoint */ - error = nfserrno(nfsd_setuser(rqstp, exp)); + error = nfsd_setuser_and_check_port(rqstp, exp); if (error) goto out; @@ -227,18 +232,22 @@ fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, int access) fhp->fh_export = exp; nfsd_nr_verified++; } else { - /* just rechecking permissions - * (e.g. nfsproc_create calls fh_verify, then nfsd_create does as well) + /* + * just rechecking permissions + * (e.g. nfsproc_create calls fh_verify, then nfsd_create + * does as well) */ dprintk("nfsd: fh_verify - just checking\n"); dentry = fhp->fh_dentry; exp = fhp->fh_export; - /* Set user creds for this exportpoint; necessary even + /* + * Set user creds for this exportpoint; necessary even * in the "just checking" case because this may be a * filehandle that was created by fh_compose, and that * is about to be used in another nfsv4 compound - * operation */ - error = nfserrno(nfsd_setuser(rqstp, exp)); + * operation. + */ + error = nfsd_setuser_and_check_port(rqstp, exp); if (error) goto out; } diff --git a/fs/ocfs2/alloc.c b/fs/ocfs2/alloc.c index 4ba7f0b..ce62c15 100644 --- a/fs/ocfs2/alloc.c +++ b/fs/ocfs2/alloc.c @@ -3946,7 +3946,7 @@ static int __ocfs2_mark_extent_written(struct inode *inode, struct ocfs2_merge_ctxt ctxt; struct ocfs2_extent_list *rightmost_el; - if (!rec->e_flags & OCFS2_EXT_UNWRITTEN) { + if (!(rec->e_flags & OCFS2_EXT_UNWRITTEN)) { ret = -EIO; mlog_errno(ret); goto out; diff --git a/fs/ocfs2/aops.c b/fs/ocfs2/aops.c index c69c1b3..56f7790 100644 --- a/fs/ocfs2/aops.c +++ b/fs/ocfs2/aops.c @@ -729,6 +729,27 @@ static void ocfs2_clear_page_regions(struct page *page, } /* + * Nonsparse file systems fully allocate before we get to the write + * code. This prevents ocfs2_write() from tagging the write as an + * allocating one, which means ocfs2_map_page_blocks() might try to + * read-in the blocks at the tail of our file. Avoid reading them by + * testing i_size against each block offset. + */ +static int ocfs2_should_read_blk(struct inode *inode, struct page *page, + unsigned int block_start) +{ + u64 offset = page_offset(page) + block_start; + + if (ocfs2_sparse_alloc(OCFS2_SB(inode->i_sb))) + return 1; + + if (i_size_read(inode) > offset) + return 1; + + return 0; +} + +/* * Some of this taken from block_prepare_write(). We already have our * mapping by now though, and the entire write will be allocating or * it won't, so not much need to use BH_New. @@ -781,6 +802,7 @@ int ocfs2_map_page_blocks(struct page *page, u64 *p_blkno, set_buffer_uptodate(bh); } else if (!buffer_uptodate(bh) && !buffer_delay(bh) && !buffer_new(bh) && + ocfs2_should_read_blk(inode, page, block_start) && (block_start < from || block_end > to)) { ll_rw_block(READ, 1, &bh); *wait_bh++=bh; @@ -1492,7 +1514,7 @@ int ocfs2_size_fits_inline_data(struct buffer_head *di_bh, u64 new_size) { struct ocfs2_dinode *di = (struct ocfs2_dinode *)di_bh->b_data; - if (new_size < le16_to_cpu(di->id2.i_data.id_count)) + if (new_size <= le16_to_cpu(di->id2.i_data.id_count)) return 1; return 0; } diff --git a/fs/ocfs2/cluster/heartbeat.c b/fs/ocfs2/cluster/heartbeat.c index 9cc7c04..f02ccb3 100644 --- a/fs/ocfs2/cluster/heartbeat.c +++ b/fs/ocfs2/cluster/heartbeat.c @@ -267,7 +267,7 @@ static struct bio *o2hb_setup_one_bio(struct o2hb_region *reg, current_page = cs / spp; page = reg->hr_slot_data[current_page]; - vec_len = min(PAGE_CACHE_SIZE, + vec_len = min(PAGE_CACHE_SIZE - vec_start, (max_slots-cs) * (PAGE_CACHE_SIZE/spp) ); mlog(ML_HB_BIO, "page %d, vec_len = %u, vec_start = %u\n", diff --git a/fs/ocfs2/cluster/masklog.h b/fs/ocfs2/cluster/masklog.h index cd04606..597e064 100644 --- a/fs/ocfs2/cluster/masklog.h +++ b/fs/ocfs2/cluster/masklog.h @@ -212,7 +212,7 @@ extern struct mlog_bits mlog_and_bits, mlog_not_bits; #define mlog_errno(st) do { \ int _st = (st); \ if (_st != -ERESTARTSYS && _st != -EINTR && \ - _st != AOP_TRUNCATED_PAGE) \ + _st != AOP_TRUNCATED_PAGE && _st != -ENOSPC) \ mlog(ML_ERROR, "status = %lld\n", (long long)_st); \ } while (0) diff --git a/fs/ocfs2/cluster/tcp.c b/fs/ocfs2/cluster/tcp.c index 685c180..d84bd15 100644 --- a/fs/ocfs2/cluster/tcp.c +++ b/fs/ocfs2/cluster/tcp.c @@ -58,6 +58,7 @@ #include <linux/slab.h> #include <linux/idr.h> #include <linux/kref.h> +#include <linux/net.h> #include <net/tcp.h> #include <asm/uaccess.h> @@ -616,8 +617,7 @@ static void o2net_shutdown_sc(struct work_struct *work) del_timer_sync(&sc->sc_idle_timeout); o2net_sc_cancel_delayed_work(sc, &sc->sc_keepalive_work); sc_put(sc); - sc->sc_sock->ops->shutdown(sc->sc_sock, - RCV_SHUTDOWN|SEND_SHUTDOWN); + kernel_sock_shutdown(sc->sc_sock, SHUT_RDWR); } /* not fatal so failed connects before the other guy has our diff --git a/fs/ocfs2/dcache.c b/fs/ocfs2/dcache.c index 3094ddb..9923278 100644 --- a/fs/ocfs2/dcache.c +++ b/fs/ocfs2/dcache.c @@ -318,9 +318,9 @@ out_attach: static void ocfs2_drop_dentry_lock(struct ocfs2_super *osb, struct ocfs2_dentry_lock *dl) { + iput(dl->dl_inode); ocfs2_simple_drop_lockres(osb, &dl->dl_lockres); ocfs2_lock_res_free(&dl->dl_lockres); - iput(dl->dl_inode); kfree(dl); } @@ -344,12 +344,24 @@ static void ocfs2_dentry_iput(struct dentry *dentry, struct inode *inode) { struct ocfs2_dentry_lock *dl = dentry->d_fsdata; - mlog_bug_on_msg(!dl && !(dentry->d_flags & DCACHE_DISCONNECTED), - "dentry: %.*s\n", dentry->d_name.len, - dentry->d_name.name); + if (!dl) { + /* + * No dentry lock is ok if we're disconnected or + * unhashed. + */ + if (!(dentry->d_flags & DCACHE_DISCONNECTED) && + !d_unhashed(dentry)) { + unsigned long long ino = 0ULL; + if (inode) + ino = (unsigned long long)OCFS2_I(inode)->ip_blkno; + mlog(ML_ERROR, "Dentry is missing cluster lock. " + "inode: %llu, d_flags: 0x%x, d_name: %.*s\n", + ino, dentry->d_flags, dentry->d_name.len, + dentry->d_name.name); + } - if (!dl) goto out; + } mlog_bug_on_msg(dl->dl_count == 0, "dentry: %.*s, count: %u\n", dentry->d_name.len, dentry->d_name.name, diff --git a/fs/ocfs2/dir.c b/fs/ocfs2/dir.c index 6a2f143..63b28fd 100644 --- a/fs/ocfs2/dir.c +++ b/fs/ocfs2/dir.c @@ -208,9 +208,9 @@ out: return NULL; } -struct buffer_head *ocfs2_find_entry_el(const char *name, int namelen, - struct inode *dir, - struct ocfs2_dir_entry **res_dir) +static struct buffer_head *ocfs2_find_entry_el(const char *name, int namelen, + struct inode *dir, + struct ocfs2_dir_entry **res_dir) { struct super_block *sb; struct buffer_head *bh_use[NAMEI_RA_SIZE]; diff --git a/fs/ocfs2/dlm/dlmmaster.c b/fs/ocfs2/dlm/dlmmaster.c index 62e4a7d..a54d33d 100644 --- a/fs/ocfs2/dlm/dlmmaster.c +++ b/fs/ocfs2/dlm/dlmmaster.c @@ -908,7 +908,7 @@ lookup: * but they might own this lockres. wait on them. */ bit = find_next_bit(dlm->recovery_map, O2NM_MAX_NODES, 0); if (bit < O2NM_MAX_NODES) { - mlog(ML_NOTICE, "%s:%.*s: at least one node (%d) to" + mlog(ML_NOTICE, "%s:%.*s: at least one node (%d) to " "recover before lock mastery can begin\n", dlm->name, namelen, (char *)lockid, bit); wait_on_recovery = 1; @@ -962,7 +962,7 @@ redo_request: spin_lock(&dlm->spinlock); bit = find_next_bit(dlm->recovery_map, O2NM_MAX_NODES, 0); if (bit < O2NM_MAX_NODES) { - mlog(ML_NOTICE, "%s:%.*s: at least one node (%d) to" + mlog(ML_NOTICE, "%s:%.*s: at least one node (%d) to " "recover before lock mastery can begin\n", dlm->name, namelen, (char *)lockid, bit); wait_on_recovery = 1; diff --git a/fs/ocfs2/dlmglue.c b/fs/ocfs2/dlmglue.c index 41c76ff..4e97dcc 100644 --- a/fs/ocfs2/dlmglue.c +++ b/fs/ocfs2/dlmglue.c @@ -670,7 +670,7 @@ static inline void ocfs2_generic_handle_attach_action(struct ocfs2_lock_res *loc { mlog_entry_void(); - BUG_ON((!lockres->l_flags & OCFS2_LOCK_BUSY)); + BUG_ON((!(lockres->l_flags & OCFS2_LOCK_BUSY))); BUG_ON(lockres->l_flags & OCFS2_LOCK_ATTACHED); if (lockres->l_requested > LKM_NLMODE && @@ -980,18 +980,6 @@ again: goto unlock; } - if (!(lockres->l_flags & OCFS2_LOCK_ATTACHED)) { - /* lock has not been created yet. */ - spin_unlock_irqrestore(&lockres->l_lock, flags); - - ret = ocfs2_lock_create(osb, lockres, LKM_NLMODE, 0); - if (ret < 0) { - mlog_errno(ret); - goto out; - } - goto again; - } - if (lockres->l_flags & OCFS2_LOCK_BLOCKED && !ocfs2_may_continue_on_blocked_lock(lockres, level)) { /* is the lock is currently blocked on behalf of @@ -1006,7 +994,14 @@ again: mlog(ML_ERROR, "lockres %s has action %u pending\n", lockres->l_name, lockres->l_action); - lockres->l_action = OCFS2_AST_CONVERT; + if (!(lockres->l_flags & OCFS2_LOCK_ATTACHED)) { + lockres->l_action = OCFS2_AST_ATTACH; + lkm_flags &= ~LKM_CONVERT; + } else { + lockres->l_action = OCFS2_AST_CONVERT; + lkm_flags |= LKM_CONVERT; + } + lockres->l_requested = level; lockres_or_flags(lockres, OCFS2_LOCK_BUSY); spin_unlock_irqrestore(&lockres->l_lock, flags); @@ -1021,7 +1016,7 @@ again: status = dlmlock(osb->dlm, level, &lockres->l_lksb, - lkm_flags|LKM_CONVERT, + lkm_flags, lockres->l_name, OCFS2_LOCK_ID_MAX_LEN - 1, ocfs2_locking_ast, diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c index f92fe91..b75b2e1 100644 --- a/fs/ocfs2/file.c +++ b/fs/ocfs2/file.c @@ -399,7 +399,7 @@ static int ocfs2_truncate_file(struct inode *inode, if (OCFS2_I(inode)->ip_dyn_features & OCFS2_INLINE_DATA_FL) { status = ocfs2_truncate_inline(inode, di_bh, new_i_size, - i_size_read(inode), 0); + i_size_read(inode), 1); if (status) mlog_errno(status); @@ -1521,6 +1521,7 @@ static int ocfs2_remove_inode_range(struct inode *inode, u32 trunc_start, trunc_len, cpos, phys_cpos, alloc_size; struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); struct ocfs2_cached_dealloc_ctxt dealloc; + struct address_space *mapping = inode->i_mapping; ocfs2_init_dealloc_ctxt(&dealloc); @@ -1529,10 +1530,20 @@ static int ocfs2_remove_inode_range(struct inode *inode, if (OCFS2_I(inode)->ip_dyn_features & OCFS2_INLINE_DATA_FL) { ret = ocfs2_truncate_inline(inode, di_bh, byte_start, - byte_start + byte_len, 1); - if (ret) + byte_start + byte_len, 0); + if (ret) { mlog_errno(ret); - return ret; + goto out; + } + /* + * There's no need to get fancy with the page cache + * truncate of an inline-data inode. We're talking + * about less than a page here, which will be cached + * in the dinode buffer anyway. + */ + unmap_mapping_range(mapping, 0, 0, 0); + truncate_inode_pages(mapping, 0); + goto out; } trunc_start = ocfs2_clusters_for_bytes(osb->sb, byte_start); @@ -1891,9 +1902,11 @@ static ssize_t ocfs2_file_aio_write(struct kiocb *iocb, ssize_t written = 0; size_t ocount; /* original count */ size_t count; /* after file limit checks */ - loff_t *ppos = &iocb->ki_pos; + loff_t old_size, *ppos = &iocb->ki_pos; + u32 old_clusters; struct file *file = iocb->ki_filp; struct inode *inode = file->f_path.dentry->d_inode; + struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); mlog_entry("(0x%p, %u, '%.*s')\n", file, (unsigned int)nr_segs, @@ -1949,6 +1962,13 @@ relock: goto relock; } + /* + * To later detect whether a journal commit for sync writes is + * necessary, we sample i_size, and cluster count here. + */ + old_size = i_size_read(inode); + old_clusters = OCFS2_I(inode)->ip_clusters; + /* communicate with ocfs2_dio_end_io */ ocfs2_iocb_set_rw_locked(iocb, rw_level); @@ -1978,6 +1998,21 @@ out_dio: /* buffered aio wouldn't have proper lock coverage today */ BUG_ON(ret == -EIOCBQUEUED && !(file->f_flags & O_DIRECT)); + if ((file->f_flags & O_SYNC && !direct_io) || IS_SYNC(inode)) { + /* + * The generic write paths have handled getting data + * to disk, but since we don't make use of the dirty + * inode list, a manual journal commit is necessary + * here. + */ + if (old_size != i_size_read(inode) || + old_clusters != OCFS2_I(inode)->ip_clusters) { + ret = journal_force_commit(osb->journal->j_journal); + if (ret < 0) + written = ret; + } + } + /* * deep in g_f_a_w_n()->ocfs2_direct_IO we pass in a ocfs2_dio_end_io * function pointer which is called when o_direct io completes so that diff --git a/fs/ocfs2/inode.c b/fs/ocfs2/inode.c index 1d5e0cb..ebb2bbe 100644 --- a/fs/ocfs2/inode.c +++ b/fs/ocfs2/inode.c @@ -455,8 +455,8 @@ static int ocfs2_read_locked_inode(struct inode *inode, status = -EINVAL; fe = (struct ocfs2_dinode *) bh->b_data; if (!OCFS2_IS_VALID_DINODE(fe)) { - mlog(ML_ERROR, "Invalid dinode #%llu: signature = %.*s\n", - (unsigned long long)le64_to_cpu(fe->i_blkno), 7, + mlog(0, "Invalid dinode #%llu: signature = %.*s\n", + (unsigned long long)args->fi_blkno, 7, fe->i_signature); goto bail; } @@ -863,7 +863,7 @@ static int ocfs2_query_inode_wipe(struct inode *inode, status = ocfs2_try_open_lock(inode, 1); if (status == -EAGAIN) { status = 0; - mlog(0, "Skipping delete of %llu because it is in use on" + mlog(0, "Skipping delete of %llu because it is in use on " "other nodes\n", (unsigned long long)oi->ip_blkno); goto bail; } diff --git a/fs/ocfs2/localalloc.c b/fs/ocfs2/localalloc.c index d272847..58ea88b 100644 --- a/fs/ocfs2/localalloc.c +++ b/fs/ocfs2/localalloc.c @@ -484,6 +484,7 @@ int ocfs2_reserve_local_alloc_bits(struct ocfs2_super *osb, alloc = (struct ocfs2_dinode *) osb->local_alloc_bh->b_data; +#ifdef OCFS2_DEBUG_FS if (le32_to_cpu(alloc->id1.bitmap1.i_used) != ocfs2_local_alloc_count_bits(alloc)) { ocfs2_error(osb->sb, "local alloc inode %llu says it has " @@ -494,6 +495,7 @@ int ocfs2_reserve_local_alloc_bits(struct ocfs2_super *osb, status = -EIO; goto bail; } +#endif free_bits = le32_to_cpu(alloc->id1.bitmap1.i_total) - le32_to_cpu(alloc->id1.bitmap1.i_used); @@ -712,9 +714,8 @@ static int ocfs2_sync_local_to_main(struct ocfs2_super *osb, void *bitmap; struct ocfs2_local_alloc *la = OCFS2_LOCAL_ALLOC(alloc); - mlog_entry("total = %u, COUNT = %u, used = %u\n", + mlog_entry("total = %u, used = %u\n", le32_to_cpu(alloc->id1.bitmap1.i_total), - ocfs2_local_alloc_count_bits(alloc), le32_to_cpu(alloc->id1.bitmap1.i_used)); if (!alloc->id1.bitmap1.i_total) { diff --git a/fs/ocfs2/namei.c b/fs/ocfs2/namei.c index 7292590..989ac27 100644 --- a/fs/ocfs2/namei.c +++ b/fs/ocfs2/namei.c @@ -1105,9 +1105,16 @@ static int ocfs2_rename(struct inode *old_dir, goto bail; } - if (!new_de && new_inode) - mlog(ML_ERROR, "inode %lu does not exist in it's parent " - "directory!", new_inode->i_ino); + if (!new_de && new_inode) { + /* + * Target was unlinked by another node while we were + * waiting to get to ocfs2_rename(). There isn't + * anything we can do here to help the situation, so + * bubble up the appropriate error. + */ + status = -ENOENT; + goto bail; + } /* In case we need to overwrite an existing file, we blow it * away first */ diff --git a/fs/ocfs2/super.c b/fs/ocfs2/super.c index be562ac..5ee7754 100644 --- a/fs/ocfs2/super.c +++ b/fs/ocfs2/super.c @@ -438,14 +438,14 @@ unlock_osb: } if (!ret) { - if (!ocfs2_is_hard_readonly(osb)) - ocfs2_set_journal_params(osb); - /* Only save off the new mount options in case of a successful * remount. */ osb->s_mount_opt = parsed_options.mount_opt; osb->s_atime_quantum = parsed_options.atime_quantum; osb->preferred_slot = parsed_options.slot; + + if (!ocfs2_is_hard_readonly(osb)) + ocfs2_set_journal_params(osb); } out: return ret; @@ -1061,7 +1061,7 @@ asmlinkage long sys_open(const char __user *filename, int flags, int mode) prevent_tail_call(ret); return ret; } -EXPORT_SYMBOL_GPL(sys_open); +EXPORT_UNUSED_SYMBOL_GPL(sys_open); /* To be deleted for 2.6.25 */ asmlinkage long sys_openat(int dfd, const char __user *filename, int flags, int mode) diff --git a/fs/proc/array.c b/fs/proc/array.c index eba339e..65c62e1 100644 --- a/fs/proc/array.c +++ b/fs/proc/array.c @@ -374,7 +374,9 @@ static cputime_t task_stime(struct task_struct *p) stime = nsec_to_clock_t(p->se.sum_exec_runtime) - cputime_to_clock_t(task_utime(p)); - p->prev_stime = max(p->prev_stime, clock_t_to_cputime(stime)); + if (stime >= 0) + p->prev_stime = max(p->prev_stime, clock_t_to_cputime(stime)); + return p->prev_stime; } #endif diff --git a/fs/proc/base.c b/fs/proc/base.c index aeaf0d0..02a63ac 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c @@ -2328,21 +2328,18 @@ out: void proc_flush_task(struct task_struct *task) { - int i, leader; - struct pid *pid, *tgid; + int i; + struct pid *pid, *tgid = NULL; struct upid *upid; - leader = thread_group_leader(task); - proc_flush_task_mnt(proc_mnt, task->pid, leader ? task->tgid : 0); pid = task_pid(task); - if (pid->level == 0) - return; + if (thread_group_leader(task)) + tgid = task_tgid(task); - tgid = task_tgid(task); - for (i = 1; i <= pid->level; i++) { + for (i = 0; i <= pid->level; i++) { upid = &pid->numbers[i]; proc_flush_task_mnt(upid->ns->proc_mnt, upid->nr, - leader ? 0 : tgid->numbers[i].nr); + tgid ? tgid->numbers[i].nr : 0); } upid = &pid->numbers[pid->level]; @@ -2414,19 +2411,23 @@ out: * Find the first task with tgid >= tgid * */ -static struct task_struct *next_tgid(unsigned int tgid, - struct pid_namespace *ns) -{ +struct tgid_iter { + unsigned int tgid; struct task_struct *task; +}; +static struct tgid_iter next_tgid(struct pid_namespace *ns, struct tgid_iter iter) +{ struct pid *pid; + if (iter.task) + put_task_struct(iter.task); rcu_read_lock(); retry: - task = NULL; - pid = find_ge_pid(tgid, ns); + iter.task = NULL; + pid = find_ge_pid(iter.tgid, ns); if (pid) { - tgid = pid_nr_ns(pid, ns) + 1; - task = pid_task(pid, PIDTYPE_PID); + iter.tgid = pid_nr_ns(pid, ns); + iter.task = pid_task(pid, PIDTYPE_PID); /* What we to know is if the pid we have find is the * pid of a thread_group_leader. Testing for task * being a thread_group_leader is the obvious thing @@ -2439,23 +2440,25 @@ retry: * found doesn't happen to be a thread group leader. * As we don't care in the case of readdir. */ - if (!task || !has_group_leader_pid(task)) + if (!iter.task || !has_group_leader_pid(iter.task)) { + iter.tgid += 1; goto retry; - get_task_struct(task); + } + get_task_struct(iter.task); } rcu_read_unlock(); - return task; + return iter; } #define TGID_OFFSET (FIRST_PROCESS_ENTRY + ARRAY_SIZE(proc_base_stuff)) static int proc_pid_fill_cache(struct file *filp, void *dirent, filldir_t filldir, - struct task_struct *task, int tgid) + struct tgid_iter iter) { char name[PROC_NUMBUF]; - int len = snprintf(name, sizeof(name), "%d", tgid); + int len = snprintf(name, sizeof(name), "%d", iter.tgid); return proc_fill_cache(filp, dirent, filldir, name, len, - proc_pid_instantiate, task, NULL); + proc_pid_instantiate, iter.task, NULL); } /* for the /proc/ directory itself, after non-process stuff has been done */ @@ -2463,8 +2466,7 @@ int proc_pid_readdir(struct file * filp, void * dirent, filldir_t filldir) { unsigned int nr = filp->f_pos - FIRST_PROCESS_ENTRY; struct task_struct *reaper = get_proc_task(filp->f_path.dentry->d_inode); - struct task_struct *task; - int tgid; + struct tgid_iter iter; struct pid_namespace *ns; if (!reaper) @@ -2477,14 +2479,14 @@ int proc_pid_readdir(struct file * filp, void * dirent, filldir_t filldir) } ns = filp->f_dentry->d_sb->s_fs_info; - tgid = filp->f_pos - TGID_OFFSET; - for (task = next_tgid(tgid, ns); - task; - put_task_struct(task), task = next_tgid(tgid + 1, ns)) { - tgid = task_pid_nr_ns(task, ns); - filp->f_pos = tgid + TGID_OFFSET; - if (proc_pid_fill_cache(filp, dirent, filldir, task, tgid) < 0) { - put_task_struct(task); + iter.task = NULL; + iter.tgid = filp->f_pos - TGID_OFFSET; + for (iter = next_tgid(ns, iter); + iter.task; + iter.tgid += 1, iter = next_tgid(ns, iter)) { + filp->f_pos = iter.tgid + TGID_OFFSET; + if (proc_pid_fill_cache(filp, dirent, filldir, iter) < 0) { + put_task_struct(iter.task); goto out; } } diff --git a/fs/proc/generic.c b/fs/proc/generic.c index 1bdb624..5fccfe2 100644 --- a/fs/proc/generic.c +++ b/fs/proc/generic.c @@ -374,9 +374,16 @@ static int proc_delete_dentry(struct dentry * dentry) return 1; } +static int proc_revalidate_dentry(struct dentry *dentry, struct nameidata *nd) +{ + d_drop(dentry); + return 0; +} + static struct dentry_operations proc_dentry_operations = { .d_delete = proc_delete_dentry, + .d_revalidate = proc_revalidate_dentry, }; /* @@ -397,8 +404,11 @@ struct dentry *proc_lookup(struct inode * dir, struct dentry *dentry, struct nam if (de->namelen != dentry->d_name.len) continue; if (!memcmp(dentry->d_name.name, de->name, de->namelen)) { - unsigned int ino = de->low_ino; + unsigned int ino; + if (de->shadow_proc) + de = de->shadow_proc(current, de); + ino = de->low_ino; de_get(de); spin_unlock(&proc_subdir_lock); error = -EINVAL; @@ -555,36 +565,6 @@ static int proc_register(struct proc_dir_entry * dir, struct proc_dir_entry * dp return 0; } -/* - * Kill an inode that got unregistered.. - */ -static void proc_kill_inodes(struct proc_dir_entry *de) -{ - struct list_head *p; - struct super_block *sb = proc_mnt->mnt_sb; - - /* - * Actually it's a partial revoke(). - */ - file_list_lock(); - list_for_each(p, &sb->s_files) { - struct file * filp = list_entry(p, struct file, f_u.fu_list); - struct dentry * dentry = filp->f_path.dentry; - struct inode * inode; - const struct file_operations *fops; - - if (dentry->d_op != &proc_dentry_operations) - continue; - inode = dentry->d_inode; - if (PDE(inode) != de) - continue; - fops = filp->f_op; - filp->f_op = NULL; - fops_put(fops); - } - file_list_unlock(); -} - static struct proc_dir_entry *proc_create(struct proc_dir_entry **parent, const char *name, mode_t mode, @@ -759,8 +739,6 @@ void remove_proc_entry(const char *name, struct proc_dir_entry *parent) continue_removing: if (S_ISDIR(de->mode)) parent->nlink--; - if (!S_ISREG(de->mode)) - proc_kill_inodes(de); de->nlink = 0; WARN_ON(de->subdir); if (!atomic_read(&de->count)) diff --git a/fs/proc/proc_net.c b/fs/proc/proc_net.c index 749def0..0afe21e 100644 --- a/fs/proc/proc_net.c +++ b/fs/proc/proc_net.c @@ -26,13 +26,6 @@ #include "internal.h" -struct proc_dir_entry *proc_net_create(struct net *net, - const char *name, mode_t mode, get_info_t *get_info) -{ - return create_proc_info_entry(name,mode, net->proc_net, get_info); -} -EXPORT_SYMBOL_GPL(proc_net_create); - struct proc_dir_entry *proc_net_fops_create(struct net *net, const char *name, mode_t mode, const struct file_operations *fops) { @@ -57,89 +50,14 @@ struct net *get_proc_net(const struct inode *inode) } EXPORT_SYMBOL_GPL(get_proc_net); -static struct proc_dir_entry *proc_net_shadow; +static struct proc_dir_entry *shadow_pde; -static struct dentry *proc_net_shadow_dentry(struct dentry *parent, +static struct proc_dir_entry *proc_net_shadow(struct task_struct *task, struct proc_dir_entry *de) { - struct dentry *shadow = NULL; - struct inode *inode; - if (!de) - goto out; - de_get(de); - inode = proc_get_inode(parent->d_inode->i_sb, de->low_ino, de); - if (!inode) - goto out_de_put; - shadow = d_alloc_name(parent, de->name); - if (!shadow) - goto out_iput; - shadow->d_op = parent->d_op; /* proc_dentry_operations */ - d_instantiate(shadow, inode); -out: - return shadow; -out_iput: - iput(inode); -out_de_put: - de_put(de); - goto out; -} - -static void *proc_net_follow_link(struct dentry *parent, struct nameidata *nd) -{ - struct net *net = current->nsproxy->net_ns; - struct dentry *shadow; - shadow = proc_net_shadow_dentry(parent, net->proc_net); - if (!shadow) - return ERR_PTR(-ENOENT); - - dput(nd->dentry); - /* My dentry count is 1 and that should be enough as the - * shadow dentry is thrown away immediately. - */ - nd->dentry = shadow; - return NULL; -} - -static struct dentry *proc_net_lookup(struct inode *dir, struct dentry *dentry, - struct nameidata *nd) -{ - struct net *net = current->nsproxy->net_ns; - struct dentry *shadow; - - shadow = proc_net_shadow_dentry(nd->dentry, net->proc_net); - if (!shadow) - return ERR_PTR(-ENOENT); - - dput(nd->dentry); - nd->dentry = shadow; - - return shadow->d_inode->i_op->lookup(shadow->d_inode, dentry, nd); + return task->nsproxy->net_ns->proc_net; } -static int proc_net_setattr(struct dentry *dentry, struct iattr *iattr) -{ - struct net *net = current->nsproxy->net_ns; - struct dentry *shadow; - int ret; - - shadow = proc_net_shadow_dentry(dentry->d_parent, net->proc_net); - if (!shadow) - return -ENOENT; - ret = shadow->d_inode->i_op->setattr(shadow, iattr); - dput(shadow); - return ret; -} - -static const struct file_operations proc_net_dir_operations = { - .read = generic_read_dir, -}; - -static struct inode_operations proc_net_dir_inode_operations = { - .follow_link = proc_net_follow_link, - .lookup = proc_net_lookup, - .setattr = proc_net_setattr, -}; - static __net_init int proc_net_ns_init(struct net *net) { struct proc_dir_entry *root, *netd, *net_statd; @@ -185,16 +103,15 @@ static __net_exit void proc_net_ns_exit(struct net *net) kfree(net->proc_net_root); } -static struct pernet_operations proc_net_ns_ops = { +static struct pernet_operations __net_initdata proc_net_ns_ops = { .init = proc_net_ns_init, .exit = proc_net_ns_exit, }; int __init proc_net_init(void) { - proc_net_shadow = proc_mkdir("net", NULL); - proc_net_shadow->proc_iops = &proc_net_dir_inode_operations; - proc_net_shadow->proc_fops = &proc_net_dir_operations; + shadow_pde = proc_mkdir("net", NULL); + shadow_pde->shadow_proc = proc_net_shadow; return register_pernet_subsys(&proc_net_ns_ops); } diff --git a/fs/read_write.c b/fs/read_write.c index 124693e..ea1f94c 100644 --- a/fs/read_write.c +++ b/fs/read_write.c @@ -370,7 +370,7 @@ asmlinkage ssize_t sys_read(unsigned int fd, char __user * buf, size_t count) return ret; } -EXPORT_SYMBOL_GPL(sys_read); +EXPORT_UNUSED_SYMBOL_GPL(sys_read); /* to be deleted for 2.6.25 */ asmlinkage ssize_t sys_write(unsigned int fd, const char __user * buf, size_t count) { diff --git a/fs/reiserfs/ioctl.c b/fs/reiserfs/ioctl.c index c438a8f..e0f0f09 100644 --- a/fs/reiserfs/ioctl.c +++ b/fs/reiserfs/ioctl.c @@ -57,6 +57,9 @@ int reiserfs_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, if (get_user(flags, (int __user *)arg)) return -EFAULT; + /* Is it quota file? Do not allow user to mess with it. */ + if (IS_NOQUOTA(inode)) + return -EPERM; if (((flags ^ REISERFS_I(inode)-> i_attrs) & (REISERFS_IMMUTABLE_FL | REISERFS_APPEND_FL)) diff --git a/fs/reiserfs/stree.c b/fs/reiserfs/stree.c index ca41567..d2db241 100644 --- a/fs/reiserfs/stree.c +++ b/fs/reiserfs/stree.c @@ -1458,9 +1458,6 @@ static void unmap_buffers(struct page *page, loff_t pos) } bh = next; } while (bh != head); - if (PAGE_SIZE == bh->b_size) { - cancel_dirty_page(page, PAGE_CACHE_SIZE); - } } } } diff --git a/fs/smbfs/file.c b/fs/smbfs/file.c index f5d14ce..efbe29a 100644 --- a/fs/smbfs/file.c +++ b/fs/smbfs/file.c @@ -234,7 +234,7 @@ smb_file_aio_read(struct kiocb *iocb, const struct iovec *iov, VERBOSE("before read, size=%ld, flags=%x, atime=%ld\n", (long)dentry->d_inode->i_size, - dentry->d_inode->i_flags, dentry->d_inode->i_atime); + dentry->d_inode->i_flags, dentry->d_inode->i_atime.tv_sec); status = generic_file_aio_read(iocb, iov, nr_segs, pos); out: @@ -269,7 +269,7 @@ smb_file_splice_read(struct file *file, loff_t *ppos, struct dentry *dentry = file->f_path.dentry; ssize_t status; - VERBOSE("file %s/%s, pos=%Ld, count=%d\n", + VERBOSE("file %s/%s, pos=%Ld, count=%lu\n", DENTRY_PATH(dentry), *ppos, count); status = smb_revalidate_inode(dentry); @@ -363,7 +363,8 @@ smb_file_aio_write(struct kiocb *iocb, const struct iovec *iov, result = generic_file_aio_write(iocb, iov, nr_segs, pos); VERBOSE("pos=%ld, size=%ld, mtime=%ld, atime=%ld\n", (long) file->f_pos, (long) dentry->d_inode->i_size, - dentry->d_inode->i_mtime, dentry->d_inode->i_atime); + dentry->d_inode->i_mtime.tv_sec, + dentry->d_inode->i_atime.tv_sec); } out: return result; diff --git a/fs/smbfs/inode.c b/fs/smbfs/inode.c index ab51775..9416ead 100644 --- a/fs/smbfs/inode.c +++ b/fs/smbfs/inode.c @@ -536,7 +536,7 @@ static int smb_fill_super(struct super_block *sb, void *raw_data, int silent) /* Allocate the global temp buffer and some superblock helper structs */ /* FIXME: move these to the smb_sb_info struct */ - VERBOSE("alloc chunk = %d\n", sizeof(struct smb_ops) + + VERBOSE("alloc chunk = %lu\n", sizeof(struct smb_ops) + sizeof(struct smb_mount_data_kernel)); mem = kmalloc(sizeof(struct smb_ops) + sizeof(struct smb_mount_data_kernel), GFP_KERNEL); diff --git a/fs/smbfs/proc.c b/fs/smbfs/proc.c index feac460..d517a27 100644 --- a/fs/smbfs/proc.c +++ b/fs/smbfs/proc.c @@ -2593,7 +2593,7 @@ smb_proc_getattr_ff(struct smb_sb_info *server, struct dentry *dentry, fattr->f_mtime.tv_sec = date_dos2unix(server, date, time); fattr->f_mtime.tv_nsec = 0; VERBOSE("name=%s, date=%x, time=%x, mtime=%ld\n", - mask, date, time, fattr->f_mtime); + mask, date, time, fattr->f_mtime.tv_sec); fattr->f_size = DVAL(req->rq_data, 12); /* ULONG allocation size */ fattr->attr = WVAL(req->rq_data, 20); diff --git a/fs/smbfs/smbiod.c b/fs/smbfs/smbiod.c index 283c572..fae8e85 100644 --- a/fs/smbfs/smbiod.c +++ b/fs/smbfs/smbiod.c @@ -227,7 +227,7 @@ int smbiod_retry(struct smb_sb_info *server) printk(KERN_ERR "smb_retry: signal failed [%d]\n", result); goto out; } - VERBOSE("signalled pid %d\n", pid); + VERBOSE("signalled pid %d\n", pid_nr(pid)); /* FIXME: The retried requests should perhaps get a "time boost". */ diff --git a/fs/sysfs/file.c b/fs/sysfs/file.c index 27d1785..4045bdc 100644 --- a/fs/sysfs/file.c +++ b/fs/sysfs/file.c @@ -119,7 +119,11 @@ static int fill_read_buffer(struct dentry * dentry, struct sysfs_buffer * buffer sysfs_put_active_two(attr_sd); - BUG_ON(count > (ssize_t)PAGE_SIZE); + /* + * The code works fine with PAGE_SIZE return but it's likely to + * indicate truncated result or overflow in normal use cases. + */ + BUG_ON(count >= (ssize_t)PAGE_SIZE); if (count >= 0) { buffer->needs_read_fill = 0; buffer->count = count; diff --git a/include/acpi/processor.h b/include/acpi/processor.h index 26d79f6..76411b1 100644 --- a/include/acpi/processor.h +++ b/include/acpi/processor.h @@ -78,7 +78,6 @@ struct acpi_processor_cx { struct acpi_processor_power { struct cpuidle_device dev; struct acpi_processor_cx *state; - struct acpi_processor_cx *bm_state; unsigned long bm_check_timestamp; u32 default_state; u32 bm_activity; diff --git a/include/asm-arm/arch-at91/board.h b/include/asm-arm/arch-at91/board.h index c0d7075..7905496 100644 --- a/include/asm-arm/arch-at91/board.h +++ b/include/asm-arm/arch-at91/board.h @@ -33,6 +33,7 @@ #include <linux/mtd/partitions.h> #include <linux/device.h> +#include <linux/i2c.h> #include <linux/spi/spi.h> /* USB Device */ @@ -94,7 +95,7 @@ struct at91_nand_data { extern void __init at91_add_device_nand(struct at91_nand_data *data); /* I2C*/ -extern void __init at91_add_device_i2c(void); +extern void __init at91_add_device_i2c(struct i2c_board_info *devices, int nr_devices); /* SPI */ extern void __init at91_add_device_spi(struct spi_board_info *devices, int nr_devices); diff --git a/include/asm-arm/arch-ixp23xx/irqs.h b/include/asm-arm/arch-ixp23xx/irqs.h index e696395..27c5808 100644 --- a/include/asm-arm/arch-ixp23xx/irqs.h +++ b/include/asm-arm/arch-ixp23xx/irqs.h @@ -153,7 +153,7 @@ */ #define NR_IXP23XX_MACH_IRQS 32 -#define NR_IRQS NR_IXP23XX_IRQS + NR_IXP23XX_MACH_IRQS +#define NR_IRQS (NR_IXP23XX_IRQS + NR_IXP23XX_MACH_IRQS) #define IXP23XX_MACH_IRQ(irq) (NR_IXP23XX_IRQ + (irq)) diff --git a/include/asm-arm/arch-omap/board-innovator.h b/include/asm-arm/arch-omap/board-innovator.h index b3cf334..56d2c98 100644 --- a/include/asm-arm/arch-omap/board-innovator.h +++ b/include/asm-arm/arch-omap/board-innovator.h @@ -37,7 +37,7 @@ #define OMAP1510P1_EMIFF_PRI_VALUE 0x00 #define NR_FPGA_IRQS 24 -#define NR_IRQS IH_BOARD_BASE + NR_FPGA_IRQS +#define NR_IRQS (IH_BOARD_BASE + NR_FPGA_IRQS) #ifndef __ASSEMBLY__ void fpga_write(unsigned char val, int reg); diff --git a/include/asm-arm/arch-pxa/irqs.h b/include/asm-arm/arch-pxa/irqs.h index 6238dbf..b76ee6d 100644 --- a/include/asm-arm/arch-pxa/irqs.h +++ b/include/asm-arm/arch-pxa/irqs.h @@ -13,7 +13,7 @@ #define PXA_IRQ(x) (x) -#ifdef CONFIG_PXA27x +#if defined(CONFIG_PXA27x) || defined(CONFIG_PXA3xx) #define IRQ_SSP3 PXA_IRQ(0) /* SSP3 service request */ #define IRQ_MSL PXA_IRQ(1) /* MSL Interface interrupt */ #define IRQ_USBH2 PXA_IRQ(2) /* USB Host interrupt 1 (OHCI) */ @@ -52,11 +52,27 @@ #define IRQ_RTC1Hz PXA_IRQ(30) /* RTC HZ Clock Tick */ #define IRQ_RTCAlrm PXA_IRQ(31) /* RTC Alarm */ -#ifdef CONFIG_PXA27x +#if defined(CONFIG_PXA27x) || defined(CONFIG_PXA3xx) #define IRQ_TPM PXA_IRQ(32) /* TPM interrupt */ #define IRQ_CAMERA PXA_IRQ(33) /* Camera Interface */ #endif +#ifdef CONFIG_PXA3xx +#define IRQ_SSP4 PXA_IRQ(13) /* SSP4 service request */ +#define IRQ_CIR PXA_IRQ(34) /* Consumer IR */ +#define IRQ_TSI PXA_IRQ(36) /* Touch Screen Interface (PXA320) */ +#define IRQ_USIM2 PXA_IRQ(38) /* USIM2 Controller */ +#define IRQ_GRPHICS PXA_IRQ(39) /* Graphics Controller */ +#define IRQ_MMC2 PXA_IRQ(41) /* MMC2 Controller */ +#define IRQ_1WIRE PXA_IRQ(44) /* 1-Wire Controller */ +#define IRQ_NAND PXA_IRQ(45) /* NAND Controller */ +#define IRQ_USB2 PXA_IRQ(46) /* USB 2.0 Device Controller */ +#define IRQ_WAKEUP0 PXA_IRQ(49) /* EXT_WAKEUP0 */ +#define IRQ_WAKEUP1 PXA_IRQ(50) /* EXT_WAKEUP1 */ +#define IRQ_DMEMC PXA_IRQ(51) /* Dynamic Memory Controller */ +#define IRQ_MMC3 PXA_IRQ(55) /* MMC3 Controller (PXA310) */ +#endif + #define PXA_GPIO_IRQ_BASE (64) #define PXA_GPIO_IRQ_NUM (128) diff --git a/include/asm-arm/arch-pxa/mfp-pxa300.h b/include/asm-arm/arch-pxa/mfp-pxa300.h index 822a27c..a209966 100644 --- a/include/asm-arm/arch-pxa/mfp-pxa300.h +++ b/include/asm-arm/arch-pxa/mfp-pxa300.h @@ -179,7 +179,7 @@ #define GPIO62_LCD_CS_N MFP_CFG_DRV(GPIO62, AF2, DS01X) #define GPIO72_LCD_FCLK MFP_CFG_DRV(GPIO72, AF1, DS01X) #define GPIO73_LCD_LCLK MFP_CFG_DRV(GPIO73, AF1, DS01X) -#define GPIO74_LCD_PCLK MFP_CFG_DRV(GPIO74, AF1, DS01X) +#define GPIO74_LCD_PCLK MFP_CFG_DRV(GPIO74, AF1, DS02X) #define GPIO75_LCD_BIAS MFP_CFG_DRV(GPIO75, AF1, DS01X) #define GPIO76_LCD_VSYNC MFP_CFG_DRV(GPIO76, AF2, DS01X) diff --git a/include/asm-arm/arch-pxa/mfp-pxa320.h b/include/asm-arm/arch-pxa/mfp-pxa320.h index 488a5bb..52deedc 100644 --- a/include/asm-arm/arch-pxa/mfp-pxa320.h +++ b/include/asm-arm/arch-pxa/mfp-pxa320.h @@ -18,7 +18,7 @@ #include <asm/arch/mfp.h> /* GPIO */ -#define GPIO46_GPIO MFP_CFG(GPIO6, AF0) +#define GPIO46_GPIO MFP_CFG(GPIO46, AF0) #define GPIO49_GPIO MFP_CFG(GPIO49, AF0) #define GPIO50_GPIO MFP_CFG(GPIO50, AF0) #define GPIO51_GPIO MFP_CFG(GPIO51, AF0) diff --git a/include/asm-arm/arch-pxa/mfp.h b/include/asm-arm/arch-pxa/mfp.h index ac4157a..03c508d 100644 --- a/include/asm-arm/arch-pxa/mfp.h +++ b/include/asm-arm/arch-pxa/mfp.h @@ -346,23 +346,31 @@ typedef uint32_t mfp_cfg_t; #define MFP_CFG_PIN(mfp_cfg) (((mfp_cfg) >> 16) & 0xffff) #define MFP_CFG_VAL(mfp_cfg) ((mfp_cfg) & 0xffff) -#define MFPR_DEFAULT (0x0000) +/* + * MFP register defaults to + * drive strength fast 3mA (010'b) + * edge detection logic disabled + * alternate function 0 + */ +#define MFPR_DEFAULT (0x0840) #define MFP_CFG(pin, af) \ ((MFP_PIN_##pin << 16) | MFPR_DEFAULT | (MFP_##af)) #define MFP_CFG_DRV(pin, af, drv) \ - ((MFP_PIN_##pin << 16) | MFPR_DEFAULT |\ + ((MFP_PIN_##pin << 16) | (MFPR_DEFAULT & ~MFPR_DRV_MASK) |\ ((MFP_##drv) << 10) | (MFP_##af)) #define MFP_CFG_LPM(pin, af, lpm) \ - ((MFP_PIN_##pin << 16) | MFPR_DEFAULT | (MFP_##af) |\ + ((MFP_PIN_##pin << 16) | (MFPR_DEFAULT & ~MFPR_LPM_MASK) |\ (((MFP_LPM_##lpm) & 0x3) << 7) |\ (((MFP_LPM_##lpm) & 0x4) << 12) |\ - (((MFP_LPM_##lpm) & 0x8) << 10)) + (((MFP_LPM_##lpm) & 0x8) << 10) |\ + (MFP_##af)) #define MFP_CFG_X(pin, af, drv, lpm) \ - ((MFP_PIN_##pin << 16) | MFPR_DEFAULT |\ + ((MFP_PIN_##pin << 16) |\ + (MFPR_DEFAULT & ~(MFPR_DRV_MASK | MFPR_LPM_MASK)) |\ ((MFP_##drv) << 10) | (MFP_##af) |\ (((MFP_LPM_##lpm) & 0x3) << 7) |\ (((MFP_LPM_##lpm) & 0x4) << 12) |\ diff --git a/include/asm-arm/arch-pxa/pxa-regs.h b/include/asm-arm/arch-pxa/pxa-regs.h index bb68b59..6b33df6 100644 --- a/include/asm-arm/arch-pxa/pxa-regs.h +++ b/include/asm-arm/arch-pxa/pxa-regs.h @@ -110,7 +110,10 @@ #define DALGN __REG(0x400000a0) /* DMA Alignment Register */ #define DINT __REG(0x400000f0) /* DMA Interrupt Register */ -#define DRCMR(n) __REG2(0x40000100, (n)<<2) +#define DRCMR(n) (*(((n) < 64) ? \ + &__REG2(0x40000100, ((n) & 0x3f) << 2) : \ + &__REG2(0x40001100, ((n) & 0x3f) << 2))) + #define DRCMR0 __REG(0x40000100) /* Request to Channel Map Register for DREQ 0 */ #define DRCMR1 __REG(0x40000104) /* Request to Channel Map Register for DREQ 1 */ #define DRCMR2 __REG(0x40000108) /* Request to Channel Map Register for I2S receive Request */ diff --git a/include/asm-arm/arch-s3c2410/spi-gpio.h b/include/asm-arm/arch-s3c2410/spi-gpio.h index c1e4db7..ba1dca8 100644 --- a/include/asm-arm/arch-s3c2410/spi-gpio.h +++ b/include/asm-arm/arch-s3c2410/spi-gpio.h @@ -21,6 +21,8 @@ struct s3c2410_spigpio_info { unsigned long pin_mosi; unsigned long pin_miso; + int bus_num; + unsigned long board_size; struct spi_board_info *board_info; diff --git a/include/asm-arm/hardware/iop3xx.h b/include/asm-arm/hardware/iop3xx.h index fb90b42..ede377e 100644 --- a/include/asm-arm/hardware/iop3xx.h +++ b/include/asm-arm/hardware/iop3xx.h @@ -231,7 +231,7 @@ extern int init_atu; IOP3XX_PCI_IO_WINDOW_SIZE - 1) #define IOP3XX_PCI_UPPER_IO_VA (IOP3XX_PCI_LOWER_IO_VA +\ IOP3XX_PCI_IO_WINDOW_SIZE - 1) -#define IOP3XX_PCI_IO_PHYS_TO_VIRT(addr) (((u32) addr -\ +#define IOP3XX_PCI_IO_PHYS_TO_VIRT(addr) (((u32) (addr) -\ IOP3XX_PCI_LOWER_IO_PA) +\ IOP3XX_PCI_LOWER_IO_VA) diff --git a/include/asm-arm/pgtable.h b/include/asm-arm/pgtable.h index d2e8171..5e01824 100644 --- a/include/asm-arm/pgtable.h +++ b/include/asm-arm/pgtable.h @@ -249,7 +249,7 @@ extern struct page *empty_zero_page; #define set_pte_ext(ptep,pte,ext) cpu_set_pte_ext(ptep,pte,ext) #define set_pte_at(mm,addr,ptep,pteval) do { \ - set_pte_ext(ptep, pteval, (addr) >= PAGE_OFFSET ? 0 : PTE_EXT_NG); \ + set_pte_ext(ptep, pteval, (addr) >= TASK_SIZE ? 0 : PTE_EXT_NG); \ } while (0) /* diff --git a/include/asm-avr32/sysreg.h b/include/asm-avr32/sysreg.h index c02bc83..dd21182 100644 --- a/include/asm-avr32/sysreg.h +++ b/include/asm-avr32/sysreg.h @@ -215,6 +215,8 @@ #define SYSREG_IRP_SIZE 6 /* Bitfields in PCCR */ +#define SYSREG_PCCR_E_OFFSET 0 +#define SYSREG_PCCR_E_SIZE 1 #define SYSREG_PCCR_R_OFFSET 1 #define SYSREG_PCCR_R_SIZE 1 #define SYSREG_PCCR_C_OFFSET 2 diff --git a/include/asm-blackfin/bfin-global.h b/include/asm-blackfin/bfin-global.h index 0212e18..39bdd86 100644 --- a/include/asm-blackfin/bfin-global.h +++ b/include/asm-blackfin/bfin-global.h @@ -50,8 +50,8 @@ extern unsigned long get_sclk(void); extern unsigned long sclk_to_usecs(unsigned long sclk); extern unsigned long usecs_to_sclk(unsigned long usecs); -extern void dump_thread(struct pt_regs *regs, struct user *dump); -extern void dump_bfin_regs(struct pt_regs *fp, void *retaddr); +extern void dump_bfin_process(struct pt_regs *regs); +extern void dump_bfin_mem(void *retaddr); extern void dump_bfin_trace_buffer(void); extern int init_arch_irq(void); @@ -63,6 +63,7 @@ extern void bfin_dcache_init(void); extern int read_iloc(void); extern int bfin_console_init(void); extern asmlinkage void lower_to_irq14(void); +extern asmlinkage void bfin_return_from_exception(void); extern void init_exception_vectors(void); extern void init_dma(void); extern void program_IAR(void); diff --git a/include/asm-blackfin/cplbinit.h b/include/asm-blackfin/cplbinit.h index bec6ecd..c4d0596 100644 --- a/include/asm-blackfin/cplbinit.h +++ b/include/asm-blackfin/cplbinit.h @@ -27,6 +27,9 @@ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ +#ifndef __ASM_CPLBINIT_H__ +#define __ASM_CPLBINIT_H__ + #include <asm/blackfin.h> #include <asm/cplb.h> @@ -57,8 +60,8 @@ struct cplb_tab { u16 size; }; -extern u_long icplb_table[MAX_CPLBS+1]; -extern u_long dcplb_table[MAX_CPLBS+1]; +extern u_long icplb_table[]; +extern u_long dcplb_table[]; /* Till here we are discussing about the static memory management model. * However, the operating envoronments commonly define more CPLB @@ -69,28 +72,16 @@ extern u_long dcplb_table[MAX_CPLBS+1]; * This is how Page descriptor Table is implemented in uClinux/Blackfin. */ -#ifdef CONFIG_CPLB_SWITCH_TAB_L1 -extern u_long ipdt_table[MAX_SWITCH_I_CPLBS+1]__attribute__((l1_data)); -extern u_long dpdt_table[MAX_SWITCH_D_CPLBS+1]__attribute__((l1_data)); - -#ifdef CONFIG_CPLB_INFO -extern u_long ipdt_swapcount_table[MAX_SWITCH_I_CPLBS]__attribute__((l1_data)); -extern u_long dpdt_swapcount_table[MAX_SWITCH_D_CPLBS]__attribute__((l1_data)); -#endif /* CONFIG_CPLB_INFO */ - -#else - -extern u_long ipdt_table[MAX_SWITCH_I_CPLBS+1]; -extern u_long dpdt_table[MAX_SWITCH_D_CPLBS+1]; - +extern u_long ipdt_table[]; +extern u_long dpdt_table[]; #ifdef CONFIG_CPLB_INFO -extern u_long ipdt_swapcount_table[MAX_SWITCH_I_CPLBS]; -extern u_long dpdt_swapcount_table[MAX_SWITCH_D_CPLBS]; -#endif /* CONFIG_CPLB_INFO */ - -#endif /*CONFIG_CPLB_SWITCH_TAB_L1*/ +extern u_long ipdt_swapcount_table[]; +extern u_long dpdt_swapcount_table[]; +#endif extern unsigned long reserved_mem_dcache_on; extern unsigned long reserved_mem_icache_on; extern void generate_cpl_tables(void); + +#endif diff --git a/include/asm-blackfin/delay.h b/include/asm-blackfin/delay.h index 52e7a10..473a811 100644 --- a/include/asm-blackfin/delay.h +++ b/include/asm-blackfin/delay.h @@ -1,29 +1,47 @@ -#ifndef _BLACKFIN_DELAY_H -#define _BLACKFIN_DELAY_H - -static inline void __delay(unsigned long loops) -{ - -/* FIXME: Currently the assembler doesn't recognize Loop Register Clobbers, - uncomment this as soon those are implemented */ /* - __asm__ __volatile__ ( "\t LSETUP (1f,1f) LC0= %0\n\t" - "1:\t NOP;\n\t" - : :"a" (loops) - : "LT0","LB0","LC0"); + * delay.h - delay functions + * + * Copyright (c) 2004-2007 Analog Devices Inc. + * + * Licensed under the GPL-2 or later. + */ + +#ifndef __ASM_DELAY_H__ +#define __ASM_DELAY_H__ -*/ +#include <asm/mach/anomaly.h> - __asm__ __volatile__("[--SP] = LC0;\n\t" - "[--SP] = LT0;\n\t" - "[--SP] = LB0;\n\t" - "LSETUP (1f,1f) LC0 = %0;\n\t" - "1:\t NOP;\n\t" - "LB0 = [SP++];\n\t" - "LT0 = [SP++];\n\t" - "LC0 = [SP++];\n" - : - :"a" (loops)); +static inline void __delay(unsigned long loops) +{ + if (ANOMALY_05000312) { + /* Interrupted loads to loop registers -> bad */ + unsigned long tmp; + __asm__ __volatile__( + "[--SP] = LC0;" + "[--SP] = LT0;" + "[--SP] = LB0;" + "LSETUP (1f,1f) LC0 = %1;" + "1: NOP;" + /* We take advantage of the fact that LC0 is 0 at + * the end of the loop. Otherwise we'd need some + * NOPs after the CLI here. + */ + "CLI %0;" + "LB0 = [SP++];" + "LT0 = [SP++];" + "LC0 = [SP++];" + "STI %0;" + : "=d" (tmp) + : "a" (loops) + ); + } else + __asm__ __volatile__ ( + "LSETUP(1f, 1f) LC0 = %0;" + "1: NOP;" + : + : "a" (loops) + : "LT0", "LB0", "LC0" + ); } #include <linux/param.h> /* needed for HZ */ @@ -41,4 +59,4 @@ static inline void udelay(unsigned long usecs) __delay(usecs * loops_per_jiffy / (1000000 / HZ)); } -#endif /* defined(_BLACKFIN_DELAY_H) */ +#endif diff --git a/include/asm-blackfin/io.h b/include/asm-blackfin/io.h index d1d2e6b..1601d62 100644 --- a/include/asm-blackfin/io.h +++ b/include/asm-blackfin/io.h @@ -122,6 +122,7 @@ extern void outsl(unsigned long port, const void *addr, unsigned long count); extern void insb(unsigned long port, void *addr, unsigned long count); extern void insw(unsigned long port, void *addr, unsigned long count); extern void insl(unsigned long port, void *addr, unsigned long count); +extern void insl_16(unsigned long port, void *addr, unsigned long count); extern void dma_outsb(unsigned long port, const void *addr, unsigned short count); extern void dma_outsw(unsigned long port, const void *addr, unsigned short count); diff --git a/include/asm-blackfin/mach-bf527/irq.h b/include/asm-blackfin/mach-bf527/irq.h index 304f5bc..4e2b3f2 100644 --- a/include/asm-blackfin/mach-bf527/irq.h +++ b/include/asm-blackfin/mach-bf527/irq.h @@ -176,11 +176,7 @@ #define GPIO_IRQ_BASE IRQ_PF0 -#ifdef CONFIG_IRQCHIP_DEMUX_GPIO #define NR_IRQS (IRQ_PH15+1) -#else -#define NR_IRQS (SYS_IRQS+1) -#endif #define IVG7 7 #define IVG8 8 diff --git a/include/asm-blackfin/mach-bf527/mem_map.h b/include/asm-blackfin/mach-bf527/mem_map.h index c5aa201..193082d 100644 --- a/include/asm-blackfin/mach-bf527/mem_map.h +++ b/include/asm-blackfin/mach-bf527/mem_map.h @@ -47,6 +47,7 @@ /* Boot ROM Memory */ #define BOOT_ROM_START 0xEF000000 +#define BOOT_ROM_LENGTH 0x8000 /* Level 1 Memory */ @@ -90,9 +91,7 @@ /* Scratch Pad Memory */ -#if defined(CONFIG_BF527) || defined(CONFIG_BF536) || defined(CONFIG_BF534) #define L1_SCRATCH_START 0xFFB00000 #define L1_SCRATCH_LENGTH 0x1000 -#endif #endif /* _MEM_MAP_527_H_ */ diff --git a/include/asm-blackfin/mach-bf533/irq.h b/include/asm-blackfin/mach-bf533/irq.h index 452fb82..832e6f6 100644 --- a/include/asm-blackfin/mach-bf533/irq.h +++ b/include/asm-blackfin/mach-bf533/irq.h @@ -130,11 +130,7 @@ Core Emulation ** #define GPIO_IRQ_BASE IRQ_PF0 -#ifdef CONFIG_IRQCHIP_DEMUX_GPIO #define NR_IRQS (IRQ_PF15+1) -#else -#define NR_IRQS SYS_IRQS -#endif #define IVG7 7 #define IVG8 8 diff --git a/include/asm-blackfin/mach-bf533/mem_map.h b/include/asm-blackfin/mach-bf533/mem_map.h index 94d8c40..bd30b6f 100644 --- a/include/asm-blackfin/mach-bf533/mem_map.h +++ b/include/asm-blackfin/mach-bf533/mem_map.h @@ -1,4 +1,3 @@ - /* * File: include/asm-blackfin/mach-bf533/mem_map.h * Based on: @@ -48,6 +47,7 @@ /* Boot ROM Memory */ #define BOOT_ROM_START 0xEF000000 +#define BOOT_ROM_LENGTH 0x400 /* Level 1 Memory */ @@ -160,9 +160,7 @@ /* Scratch Pad Memory */ -#if defined(CONFIG_BF533) || defined(CONFIG_BF532) || defined(CONFIG_BF531) #define L1_SCRATCH_START 0xFFB00000 #define L1_SCRATCH_LENGTH 0x1000 -#endif #endif /* _MEM_MAP_533_H_ */ diff --git a/include/asm-blackfin/mach-bf537/irq.h b/include/asm-blackfin/mach-bf537/irq.h index 36c44bc..be6f2ff 100644 --- a/include/asm-blackfin/mach-bf537/irq.h +++ b/include/asm-blackfin/mach-bf537/irq.h @@ -162,11 +162,7 @@ Core Emulation ** #define GPIO_IRQ_BASE IRQ_PF0 -#ifdef CONFIG_IRQCHIP_DEMUX_GPIO #define NR_IRQS (IRQ_PH15+1) -#else -#define NR_IRQS (IRQ_UART1_ERROR+1) -#endif #define IVG7 7 #define IVG8 8 diff --git a/include/asm-blackfin/mach-bf537/mem_map.h b/include/asm-blackfin/mach-bf537/mem_map.h index 18759e3..5c6726d 100644 --- a/include/asm-blackfin/mach-bf537/mem_map.h +++ b/include/asm-blackfin/mach-bf537/mem_map.h @@ -47,6 +47,7 @@ /* Boot ROM Memory */ #define BOOT_ROM_START 0xEF000000 +#define BOOT_ROM_LENGTH 0x800 /* Level 1 Memory */ @@ -167,9 +168,7 @@ /* Scratch Pad Memory */ -#if defined(CONFIG_BF537) || defined(CONFIG_BF536) || defined(CONFIG_BF534) #define L1_SCRATCH_START 0xFFB00000 #define L1_SCRATCH_LENGTH 0x1000 -#endif #endif /* _MEM_MAP_537_H_ */ diff --git a/include/asm-blackfin/mach-bf548/bf548.h b/include/asm-blackfin/mach-bf548/bf548.h index 7e6d349..e748588 100644 --- a/include/asm-blackfin/mach-bf548/bf548.h +++ b/include/asm-blackfin/mach-bf548/bf548.h @@ -106,24 +106,22 @@ #define AMGCTLVAL (V_AMBEN | V_AMCKEN) -#ifdef CONFIG_BF542 -#define CPU "BF542" -#define CPUID 0x027c8000 -#endif -#ifdef CONFIG_BF544 -#define CPU "BF544" -#define CPUID 0x027c8000 -#endif -#ifdef CONFIG_BF548 -#define CPU "BF548" -#define CPUID 0x027c6000 -#endif -#ifdef CONFIG_BF549 -#define CPU "BF549" -#endif -#ifndef CPU -#define CPU "UNKNOWN" -#define CPUID 0x0 +#if defined(CONFIG_BF542) +# define CPU "BF542" +# define CPUID 0x027c8000 +#elif defined(CONFIG_BF544) +# define CPU "BF544" +# define CPUID 0x027c8000 +#elif defined(CONFIG_BF547) +# define CPU "BF547" +#elif defined(CONFIG_BF548) +# define CPU "BF548" +# define CPUID 0x027c6000 +#elif defined(CONFIG_BF549) +# define CPU "BF549" +#else +# define CPU "UNKNOWN" +# define CPUID 0x0 #endif #endif /* __MACH_BF48_H__ */ diff --git a/include/asm-blackfin/mach-bf548/defBF544.h b/include/asm-blackfin/mach-bf548/defBF544.h index 760307e..b8b9870 100644 --- a/include/asm-blackfin/mach-bf548/defBF544.h +++ b/include/asm-blackfin/mach-bf548/defBF544.h @@ -645,7 +645,7 @@ /* Bit masks for HOST_STATUS */ -#define READY 0x1 /* DMA Ready */ +#define DMA_READY 0x1 /* DMA Ready */ #define FIFOFULL 0x2 /* FIFO Full */ #define FIFOEMPTY 0x4 /* FIFO Empty */ #define COMPLETE 0x8 /* DMA Complete */ diff --git a/include/asm-blackfin/mach-bf548/defBF548.h b/include/asm-blackfin/mach-bf548/defBF548.h index 70af33c..ecbca95 100644 --- a/include/asm-blackfin/mach-bf548/defBF548.h +++ b/include/asm-blackfin/mach-bf548/defBF548.h @@ -1007,7 +1007,7 @@ /* Bit masks for HOST_STATUS */ -#define READY 0x1 /* DMA Ready */ +#define DMA_READY 0x1 /* DMA Ready */ #define FIFOFULL 0x2 /* FIFO Full */ #define FIFOEMPTY 0x4 /* FIFO Empty */ #define COMPLETE 0x8 /* DMA Complete */ diff --git a/include/asm-blackfin/mach-bf548/irq.h b/include/asm-blackfin/mach-bf548/irq.h index 3b08cf9..9fb7bc5 100644 --- a/include/asm-blackfin/mach-bf548/irq.h +++ b/include/asm-blackfin/mach-bf548/irq.h @@ -338,11 +338,7 @@ Events (highest priority) EMU 0 #define GPIO_IRQ_BASE IRQ_PA0 -#ifdef CONFIG_IRQCHIP_DEMUX_GPIO #define NR_IRQS (IRQ_PJ15+1) -#else -#define NR_IRQS (SYS_IRQS+1) -#endif /* For compatibility reasons with existing code */ diff --git a/include/asm-blackfin/mach-bf548/mem_map.h b/include/asm-blackfin/mach-bf548/mem_map.h index ec1597e..f99f47b 100644 --- a/include/asm-blackfin/mach-bf548/mem_map.h +++ b/include/asm-blackfin/mach-bf548/mem_map.h @@ -47,6 +47,12 @@ /* Boot ROM Memory */ #define BOOT_ROM_START 0xEF000000 +#define BOOT_ROM_LENGTH 0x1000 + +/* L1 Instruction ROM */ + +#define L1_ROM_START 0xFFA14000 +#define L1_ROM_LENGTH 0x10000 /* Level 1 Memory */ @@ -87,11 +93,19 @@ #define BFIN_DSUPBANKS 0 #endif /*CONFIG_BFIN_DCACHE*/ +/* Level 2 Memory */ +#if !defined(CONFIG_BF542) +# define L2_START 0xFEB00000 +# if defined(CONFIG_BF544) +# define L2_LENGTH 0x10000 +# else +# define L2_LENGTH 0x20000 +# endif +#endif + /* Scratch Pad Memory */ -#if defined(CONFIG_BF54x) #define L1_SCRATCH_START 0xFFB00000 #define L1_SCRATCH_LENGTH 0x1000 -#endif #endif/* _MEM_MAP_548_H_ */ diff --git a/include/asm-blackfin/mach-bf561/bf561.h b/include/asm-blackfin/mach-bf561/bf561.h index 17e1d5d..3ef9e5f 100644 --- a/include/asm-blackfin/mach-bf561/bf561.h +++ b/include/asm-blackfin/mach-bf561/bf561.h @@ -33,25 +33,6 @@ #define SUPPORTED_REVID 0x3 #define OFFSET_(x) ((x) & 0x0000FFFF) -#define L1_ISRAM 0xFFA00000 -#define L1_ISRAM_END 0xFFA04000 -#define DATA_BANKA_SRAM 0xFF800000 -#define DATA_BANKA_SRAM_END 0xFF804000 -#define DATA_BANKB_SRAM 0xFF900000 -#define DATA_BANKB_SRAM_END 0xFF904000 -#define L1_DSRAMA 0xFF800000 -#define L1_DSRAMA_END 0xFF804000 -#define L1_DSRAMB 0xFF900000 -#define L1_DSRAMB_END 0xFF904000 -#define L2_SRAM 0xFEB00000 -#define L2_SRAM_END 0xFEB20000 -#define AMB_FLASH 0x20000000 -#define AMB_FLASH_END 0x21000000 -#define AMB_FLASH_LENGTH 0x01000000 -#define L1_ISRAM_LENGTH 0x4000 -#define L1_DSRAMA_LENGTH 0x4000 -#define L1_DSRAMB_LENGTH 0x4000 -#define L2_SRAM_LENGTH 0x20000 /*some misc defines*/ #define IMASK_IVG15 0x8000 diff --git a/include/asm-blackfin/mach-bf561/defBF561.h b/include/asm-blackfin/mach-bf561/defBF561.h index 7945e8a..c3c0eb1 100644 --- a/include/asm-blackfin/mach-bf561/defBF561.h +++ b/include/asm-blackfin/mach-bf561/defBF561.h @@ -55,6 +55,7 @@ /* For MMR's that are reserved on Core B, set up defines to better integrate with other ports */ #define SWRST SICA_SWRST #define SYSCR SICA_SYSCR +#define DOUBLE_FAULT (DOUBLE_FAULT_B|DOUBLE_FAULT_A) #define RESET_DOUBLE (SWRST_DBL_FAULT_B|SWRST_DBL_FAULT_A) #define RESET_WDOG (SWRST_WDT_B|SWRST_WDT_A) #define RESET_SOFTWARE (SWRST_OCCURRED) @@ -877,12 +878,14 @@ #define PLL_LOCKED 0x0020 /* PLL_LOCKCNT Has Been Reached */ /* SWRST Mask */ -#define SYSTEM_RESET 0x00000007 /* Initiates a system software reset */ -#define SWRST_DBL_FAULT_B 0x00000800 /* SWRST Core B Double Fault */ -#define SWRST_DBL_FAULT_A 0x00001000 /* SWRST Core A Double Fault */ -#define SWRST_WDT_B 0x00002000 /* SWRST Watchdog B */ -#define SWRST_WDT_A 0x00004000 /* SWRST Watchdog A */ -#define SWRST_OCCURRED 0x00008000 /* SWRST Status */ +#define SYSTEM_RESET 0x0007 /* Initiates a system software reset */ +#define DOUBLE_FAULT_A 0x0008 /* Core A Double Fault Causes Reset */ +#define DOUBLE_FAULT_B 0x0010 /* Core B Double Fault Causes Reset */ +#define SWRST_DBL_FAULT_A 0x0800 /* SWRST Core A Double Fault */ +#define SWRST_DBL_FAULT_B 0x1000 /* SWRST Core B Double Fault */ +#define SWRST_WDT_B 0x2000 /* SWRST Watchdog B */ +#define SWRST_WDT_A 0x4000 /* SWRST Watchdog A */ +#define SWRST_OCCURRED 0x8000 /* SWRST Status */ /* ************* SYSTEM INTERRUPT CONTROLLER MASKS ***************** */ diff --git a/include/asm-blackfin/mach-bf561/irq.h b/include/asm-blackfin/mach-bf561/irq.h index 1278992..83f0383 100644 --- a/include/asm-blackfin/mach-bf561/irq.h +++ b/include/asm-blackfin/mach-bf561/irq.h @@ -291,11 +291,7 @@ #define GPIO_IRQ_BASE IRQ_PF0 -#ifdef CONFIG_IRQCHIP_DEMUX_GPIO #define NR_IRQS (IRQ_PF47 + 1) -#else -#define NR_IRQS SYS_IRQS -#endif #define IVG7 7 #define IVG8 8 diff --git a/include/asm-blackfin/mach-bf561/mem_map.h b/include/asm-blackfin/mach-bf561/mem_map.h index f7ac09c..c26d848 100644 --- a/include/asm-blackfin/mach-bf561/mem_map.h +++ b/include/asm-blackfin/mach-bf561/mem_map.h @@ -19,6 +19,11 @@ #define ASYNC_BANK0_BASE 0x20000000 /* Async Bank 0 */ #define ASYNC_BANK0_SIZE 0x04000000 /* 64M */ +/* Boot ROM Memory */ + +#define BOOT_ROM_START 0xEF000000 +#define BOOT_ROM_LENGTH 0x800 + /* Level 1 Memory */ #ifdef CONFIG_BFIN_ICACHE @@ -67,9 +72,7 @@ /* Scratch Pad Memory */ -#if defined(CONFIG_BF561) #define L1_SCRATCH_START 0xFFB00000 #define L1_SCRATCH_LENGTH 0x1000 -#endif #endif /* _MEM_MAP_533_H_ */ diff --git a/include/asm-blackfin/mach-common/def_LPBlackfin.h b/include/asm-blackfin/mach-common/def_LPBlackfin.h index c1d8c4a..e8967f6 100644 --- a/include/asm-blackfin/mach-common/def_LPBlackfin.h +++ b/include/asm-blackfin/mach-common/def_LPBlackfin.h @@ -46,7 +46,7 @@ #endif #define bfin_read8(addr) ({ \ - uint8_t __v; \ + uint32_t __v; \ __asm__ __volatile__( \ NOP_PAD_ANOMALY_05000198 \ "%0 = b[%1] (z);" \ @@ -56,7 +56,7 @@ __v; }) #define bfin_read16(addr) ({ \ - uint16_t __v; \ + uint32_t __v; \ __asm__ __volatile__( \ NOP_PAD_ANOMALY_05000198 \ "%0 = w[%1] (z);" \ @@ -80,7 +80,7 @@ NOP_PAD_ANOMALY_05000198 \ "b[%0] = %1;" \ : \ - : "a" (addr), "d" (val) \ + : "a" (addr), "d" ((uint8_t)(val)) \ : "memory" \ ) @@ -89,7 +89,7 @@ NOP_PAD_ANOMALY_05000198 \ "w[%0] = %1;" \ : \ - : "a" (addr), "d" (val) \ + : "a" (addr), "d" ((uint16_t)(val)) \ : "memory" \ ) diff --git a/include/asm-blackfin/page_offset.h b/include/asm-blackfin/page_offset.h index 3b671d5..cbaff24 100644 --- a/include/asm-blackfin/page_offset.h +++ b/include/asm-blackfin/page_offset.h @@ -1,6 +1,6 @@ /* This handles the memory map.. */ -#ifdef CONFIG_BFIN +#ifdef CONFIG_BLACKFIN #define PAGE_OFFSET_RAW 0x00000000 #endif diff --git a/include/asm-blackfin/string.h b/include/asm-blackfin/string.h index e8ada91..321f4d9 100644 --- a/include/asm-blackfin/string.h +++ b/include/asm-blackfin/string.h @@ -1,6 +1,8 @@ #ifndef _BLACKFIN_STRING_H_ #define _BLACKFIN_STRING_H_ +#include <linux/types.h> + #ifdef __KERNEL__ /* only set these up for kernel code */ #define __HAVE_ARCH_STRCPY diff --git a/include/asm-blackfin/traps.h b/include/asm-blackfin/traps.h index fe365b1..ee1cbf7 100644 --- a/include/asm-blackfin/traps.h +++ b/include/asm-blackfin/traps.h @@ -48,28 +48,80 @@ #ifndef __ASSEMBLY__ -#define HWC_x2 "System MMR Error\nAn error occurred due to an invalid access to an System MMR location\nPossible reason: a 32-bit register is accessed with a 16-bit instruction,\nor a 16-bit register is accessed with a 32-bit instruction.\n" -#define HWC_x3 "External Memory Addressing Error\n" -#define HWC_x12 "Performance Monitor Overflow\n" -#define HWC_x18 "RAISE 5 instruction\n Software issued a RAISE 5 instruction to invoke the Hardware\n" -#define HWC_default "Reserved\n" - -#define EXC_0x03 "Application stack overflow\n - Please increase the stack size of the application using elf2flt -s option,\n and/or reduce the stack use of the application.\n" -#define EXC_0x10 "Single step\n - When the processor is in single step mode, every instruction\n generates an exception. Primarily used for debugging.\n" -#define EXC_0x11 "Exception caused by a trace buffer full condition\n - The processor takes this exception when the trace\n buffer overflows (only when enabled by the Trace Unit Control register).\n" -#define EXC_0x21 "Undefined instruction\n - May be used to emulate instructions that are not defined for\n a particular processor implementation.\n" -#define EXC_0x22 "Illegal instruction combination\n - See section for multi-issue rules in the ADSP-BF53x Blackfin\n Processor Instruction Set Reference.\n" -#define EXC_0x23 "Data access CPLB protection violation\n - Attempted read or write to Supervisor resource,\n or illegal data memory access. \n" -#define EXC_0x24 "Data access misaligned address violation\n - Attempted misaligned data memory or data cache access.\n" -#define EXC_0x25 "Unrecoverable event\n - For example, an exception generated while processing a previous exception.\n" -#define EXC_0x26 "Data access CPLB miss\n - Used by the MMU to signal a CPLB miss on a data access.\n" -#define EXC_0x27 "Data access multiple CPLB hits\n - More than one CPLB entry matches data fetch address.\n" -#define EXC_0x28 "Program Sequencer Exception caused by an emulation watchpoint match\n - There is a watchpoint match, and one of the EMUSW\n bits in the Watchpoint Instruction Address Control register (WPIACTL) is set.\n" -#define EXC_0x2A "Instruction fetch misaligned address violation\n - Attempted misaligned instruction cache fetch. On a misaligned instruction fetch exception,\n the return address provided in RETX is the destination address which is misaligned, rather than the address of the offending instruction.\n" -#define EXC_0x2B "CPLB protection violation\n - Illegal instruction fetch access (memory protection violation).\n" -#define EXC_0x2C "Instruction fetch CPLB miss\n - CPLB miss on an instruction fetch.\n" -#define EXC_0x2D "Instruction fetch multiple CPLB hits\n - More than one CPLB entry matches instruction fetch address.\n" -#define EXC_0x2E "Illegal use of supervisor resource\n - Attempted to use a Supervisor register or instruction from User mode.\n Supervisor resources are registers and instructions that are reserved\n for Supervisor use: Supervisor only registers, all MMRs, and Supervisor\n only instructions.\n" +#define HWC_x2(level) \ + "System MMR Error\n" \ + level " - An error occurred due to an invalid access to an System MMR location\n" \ + level " Possible reason: a 32-bit register is accessed with a 16-bit instruction\n" \ + level " or a 16-bit register is accessed with a 32-bit instruction.\n" +#define HWC_x3(level) \ + "External Memory Addressing Error\n" +#define HWC_x12(level) \ + "Performance Monitor Overflow\n" +#define HWC_x18(level) \ + "RAISE 5 instruction\n" \ + level " Software issued a RAISE 5 instruction to invoke the Hardware\n" +#define HWC_default(level) \ + "Reserved\n" +#define EXC_0x03(level) \ + "Application stack overflow\n" \ + level " - Please increase the stack size of the application using elf2flt -s option,\n" \ + level " and/or reduce the stack use of the application.\n" +#define EXC_0x10(level) \ + "Single step\n" \ + level " - When the processor is in single step mode, every instruction\n" \ + level " generates an exception. Primarily used for debugging.\n" +#define EXC_0x11(level) \ + "Exception caused by a trace buffer full condition\n" \ + level " - The processor takes this exception when the trace\n" \ + level " buffer overflows (only when enabled by the Trace Unit Control register).\n" +#define EXC_0x21(level) \ + "Undefined instruction\n" \ + level " - May be used to emulate instructions that are not defined for\n" \ + level " a particular processor implementation.\n" +#define EXC_0x22(level) \ + "Illegal instruction combination\n" \ + level " - See section for multi-issue rules in the ADSP-BF53x Blackfin\n" \ + level " Processor Instruction Set Reference.\n" +#define EXC_0x23(level) \ + "Data access CPLB protection violation\n" \ + level " - Attempted read or write to Supervisor resource,\n" \ + level " or illegal data memory access. \n" +#define EXC_0x24(level) \ + "Data access misaligned address violation\n" \ + level " - Attempted misaligned data memory or data cache access.\n" +#define EXC_0x25(level) \ + "Unrecoverable event\n" \ + level " - For example, an exception generated while processing a previous exception.\n" +#define EXC_0x26(level) \ + "Data access CPLB miss\n" \ + level " - Used by the MMU to signal a CPLB miss on a data access.\n" +#define EXC_0x27(level) \ + "Data access multiple CPLB hits\n" \ + level " - More than one CPLB entry matches data fetch address.\n" +#define EXC_0x28(level) \ + "Program Sequencer Exception caused by an emulation watchpoint match\n" \ + level " - There is a watchpoint match, and one of the EMUSW\n" \ + level " bits in the Watchpoint Instruction Address Control register (WPIACTL) is set.\n" +#define EXC_0x2A(level) \ + "Instruction fetch misaligned address violation\n" \ + level " - Attempted misaligned instruction cache fetch. On a misaligned instruction fetch\n" \ + level " exception, the return address provided in RETX is the destination address which is\n" \ + level " misaligned, rather than the address of the offending instruction.\n" +#define EXC_0x2B(level) \ + "CPLB protection violation\n" \ + level " - Illegal instruction fetch access (memory protection violation).\n" +#define EXC_0x2C(level) \ + "Instruction fetch CPLB miss\n" \ + level " - CPLB miss on an instruction fetch.\n" +#define EXC_0x2D(level) \ + "Instruction fetch multiple CPLB hits\n" \ + level " - More than one CPLB entry matches instruction fetch address.\n" +#define EXC_0x2E(level) \ + "Illegal use of supervisor resource\n" \ + level " - Attempted to use a Supervisor register or instruction from User mode.\n" \ + level " Supervisor resources are registers and instructions that are reserved\n" \ + level " for Supervisor use: Supervisor only registers, all MMRs, and Supervisor\n" \ + level " only instructions.\n" #endif /* __ASSEMBLY__ */ #endif /* _BFIN_TRAPS_H */ diff --git a/include/asm-cris/atomic.h b/include/asm-cris/atomic.h index 0b51a87..2949a94 100644 --- a/include/asm-cris/atomic.h +++ b/include/asm-cris/atomic.h @@ -3,6 +3,8 @@ #ifndef __ASM_CRIS_ATOMIC__ #define __ASM_CRIS_ATOMIC__ +#include <linux/compiler.h> + #include <asm/system.h> #include <asm/arch/atomic.h> diff --git a/include/asm-cris/checksum.h b/include/asm-cris/checksum.h index 180dbf2..c6c5be6 100644 --- a/include/asm-cris/checksum.h +++ b/include/asm-cris/checksum.h @@ -62,7 +62,7 @@ static inline __sum16 ip_fast_csum(const void *iph, unsigned int ihl) * returns a 16-bit checksum, already complemented */ -static inline __sum16 int csum_tcpudp_magic(__be32 saddr, __be32 daddr, +static inline __sum16 csum_tcpudp_magic(__be32 saddr, __be32 daddr, unsigned short len, unsigned short proto, __wsum sum) diff --git a/include/asm-cris/ethernet.h b/include/asm-cris/ethernet.h index 30da58a..4d58652 100644 --- a/include/asm-cris/ethernet.h +++ b/include/asm-cris/ethernet.h @@ -15,4 +15,7 @@ #define SET_ETH_DUPLEX_AUTO SIOCDEVPRIVATE+3 /* Auto neg duplex */ #define SET_ETH_DUPLEX_HALF SIOCDEVPRIVATE+4 /* Full duplex */ #define SET_ETH_DUPLEX_FULL SIOCDEVPRIVATE+5 /* Half duplex */ +#define SET_ETH_ENABLE_LEDS SIOCDEVPRIVATE+6 /* Enable net LEDs */ +#define SET_ETH_DISABLE_LEDS SIOCDEVPRIVATE+7 /* Disable net LEDs */ +#define SET_ETH_AUTONEG SIOCDEVPRIVATE+8 #endif /* _CRIS_ETHERNET_H */ diff --git a/include/asm-cris/fasttimer.h b/include/asm-cris/fasttimer.h index a3a7713..8f8a8d6 100644 --- a/include/asm-cris/fasttimer.h +++ b/include/asm-cris/fasttimer.h @@ -1,9 +1,8 @@ -/* $Id: fasttimer.h,v 1.3 2004/05/14 10:19:19 starvik Exp $ +/* * linux/include/asm-cris/fasttimer.h * * Fast timers for ETRAX100LX - * This may be useful in other OS than Linux so use 2 space indentation... - * Copyright (C) 2000, 2002 Axis Communications AB + * Copyright (C) 2000-2007 Axis Communications AB */ #include <linux/time.h> /* struct timeval */ #include <linux/timex.h> @@ -12,11 +11,16 @@ typedef void fast_timer_function_type(unsigned long); +struct fasttime_t { + unsigned long tv_jiff; /* jiffies */ + unsigned long tv_usec; /* microseconds */ +}; + struct fast_timer{ /* Close to timer_list */ struct fast_timer *next; struct fast_timer *prev; - struct timeval tv_set; - struct timeval tv_expires; + struct fasttime_t tv_set; + struct fasttime_t tv_expires; unsigned long delay_us; fast_timer_function_type *function; unsigned long data; @@ -38,6 +42,6 @@ int del_fast_timer(struct fast_timer * t); void schedule_usleep(unsigned long us); -void fast_timer_init(void); +int fast_timer_init(void); #endif diff --git a/include/asm-cris/hardirq.h b/include/asm-cris/hardirq.h index 1c13dd3..74178ad 100644 --- a/include/asm-cris/hardirq.h +++ b/include/asm-cris/hardirq.h @@ -1,6 +1,7 @@ #ifndef __ASM_HARDIRQ_H #define __ASM_HARDIRQ_H +#include <asm/irq.h> #include <linux/threads.h> #include <linux/cache.h> diff --git a/include/asm-cris/posix_types.h b/include/asm-cris/posix_types.h index 92000d0..3a5e4c4 100644 --- a/include/asm-cris/posix_types.h +++ b/include/asm-cris/posix_types.h @@ -52,7 +52,6 @@ typedef struct { } __kernel_fsid_t; #ifdef __KERNEL__ -#include <linux/bitops.h> #undef __FD_SET #define __FD_SET(fd,fdsetp) set_bit(fd, (void *)(fdsetp)) diff --git a/include/asm-cris/termbits.h b/include/asm-cris/termbits.h index 71c1b36..66e1a74 100644 --- a/include/asm-cris/termbits.h +++ b/include/asm-cris/termbits.h @@ -171,6 +171,19 @@ struct ktermios { #define B115200 0010002 #define B230400 0010003 #define B460800 0010004 + +/* Unsupported rates, but needed to avoid compile error. */ +#define B500000 0010005 +#define B576000 0010006 +#define B1000000 0010010 +#define B1152000 0010011 +#define B1500000 0010012 +#define B2000000 0010013 +#define B2500000 0010014 +#define B3000000 0010015 +#define B3500000 0010016 +#define B4000000 0010017 + /* etrax supports these additional three baud rates */ #define B921600 0010005 #define B1843200 0010006 diff --git a/include/asm-cris/thread_info.h b/include/asm-cris/thread_info.h index fde39f6..784668a 100644 --- a/include/asm-cris/thread_info.h +++ b/include/asm-cris/thread_info.h @@ -32,6 +32,7 @@ struct thread_info { unsigned long flags; /* low level flags */ __u32 cpu; /* current CPU */ int preempt_count; /* 0 => preemptable, <0 => BUG */ + __u32 tls; /* TLS for this thread */ mm_segment_t addr_limit; /* thread address space: 0-0xBFFFFFFF for user-thead @@ -79,14 +80,18 @@ struct thread_info { * - other flags in MSW */ #define TIF_SYSCALL_TRACE 0 /* syscall trace active */ -#define TIF_SIGPENDING 1 /* signal pending */ -#define TIF_NEED_RESCHED 2 /* rescheduling necessary */ +#define TIF_NOTIFY_RESUME 1 /* resumption notification requested */ +#define TIF_SIGPENDING 2 /* signal pending */ +#define TIF_NEED_RESCHED 3 /* rescheduling necessary */ +#define TIF_RESTORE_SIGMASK 9 /* restore signal mask in do_signal() */ #define TIF_POLLING_NRFLAG 16 /* true if poll_idle() is polling TIF_NEED_RESCHED */ #define TIF_MEMDIE 17 #define _TIF_SYSCALL_TRACE (1<<TIF_SYSCALL_TRACE) +#define _TIF_NOTIFY_RESUME (1<<TIF_NOTIFY_RESUME) #define _TIF_SIGPENDING (1<<TIF_SIGPENDING) #define _TIF_NEED_RESCHED (1<<TIF_NEED_RESCHED) +#define _TIF_RESTORE_SIGMASK (1<<TIF_RESTORE_SIGMASK) #define _TIF_POLLING_NRFLAG (1<<TIF_POLLING_NRFLAG) #define _TIF_WORK_MASK 0x0000FFFE /* work to do on interrupt/exception return */ diff --git a/include/asm-cris/tlb.h b/include/asm-cris/tlb.h index 6cc26de..7724246 100644 --- a/include/asm-cris/tlb.h +++ b/include/asm-cris/tlb.h @@ -1,6 +1,8 @@ #ifndef _CRIS_TLB_H #define _CRIS_TLB_H +#include <linux/pagemap.h> + #include <asm/arch/tlb.h> /* diff --git a/include/asm-cris/unistd.h b/include/asm-cris/unistd.h index 7c90fa9..6f2d924 100644 --- a/include/asm-cris/unistd.h +++ b/include/asm-cris/unistd.h @@ -255,6 +255,7 @@ #define __NR_io_submit 248 #define __NR_io_cancel 249 #define __NR_fadvise64 250 +/* 251 is available for reuse (was briefly sys_set_zone_reclaim) */ #define __NR_exit_group 252 #define __NR_lookup_dcookie 253 #define __NR_epoll_create 254 @@ -292,10 +293,46 @@ #define __NR_add_key 286 #define __NR_request_key 287 #define __NR_keyctl 288 +#define __NR_ioprio_set 289 +#define __NR_ioprio_get 290 +#define __NR_inotify_init 291 +#define __NR_inotify_add_watch 292 +#define __NR_inotify_rm_watch 293 +#define __NR_migrate_pages 294 +#define __NR_openat 295 +#define __NR_mkdirat 296 +#define __NR_mknodat 297 +#define __NR_fchownat 298 +#define __NR_futimesat 299 +#define __NR_fstatat64 300 +#define __NR_unlinkat 301 +#define __NR_renameat 302 +#define __NR_linkat 303 +#define __NR_symlinkat 304 +#define __NR_readlinkat 305 +#define __NR_fchmodat 306 +#define __NR_faccessat 307 +#define __NR_pselect6 308 +#define __NR_ppoll 309 +#define __NR_unshare 310 +#define __NR_set_robust_list 311 +#define __NR_get_robust_list 312 +#define __NR_splice 313 +#define __NR_sync_file_range 314 +#define __NR_tee 315 +#define __NR_vmsplice 316 +#define __NR_move_pages 317 +#define __NR_getcpu 318 +#define __NR_epoll_pwait 319 +#define __NR_utimensat 320 +#define __NR_signalfd 321 +#define __NR_timerfd 322 +#define __NR_eventfd 323 +#define __NR_fallocate 324 #ifdef __KERNEL__ -#define NR_syscalls 289 +#define NR_syscalls 325 #include <asm/arch/unistd.h> diff --git a/include/asm-frv/irq.h b/include/asm-frv/irq.h index 8fefd6b..3a66ebd 100644 --- a/include/asm-frv/irq.h +++ b/include/asm-frv/irq.h @@ -12,9 +12,6 @@ #ifndef _ASM_IRQ_H_ #define _ASM_IRQ_H_ -/* this number is used when no interrupt has been assigned */ -#define NO_IRQ (-1) - #define NR_IRQS 48 #define IRQ_BASE_CPU (0 * 16) #define IRQ_BASE_FPGA (1 * 16) diff --git a/include/asm-generic/resource.h b/include/asm-generic/resource.h index cfe3692..a4a22cc 100644 --- a/include/asm-generic/resource.h +++ b/include/asm-generic/resource.h @@ -12,7 +12,7 @@ * then it defines them prior including asm-generic/resource.h. ) */ -#define RLIMIT_CPU 0 /* CPU time in ms */ +#define RLIMIT_CPU 0 /* CPU time in sec */ #define RLIMIT_FSIZE 1 /* Maximum filesize */ #define RLIMIT_DATA 2 /* max data size */ #define RLIMIT_STACK 3 /* max stack size */ diff --git a/include/asm-ia64/acpi.h b/include/asm-ia64/acpi.h index 49730ff..81bcd5e 100644 --- a/include/asm-ia64/acpi.h +++ b/include/asm-ia64/acpi.h @@ -94,6 +94,7 @@ ia64_acpi_release_global_lock (unsigned int *lock) #define acpi_noirq 0 /* ACPI always enabled on IA64 */ #define acpi_pci_disabled 0 /* ACPI PCI always enabled on IA64 */ #define acpi_strict 1 /* no ACPI spec workarounds on IA64 */ +#define acpi_processor_cstate_check(x) (x) /* no idle limits on IA64 :) */ static inline void disable_acpi(void) { } const char *acpi_get_sysname (void); diff --git a/include/asm-ia64/pal.h b/include/asm-ia64/pal.h index abfcb3a..8a695d3 100644 --- a/include/asm-ia64/pal.h +++ b/include/asm-ia64/pal.h @@ -1379,10 +1379,11 @@ struct pal_features_s; static inline s64 ia64_pal_proc_get_features (u64 *features_avail, u64 *features_status, - u64 *features_control) + u64 *features_control, + u64 features_set) { struct ia64_pal_retval iprv; - PAL_CALL_PHYS(iprv, PAL_PROC_GET_FEATURES, 0, 0, 0); + PAL_CALL_PHYS(iprv, PAL_PROC_GET_FEATURES, 0, features_set, 0); if (iprv.status == 0) { *features_avail = iprv.v0; *features_status = iprv.v1; diff --git a/include/asm-m32r/thread_info.h b/include/asm-m32r/thread_info.h index c039820..1effcd0 100644 --- a/include/asm-m32r/thread_info.h +++ b/include/asm-m32r/thread_info.h @@ -149,16 +149,21 @@ static inline unsigned int get_thread_fault_code(void) #define TIF_NEED_RESCHED 2 /* rescheduling necessary */ #define TIF_SINGLESTEP 3 /* restore singlestep on return to user mode */ #define TIF_IRET 4 /* return with iret */ -#define TIF_POLLING_NRFLAG 16 /* true if poll_idle() is polling TIF_NEED_RESCHED */ - /* 31..28 fault code */ -#define TIF_MEMDIE 17 +#define TIF_RESTORE_SIGMASK 8 /* restore signal mask in do_signal() */ +#define TIF_USEDFPU 16 /* FPU was used by this task this quantum (SMP) */ +#define TIF_POLLING_NRFLAG 17 /* true if poll_idle() is polling TIF_NEED_RESCHED */ +#define TIF_MEMDIE 18 /* OOM killer killed process */ +#define TIF_FREEZE 19 /* is freezing for suspend */ #define _TIF_SYSCALL_TRACE (1<<TIF_SYSCALL_TRACE) #define _TIF_SIGPENDING (1<<TIF_SIGPENDING) #define _TIF_NEED_RESCHED (1<<TIF_NEED_RESCHED) #define _TIF_SINGLESTEP (1<<TIF_SINGLESTEP) #define _TIF_IRET (1<<TIF_IRET) +#define _TIF_RESTORE_SIGMASK (1<<TIF_RESTORE_SIGMASK) +#define _TIF_USEDFPU (1<<TIF_USEDFPU) #define _TIF_POLLING_NRFLAG (1<<TIF_POLLING_NRFLAG) +#define _TIF_FREEZE (1<<TIF_FREEZE) #define _TIF_WORK_MASK 0x0000FFFE /* work to do on interrupt/exception return */ #define _TIF_ALLWORK_MASK 0x0000FFFF /* work to do on any return to u-space */ diff --git a/include/asm-m32r/unistd.h b/include/asm-m32r/unistd.h index cbbd537..f467eac 100644 --- a/include/asm-m32r/unistd.h +++ b/include/asm-m32r/unistd.h @@ -290,10 +290,50 @@ #define __NR_mq_getsetattr (__NR_mq_open+5) #define __NR_kexec_load 283 #define __NR_waitid 284 +/* 285 is unused */ +#define __NR_add_key 286 +#define __NR_request_key 287 +#define __NR_keyctl 288 +#define __NR_ioprio_set 289 +#define __NR_ioprio_get 290 +#define __NR_inotify_init 291 +#define __NR_inotify_add_watch 292 +#define __NR_inotify_rm_watch 293 +#define __NR_migrate_pages 294 +#define __NR_openat 295 +#define __NR_mkdirat 296 +#define __NR_mknodat 297 +#define __NR_fchownat 298 +#define __NR_futimesat 299 +#define __NR_fstatat64 300 +#define __NR_unlinkat 301 +#define __NR_renameat 302 +#define __NR_linkat 303 +#define __NR_symlinkat 304 +#define __NR_readlinkat 305 +#define __NR_fchmodat 306 +#define __NR_faccessat 307 +#define __NR_pselect6 308 +#define __NR_ppoll 309 +#define __NR_unshare 310 +#define __NR_set_robust_list 311 +#define __NR_get_robust_list 312 +#define __NR_splice 313 +#define __NR_sync_file_range 314 +#define __NR_tee 315 +#define __NR_vmsplice 316 +#define __NR_move_pages 317 +#define __NR_getcpu 318 +#define __NR_epoll_pwait 319 +#define __NR_utimensat 320 +#define __NR_signalfd 321 +#define __NR_timerfd 322 +#define __NR_eventfd 323 +#define __NR_fallocate 324 #ifdef __KERNEL__ -#define NR_syscalls 285 +#define NR_syscalls 325 #define __ARCH_WANT_IPC_PARSE_VERSION #define __ARCH_WANT_STAT64 @@ -311,6 +351,30 @@ #define __ARCH_WANT_SYS_OLDUMOUNT #define __ARCH_WANT_SYS_RT_SIGACTION +#define __IGNORE_lchown +#define __IGNORE_setuid +#define __IGNORE_getuid +#define __IGNORE_setgid +#define __IGNORE_getgid +#define __IGNORE_geteuid +#define __IGNORE_getegid +#define __IGNORE_fcntl +#define __IGNORE_setreuid +#define __IGNORE_setregid +#define __IGNORE_getrlimit +#define __IGNORE_getgroups +#define __IGNORE_setgroups +#define __IGNORE_select +#define __IGNORE_mmap +#define __IGNORE_fchown +#define __IGNORE_setfsuid +#define __IGNORE_setfsgid +#define __IGNORE_setresuid +#define __IGNORE_getresuid +#define __IGNORE_setresgid +#define __IGNORE_getresgid +#define __IGNORE_chown + /* * "Conditional" syscalls * diff --git a/include/asm-mips/8253pit.h b/include/asm-mips/8253pit.h deleted file mode 100644 index 285f784..0000000 --- a/include/asm-mips/8253pit.h +++ /dev/null @@ -1,10 +0,0 @@ -/* - * 8253/8254 Programmable Interval Timer - */ - -#ifndef _8253PIT_H -#define _8253PIT_H - -#define PIT_TICK_RATE 1193182UL - -#endif diff --git a/include/asm-mips/cpu-features.h b/include/asm-mips/cpu-features.h index f6bd308..5ea701f 100644 --- a/include/asm-mips/cpu-features.h +++ b/include/asm-mips/cpu-features.h @@ -207,13 +207,13 @@ #endif #ifndef cpu_dcache_line_size -#define cpu_dcache_line_size() current_cpu_data.dcache.linesz +#define cpu_dcache_line_size() cpu_data[0].dcache.linesz #endif #ifndef cpu_icache_line_size -#define cpu_icache_line_size() current_cpu_data.icache.linesz +#define cpu_icache_line_size() cpu_data[0].icache.linesz #endif #ifndef cpu_scache_line_size -#define cpu_scache_line_size() current_cpu_data.scache.linesz +#define cpu_scache_line_size() cpu_data[0].scache.linesz #endif #endif /* __ASM_CPU_FEATURES_H */ diff --git a/include/asm-mips/cpu-info.h b/include/asm-mips/cpu-info.h index 94f1c81..ed5c02c 100644 --- a/include/asm-mips/cpu-info.h +++ b/include/asm-mips/cpu-info.h @@ -54,6 +54,7 @@ struct cpuinfo_mips { struct cache_desc dcache; /* Primary D or combined I/D cache */ struct cache_desc scache; /* Secondary cache */ struct cache_desc tcache; /* Tertiary/split secondary cache */ + int srsets; /* Shadow register sets */ #if defined(CONFIG_MIPS_MT_SMTC) /* * In the MIPS MT "SMTC" model, each TC is considered diff --git a/include/asm-mips/dma.h b/include/asm-mips/dma.h index 833437d..d6a6c21 100644 --- a/include/asm-mips/dma.h +++ b/include/asm-mips/dma.h @@ -92,6 +92,7 @@ #define MAX_DMA_ADDRESS (PAGE_OFFSET + 0x01000000) #endif #define MAX_DMA_PFN PFN_DOWN(virt_to_phys((void *)MAX_DMA_ADDRESS)) +#define MAX_DMA32_PFN (1UL << (32 - PAGE_SHIFT)) /* 8237 DMA controllers */ #define IO_DMA1_BASE 0x00 /* 8 bit slave DMA, channels 0..3 */ diff --git a/include/asm-mips/futex.h b/include/asm-mips/futex.h index 3e7e30d..17f082c 100644 --- a/include/asm-mips/futex.h +++ b/include/asm-mips/futex.h @@ -35,7 +35,7 @@ " .set mips0 \n" \ " .section .fixup,\"ax\" \n" \ "4: li %0, %6 \n" \ - " j 2b \n" \ + " j 3b \n" \ " .previous \n" \ " .section __ex_table,\"a\" \n" \ " "__UA_ADDR "\t1b, 4b \n" \ @@ -61,7 +61,7 @@ " .set mips0 \n" \ " .section .fixup,\"ax\" \n" \ "4: li %0, %6 \n" \ - " j 2b \n" \ + " j 3b \n" \ " .previous \n" \ " .section __ex_table,\"a\" \n" \ " "__UA_ADDR "\t1b, 4b \n" \ @@ -200,4 +200,4 @@ futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval) } #endif -#endif +#endif /* _ASM_FUTEX_H */ diff --git a/include/asm-mips/i8253.h b/include/asm-mips/i8253.h index 032ca73..5dabc87 100644 --- a/include/asm-mips/i8253.h +++ b/include/asm-mips/i8253.h @@ -12,6 +12,8 @@ #define PIT_CH0 0x40 #define PIT_CH2 0x42 +#define PIT_TICK_RATE 1193182UL + extern spinlock_t i8253_lock; extern void setup_pit_timer(void); diff --git a/include/asm-mips/ip32/ip32_ints.h b/include/asm-mips/ip32/ip32_ints.h index ab5612f..85bc530 100644 --- a/include/asm-mips/ip32/ip32_ints.h +++ b/include/asm-mips/ip32/ip32_ints.h @@ -22,7 +22,7 @@ enum ip32_irq_no { * CPU interrupts are 0 ... 7 */ - CRIME_IRQ_BASE = MIPS_CPU_IRQ_BASE, + CRIME_IRQ_BASE = MIPS_CPU_IRQ_BASE + 8, /* * MACE diff --git a/include/asm-mips/lasat/lasatint.h b/include/asm-mips/lasat/lasatint.h index 581dc45..e0d2458 100644 --- a/include/asm-mips/lasat/lasatint.h +++ b/include/asm-mips/lasat/lasatint.h @@ -1,11 +1,6 @@ #ifndef __ASM_LASAT_LASATINT_H #define __ASM_LASAT_LASATINT_H -#include <linux/irq.h> - -#define LASATINT_BASE MIPS_CPU_IRQ_BASE -#define LASATINT_END (LASATINT_BASE + 16) - /* lasat 100 */ #define LASAT_INT_STATUS_REG_100 (KSEG1ADDR(0x1c880000)) #define LASAT_INT_MASK_REG_100 (KSEG1ADDR(0x1c890000)) diff --git a/include/asm-mips/mach-lasat/irq.h b/include/asm-mips/mach-lasat/irq.h new file mode 100644 index 0000000..da75f89 --- /dev/null +++ b/include/asm-mips/mach-lasat/irq.h @@ -0,0 +1,13 @@ +#ifndef _ASM_MACH_LASAT_IRQ_H +#define _ASM_MACH_LASAT_IRQ_H + +#define LASAT_CASCADE_IRQ (MIPS_CPU_IRQ_BASE + 0) + +#define LASAT_IRQ_BASE 8 +#define LASAT_IRQ_END 23 + +#define NR_IRQS 24 + +#include_next <irq.h> + +#endif /* _ASM_MACH_LASAT_IRQ_H */ diff --git a/include/asm-mips/system.h b/include/asm-mips/system.h index 90e4b40..a944eda 100644 --- a/include/asm-mips/system.h +++ b/include/asm-mips/system.h @@ -68,11 +68,15 @@ do { \ if (cpu_has_dsp) \ __save_dsp(prev); \ (last) = resume(prev, next, task_thread_info(next)); \ +} while (0) + +#define finish_arch_switch(prev) \ +do { \ if (cpu_has_dsp) \ __restore_dsp(current); \ if (cpu_has_userlocal) \ - write_c0_userlocal(task_thread_info(current)->tp_value);\ -} while(0) + write_c0_userlocal(current_thread_info()->tp_value); \ +} while (0) static inline unsigned long __xchg_u32(volatile int * m, unsigned int val) { @@ -205,8 +209,6 @@ extern void *set_except_vector(int n, void *addr); extern unsigned long ebase; extern void per_cpu_trap_init(void); -extern int stop_a_enabled; - /* * See include/asm-ia64/system.h; prevents deadlock on SMP * systems. diff --git a/include/asm-mips/time.h b/include/asm-mips/time.h index ee1663e..7717934 100644 --- a/include/asm-mips/time.h +++ b/include/asm-mips/time.h @@ -58,10 +58,22 @@ extern int (*perf_irq)(void); * Initialize the calling CPU's compare interrupt as clockevent device */ #ifdef CONFIG_CEVT_R4K -extern void mips_clockevent_init(void); +extern int mips_clockevent_init(void); extern unsigned int __weak get_c0_compare_int(void); #else -static inline void mips_clockevent_init(void) +static inline int mips_clockevent_init(void) +{ + return -ENXIO; +} +#endif + +/* + * Initialize the count register as a clocksource + */ +#ifdef CONFIG_CEVT_R4K +extern void init_mips_clocksource(void); +#else +static inline void init_mips_clocksource(void) { } #endif diff --git a/include/asm-mips/timex.h b/include/asm-mips/timex.h index 5816ad1..6529704 100644 --- a/include/asm-mips/timex.h +++ b/include/asm-mips/timex.h @@ -35,7 +35,7 @@ typedef unsigned int cycles_t; static inline cycles_t get_cycles(void) { - return read_c0_count(); + return 0; } #endif /* __KERNEL__ */ diff --git a/include/asm-powerpc/cputable.h b/include/asm-powerpc/cputable.h index 9d74338..4525c78 100644 --- a/include/asm-powerpc/cputable.h +++ b/include/asm-powerpc/cputable.h @@ -138,6 +138,7 @@ extern void do_feature_fixups(unsigned long value, void *fixup_start, #define CPU_FTR_FPU_UNAVAILABLE ASM_CONST(0x0000000000800000) #define CPU_FTR_UNIFIED_ID_CACHE ASM_CONST(0x0000000001000000) #define CPU_FTR_SPE ASM_CONST(0x0000000002000000) +#define CPU_FTR_NEED_PAIRED_STWCX ASM_CONST(0x0000000004000000) /* * Add the 64-bit processor unique features in the top half of the word; @@ -261,25 +262,25 @@ extern void do_feature_fixups(unsigned long value, void *fixup_start, #define CPU_FTRS_7450_20 (CPU_FTR_COMMON | \ CPU_FTR_USE_TB | CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | \ CPU_FTR_L3CR | CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | \ - CPU_FTR_NEED_COHERENT | CPU_FTR_PPC_LE) + CPU_FTR_NEED_COHERENT | CPU_FTR_PPC_LE | CPU_FTR_NEED_PAIRED_STWCX) #define CPU_FTRS_7450_21 (CPU_FTR_COMMON | \ CPU_FTR_USE_TB | \ CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | \ CPU_FTR_L3CR | CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | \ CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_L3_DISABLE_NAP | \ - CPU_FTR_NEED_COHERENT | CPU_FTR_PPC_LE) + CPU_FTR_NEED_COHERENT | CPU_FTR_PPC_LE | CPU_FTR_NEED_PAIRED_STWCX) #define CPU_FTRS_7450_23 (CPU_FTR_COMMON | \ - CPU_FTR_USE_TB | \ + CPU_FTR_USE_TB | CPU_FTR_NEED_PAIRED_STWCX | \ CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | \ CPU_FTR_L3CR | CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | \ CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_NEED_COHERENT | CPU_FTR_PPC_LE) #define CPU_FTRS_7455_1 (CPU_FTR_COMMON | \ - CPU_FTR_USE_TB | \ + CPU_FTR_USE_TB | CPU_FTR_NEED_PAIRED_STWCX | \ CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | CPU_FTR_L3CR | \ CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | CPU_FTR_HAS_HIGH_BATS | \ CPU_FTR_NEED_COHERENT | CPU_FTR_PPC_LE) #define CPU_FTRS_7455_20 (CPU_FTR_COMMON | \ - CPU_FTR_USE_TB | \ + CPU_FTR_USE_TB | CPU_FTR_NEED_PAIRED_STWCX | \ CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | \ CPU_FTR_L3CR | CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | \ CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_L3_DISABLE_NAP | \ @@ -289,31 +290,32 @@ extern void do_feature_fixups(unsigned long value, void *fixup_start, CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | \ CPU_FTR_L3CR | CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | \ CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_HAS_HIGH_BATS | \ - CPU_FTR_NEED_COHERENT | CPU_FTR_PPC_LE) + CPU_FTR_NEED_COHERENT | CPU_FTR_PPC_LE | CPU_FTR_NEED_PAIRED_STWCX) #define CPU_FTRS_7447_10 (CPU_FTR_COMMON | \ CPU_FTR_USE_TB | \ CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | \ CPU_FTR_L3CR | CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | \ CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_HAS_HIGH_BATS | \ - CPU_FTR_NEED_COHERENT | CPU_FTR_NO_BTIC | CPU_FTR_PPC_LE) + CPU_FTR_NEED_COHERENT | CPU_FTR_NO_BTIC | CPU_FTR_PPC_LE | \ + CPU_FTR_NEED_PAIRED_STWCX) #define CPU_FTRS_7447 (CPU_FTR_COMMON | \ CPU_FTR_USE_TB | \ CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | \ CPU_FTR_L3CR | CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | \ CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_HAS_HIGH_BATS | \ - CPU_FTR_NEED_COHERENT | CPU_FTR_PPC_LE) + CPU_FTR_NEED_COHERENT | CPU_FTR_PPC_LE | CPU_FTR_NEED_PAIRED_STWCX) #define CPU_FTRS_7447A (CPU_FTR_COMMON | \ CPU_FTR_USE_TB | \ CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | \ CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | \ CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_HAS_HIGH_BATS | \ - CPU_FTR_NEED_COHERENT | CPU_FTR_PPC_LE) + CPU_FTR_NEED_COHERENT | CPU_FTR_PPC_LE | CPU_FTR_NEED_PAIRED_STWCX) #define CPU_FTRS_7448 (CPU_FTR_COMMON | \ CPU_FTR_USE_TB | \ CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | \ CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | \ CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_HAS_HIGH_BATS | \ - CPU_FTR_PPC_LE) + CPU_FTR_PPC_LE | CPU_FTR_NEED_PAIRED_STWCX) #define CPU_FTRS_82XX (CPU_FTR_COMMON | \ CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB) #define CPU_FTRS_G2_LE (CPU_FTR_COMMON | CPU_FTR_MAYBE_CAN_DOZE | \ diff --git a/include/asm-powerpc/page_32.h b/include/asm-powerpc/page_32.h index 374d0db..17110af 100644 --- a/include/asm-powerpc/page_32.h +++ b/include/asm-powerpc/page_32.h @@ -6,6 +6,10 @@ #define PPC_MEMSTART 0 +#ifdef CONFIG_NOT_COHERENT_CACHE +#define ARCH_KMALLOC_MINALIGN L1_CACHE_BYTES +#endif + #ifndef __ASSEMBLY__ /* * The basic type of a PTE - 64 bits for those CPUs with > 32 bit diff --git a/include/asm-powerpc/pci-bridge.h b/include/asm-powerpc/pci-bridge.h index dc31845..d8bdc79 100644 --- a/include/asm-powerpc/pci-bridge.h +++ b/include/asm-powerpc/pci-bridge.h @@ -246,7 +246,6 @@ static inline struct pci_controller *pci_bus_to_host(struct pci_bus *bus) return PCI_DN(busdn)->phb; } -extern void pcibios_free_controller(struct pci_controller *phb); extern void isa_bridge_find_early(struct pci_controller *hose); @@ -282,9 +281,11 @@ extern void pci_process_bridge_OF_ranges(struct pci_controller *hose, struct device_node *dev, int primary); -/* Allocate a new PCI host bridge structure */ +/* Allocate & free a PCI host bridge structure */ extern struct pci_controller * pcibios_alloc_controller(struct device_node *dev); +extern void pcibios_free_controller(struct pci_controller *phb); + #ifdef CONFIG_PCI extern unsigned long pci_address_to_pio(phys_addr_t address); extern int pcibios_vaddr_is_ioport(void __iomem *address); diff --git a/include/asm-powerpc/pgtable-ppc32.h b/include/asm-powerpc/pgtable-ppc32.h index 86a54a4a..fea2d8f 100644 --- a/include/asm-powerpc/pgtable-ppc32.h +++ b/include/asm-powerpc/pgtable-ppc32.h @@ -11,6 +11,11 @@ extern unsigned long va_to_phys(unsigned long address); extern pte_t *va_to_pte(unsigned long address); extern unsigned long ioremap_bot, ioremap_base; + +#ifdef CONFIG_44x +extern int icache_44x_need_flush; +#endif + #endif /* __ASSEMBLY__ */ /* @@ -562,6 +567,10 @@ static inline unsigned long pte_update(pte_t *p, unsigned long clr, : "=&r" (old), "=&r" (tmp), "=m" (*p) : "r" (p), "r" (clr), "r" (set), "m" (*p) : "cc" ); +#ifdef CONFIG_44x + if ((old & _PAGE_USER) && (old & _PAGE_HWEXEC)) + icache_44x_need_flush = 1; +#endif return old; } #else @@ -582,6 +591,10 @@ static inline unsigned long long pte_update(pte_t *p, unsigned long clr, : "=&r" (old), "=&r" (tmp), "=m" (*p) : "r" (p), "r" ((unsigned long)(p) + 4), "r" (clr), "r" (set), "m" (*p) : "cc" ); +#ifdef CONFIG_44x + if ((old & _PAGE_USER) && (old & _PAGE_HWEXEC)) + icache_44x_need_flush = 1; +#endif return old; } #endif diff --git a/include/asm-powerpc/rtas.h b/include/asm-powerpc/rtas.h index 8eaa7b2..87db872 100644 --- a/include/asm-powerpc/rtas.h +++ b/include/asm-powerpc/rtas.h @@ -164,7 +164,8 @@ extern int rtas_call(int token, int, int, int *, ...); extern void rtas_restart(char *cmd); extern void rtas_power_off(void); extern void rtas_halt(void); -extern void rtas_os_term(char *str); +extern void rtas_panic_msg(char *str); +extern void rtas_os_term(void); extern int rtas_get_sensor(int sensor, int index, int *state); extern int rtas_get_power_level(int powerdomain, int *level); extern int rtas_set_power_level(int powerdomain, int level, int *setlevel); diff --git a/include/asm-powerpc/systbl.h b/include/asm-powerpc/systbl.h index cc6d872..11d5383 100644 --- a/include/asm-powerpc/systbl.h +++ b/include/asm-powerpc/systbl.h @@ -308,8 +308,8 @@ COMPAT_SYS_SPU(move_pages) SYSCALL_SPU(getcpu) COMPAT_SYS(epoll_pwait) COMPAT_SYS_SPU(utimensat) -COMPAT_SYS(fallocate) COMPAT_SYS_SPU(signalfd) COMPAT_SYS_SPU(timerfd) SYSCALL_SPU(eventfd) COMPAT_SYS_SPU(sync_file_range2) +COMPAT_SYS(fallocate) diff --git a/include/asm-powerpc/time.h b/include/asm-powerpc/time.h index f058955..780f826 100644 --- a/include/asm-powerpc/time.h +++ b/include/asm-powerpc/time.h @@ -176,25 +176,31 @@ static inline unsigned int get_dec(void) #endif } +/* + * Note: Book E and 4xx processors differ from other PowerPC processors + * in when the decrementer generates its interrupt: on the 1 to 0 + * transition for Book E/4xx, but on the 0 to -1 transition for others. + */ static inline void set_dec(int val) { #if defined(CONFIG_40x) mtspr(SPRN_PIT, val); #elif defined(CONFIG_8xx_CPU6) - set_dec_cpu6(val); + set_dec_cpu6(val - 1); #else +#ifndef CONFIG_BOOKE + --val; +#endif #ifdef CONFIG_PPC_ISERIES - int cur_dec; - if (firmware_has_feature(FW_FEATURE_ISERIES) && get_lppaca()->shared_proc) { get_lppaca()->virtual_decr = val; - cur_dec = get_dec(); - if (cur_dec > val) + if (get_dec() > val) HvCall_setVirtualDecr(); - } else + return; + } #endif - mtspr(SPRN_DEC, val); + mtspr(SPRN_DEC, val); #endif /* not 40x or 8xx_CPU6 */ } diff --git a/include/asm-powerpc/tlbflush.h b/include/asm-powerpc/tlbflush.h index b6b036c..5c91081 100644 --- a/include/asm-powerpc/tlbflush.h +++ b/include/asm-powerpc/tlbflush.h @@ -1,5 +1,6 @@ #ifndef _ASM_POWERPC_TLBFLUSH_H #define _ASM_POWERPC_TLBFLUSH_H + /* * TLB flushing: * @@ -16,9 +17,6 @@ */ #ifdef __KERNEL__ -struct mm_struct; -struct vm_area_struct; - #if defined(CONFIG_4xx) || defined(CONFIG_8xx) || defined(CONFIG_FSL_BOOKE) /* * TLB flushing for software loaded TLB chips @@ -28,7 +26,9 @@ struct vm_area_struct; * specific tlbie's */ -extern void _tlbie(unsigned long address); +#include <linux/mm.h> + +extern void _tlbie(unsigned long address, unsigned int pid); #if defined(CONFIG_40x) || defined(CONFIG_8xx) #define _tlbia() asm volatile ("tlbia; sync" : : : "memory") @@ -44,13 +44,13 @@ static inline void flush_tlb_mm(struct mm_struct *mm) static inline void flush_tlb_page(struct vm_area_struct *vma, unsigned long vmaddr) { - _tlbie(vmaddr); + _tlbie(vmaddr, vma ? vma->vm_mm->context.id : 0); } static inline void flush_tlb_page_nohash(struct vm_area_struct *vma, unsigned long vmaddr) { - _tlbie(vmaddr); + _tlbie(vmaddr, vma ? vma->vm_mm->context.id : 0); } static inline void flush_tlb_range(struct vm_area_struct *vma, diff --git a/include/asm-powerpc/vdso_datapage.h b/include/asm-powerpc/vdso_datapage.h index 8a94f0e..f013932 100644 --- a/include/asm-powerpc/vdso_datapage.h +++ b/include/asm-powerpc/vdso_datapage.h @@ -77,6 +77,10 @@ struct vdso_data { /* those additional ones don't have to be located anywhere * special as they were not part of the original systemcfg */ + __u32 dcache_block_size; /* L1 d-cache block size */ + __u32 icache_block_size; /* L1 i-cache block size */ + __u32 dcache_log_block_size; /* L1 d-cache log block size */ + __u32 icache_log_block_size; /* L1 i-cache log block size */ __s32 wtom_clock_sec; /* Wall to monotonic clock */ __s32 wtom_clock_nsec; __u32 syscall_map_64[SYSCALL_MAP_SIZE]; /* map of syscalls */ @@ -99,6 +103,10 @@ struct vdso_data { __s32 wtom_clock_sec; /* Wall to monotonic clock */ __s32 wtom_clock_nsec; __u32 syscall_map_32[SYSCALL_MAP_SIZE]; /* map of syscalls */ + __u32 dcache_block_size; /* L1 d-cache block size */ + __u32 icache_block_size; /* L1 i-cache block size */ + __u32 dcache_log_block_size; /* L1 d-cache log block size */ + __u32 icache_log_block_size; /* L1 i-cache log block size */ }; #endif /* CONFIG_PPC64 */ diff --git a/include/asm-s390/system.h b/include/asm-s390/system.h index d866d33..44bda78 100644 --- a/include/asm-s390/system.h +++ b/include/asm-s390/system.h @@ -388,6 +388,11 @@ extern void (*_machine_power_off)(void); #define arch_align_stack(x) (x) +#ifdef CONFIG_TRACE_IRQFLAGS +extern psw_t sysc_restore_trace_psw; +extern psw_t io_restore_trace_psw; +#endif + #endif /* __KERNEL__ */ #endif diff --git a/include/asm-sh/cacheflush.h b/include/asm-sh/cacheflush.h index aa558da..9d528ad 100644 --- a/include/asm-sh/cacheflush.h +++ b/include/asm-sh/cacheflush.h @@ -43,21 +43,31 @@ extern void __flush_purge_region(void *start, int size); extern void __flush_invalidate_region(void *start, int size); #endif -#define flush_cache_vmap(start, end) flush_cache_all() -#define flush_cache_vunmap(start, end) flush_cache_all() +#if defined(CONFIG_CPU_SH4) && !defined(CONFIG_CACHE_OFF) +extern void copy_to_user_page(struct vm_area_struct *vma, + struct page *page, unsigned long vaddr, void *dst, const void *src, + unsigned long len); -#define copy_to_user_page(vma, page, vaddr, dst, src, len) \ +extern void copy_from_user_page(struct vm_area_struct *vma, + struct page *page, unsigned long vaddr, void *dst, const void *src, + unsigned long len); +#else +#define copy_to_user_page(vma, page, vaddr, dst, src, len) \ do { \ flush_cache_page(vma, vaddr, page_to_pfn(page));\ memcpy(dst, src, len); \ flush_icache_user_range(vma, page, vaddr, len); \ } while (0) -#define copy_from_user_page(vma, page, vaddr, dst, src, len) \ +#define copy_from_user_page(vma, page, vaddr, dst, src, len) \ do { \ flush_cache_page(vma, vaddr, page_to_pfn(page));\ memcpy(dst, src, len); \ } while (0) +#endif + +#define flush_cache_vmap(start, end) flush_cache_all() +#define flush_cache_vunmap(start, end) flush_cache_all() #define HAVE_ARCH_UNMAPPED_AREA diff --git a/include/asm-sh/cpu-sh3/timer.h b/include/asm-sh/cpu-sh3/timer.h index 3880ce0..7b795ac 100644 --- a/include/asm-sh/cpu-sh3/timer.h +++ b/include/asm-sh/cpu-sh3/timer.h @@ -23,8 +23,7 @@ * --------------------------------------------------------------------------- */ -#if !defined(CONFIG_CPU_SUBTYPE_SH7720) && \ - !defined(CONFIG_CPU_SUBTYPE_SH7727) +#if !defined(CONFIG_CPU_SUBTYPE_SH7720) #define TMU_TOCR 0xfffffe90 /* Byte access */ #endif @@ -58,8 +57,7 @@ #define TMU2_TCOR 0xfffffeac /* Long access */ #define TMU2_TCNT 0xfffffeb0 /* Long access */ #define TMU2_TCR 0xfffffeb4 /* Word access */ -#if !defined(CONFIG_CPU_SUBTYPE_SH7720) && \ - !defined(CONFIG_CPU_SUBTYPE_SH7727) +#if !defined(CONFIG_CPU_SUBTYPE_SH7720) #define TMU2_TCPR2 0xfffffeb8 /* Long access */ #endif #endif diff --git a/include/asm-sh/page.h b/include/asm-sh/page.h index 3aa8b07..d00a8fd 100644 --- a/include/asm-sh/page.h +++ b/include/asm-sh/page.h @@ -73,10 +73,13 @@ extern void copy_page_nommu(void *to, void *from); #if !defined(CONFIG_CACHE_OFF) && defined(CONFIG_MMU) && \ (defined(CONFIG_CPU_SH4) || defined(CONFIG_SH7705_CACHE_32KB)) struct page; -extern void clear_user_page(void *to, unsigned long address, struct page *pg); -extern void copy_user_page(void *to, void *from, unsigned long address, struct page *pg); -extern void __clear_user_page(void *to, void *orig_to); -extern void __copy_user_page(void *to, void *from, void *orig_to); +struct vm_area_struct; +extern void clear_user_page(void *to, unsigned long address, struct page *page); +#ifdef CONFIG_CPU_SH4 +extern void copy_user_highpage(struct page *to, struct page *from, + unsigned long vaddr, struct vm_area_struct *vma); +#define __HAVE_ARCH_COPY_USER_HIGHPAGE +#endif #else #define clear_user_page(page, vaddr, pg) clear_page(page) #define copy_user_page(to, from, vaddr, pg) copy_page(to, from) diff --git a/include/asm-sh/pgtable.h b/include/asm-sh/pgtable.h index 0b1d7c6..8f1e8be 100644 --- a/include/asm-sh/pgtable.h +++ b/include/asm-sh/pgtable.h @@ -322,7 +322,9 @@ extern unsigned long empty_zero_page[PAGE_SIZE / sizeof(unsigned long)]; #define PAGE_KERNEL __pgprot(0) #define PAGE_KERNEL_NOCACHE __pgprot(0) #define PAGE_KERNEL_RO __pgprot(0) -#define PAGE_KERNEL_PCC __pgprot(0) + +#define PAGE_KERNEL_PCC(slot, type) \ + __pgprot(0) #endif #endif /* __ASSEMBLY__ */ diff --git a/include/asm-sh/processor.h b/include/asm-sh/processor.h index ab0028d..fda6848 100644 --- a/include/asm-sh/processor.h +++ b/include/asm-sh/processor.h @@ -49,7 +49,7 @@ enum cpu_type { /* SH-4 types */ CPU_SH7750, CPU_SH7750S, CPU_SH7750R, CPU_SH7751, CPU_SH7751R, - CPU_SH7760, CPU_ST40RA, CPU_ST40GX1, CPU_SH4_202, CPU_SH4_501, + CPU_SH7760, CPU_SH4_202, CPU_SH4_501, /* SH-4A types */ CPU_SH7770, CPU_SH7780, CPU_SH7781, CPU_SH7785, CPU_SHX3, diff --git a/include/asm-sh/ptrace.h b/include/asm-sh/ptrace.h index ed358a3..b9789c8 100644 --- a/include/asm-sh/ptrace.h +++ b/include/asm-sh/ptrace.h @@ -42,9 +42,6 @@ #define REG_FPSCR 55 #define REG_FPUL 56 -/* options set using PTRACE_SETOPTIONS */ -#define PTRACE_O_TRACESYSGOOD 0x00000001 - /* * This struct defines the way the registers are stored on the * kernel stack during a system call or other kernel entry. diff --git a/include/asm-sh/vga.h b/include/asm-sh/vga.h new file mode 100644 index 0000000..06a5de8 --- /dev/null +++ b/include/asm-sh/vga.h @@ -0,0 +1,6 @@ +#ifndef __ASM_SH_VGA_H +#define __ASM_SH_VGA_H + +/* Stupid drivers. */ + +#endif /* __ASM_SH_VGA_H */ diff --git a/include/asm-sh64/ptrace.h b/include/asm-sh64/ptrace.h index a6d4da5..c424f80 100644 --- a/include/asm-sh64/ptrace.h +++ b/include/asm-sh64/ptrace.h @@ -32,6 +32,4 @@ struct pt_regs { extern void show_regs(struct pt_regs *); #endif -#define PTRACE_O_TRACESYSGOOD 0x00000001 - #endif /* __ASM_SH64_PTRACE_H */ diff --git a/include/asm-sparc64/vio.h b/include/asm-sparc64/vio.h index f7417e9..d4de32f 100644 --- a/include/asm-sparc64/vio.h +++ b/include/asm-sparc64/vio.h @@ -8,6 +8,7 @@ #include <linux/spinlock.h> #include <linux/completion.h> #include <linux/list.h> +#include <linux/log2.h> #include <asm/ldc.h> #include <asm/mdesc.h> @@ -257,8 +258,7 @@ static inline void *vio_dring_entry(struct vio_dring_state *dr, static inline u32 vio_dring_avail(struct vio_dring_state *dr, unsigned int ring_size) { - /* Ensure build-time power-of-2. */ - BUILD_BUG_ON(ring_size & (ring_size - 1)); + BUILD_BUG_ON(!is_power_of_2(ring_size)); return (dr->pending - ((dr->prod - dr->cons) & (ring_size - 1))); diff --git a/include/asm-um/pgtable-3level.h b/include/asm-um/pgtable-3level.h index aa82b88..3ebafba 100644 --- a/include/asm-um/pgtable-3level.h +++ b/include/asm-um/pgtable-3level.h @@ -71,7 +71,7 @@ static inline pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long address) static inline void pud_clear (pud_t *pud) { - set_pud(pud, __pud(0)); + set_pud(pud, __pud(_PAGE_NEWPAGE)); } #define pud_page(pud) phys_to_page(pud_val(pud) & PAGE_MASK) diff --git a/include/asm-x86/acpi.h b/include/asm-x86/acpi.h index 0693689..f8a8979 100644 --- a/include/asm-x86/acpi.h +++ b/include/asm-x86/acpi.h @@ -1,5 +1,32 @@ +#ifndef _ASM_X86_ACPI_H +#define _ASM_X86_ACPI_H + #ifdef CONFIG_X86_32 # include "acpi_32.h" #else # include "acpi_64.h" #endif + +#include <asm/processor.h> + +/* + * Check if the CPU can handle C2 and deeper + */ +static inline unsigned int acpi_processor_cstate_check(unsigned int max_cstate) +{ + /* + * Early models (<=5) of AMD Opterons are not supposed to go into + * C2 state. + * + * Steppings 0x0A and later are good + */ + if (boot_cpu_data.x86 == 0x0F && + boot_cpu_data.x86_vendor == X86_VENDOR_AMD && + boot_cpu_data.x86_model <= 0x05 && + boot_cpu_data.x86_mask < 0x0A) + return 1; + else + return max_cstate; +} + +#endif diff --git a/include/asm-x86/apic_32.h b/include/asm-x86/apic_32.h index 4091b33..be158b2 100644 --- a/include/asm-x86/apic_32.h +++ b/include/asm-x86/apic_32.h @@ -120,6 +120,7 @@ extern int local_apic_timer_disabled; #else /* !CONFIG_X86_LOCAL_APIC */ static inline void lapic_shutdown(void) { } +#define local_apic_timer_c2_ok 1 #endif /* !CONFIG_X86_LOCAL_APIC */ diff --git a/include/asm-x86/i387_64.h b/include/asm-x86/i387_64.h index 0217b74..3a4ffba 100644 --- a/include/asm-x86/i387_64.h +++ b/include/asm-x86/i387_64.h @@ -203,6 +203,11 @@ static inline void save_init_fpu(struct task_struct *tsk) */ static inline int restore_i387(struct _fpstate __user *buf) { + set_used_math(); + if (!(task_thread_info(current)->status & TS_USEDFPU)) { + clts(); + task_thread_info(current)->status |= TS_USEDFPU; + } return restore_fpu_checking((__force struct i387_fxsave_struct *)buf); } diff --git a/include/asm-x86/mach-default/mach_reboot.h b/include/asm-x86/mach-default/mach_reboot.h index e23fd9f..6adee6a 100644 --- a/include/asm-x86/mach-default/mach_reboot.h +++ b/include/asm-x86/mach-default/mach_reboot.h @@ -49,7 +49,7 @@ static inline void mach_reboot(void) udelay(50); kb_wait(); udelay(50); - outb(cmd | 0x04, 0x60); /* set "System flag" */ + outb(cmd | 0x14, 0x60); /* set "System flag" and "Keyboard Disabled" */ udelay(50); kb_wait(); udelay(50); diff --git a/include/asm-x86/mach-es7000/mach_mpparse.h b/include/asm-x86/mach-es7000/mach_mpparse.h index 8aa1054..52ee75c 100644 --- a/include/asm-x86/mach-es7000/mach_mpparse.h +++ b/include/asm-x86/mach-es7000/mach_mpparse.h @@ -29,9 +29,9 @@ extern int mps_oem_check(struct mp_config_table *mpc, char *oem, static inline int es7000_check_dsdt(void) { struct acpi_table_header header; - memcpy(&header, 0, sizeof(struct acpi_table_header)); - acpi_get_table_header(ACPI_SIG_DSDT, 0, &header); - if (!strncmp(header.oem_id, "UNISYS", 6)) + + if (ACPI_SUCCESS(acpi_get_table_header(ACPI_SIG_DSDT, 0, &header)) && + !strncmp(header.oem_id, "UNISYS", 6)) return 1; return 0; } diff --git a/include/asm-x86/mach-voyager/setup_arch.h b/include/asm-x86/mach-voyager/setup_arch.h index 84d01ad..71729ca 100644 --- a/include/asm-x86/mach-voyager/setup_arch.h +++ b/include/asm-x86/mach-voyager/setup_arch.h @@ -1,5 +1,7 @@ #include <asm/voyager.h> -#define VOYAGER_BIOS_INFO ((struct voyager_bios_info *)(PARAM+0x40)) +#include <asm/setup.h> +#define VOYAGER_BIOS_INFO ((struct voyager_bios_info *) \ + (&boot_params.apm_bios_info)) /* Hook to call BIOS initialisation function */ diff --git a/include/asm-x86/ptrace.h b/include/asm-x86/ptrace.h index 213c973..51ddb25 100644 --- a/include/asm-x86/ptrace.h +++ b/include/asm-x86/ptrace.h @@ -60,7 +60,7 @@ static inline int v8086_mode(struct pt_regs *regs) #define instruction_pointer(regs) ((regs)->eip) #define frame_pointer(regs) ((regs)->ebp) -#define stack_pointer(regs) ((regs)->esp) +#define stack_pointer(regs) ((unsigned long)(regs)) #define regs_return_value(regs) ((regs)->eax) extern unsigned long profile_pc(struct pt_regs *regs); diff --git a/include/linux/acpi.h b/include/linux/acpi.h index 8ccedf7..e3c16c9 100644 --- a/include/linux/acpi.h +++ b/include/linux/acpi.h @@ -132,6 +132,11 @@ extern unsigned long acpi_realmode_flags; int acpi_register_gsi (u32 gsi, int triggering, int polarity); int acpi_gsi_to_irq (u32 gsi, unsigned int *irq); +#ifdef CONFIG_X86_IO_APIC +extern int acpi_get_override_irq(int bus_irq, int *trigger, int *polarity); +#else +#define acpi_get_override_irq(bus, trigger, polarity) (-1) +#endif /* * This function undoes the effect of one call to acpi_register_gsi(). * If this matches the last registration, any IRQ resources for gsi diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index 8396db2..d18ee67 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h @@ -697,6 +697,7 @@ extern int blk_execute_rq(struct request_queue *, struct gendisk *, extern void blk_execute_rq_nowait(struct request_queue *, struct gendisk *, struct request *, int, rq_end_io_fn *); extern int blk_verify_command(unsigned char *, int); +extern void blk_unplug(struct request_queue *q); static inline struct request_queue *bdev_get_queue(struct block_device *bdev) { diff --git a/include/linux/cgroup_subsys.h b/include/linux/cgroup_subsys.h index 0b9bfbd..d62fcee 100644 --- a/include/linux/cgroup_subsys.h +++ b/include/linux/cgroup_subsys.h @@ -13,12 +13,6 @@ SUBSYS(cpuset) /* */ -#ifdef CONFIG_CGROUP_CPUACCT -SUBSYS(cpuacct) -#endif - -/* */ - #ifdef CONFIG_CGROUP_DEBUG SUBSYS(debug) #endif diff --git a/include/linux/cpu_acct.h b/include/linux/cpu_acct.h deleted file mode 100644 index 6b5fd8a..0000000 --- a/include/linux/cpu_acct.h +++ /dev/null @@ -1,14 +0,0 @@ - -#ifndef _LINUX_CPU_ACCT_H -#define _LINUX_CPU_ACCT_H - -#include <linux/cgroup.h> -#include <asm/cputime.h> - -#ifdef CONFIG_CGROUP_CPUACCT -extern void cpuacct_charge(struct task_struct *, cputime_t cputime); -#else -static void inline cpuacct_charge(struct task_struct *p, cputime_t cputime) {} -#endif - -#endif diff --git a/include/linux/cpuidle.h b/include/linux/cpuidle.h index 16a5154..c4e0016 100644 --- a/include/linux/cpuidle.h +++ b/include/linux/cpuidle.h @@ -92,6 +92,7 @@ struct cpuidle_device { struct kobject kobj; struct completion kobj_unregister; void *governor_data; + struct cpuidle_state *safe_state; }; DECLARE_PER_CPU(struct cpuidle_device *, cpuidle_devices); diff --git a/include/linux/ext2_fs.h b/include/linux/ext2_fs.h index 0f6c86c..84cec2a 100644 --- a/include/linux/ext2_fs.h +++ b/include/linux/ext2_fs.h @@ -563,11 +563,4 @@ enum { ~EXT2_DIR_ROUND) #define EXT2_MAX_REC_LEN ((1<<16)-1) -static inline ext2_fsblk_t -ext2_group_first_block_no(struct super_block *sb, unsigned long group_no) -{ - return group_no * (ext2_fsblk_t)EXT2_BLOCKS_PER_GROUP(sb) + - le32_to_cpu(EXT2_SB(sb)->s_es->s_first_data_block); -} - #endif /* _LINUX_EXT2_FS_H */ diff --git a/include/linux/ext3_fs.h b/include/linux/ext3_fs.h index 6413445..241c01c 100644 --- a/include/linux/ext3_fs.h +++ b/include/linux/ext3_fs.h @@ -656,6 +656,26 @@ struct ext3_dir_entry_2 { #define EXT3_DIR_ROUND (EXT3_DIR_PAD - 1) #define EXT3_DIR_REC_LEN(name_len) (((name_len) + 8 + EXT3_DIR_ROUND) & \ ~EXT3_DIR_ROUND) +#define EXT3_MAX_REC_LEN ((1<<16)-1) + +static inline unsigned ext3_rec_len_from_disk(__le16 dlen) +{ + unsigned len = le16_to_cpu(dlen); + + if (len == EXT3_MAX_REC_LEN) + return 1 << 16; + return len; +} + +static inline __le16 ext3_rec_len_to_disk(unsigned len) +{ + if (len == (1 << 16)) + return cpu_to_le16(EXT3_MAX_REC_LEN); + else if (len > (1 << 16)) + BUG(); + return cpu_to_le16(len); +} + /* * Hash Tree Directory indexing * (c) Daniel Phillips, 2001 diff --git a/include/linux/f75375s.h b/include/linux/f75375s.h new file mode 100644 index 0000000..e99e225 --- /dev/null +++ b/include/linux/f75375s.h @@ -0,0 +1,21 @@ +/* + * f75375s.h - platform data structure for f75375s sensor + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 2007, Riku Voipio <riku.voipio@iki.fi> + */ + +#ifndef __LINUX_F75375S_H +#define __LINUX_F75375S_H + +/* We want to set fans spinning on systems where there is no + * BIOS to do that for us */ +struct f75375s_platform_data { + u8 pwm[2]; + u8 pwm_enable[2]; +}; + +#endif /* __LINUX_F75375S_H */ diff --git a/include/linux/fuse.h b/include/linux/fuse.h index d0c4370..5c86f11 100644 --- a/include/linux/fuse.h +++ b/include/linux/fuse.h @@ -16,6 +16,7 @@ * - add lk_flags in fuse_lk_in * - add lock_owner field to fuse_setattr_in, fuse_read_in and fuse_write_in * - add blksize field to fuse_attr + * - add file flags field to fuse_read_in and fuse_write_in */ #include <asm/types.h> @@ -280,6 +281,8 @@ struct fuse_read_in { __u32 size; __u32 read_flags; __u64 lock_owner; + __u32 flags; + __u32 padding; }; #define FUSE_COMPAT_WRITE_IN_SIZE 24 @@ -290,6 +293,8 @@ struct fuse_write_in { __u32 size; __u32 write_flags; __u64 lock_owner; + __u32 flags; + __u32 padding; }; struct fuse_write_out { diff --git a/include/linux/hugetlb.h b/include/linux/hugetlb.h index ea0f50b..2496879 100644 --- a/include/linux/hugetlb.h +++ b/include/linux/hugetlb.h @@ -19,7 +19,7 @@ static inline int is_vm_hugetlb_page(struct vm_area_struct *vma) int hugetlb_sysctl_handler(struct ctl_table *, int, struct file *, void __user *, size_t *, loff_t *); int hugetlb_treat_movable_handler(struct ctl_table *, int, struct file *, void __user *, size_t *, loff_t *); int copy_hugetlb_page_range(struct mm_struct *, struct mm_struct *, struct vm_area_struct *); -int follow_hugetlb_page(struct mm_struct *, struct vm_area_struct *, struct page **, struct vm_area_struct **, unsigned long *, int *, int); +int follow_hugetlb_page(struct mm_struct *, struct vm_area_struct *, struct page **, struct vm_area_struct **, unsigned long *, int *, int, int); void unmap_hugepage_range(struct vm_area_struct *, unsigned long, unsigned long); void __unmap_hugepage_range(struct vm_area_struct *, unsigned long, unsigned long); int hugetlb_prefault(struct address_space *, struct vm_area_struct *); @@ -106,7 +106,7 @@ static inline unsigned long hugetlb_total_pages(void) return 0; } -#define follow_hugetlb_page(m,v,p,vs,a,b,i) ({ BUG(); 0; }) +#define follow_hugetlb_page(m,v,p,vs,a,b,i,w) ({ BUG(); 0; }) #define follow_huge_addr(mm, addr, write) ERR_PTR(-EINVAL) #define copy_hugetlb_page_range(src, dst, vma) ({ BUG(); 0; }) #define hugetlb_prefault(mapping, vma) ({ BUG(); 0; }) @@ -165,8 +165,10 @@ static inline struct hugetlbfs_sb_info *HUGETLBFS_SB(struct super_block *sb) extern const struct file_operations hugetlbfs_file_operations; extern struct vm_operations_struct hugetlb_vm_ops; struct file *hugetlb_file_setup(const char *name, size_t); -int hugetlb_get_quota(struct address_space *mapping); -void hugetlb_put_quota(struct address_space *mapping); +int hugetlb_get_quota(struct address_space *mapping, long delta); +void hugetlb_put_quota(struct address_space *mapping, long delta); + +#define BLOCKS_PER_HUGEPAGE (HPAGE_SIZE / 512) static inline int is_file_hugepages(struct file *file) { diff --git a/include/linux/i2c.h b/include/linux/i2c.h index 8033e6b..a100c9f 100644 --- a/include/linux/i2c.h +++ b/include/linux/i2c.h @@ -400,11 +400,6 @@ extern int i2c_release_client(struct i2c_client *); extern void i2c_clients_command(struct i2c_adapter *adap, unsigned int cmd, void *arg); -/* returns -EBUSY if address has been taken, 0 if not. Note that the only - other place at which this is called is within i2c_attach_client; so - you can cheat by simply not registering. Not recommended, of course! */ -extern int i2c_check_addr (struct i2c_adapter *adapter, int addr); - /* Detect function. It iterates over all possible addresses itself. * It will only call found_proc if some client is connected at the * specific address (unless a 'force' matched); diff --git a/include/linux/input.h b/include/linux/input.h index b45f240..2075d6d 100644 --- a/include/linux/input.h +++ b/include/linux/input.h @@ -530,6 +530,11 @@ struct input_absinfo { #define KEY_DOLLAR 0x1b2 #define KEY_EURO 0x1b3 +#define KEY_FRAMEBACK 0x1b4 /* Consumer - transport controls */ +#define KEY_FRAMEFORWARD 0x1b5 + +#define KEY_CONTEXT_MENU 0x1b6 /* GenDesc - system context menu */ + #define KEY_DEL_EOL 0x1c0 #define KEY_DEL_EOS 0x1c1 #define KEY_INS_LINE 0x1c2 diff --git a/include/linux/kd.h b/include/linux/kd.h index c91fc0c..15f2853 100644 --- a/include/linux/kd.h +++ b/include/linux/kd.h @@ -126,7 +126,7 @@ struct kbdiacrs { #define KDSKBDIACR 0x4B4B /* write kernel accent table */ struct kbdiacruc { - __u32 diacr, base, result; + unsigned int diacr, base, result; }; struct kbdiacrsuc { unsigned int kb_cnt; /* number of entries in following array */ diff --git a/include/linux/libata.h b/include/linux/libata.h index 56a5673..ef52a07 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -340,6 +340,7 @@ enum { ATA_HORKAGE_HPA_SIZE = (1 << 6), /* native size off by one */ ATA_HORKAGE_IPM = (1 << 7), /* Link PM problems */ ATA_HORKAGE_IVB = (1 << 8), /* cbl det validity bit bugs */ + ATA_HORKAGE_STUCK_ERR = (1 << 9), /* stuck ERR on next PACKET */ /* DMA mask for user DMA control: User visible values; DO NOT renumber */ @@ -771,8 +772,6 @@ static inline int ata_port_is_dummy(struct ata_port *ap) extern void sata_print_link_status(struct ata_link *link); extern void ata_port_probe(struct ata_port *); -extern void __sata_phy_reset(struct ata_port *ap); -extern void sata_phy_reset(struct ata_port *ap); extern void ata_bus_reset(struct ata_port *ap); extern int sata_set_spd(struct ata_link *link); extern int sata_link_debounce(struct ata_link *link, @@ -994,8 +993,6 @@ extern void sata_pmp_do_eh(struct ata_port *ap, /* * EH */ -extern void ata_eng_timeout(struct ata_port *ap); - extern void ata_port_schedule_eh(struct ata_port *ap); extern int ata_link_abort(struct ata_link *link); extern int ata_port_abort(struct ata_port *ap); diff --git a/include/linux/mc146818rtc.h b/include/linux/mc146818rtc.h index 580b3f4..2f4e957 100644 --- a/include/linux/mc146818rtc.h +++ b/include/linux/mc146818rtc.h @@ -109,8 +109,11 @@ struct cmos_rtc_board_info { #ifndef ARCH_RTC_LOCATION /* Override by <asm/mc146818rtc.h>? */ #define RTC_IO_EXTENT 0x8 +#define RTC_IO_EXTENT_USED 0x2 #define RTC_IOMAPPED 1 /* Default to I/O mapping. */ +#else +#define RTC_IO_EXTENT_USED RTC_IO_EXTENT #endif /* ARCH_RTC_LOCATION */ #endif /* _MC146818RTC_H */ diff --git a/include/linux/mroute.h b/include/linux/mroute.h index 7da2cee..35a8277 100644 --- a/include/linux/mroute.h +++ b/include/linux/mroute.h @@ -128,6 +128,18 @@ struct igmpmsg #ifdef __KERNEL__ #include <net/sock.h> +#ifdef CONFIG_IP_MROUTE +static inline int ip_mroute_opt(int opt) +{ + return (opt >= MRT_BASE) && (opt <= MRT_BASE + 10); +} +#else +static inline int ip_mroute_opt(int opt) +{ + return 0; +} +#endif + extern int ip_mroute_setsockopt(struct sock *, int, char __user *, int); extern int ip_mroute_getsockopt(struct sock *, int, char __user *, int __user *); extern int ipmr_ioctl(struct sock *sk, int cmd, void __user *arg); diff --git a/include/linux/net.h b/include/linux/net.h index dd79cdb..596131e 100644 --- a/include/linux/net.h +++ b/include/linux/net.h @@ -95,6 +95,12 @@ enum sock_type { #endif /* ARCH_HAS_SOCKET_TYPES */ +enum sock_shutdown_cmd { + SHUT_RD = 0, + SHUT_WR = 1, + SHUT_RDWR = 2, +}; + /** * struct socket - general BSD socket * @state: socket state (%SS_CONNECTED, etc) @@ -223,6 +229,8 @@ extern int kernel_setsockopt(struct socket *sock, int level, int optname, extern int kernel_sendpage(struct socket *sock, struct page *page, int offset, size_t size, int flags); extern int kernel_sock_ioctl(struct socket *sock, int cmd, unsigned long arg); +extern int kernel_sock_shutdown(struct socket *sock, + enum sock_shutdown_cmd how); #ifndef CONFIG_SMP #define SOCKOPS_WRAPPED(name) name diff --git a/include/linux/netfilter/Kbuild b/include/linux/netfilter/Kbuild index f2eaea2..b87e83a 100644 --- a/include/linux/netfilter/Kbuild +++ b/include/linux/netfilter/Kbuild @@ -4,25 +4,28 @@ header-y += nfnetlink_conntrack.h header-y += nfnetlink_log.h header-y += nfnetlink_queue.h header-y += xt_CLASSIFY.h +header-y += xt_CONNMARK.h +header-y += xt_CONNSECMARK.h +header-y += xt_DSCP.h +header-y += xt_MARK.h +header-y += xt_NFLOG.h +header-y += xt_NFQUEUE.h +header-y += xt_SECMARK.h +header-y += xt_TCPMSS.h header-y += xt_comment.h header-y += xt_connbytes.h header-y += xt_connmark.h -header-y += xt_CONNMARK.h header-y += xt_conntrack.h header-y += xt_dccp.h header-y += xt_dscp.h -header-y += xt_DSCP.h header-y += xt_esp.h -header-y += xt_helper.h header-y += xt_hashlimit.h +header-y += xt_helper.h header-y += xt_length.h header-y += xt_limit.h header-y += xt_mac.h header-y += xt_mark.h -header-y += xt_MARK.h header-y += xt_multiport.h -header-y += xt_NFQUEUE.h -header-y += xt_NFLOG.h header-y += xt_pkttype.h header-y += xt_policy.h header-y += xt_realm.h @@ -32,9 +35,6 @@ header-y += xt_statistic.h header-y += xt_string.h header-y += xt_tcpmss.h header-y += xt_tcpudp.h -header-y += xt_SECMARK.h -header-y += xt_CONNSECMARK.h -header-y += xt_TCPMSS.h unifdef-y += nf_conntrack_common.h unifdef-y += nf_conntrack_ftp.h diff --git a/include/linux/netfilter_ipv4/Kbuild b/include/linux/netfilter_ipv4/Kbuild index 7185792..3a7105b 100644 --- a/include/linux/netfilter_ipv4/Kbuild +++ b/include/linux/netfilter_ipv4/Kbuild @@ -1,47 +1,47 @@ -header-y += ipt_addrtype.h -header-y += ipt_ah.h header-y += ipt_CLASSIFY.h header-y += ipt_CLUSTERIP.h +header-y += ipt_CONNMARK.h +header-y += ipt_DSCP.h +header-y += ipt_ECN.h +header-y += ipt_LOG.h +header-y += ipt_MARK.h +header-y += ipt_NFQUEUE.h +header-y += ipt_REJECT.h +header-y += ipt_SAME.h +header-y += ipt_TCPMSS.h +header-y += ipt_TOS.h +header-y += ipt_TTL.h +header-y += ipt_ULOG.h +header-y += ipt_addrtype.h +header-y += ipt_ah.h header-y += ipt_comment.h header-y += ipt_connbytes.h header-y += ipt_connmark.h -header-y += ipt_CONNMARK.h header-y += ipt_conntrack.h header-y += ipt_dccp.h header-y += ipt_dscp.h -header-y += ipt_DSCP.h header-y += ipt_ecn.h -header-y += ipt_ECN.h header-y += ipt_esp.h header-y += ipt_hashlimit.h header-y += ipt_helper.h header-y += ipt_iprange.h header-y += ipt_length.h header-y += ipt_limit.h -header-y += ipt_LOG.h header-y += ipt_mac.h header-y += ipt_mark.h -header-y += ipt_MARK.h header-y += ipt_multiport.h -header-y += ipt_NFQUEUE.h header-y += ipt_owner.h header-y += ipt_physdev.h header-y += ipt_pkttype.h header-y += ipt_policy.h header-y += ipt_realm.h header-y += ipt_recent.h -header-y += ipt_REJECT.h -header-y += ipt_SAME.h header-y += ipt_sctp.h header-y += ipt_state.h header-y += ipt_string.h header-y += ipt_tcpmss.h -header-y += ipt_TCPMSS.h header-y += ipt_tos.h -header-y += ipt_TOS.h header-y += ipt_ttl.h -header-y += ipt_TTL.h -header-y += ipt_ULOG.h unifdef-y += ip_queue.h unifdef-y += ip_tables.h diff --git a/include/linux/netfilter_ipv6/Kbuild b/include/linux/netfilter_ipv6/Kbuild index 9dd978d..8887a5f 100644 --- a/include/linux/netfilter_ipv6/Kbuild +++ b/include/linux/netfilter_ipv6/Kbuild @@ -14,8 +14,8 @@ header-y += ip6t_mark.h header-y += ip6t_multiport.h header-y += ip6t_opts.h header-y += ip6t_owner.h -header-y += ip6t_policy.h header-y += ip6t_physdev.h +header-y += ip6t_policy.h header-y += ip6t_rt.h unifdef-y += ip6_tables.h diff --git a/include/linux/netlink.h b/include/linux/netlink.h index 7c1f3b1..d5bfaba 100644 --- a/include/linux/netlink.h +++ b/include/linux/netlink.h @@ -192,7 +192,7 @@ extern int netlink_unregister_notifier(struct notifier_block *nb); /* finegrained unicast helpers: */ struct sock *netlink_getsockbyfilp(struct file *filp); int netlink_attachskb(struct sock *sk, struct sk_buff *skb, int nonblock, - long timeo, struct sock *ssk); + long *timeo, struct sock *ssk); void netlink_detachskb(struct sock *sk, struct sk_buff *skb); int netlink_sendskb(struct sock *sk, struct sk_buff *skb); diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h index e82a6eb..2d15d4a 100644 --- a/include/linux/nfs_fs.h +++ b/include/linux/nfs_fs.h @@ -422,7 +422,6 @@ extern long nfs_sync_mapping_wait(struct address_space *, struct writeback_contr extern int nfs_wb_all(struct inode *inode); extern int nfs_wb_nocommit(struct inode *inode); extern int nfs_wb_page(struct inode *inode, struct page* page); -extern int nfs_wb_page_priority(struct inode *inode, struct page* page, int how); extern int nfs_wb_page_cancel(struct inode *inode, struct page* page); #if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4) extern int nfs_commit_inode(struct inode *, int); diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index fbe1964..111aa10 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h @@ -1237,6 +1237,10 @@ #define PCI_DEVICE_ID_NVIDIA_NVENET_33 0x0761 #define PCI_DEVICE_ID_NVIDIA_NVENET_34 0x0762 #define PCI_DEVICE_ID_NVIDIA_NVENET_35 0x0763 +#define PCI_DEVICE_ID_NVIDIA_NVENET_36 0x0AB0 +#define PCI_DEVICE_ID_NVIDIA_NVENET_37 0x0AB1 +#define PCI_DEVICE_ID_NVIDIA_NVENET_38 0x0AB2 +#define PCI_DEVICE_ID_NVIDIA_NVENET_39 0x0AB3 #define PCI_VENDOR_ID_IMS 0x10e0 #define PCI_DEVICE_ID_IMS_TT128 0x9128 @@ -2276,6 +2280,9 @@ #define PCI_DEVICE_ID_INTEL_82915G_IG 0x2582 #define PCI_DEVICE_ID_INTEL_82915GM_HB 0x2590 #define PCI_DEVICE_ID_INTEL_82915GM_IG 0x2592 +#define PCI_DEVICE_ID_INTEL_5000_ERR 0x25F0 +#define PCI_DEVICE_ID_INTEL_5000_FBD0 0x25F5 +#define PCI_DEVICE_ID_INTEL_5000_FBD1 0x25F6 #define PCI_DEVICE_ID_INTEL_82945G_HB 0x2770 #define PCI_DEVICE_ID_INTEL_82945G_IG 0x2772 #define PCI_DEVICE_ID_INTEL_3000_HB 0x2778 @@ -2329,6 +2336,7 @@ #define PCI_DEVICE_ID_INTEL_MCH_PC1 0x359a #define PCI_DEVICE_ID_INTEL_E7525_MCH 0x359e #define PCI_DEVICE_ID_INTEL_IOAT_CNB 0x360b +#define PCI_DEVICE_ID_INTEL_IOAT_SNB 0x402f #define PCI_DEVICE_ID_INTEL_IOAT_SCNB 0x65ff #define PCI_DEVICE_ID_INTEL_TOLAPAI_0 0x5031 #define PCI_DEVICE_ID_INTEL_TOLAPAI_1 0x5032 diff --git a/include/linux/phy.h b/include/linux/phy.h index f0742b6..e10763d 100644 --- a/include/linux/phy.h +++ b/include/linux/phy.h @@ -58,6 +58,8 @@ typedef enum { PHY_INTERFACE_MODE_RMII, PHY_INTERFACE_MODE_RGMII, PHY_INTERFACE_MODE_RGMII_ID, + PHY_INTERFACE_MODE_RGMII_RXID, + PHY_INTERFACE_MODE_RGMII_TXID, PHY_INTERFACE_MODE_RTBI } phy_interface_t; diff --git a/include/linux/pid_namespace.h b/include/linux/pid_namespace.h index 0135c76..1689e28 100644 --- a/include/linux/pid_namespace.h +++ b/include/linux/pid_namespace.h @@ -29,6 +29,7 @@ struct pid_namespace { extern struct pid_namespace init_pid_ns; +#ifdef CONFIG_PID_NS static inline struct pid_namespace *get_pid_ns(struct pid_namespace *ns) { if (ns != &init_pid_ns) @@ -45,6 +46,28 @@ static inline void put_pid_ns(struct pid_namespace *ns) kref_put(&ns->kref, free_pid_ns); } +#else /* !CONFIG_PID_NS */ +#include <linux/err.h> + +static inline struct pid_namespace *get_pid_ns(struct pid_namespace *ns) +{ + return ns; +} + +static inline struct pid_namespace * +copy_pid_ns(unsigned long flags, struct pid_namespace *ns) +{ + if (flags & CLONE_NEWPID) + ns = ERR_PTR(-EINVAL); + return ns; +} + +static inline void put_pid_ns(struct pid_namespace *ns) +{ +} + +#endif /* CONFIG_PID_NS */ + static inline struct pid_namespace *task_active_pid_ns(struct task_struct *tsk) { return tsk->nsproxy->pid_ns; diff --git a/include/linux/pnp.h b/include/linux/pnp.h index 664d68c..0a0426c 100644 --- a/include/linux/pnp.h +++ b/include/linux/pnp.h @@ -13,8 +13,8 @@ #include <linux/errno.h> #include <linux/mod_devicetable.h> -#define PNP_MAX_PORT 8 -#define PNP_MAX_MEM 4 +#define PNP_MAX_PORT 24 +#define PNP_MAX_MEM 12 #define PNP_MAX_IRQ 2 #define PNP_MAX_DMA 2 #define PNP_NAME_LEN 50 diff --git a/include/linux/proc_fs.h b/include/linux/proc_fs.h index 1ff4616..523528d 100644 --- a/include/linux/proc_fs.h +++ b/include/linux/proc_fs.h @@ -48,6 +48,8 @@ typedef int (read_proc_t)(char *page, char **start, off_t off, typedef int (write_proc_t)(struct file *file, const char __user *buffer, unsigned long count, void *data); typedef int (get_info_t)(char *, char **, off_t, int); +typedef struct proc_dir_entry *(shadow_proc_t)(struct task_struct *task, + struct proc_dir_entry *pde); struct proc_dir_entry { unsigned int low_ino; @@ -79,6 +81,7 @@ struct proc_dir_entry { int pde_users; /* number of callers into module in progress */ spinlock_t pde_unload_lock; /* proc_fops checks and pde_users bumps */ struct completion *pde_unload_completion; + shadow_proc_t *shadow_proc; }; struct kcore_list { @@ -196,8 +199,6 @@ static inline struct proc_dir_entry *create_proc_info_entry(const char *name, return res; } -extern struct proc_dir_entry *proc_net_create(struct net *net, - const char *name, mode_t mode, get_info_t *get_info); extern struct proc_dir_entry *proc_net_fops_create(struct net *net, const char *name, mode_t mode, const struct file_operations *fops); extern void proc_net_remove(struct net *net, const char *name); @@ -208,7 +209,6 @@ extern void proc_net_remove(struct net *net, const char *name); #define proc_bus NULL #define proc_net_fops_create(net, name, mode, fops) ({ (void)(mode), NULL; }) -#define proc_net_create(net, name, mode, info) ({ (void)(mode), NULL; }) static inline void proc_net_remove(struct net *net, const char *name) {} static inline void proc_flush_task(struct task_struct *task) diff --git a/include/linux/rtc.h b/include/linux/rtc.h index 6d5e4a4..f2d0d15 100644 --- a/include/linux/rtc.h +++ b/include/linux/rtc.h @@ -133,6 +133,9 @@ struct rtc_class_ops { #define RTC_DEVICE_NAME_SIZE 20 struct rtc_task; +/* flags */ +#define RTC_DEV_BUSY 0 + struct rtc_device { struct device dev; @@ -145,7 +148,7 @@ struct rtc_device struct mutex ops_lock; struct cdev char_dev; - struct mutex char_lock; + unsigned long flags; unsigned long irq_data; spinlock_t irq_lock; diff --git a/include/linux/rtnetlink.h b/include/linux/rtnetlink.h index 5bf6182..4e81836 100644 --- a/include/linux/rtnetlink.h +++ b/include/linux/rtnetlink.h @@ -491,9 +491,11 @@ struct nduseroptmsg unsigned char nduseropt_family; unsigned char nduseropt_pad1; unsigned short nduseropt_opts_len; /* Total length of options */ + int nduseropt_ifindex; __u8 nduseropt_icmp_type; __u8 nduseropt_icmp_code; unsigned short nduseropt_pad2; + unsigned int nduseropt_pad3; /* Followed by one or more ND options */ }; diff --git a/include/linux/scatterlist.h b/include/linux/scatterlist.h index 2597350..416e000 100644 --- a/include/linux/scatterlist.h +++ b/include/linux/scatterlist.h @@ -26,6 +26,16 @@ #define SG_MAGIC 0x87654321 +/* + * We overload the LSB of the page pointer to indicate whether it's + * a valid sg entry, or whether it points to the start of a new scatterlist. + * Those low bits are there for everyone! (thanks mason :-) + */ +#define sg_is_chain(sg) ((sg)->page_link & 0x01) +#define sg_is_last(sg) ((sg)->page_link & 0x02) +#define sg_chain_ptr(sg) \ + ((struct scatterlist *) ((sg)->page_link & ~0x03)) + /** * sg_assign_page - Assign a given page to an SG entry * @sg: SG entry @@ -47,6 +57,7 @@ static inline void sg_assign_page(struct scatterlist *sg, struct page *page) BUG_ON((unsigned long) page & 0x03); #ifdef CONFIG_DEBUG_SG BUG_ON(sg->sg_magic != SG_MAGIC); + BUG_ON(sg_is_chain(sg)); #endif sg->page_link = page_link | (unsigned long) page; } @@ -73,7 +84,14 @@ static inline void sg_set_page(struct scatterlist *sg, struct page *page, sg->length = len; } -#define sg_page(sg) ((struct page *) ((sg)->page_link & ~0x3)) +static inline struct page *sg_page(struct scatterlist *sg) +{ +#ifdef CONFIG_DEBUG_SG + BUG_ON(sg->sg_magic != SG_MAGIC); + BUG_ON(sg_is_chain(sg)); +#endif + return (struct page *)((sg)->page_link & ~0x3); +} /** * sg_set_buf - Set sg entry to point at given data @@ -88,16 +106,6 @@ static inline void sg_set_buf(struct scatterlist *sg, const void *buf, sg_set_page(sg, virt_to_page(buf), buflen, offset_in_page(buf)); } -/* - * We overload the LSB of the page pointer to indicate whether it's - * a valid sg entry, or whether it points to the start of a new scatterlist. - * Those low bits are there for everyone! (thanks mason :-) - */ -#define sg_is_chain(sg) ((sg)->page_link & 0x01) -#define sg_is_last(sg) ((sg)->page_link & 0x02) -#define sg_chain_ptr(sg) \ - ((struct scatterlist *) ((sg)->page_link & ~0x03)) - /** * sg_next - return the next scatterlist entry in a list * @sg: The current sg entry @@ -179,6 +187,13 @@ static inline void sg_chain(struct scatterlist *prv, unsigned int prv_nents, #ifndef ARCH_HAS_SG_CHAIN BUG(); #endif + + /* + * offset and length are unused for chain entry. Clear them. + */ + prv->offset = 0; + prv->length = 0; + /* * Set lowest bit to indicate a link pointer, and make sure to clear * the termination bit if it happens to be set. diff --git a/include/linux/sched.h b/include/linux/sched.h index 155d743..ac3d496 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -254,6 +254,7 @@ long io_schedule_timeout(long timeout); extern void cpu_init (void); extern void trap_init(void); +extern void account_process_tick(struct task_struct *task, int user); extern void update_process_times(int user); extern void scheduler_tick(void); @@ -281,6 +282,10 @@ static inline void touch_all_softlockup_watchdogs(void) /* Attach to any functions which should be ignored in wchan output. */ #define __sched __attribute__((__section__(".sched.text"))) + +/* Linker adds these: start and end of __sched functions */ +extern char __sched_text_start[], __sched_text_end[]; + /* Is this address in the __sched functions? */ extern int in_sched_functions(unsigned long addr); @@ -862,7 +867,6 @@ struct sched_entity { struct load_weight load; /* for load-balancing */ struct rb_node run_node; unsigned int on_rq; - int peer_preempt; u64 exec_start; u64 sum_exec_runtime; @@ -1460,12 +1464,17 @@ extern void sched_idle_next(void); #ifdef CONFIG_SCHED_DEBUG extern unsigned int sysctl_sched_latency; -extern unsigned int sysctl_sched_nr_latency; +extern unsigned int sysctl_sched_min_granularity; extern unsigned int sysctl_sched_wakeup_granularity; extern unsigned int sysctl_sched_batch_wakeup_granularity; extern unsigned int sysctl_sched_child_runs_first; extern unsigned int sysctl_sched_features; extern unsigned int sysctl_sched_migration_cost; +extern unsigned int sysctl_sched_nr_migrate; + +int sched_nr_latency_handler(struct ctl_table *table, int write, + struct file *file, void __user *buffer, size_t *length, + loff_t *ppos); #endif extern unsigned int sysctl_sched_compat_yield; @@ -1983,6 +1992,14 @@ static inline void inc_syscw(struct task_struct *tsk) } #endif +#ifdef CONFIG_SMP +void migration_init(void); +#else +static inline void migration_init(void) +{ +} +#endif + #endif /* __KERNEL__ */ #endif diff --git a/include/linux/screen_info.h b/include/linux/screen_info.h index 827b85b..1ee2c05 100644 --- a/include/linux/screen_info.h +++ b/include/linux/screen_info.h @@ -63,6 +63,8 @@ struct screen_info { #define VIDEO_TYPE_PMAC 0x60 /* PowerMacintosh frame buffer. */ +#define VIDEO_TYPE_EFI 0x70 /* EFI graphic mode */ + #ifdef __KERNEL__ extern struct screen_info screen_info; diff --git a/include/linux/selinux.h b/include/linux/selinux.h index d1b7ca6..6080f73 100644 --- a/include/linux/selinux.h +++ b/include/linux/selinux.h @@ -136,7 +136,7 @@ static inline int selinux_audit_rule_init(u32 field, u32 op, char *rulestr, struct selinux_audit_rule **rule) { - return -ENOTSUPP; + return -EOPNOTSUPP; } static inline void selinux_audit_rule_free(struct selinux_audit_rule *rule) diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h index 6a5203f..9963f81 100644 --- a/include/linux/serial_core.h +++ b/include/linux/serial_core.h @@ -437,7 +437,7 @@ uart_handle_sysrq_char(struct uart_port *port, unsigned int ch) #ifdef SUPPORT_SYSRQ if (port->sysrq) { if (ch && time_before(jiffies, port->sysrq)) { - handle_sysrq(ch, port->info->tty); + handle_sysrq(ch, port->info ? port->info->tty : NULL); port->sysrq = 0; return 1; } diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index 94e4991..bddd50b 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h @@ -356,7 +356,6 @@ static inline struct sk_buff *alloc_skb_fclone(unsigned int size, return __alloc_skb(size, priority, 1, -1); } -extern void kfree_skbmem(struct sk_buff *skb); extern struct sk_buff *skb_morph(struct sk_buff *dst, struct sk_buff *src); extern struct sk_buff *skb_clone(struct sk_buff *skb, gfp_t priority); @@ -387,7 +386,9 @@ extern void skb_truesize_bug(struct sk_buff *skb); static inline void skb_truesize_check(struct sk_buff *skb) { - if (unlikely((int)skb->truesize < sizeof(struct sk_buff) + skb->len)) + int len = sizeof(struct sk_buff) + skb->len; + + if (unlikely((int)skb->truesize < len)) skb_truesize_bug(skb); } diff --git a/include/linux/smp.h b/include/linux/smp.h index 259a13c..c25e66b 100644 --- a/include/linux/smp.h +++ b/include/linux/smp.h @@ -84,11 +84,12 @@ void smp_prepare_boot_cpu(void); * These macros fold the SMP functionality into a single CPU system */ #define raw_smp_processor_id() 0 -static inline int up_smp_call_function(void) +static inline int up_smp_call_function(void (*func)(void *), void *info) { return 0; } -#define smp_call_function(func,info,retry,wait) (up_smp_call_function()) +#define smp_call_function(func, info, retry, wait) \ + (up_smp_call_function(func, info)) #define on_each_cpu(func,info,retry,wait) \ ({ \ local_irq_disable(); \ @@ -107,6 +108,8 @@ static inline void smp_send_reschedule(int cpu) { } local_irq_enable(); \ 0; \ }) +#define smp_call_function_mask(mask, func, info, wait) \ + (up_smp_call_function(func, info)) #endif /* !SMP */ diff --git a/include/linux/sunrpc/debug.h b/include/linux/sunrpc/debug.h index 3347c72..3912cf1 100644 --- a/include/linux/sunrpc/debug.h +++ b/include/linux/sunrpc/debug.h @@ -88,11 +88,6 @@ enum { CTL_SLOTTABLE_TCP, CTL_MIN_RESVPORT, CTL_MAX_RESVPORT, - CTL_SLOTTABLE_RDMA, - CTL_RDMA_MAXINLINEREAD, - CTL_RDMA_MAXINLINEWRITE, - CTL_RDMA_WRITEPADDING, - CTL_RDMA_MEMREG, }; #endif /* _LINUX_SUNRPC_DEBUG_H_ */ diff --git a/include/linux/sunrpc/xprtsock.h b/include/linux/sunrpc/xprtsock.h index 2c6c2c2..c2a46c4 100644 --- a/include/linux/sunrpc/xprtsock.h +++ b/include/linux/sunrpc/xprtsock.h @@ -9,12 +9,6 @@ #ifdef __KERNEL__ -/* - * Socket transport setup operations - */ -struct rpc_xprt *xs_setup_udp(struct xprt_create *args); -struct rpc_xprt *xs_setup_tcp(struct xprt_create *args); - int init_socket_xprt(void); void cleanup_socket_xprt(void); diff --git a/include/linux/sysctl.h b/include/linux/sysctl.h index e99171f..4f5047d 100644 --- a/include/linux/sysctl.h +++ b/include/linux/sysctl.h @@ -70,7 +70,6 @@ enum CTL_ABI=9, /* Binary emulation */ CTL_CPU=10, /* CPU stuff (speed scaling, etc) */ CTL_ARLAN=254, /* arlan wireless driver */ - CTL_APPLDATA=2120, /* s390 appldata */ CTL_S390DBF=5677, /* s390 debug */ CTL_SUNRPC=7249, /* sunrpc debug */ CTL_PM=9899, /* frv power management */ @@ -207,11 +206,6 @@ enum VM_PANIC_ON_OOM=33, /* panic at out-of-memory */ VM_VDSO_ENABLED=34, /* map VDSO into new processes? */ VM_MIN_SLAB=35, /* Percent pages ignored by zone reclaim */ - - /* s390 vm cmm sysctls */ - VM_CMM_PAGES=1111, - VM_CMM_TIMED_PAGES=1112, - VM_CMM_TIMEOUT=1113, }; diff --git a/include/linux/timex.h b/include/linux/timex.h index 37ac3ff..24c6a2b 100644 --- a/include/linux/timex.h +++ b/include/linux/timex.h @@ -137,6 +137,7 @@ struct timex { #define ADJ_TIMECONST 0x0020 /* pll time constant */ #define ADJ_TICK 0x4000 /* tick value */ #define ADJ_OFFSET_SINGLESHOT 0x8001 /* old-fashioned adjtime */ +#define ADJ_OFFSET_SS_READ 0xa001 /* read-only adjtime */ /* xntp 3.4 compatibility names */ #define MOD_OFFSET ADJ_OFFSET diff --git a/include/linux/tty.h b/include/linux/tty.h index 56164d7..c555f54 100644 --- a/include/linux/tty.h +++ b/include/linux/tty.h @@ -332,7 +332,9 @@ extern void tty_ldisc_flush(struct tty_struct *tty); extern int tty_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg); - +extern int tty_mode_ioctl(struct tty_struct *tty, struct file *file, + unsigned int cmd, unsigned long arg); +extern int tty_perform_flush(struct tty_struct *tty, unsigned long arg); extern dev_t tty_devnum(struct tty_struct *tty); extern void proc_clear_tty(struct task_struct *p); extern struct tty_struct *get_current_tty(void); diff --git a/include/linux/usb.h b/include/linux/usb.h index c5c8f16..416ee76 100644 --- a/include/linux/usb.h +++ b/include/linux/usb.h @@ -157,6 +157,7 @@ struct usb_interface { * bound to */ enum usb_interface_condition condition; /* state of binding */ unsigned is_active:1; /* the interface is not suspended */ + unsigned sysfs_files_created:1; /* the sysfs attributes exist */ unsigned needs_remote_wakeup:1; /* driver requires remote wakeup */ struct device dev; /* interface specific device info */ diff --git a/include/linux/usbdevice_fs.h b/include/linux/usbdevice_fs.h index 342dd5a..8ca5a7f 100644 --- a/include/linux/usbdevice_fs.h +++ b/include/linux/usbdevice_fs.h @@ -102,7 +102,8 @@ struct usbdevfs_urb { int start_frame; int number_of_packets; int error_count; - unsigned int signr; /* signal to be sent on error, -1 if none should be sent */ + unsigned int signr; /* signal to be sent on completion, + or 0 if none should be sent. */ void *usercontext; struct usbdevfs_iso_packet_desc iso_frame_desc[0]; }; diff --git a/include/linux/virtio_ring.h b/include/linux/virtio_ring.h index ac69e7b..1a4ed49 100644 --- a/include/linux/virtio_ring.h +++ b/include/linux/virtio_ring.h @@ -67,7 +67,7 @@ struct vring { }; /* The standard layout for the ring is a continuous chunk of memory which looks - * like this. The used fields will be aligned to a "num+1" boundary. + * like this. We assume num is a power of 2. * * struct vring * { @@ -79,8 +79,8 @@ struct vring { * __u16 avail_idx; * __u16 available[num]; * - * // Padding so a correctly-chosen num value will cache-align used_idx. - * char pad[sizeof(struct vring_desc) - sizeof(avail_flags)]; + * // Padding to the next page boundary. + * char pad[]; * * // A ring of used descriptor heads with free-running index. * __u16 used_flags; @@ -88,18 +88,21 @@ struct vring { * struct vring_used_elem used[num]; * }; */ -static inline void vring_init(struct vring *vr, unsigned int num, void *p) +static inline void vring_init(struct vring *vr, unsigned int num, void *p, + unsigned int pagesize) { vr->num = num; vr->desc = p; - vr->avail = p + num*sizeof(struct vring); - vr->used = p + (num+1)*(sizeof(struct vring) + sizeof(__u16)); + vr->avail = p + num*sizeof(struct vring_desc); + vr->used = (void *)(((unsigned long)&vr->avail->ring[num] + pagesize-1) + & ~(pagesize - 1)); } -static inline unsigned vring_size(unsigned int num) +static inline unsigned vring_size(unsigned int num, unsigned int pagesize) { - return (num + 1) * (sizeof(struct vring_desc) + sizeof(__u16)) - + sizeof(__u32) + num * sizeof(struct vring_used_elem); + return ((sizeof(struct vring_desc) * num + sizeof(__u16) * (2 + num) + + pagesize - 1) & ~(pagesize - 1)) + + sizeof(__u16) * 2 + sizeof(struct vring_used_elem) * num; } #ifdef __KERNEL__ diff --git a/include/net/af_unix.h b/include/net/af_unix.h index 0864a77..a1c805d 100644 --- a/include/net/af_unix.h +++ b/include/net/af_unix.h @@ -12,7 +12,7 @@ extern void unix_gc(void); #define UNIX_HASH_SIZE 256 -extern atomic_t unix_tot_inflight; +extern unsigned int unix_tot_inflight; struct unix_address { atomic_t refcnt; diff --git a/include/net/dst.h b/include/net/dst.h index e9ff4a4..2f65e89 100644 --- a/include/net/dst.h +++ b/include/net/dst.h @@ -143,6 +143,13 @@ static inline void dst_hold(struct dst_entry * dst) atomic_inc(&dst->__refcnt); } +static inline void dst_use(struct dst_entry *dst, unsigned long time) +{ + dst_hold(dst); + dst->__use++; + dst->lastuse = time; +} + static inline struct dst_entry * dst_clone(struct dst_entry * dst) { diff --git a/include/net/fib_rules.h b/include/net/fib_rules.h index 017aebd..41a301e 100644 --- a/include/net/fib_rules.h +++ b/include/net/fib_rules.h @@ -107,4 +107,7 @@ extern int fib_rules_unregister(struct fib_rules_ops *); extern int fib_rules_lookup(struct fib_rules_ops *, struct flowi *, int flags, struct fib_lookup_arg *); +extern int fib_default_rule_add(struct fib_rules_ops *, + u32 pref, u32 table, + u32 flags); #endif diff --git a/include/net/ieee80211.h b/include/net/ieee80211.h index 164d132..d8ae484 100644 --- a/include/net/ieee80211.h +++ b/include/net/ieee80211.h @@ -115,8 +115,16 @@ extern u32 ieee80211_debug_level; do { if (ieee80211_debug_level & (level)) \ printk(KERN_DEBUG "ieee80211: %c %s " fmt, \ in_interrupt() ? 'I' : 'U', __FUNCTION__ , ## args); } while (0) +static inline bool ieee80211_ratelimit_debug(u32 level) +{ + return (ieee80211_debug_level & level) && net_ratelimit(); +} #else #define IEEE80211_DEBUG(level, fmt, args...) do {} while (0) +static inline bool ieee80211_ratelimit_debug(u32 level) +{ + return false; +} #endif /* CONFIG_IEEE80211_DEBUG */ /* escape_essid() is intended to be used in debug (and possibly error) diff --git a/include/net/inet_common.h b/include/net/inet_common.h index 227adcb..38d5a1e 100644 --- a/include/net/inet_common.h +++ b/include/net/inet_common.h @@ -13,9 +13,6 @@ struct sock; struct sockaddr; struct socket; -extern void inet_remove_sock(struct sock *sk1); -extern void inet_put_sock(unsigned short num, - struct sock *sk); extern int inet_release(struct socket *sock); extern int inet_stream_connect(struct socket *sock, struct sockaddr * uaddr, @@ -30,7 +27,6 @@ extern int inet_sendmsg(struct kiocb *iocb, struct msghdr *msg, size_t size); extern int inet_shutdown(struct socket *sock, int how); -extern unsigned int inet_poll(struct file * file, struct socket *sock, struct poll_table_struct *wait); extern int inet_listen(struct socket *sock, int backlog); extern void inet_sock_destruct(struct sock *sk); diff --git a/include/net/inet_hashtables.h b/include/net/inet_hashtables.h index 4427dcd..37f6cb1 100644 --- a/include/net/inet_hashtables.h +++ b/include/net/inet_hashtables.h @@ -23,6 +23,7 @@ #include <linux/spinlock.h> #include <linux/types.h> #include <linux/wait.h> +#include <linux/vmalloc.h> #include <net/inet_connection_sock.h> #include <net/inet_sock.h> @@ -37,7 +38,6 @@ * I'll experiment with dynamic table growth later. */ struct inet_ehash_bucket { - rwlock_t lock; struct hlist_head chain; struct hlist_head twchain; }; @@ -100,6 +100,9 @@ struct inet_hashinfo { * TIME_WAIT sockets use a separate chain (twchain). */ struct inet_ehash_bucket *ehash; + rwlock_t *ehash_locks; + unsigned int ehash_size; + unsigned int ehash_locks_mask; /* Ok, let's try this, I give up, we do need a local binding * TCP hash as well as the others for fast bind/connect. @@ -107,7 +110,7 @@ struct inet_hashinfo { struct inet_bind_hashbucket *bhash; unsigned int bhash_size; - unsigned int ehash_size; + /* Note : 4 bytes padding on 64 bit arches */ /* All sockets in TCP_LISTEN state will be in here. This is the only * table where wildcard'd TCP sockets can exist. Hash function here @@ -134,6 +137,61 @@ static inline struct inet_ehash_bucket *inet_ehash_bucket( return &hashinfo->ehash[hash & (hashinfo->ehash_size - 1)]; } +static inline rwlock_t *inet_ehash_lockp( + struct inet_hashinfo *hashinfo, + unsigned int hash) +{ + return &hashinfo->ehash_locks[hash & hashinfo->ehash_locks_mask]; +} + +static inline int inet_ehash_locks_alloc(struct inet_hashinfo *hashinfo) +{ + unsigned int i, size = 256; +#if defined(CONFIG_PROVE_LOCKING) + unsigned int nr_pcpus = 2; +#else + unsigned int nr_pcpus = num_possible_cpus(); +#endif + if (nr_pcpus >= 4) + size = 512; + if (nr_pcpus >= 8) + size = 1024; + if (nr_pcpus >= 16) + size = 2048; + if (nr_pcpus >= 32) + size = 4096; + if (sizeof(rwlock_t) != 0) { +#ifdef CONFIG_NUMA + if (size * sizeof(rwlock_t) > PAGE_SIZE) + hashinfo->ehash_locks = vmalloc(size * sizeof(rwlock_t)); + else +#endif + hashinfo->ehash_locks = kmalloc(size * sizeof(rwlock_t), + GFP_KERNEL); + if (!hashinfo->ehash_locks) + return ENOMEM; + for (i = 0; i < size; i++) + rwlock_init(&hashinfo->ehash_locks[i]); + } + hashinfo->ehash_locks_mask = size - 1; + return 0; +} + +static inline void inet_ehash_locks_free(struct inet_hashinfo *hashinfo) +{ + if (hashinfo->ehash_locks) { +#ifdef CONFIG_NUMA + unsigned int size = (hashinfo->ehash_locks_mask + 1) * + sizeof(rwlock_t); + if (size > PAGE_SIZE) + vfree(hashinfo->ehash_locks); + else +#endif + kfree(hashinfo->ehash_locks); + hashinfo->ehash_locks = NULL; + } +} + extern struct inet_bind_bucket * inet_bind_bucket_create(struct kmem_cache *cachep, struct inet_bind_hashbucket *head, @@ -222,7 +280,7 @@ static inline void __inet_hash(struct inet_hashinfo *hashinfo, sk->sk_hash = inet_sk_ehashfn(sk); head = inet_ehash_bucket(hashinfo, sk->sk_hash); list = &head->chain; - lock = &head->lock; + lock = inet_ehash_lockp(hashinfo, sk->sk_hash); write_lock(lock); } __sk_add_node(sk, list); @@ -253,7 +311,7 @@ static inline void inet_unhash(struct inet_hashinfo *hashinfo, struct sock *sk) inet_listen_wlock(hashinfo); lock = &hashinfo->lhash_lock; } else { - lock = &inet_ehash_bucket(hashinfo, sk->sk_hash)->lock; + lock = inet_ehash_lockp(hashinfo, sk->sk_hash); write_lock_bh(lock); } @@ -354,9 +412,10 @@ static inline struct sock * */ unsigned int hash = inet_ehashfn(daddr, hnum, saddr, sport); struct inet_ehash_bucket *head = inet_ehash_bucket(hashinfo, hash); + rwlock_t *lock = inet_ehash_lockp(hashinfo, hash); prefetch(head->chain.first); - read_lock(&head->lock); + read_lock(lock); sk_for_each(sk, node, &head->chain) { if (INET_MATCH(sk, hash, acookie, saddr, daddr, ports, dif)) goto hit; /* You sunk my battleship! */ @@ -369,7 +428,7 @@ static inline struct sock * } sk = NULL; out: - read_unlock(&head->lock); + read_unlock(lock); return sk; hit: sock_hold(sk); diff --git a/include/net/inetpeer.h b/include/net/inetpeer.h index aa10a81..ad8404b 100644 --- a/include/net/inetpeer.h +++ b/include/net/inetpeer.h @@ -22,7 +22,7 @@ struct inet_peer __be32 v4daddr; /* peer's address */ __u16 avl_height; __u16 ip_id_count; /* IP ID for the next packet */ - struct inet_peer *unused_next, **unused_prevp; + struct list_head unused; __u32 dtime; /* the time of last use of not * referenced entries */ atomic_t refcnt; diff --git a/include/net/ip_fib.h b/include/net/ip_fib.h index 8cadc77..ed514bf 100644 --- a/include/net/ip_fib.h +++ b/include/net/ip_fib.h @@ -185,6 +185,12 @@ static inline void fib_select_default(const struct flowi *flp, struct fib_result } #else /* CONFIG_IP_MULTIPLE_TABLES */ +extern void __init fib4_rules_init(void); + +#ifdef CONFIG_NET_CLS_ROUTE +extern u32 fib_rules_tclass(struct fib_result *res); +#endif + #define ip_fib_local_table fib_get_table(RT_TABLE_LOCAL) #define ip_fib_main_table fib_get_table(RT_TABLE_MAIN) @@ -214,15 +220,6 @@ extern __be32 __fib_res_prefsrc(struct fib_result *res); /* Exported by fib_hash.c */ extern struct fib_table *fib_hash_init(u32 id); -#ifdef CONFIG_IP_MULTIPLE_TABLES -extern void __init fib4_rules_init(void); - -#ifdef CONFIG_NET_CLS_ROUTE -extern u32 fib_rules_tclass(struct fib_result *res); -#endif - -#endif - static inline void fib_combine_itag(u32 *itag, struct fib_result *res) { #ifdef CONFIG_NET_CLS_ROUTE diff --git a/include/net/ip_vs.h b/include/net/ip_vs.h index 4187056..8a7d59b 100644 --- a/include/net/ip_vs.h +++ b/include/net/ip_vs.h @@ -328,40 +328,6 @@ extern int ip_vs_get_debug_level(void); #define FTPDATA __constant_htons(20) /* - * IPVS sysctl variables under the /proc/sys/net/ipv4/vs/ - */ -#define NET_IPV4_VS 21 - -enum { - NET_IPV4_VS_DEBUG_LEVEL=1, - NET_IPV4_VS_AMEMTHRESH=2, - NET_IPV4_VS_AMDROPRATE=3, - NET_IPV4_VS_DROP_ENTRY=4, - NET_IPV4_VS_DROP_PACKET=5, - NET_IPV4_VS_SECURE_TCP=6, - NET_IPV4_VS_TO_ES=7, - NET_IPV4_VS_TO_SS=8, - NET_IPV4_VS_TO_SR=9, - NET_IPV4_VS_TO_FW=10, - NET_IPV4_VS_TO_TW=11, - NET_IPV4_VS_TO_CL=12, - NET_IPV4_VS_TO_CW=13, - NET_IPV4_VS_TO_LA=14, - NET_IPV4_VS_TO_LI=15, - NET_IPV4_VS_TO_SA=16, - NET_IPV4_VS_TO_UDP=17, - NET_IPV4_VS_TO_ICMP=18, - NET_IPV4_VS_LBLC_EXPIRE=19, - NET_IPV4_VS_LBLCR_EXPIRE=20, - NET_IPV4_VS_CACHE_BYPASS=22, - NET_IPV4_VS_EXPIRE_NODEST_CONN=23, - NET_IPV4_VS_SYNC_THRESHOLD=24, - NET_IPV4_VS_NAT_ICMP_SEND=25, - NET_IPV4_VS_EXPIRE_QUIESCENT_TEMPLATE=26, - NET_IPV4_VS_LAST -}; - -/* * TCP State Values */ enum { @@ -520,6 +486,10 @@ struct ip_vs_conn { spinlock_t lock; /* lock for state transition */ volatile __u16 flags; /* status flags */ volatile __u16 state; /* state info */ + volatile __u16 old_state; /* old state, to be used for + * state transition triggerd + * synchronization + */ /* Control members */ struct ip_vs_conn *control; /* Master control connection */ @@ -901,6 +871,10 @@ extern int ip_vs_use_count_inc(void); extern void ip_vs_use_count_dec(void); extern int ip_vs_control_init(void); extern void ip_vs_control_cleanup(void); +extern struct ip_vs_dest * +ip_vs_find_dest(__be32 daddr, __be16 dport, + __be32 vaddr, __be16 vport, __u16 protocol); +extern struct ip_vs_dest *ip_vs_try_bind_dest(struct ip_vs_conn *cp); /* diff --git a/include/net/mac80211.h b/include/net/mac80211.h index 5fcc4c1..17b6039 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -706,11 +706,16 @@ enum ieee80211_hw_flags { * * @queues: number of available hardware transmit queues for * data packets. WMM/QoS requires at least four. + * + * @rate_control_algorithm: rate control algorithm for this hardware. + * If unset (NULL), the default algorithm will be used. Must be + * set before calling ieee80211_register_hw(). */ struct ieee80211_hw { struct ieee80211_conf conf; struct wiphy *wiphy; struct workqueue_struct *workqueue; + const char *rate_control_algorithm; void *priv; u32 flags; unsigned int extra_tx_headroom; @@ -936,27 +941,11 @@ enum ieee80211_erp_change_flags { * and remove_interface calls, i.e. while the interface with the * given local_address is enabled. * - * @set_ieee8021x: Enable/disable IEEE 802.1X. This item requests wlan card - * to pass unencrypted EAPOL-Key frames even when encryption is - * configured. If the wlan card does not require such a configuration, - * this function pointer can be set to NULL. - * - * @set_port_auth: Set port authorization state (IEEE 802.1X PAE) to be - * authorized (@authorized=1) or unauthorized (=0). This function can be - * used if the wlan hardware or low-level driver implements PAE. - * mac80211 will filter frames based on authorization state in any case, - * so this function pointer can be NULL if low-level driver does not - * require event notification about port state changes. - * * @hw_scan: Ask the hardware to service the scan request, no need to start * the scan state machine in stack. * * @get_stats: return low-level statistics * - * @set_privacy_invoked: For devices that generate their own beacons and probe - * response or association responses this updates the state of privacy_invoked - * returns 0 for success or an error number. - * * @get_sequence_counter: For devices that have internal sequence counters this * callback allows mac80211 to access the current value of a counter. * This callback seems not well-defined, tell us if you need it. @@ -1029,14 +1018,9 @@ struct ieee80211_ops { int (*set_key)(struct ieee80211_hw *hw, enum set_key_cmd cmd, const u8 *local_address, const u8 *address, struct ieee80211_key_conf *key); - int (*set_ieee8021x)(struct ieee80211_hw *hw, int use_ieee8021x); - int (*set_port_auth)(struct ieee80211_hw *hw, u8 *addr, - int authorized); int (*hw_scan)(struct ieee80211_hw *hw, u8 *ssid, size_t len); int (*get_stats)(struct ieee80211_hw *hw, struct ieee80211_low_level_stats *stats); - int (*set_privacy_invoked)(struct ieee80211_hw *hw, - int privacy_invoked); int (*get_sequence_counter)(struct ieee80211_hw *hw, u8* addr, u8 keyidx, u8 txrx, u32* iv32, u16* iv16); diff --git a/include/net/net_namespace.h b/include/net/net_namespace.h index 1fd449a..5dd6d90 100644 --- a/include/net/net_namespace.h +++ b/include/net/net_namespace.h @@ -119,9 +119,11 @@ static inline struct net *maybe_get_net(struct net *net) #ifdef CONFIG_NET_NS #define __net_init #define __net_exit +#define __net_initdata #else #define __net_init __init #define __net_exit __exit_refok +#define __net_initdata __initdata #endif struct pernet_operations { diff --git a/include/net/request_sock.h b/include/net/request_sock.h index 7aed02c..cff4608 100644 --- a/include/net/request_sock.h +++ b/include/net/request_sock.h @@ -124,23 +124,7 @@ struct request_sock_queue { extern int reqsk_queue_alloc(struct request_sock_queue *queue, unsigned int nr_table_entries); -static inline struct listen_sock *reqsk_queue_yank_listen_sk(struct request_sock_queue *queue) -{ - struct listen_sock *lopt; - - write_lock_bh(&queue->syn_wait_lock); - lopt = queue->listen_opt; - queue->listen_opt = NULL; - write_unlock_bh(&queue->syn_wait_lock); - - return lopt; -} - -static inline void __reqsk_queue_destroy(struct request_sock_queue *queue) -{ - kfree(reqsk_queue_yank_listen_sk(queue)); -} - +extern void __reqsk_queue_destroy(struct request_sock_queue *queue); extern void reqsk_queue_destroy(struct request_sock_queue *queue); static inline struct request_sock * diff --git a/include/net/sctp/command.h b/include/net/sctp/command.h index b873336..c1f7976 100644 --- a/include/net/sctp/command.h +++ b/include/net/sctp/command.h @@ -103,6 +103,7 @@ typedef enum { SCTP_CMD_ASSOC_CHANGE, /* generate and send assoc_change event */ SCTP_CMD_ADAPTATION_IND, /* generate and send adaptation event */ SCTP_CMD_ASSOC_SHKEY, /* generate the association shared keys */ + SCTP_CMD_T1_RETRAN, /* Mark for retransmission after T1 timeout */ SCTP_CMD_LAST } sctp_verb_t; diff --git a/include/net/sctp/constants.h b/include/net/sctp/constants.h index da8354e..05f22a6 100644 --- a/include/net/sctp/constants.h +++ b/include/net/sctp/constants.h @@ -186,6 +186,8 @@ typedef enum { SCTP_IERROR_AUTH_BAD_HMAC, SCTP_IERROR_AUTH_BAD_KEYID, SCTP_IERROR_PROTO_VIOLATION, + SCTP_IERROR_ERROR, + SCTP_IERROR_ABORT, } sctp_ierror_t; @@ -407,6 +409,7 @@ typedef enum { SCTP_RTXR_T3_RTX, SCTP_RTXR_FAST_RTX, SCTP_RTXR_PMTUD, + SCTP_RTXR_T1_RTX, } sctp_retransmit_reason_t; /* Reasons to lower cwnd. */ @@ -438,11 +441,14 @@ enum { SCTP_AUTH_HMAC_ID_RESERVED_0, SCTP_AUTH_HMAC_ID_SHA1, SCTP_AUTH_HMAC_ID_RESERVED_2, - SCTP_AUTH_HMAC_ID_SHA256 +#if defined (CONFIG_CRYPTO_SHA256) || defined (CONFIG_CRYPTO_SHA256_MODULE) + SCTP_AUTH_HMAC_ID_SHA256, +#endif + __SCTP_AUTH_HMAC_MAX }; -#define SCTP_AUTH_HMAC_ID_MAX SCTP_AUTH_HMAC_ID_SHA256 -#define SCTP_AUTH_NUM_HMACS (SCTP_AUTH_HMAC_ID_SHA256 + 1) +#define SCTP_AUTH_HMAC_ID_MAX __SCTP_AUTH_HMAC_MAX - 1 +#define SCTP_AUTH_NUM_HMACS __SCTP_AUTH_HMAC_MAX #define SCTP_SHA1_SIG_SIZE 20 #define SCTP_SHA256_SIG_SIZE 32 diff --git a/include/net/sctp/sctp.h b/include/net/sctp/sctp.h index 93eb708..34318a3 100644 --- a/include/net/sctp/sctp.h +++ b/include/net/sctp/sctp.h @@ -65,7 +65,6 @@ #ifdef TEST_FRAME -#undef CONFIG_PROC_FS #undef CONFIG_SCTP_DBG_OBJCNT #undef CONFIG_SYSCTL #endif /* TEST_FRAME */ @@ -267,6 +266,7 @@ enum SCTP_MIB_T5_SHUTDOWN_GUARD_EXPIREDS, SCTP_MIB_DELAY_SACK_EXPIREDS, SCTP_MIB_AUTOCLOSE_EXPIREDS, + SCTP_MIB_T1_RETRANSMITS, SCTP_MIB_T3_RETRANSMITS, SCTP_MIB_PMTUD_RETRANSMITS, SCTP_MIB_FAST_RETRANSMITS, @@ -664,6 +664,9 @@ static inline int sctp_vtag_hashfn(__u16 lport, __u16 rport, __u32 vtag) return (h & (sctp_assoc_hashsize-1)); } +#define sctp_for_each_hentry(epb, node, head) \ + hlist_for_each_entry(epb, node, head, node) + /* Is a socket of this style? */ #define sctp_style(sk, style) __sctp_style((sk), (SCTP_SOCKET_##style)) static inline int __sctp_style(const struct sock *sk, sctp_socket_type_t style) diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h index ef892e0..eb3113c 100644 --- a/include/net/sctp/structs.h +++ b/include/net/sctp/structs.h @@ -100,20 +100,19 @@ struct crypto_hash; struct sctp_bind_bucket { unsigned short port; unsigned short fastreuse; - struct sctp_bind_bucket *next; - struct sctp_bind_bucket **pprev; + struct hlist_node node; struct hlist_head owner; }; struct sctp_bind_hashbucket { spinlock_t lock; - struct sctp_bind_bucket *chain; + struct hlist_head chain; }; /* Used for hashing all associations. */ struct sctp_hashbucket { rwlock_t lock; - struct sctp_ep_common *chain; + struct hlist_head chain; } __attribute__((__aligned__(8))); @@ -212,6 +211,7 @@ extern struct sctp_globals { /* Flag to indicate if addip is enabled. */ int addip_enable; + int addip_noauth_enable; /* Flag to indicate if PR-SCTP is enabled. */ int prsctp_enable; @@ -249,6 +249,7 @@ extern struct sctp_globals { #define sctp_local_addr_list (sctp_globals.local_addr_list) #define sctp_local_addr_lock (sctp_globals.addr_list_lock) #define sctp_addip_enable (sctp_globals.addip_enable) +#define sctp_addip_noauth (sctp_globals.addip_noauth_enable) #define sctp_prsctp_enable (sctp_globals.prsctp_enable) #define sctp_auth_enable (sctp_globals.auth_enable) @@ -873,10 +874,11 @@ struct sctp_transport { * address list derived from the INIT or INIT ACK chunk, a * number of data elements needs to be maintained including: */ - __u32 rtt; /* This is the most recent RTT. */ - /* RTO : The current retransmission timeout value. */ unsigned long rto; + unsigned long last_rto; + + __u32 rtt; /* This is the most recent RTT. */ /* RTTVAR : The current RTT variation. */ __u32 rttvar; @@ -1184,9 +1186,7 @@ int sctp_bind_addr_copy(struct sctp_bind_addr *dest, int flags); int sctp_add_bind_addr(struct sctp_bind_addr *, union sctp_addr *, __u8 use_as_src, gfp_t gfp); -int sctp_del_bind_addr(struct sctp_bind_addr *, union sctp_addr *, - void fastcall (*rcu_call)(struct rcu_head *, - void (*func)(struct rcu_head *))); +int sctp_del_bind_addr(struct sctp_bind_addr *, union sctp_addr *); int sctp_bind_addr_match(struct sctp_bind_addr *, const union sctp_addr *, struct sctp_sock *); union sctp_addr *sctp_find_unmatch_addr(struct sctp_bind_addr *bp, @@ -1229,8 +1229,7 @@ typedef enum { struct sctp_ep_common { /* Fields to help us manage our entries in the hash tables. */ - struct sctp_ep_common *next; - struct sctp_ep_common **pprev; + struct hlist_node node; int hashent; /* Runtime type information. What kind of endpoint is this? */ @@ -1541,7 +1540,6 @@ struct sctp_association { __u8 asconf_capable; /* Does peer support ADDIP? */ __u8 prsctp_capable; /* Can peer do PR-SCTP? */ __u8 auth_capable; /* Is peer doing SCTP-AUTH? */ - __u8 addip_capable; /* Can peer do ADD-IP */ __u32 adaptation_ind; /* Adaptation Code point. */ diff --git a/include/net/sock.h b/include/net/sock.h index 20de3fa..67e35c7 100644 --- a/include/net/sock.h +++ b/include/net/sock.h @@ -560,6 +560,14 @@ struct proto { void (*unhash)(struct sock *sk); int (*get_port)(struct sock *sk, unsigned short snum); +#ifdef CONFIG_SMP + /* Keeping track of sockets in use */ + void (*inuse_add)(struct proto *prot, int inc); + int (*inuse_getval)(const struct proto *prot); + int *inuse_ptr; +#else + int inuse; +#endif /* Memory pressure */ void (*enter_memory_pressure)(void); atomic_t *memory_allocated; /* Current allocated memory. */ @@ -592,12 +600,38 @@ struct proto { #ifdef SOCK_REFCNT_DEBUG atomic_t socks; #endif - struct { - int inuse; - u8 __pad[SMP_CACHE_BYTES - sizeof(int)]; - } stats[NR_CPUS]; }; +/* + * Special macros to let protos use a fast version of inuse{get|add} + * using a static percpu variable per proto instead of an allocated one, + * saving one dereference. + * This might be changed if/when dynamic percpu vars become fast. + */ +#ifdef CONFIG_SMP +# define DEFINE_PROTO_INUSE(NAME) \ +static DEFINE_PER_CPU(int, NAME##_inuse); \ +static void NAME##_inuse_add(struct proto *prot, int inc) \ +{ \ + __get_cpu_var(NAME##_inuse) += inc; \ +} \ + \ +static int NAME##_inuse_getval(const struct proto *prot)\ +{ \ + int res = 0, cpu; \ + \ + for_each_possible_cpu(cpu) \ + res += per_cpu(NAME##_inuse, cpu); \ + return res; \ +} +# define REF_PROTO_INUSE(NAME) \ + .inuse_add = NAME##_inuse_add, \ + .inuse_getval = NAME##_inuse_getval, +#else +# define DEFINE_PROTO_INUSE(NAME) +# define REF_PROTO_INUSE(NAME) +#endif + extern int proto_register(struct proto *prot, int alloc_slab); extern void proto_unregister(struct proto *prot); @@ -629,12 +663,29 @@ static inline void sk_refcnt_debug_release(const struct sock *sk) /* Called with local bh disabled */ static __inline__ void sock_prot_inc_use(struct proto *prot) { - prot->stats[smp_processor_id()].inuse++; +#ifdef CONFIG_SMP + prot->inuse_add(prot, 1); +#else + prot->inuse++; +#endif } static __inline__ void sock_prot_dec_use(struct proto *prot) { - prot->stats[smp_processor_id()].inuse--; +#ifdef CONFIG_SMP + prot->inuse_add(prot, -1); +#else + prot->inuse--; +#endif +} + +static __inline__ int sock_prot_inuse(struct proto *proto) +{ +#ifdef CONFIG_SMP + return proto->inuse_getval(proto); +#else + return proto->inuse; +#endif } /* With per-bucket locks this operation is not-atomic, so that @@ -1184,14 +1235,19 @@ static inline struct sk_buff *sk_stream_alloc_pskb(struct sock *sk, gfp_t gfp) { struct sk_buff *skb; - int hdr_len; - hdr_len = SKB_DATA_ALIGN(sk->sk_prot->max_header); - skb = alloc_skb_fclone(size + hdr_len, gfp); + /* The TCP header must be at least 32-bit aligned. */ + size = ALIGN(size, 4); + + skb = alloc_skb_fclone(size + sk->sk_prot->max_header, gfp); if (skb) { skb->truesize += mem; if (sk_stream_wmem_schedule(sk, skb->truesize)) { - skb_reserve(skb, hdr_len); + /* + * Make sure that we have exactly size bytes + * available to the caller, no more, no less. + */ + skb_reserve(skb, skb_tailroom(skb) - size); return skb; } __kfree_skb(skb); diff --git a/include/net/tcp.h b/include/net/tcp.h index d695cea..cb5b033 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h @@ -1288,6 +1288,9 @@ static inline void tcp_insert_write_queue_before(struct sk_buff *new, struct sock *sk) { __skb_insert(new, skb->prev, skb, &sk->sk_write_queue); + + if (sk->sk_send_head == skb) + sk->sk_send_head = new; } static inline void tcp_unlink_write_queue(struct sk_buff *skb, struct sock *sk) diff --git a/include/pcmcia/cs_types.h b/include/pcmcia/cs_types.h index c1d1629..5f38803 100644 --- a/include/pcmcia/cs_types.h +++ b/include/pcmcia/cs_types.h @@ -21,7 +21,7 @@ #include <sys/types.h> #endif -#if defined(__arm__) || defined(__mips__) +#if defined(__arm__) || defined(__mips__) || defined(__avr32__) /* This (ioaddr_t) is exposed to userspace & hence cannot be changed. */ typedef u_int ioaddr_t; #else diff --git a/include/sound/version.h b/include/sound/version.h index a2be8ad..a9781eb 100644 --- a/include/sound/version.h +++ b/include/sound/version.h @@ -1,3 +1,3 @@ /* include/version.h. Generated by alsa/ksync script. */ #define CONFIG_SND_VERSION "1.0.15" -#define CONFIG_SND_DATE " (Tue Oct 23 06:09:18 2007 UTC)" +#define CONFIG_SND_DATE " (Tue Nov 20 19:16:42 2007 UTC)" diff --git a/init/Kconfig b/init/Kconfig index 8b88d0b..d35e44f 100644 --- a/init/Kconfig +++ b/init/Kconfig @@ -215,6 +215,18 @@ config USER_NS vservers, to use user namespaces to provide different user info for different servers. If unsure, say N. +config PID_NS + bool "PID Namespaces (EXPERIMENTAL)" + default n + depends on EXPERIMENTAL + help + Suport process id namespaces. This allows having multiple + process with the same pid as long as they are in different + pid namespaces. This is a building block of containers. + + Unless you want to work with an experimental feature + say N here. + config AUDIT bool "Auditing support" depends on NET @@ -301,13 +313,6 @@ config CGROUP_NS for instance virtual servers and checkpoint/restart jobs. -config CGROUP_CPUACCT - bool "Simple CPU accounting cgroup subsystem" - depends on CGROUPS - help - Provides a simple Resource Controller for monitoring the - total CPU consumed by the tasks in a cgroup - config CPUSETS bool "Cpuset support" depends on SMP && CGROUPS @@ -433,7 +438,7 @@ menuconfig EMBEDDED config UID16 bool "Enable 16-bit UID system calls" if EMBEDDED - depends on ARM || BFIN || CRIS || FRV || H8300 || X86_32 || M68K || (S390 && !64BIT) || SUPERH || SPARC32 || (SPARC64 && SPARC32_COMPAT) || UML || (X86_64 && IA32_EMULATION) + depends on ARM || BLACKFIN || CRIS || FRV || H8300 || X86_32 || M68K || (S390 && !64BIT) || SUPERH || SPARC32 || (SPARC64 && SPARC32_COMPAT) || UML || (X86_64 && IA32_EMULATION) default y help This enables the legacy 16-bit UID syscall wrappers. diff --git a/init/main.c b/init/main.c index f605a96..80b04b6 100644 --- a/init/main.c +++ b/init/main.c @@ -56,6 +56,7 @@ #include <linux/pid_namespace.h> #include <linux/device.h> #include <linux/kthread.h> +#include <linux/sched.h> #include <asm/io.h> #include <asm/bugs.h> @@ -747,11 +748,8 @@ __setup("nosoftlockup", nosoftlockup_setup); static void __init do_pre_smp_initcalls(void) { extern int spawn_ksoftirqd(void); -#ifdef CONFIG_SMP - extern int migration_init(void); migration_init(); -#endif spawn_ksoftirqd(); if (!nosoftlockup) spawn_softlockup_task(); diff --git a/ipc/mqueue.c b/ipc/mqueue.c index bfa274b..6ca7b97 100644 --- a/ipc/mqueue.c +++ b/ipc/mqueue.c @@ -1010,6 +1010,8 @@ asmlinkage long sys_mq_notify(mqd_t mqdes, return -EINVAL; } if (notification.sigev_notify == SIGEV_THREAD) { + long timeo; + /* create the notify skb */ nc = alloc_skb(NOTIFY_COOKIE_LEN, GFP_KERNEL); ret = -ENOMEM; @@ -1038,8 +1040,8 @@ retry: goto out; } - ret = netlink_attachskb(sock, nc, 0, - MAX_SCHEDULE_TIMEOUT, NULL); + timeo = MAX_SCHEDULE_TIMEOUT; + ret = netlink_attachskb(sock, nc, 0, &timeo, NULL); if (ret == 1) goto retry; if (ret) { @@ -1136,8 +1138,10 @@ asmlinkage long sys_mq_getsetattr(mqd_t mqdes, omqstat.mq_flags = filp->f_flags & O_NONBLOCK; if (u_mqstat) { ret = audit_mq_getsetattr(mqdes, &mqstat); - if (ret != 0) - goto out; + if (ret != 0) { + spin_unlock(&info->lock); + goto out_fput; + } if (mqstat.mq_flags & O_NONBLOCK) filp->f_flags |= O_NONBLOCK; else diff --git a/kernel/Kconfig.instrumentation b/kernel/Kconfig.instrumentation index f5f2c76..2ea1e34 100644 --- a/kernel/Kconfig.instrumentation +++ b/kernel/Kconfig.instrumentation @@ -21,7 +21,7 @@ config PROFILING config OPROFILE tristate "OProfile system profiling (EXPERIMENTAL)" depends on PROFILING - depends on ALPHA || ARM || BLACKFIN || X86_32 || IA64 || M32R || MIPS || PARISC || PPC || S390 || SUPERH || SPARC || X86_64 + depends on (ALPHA || ARM || BLACKFIN || X86_32 || IA64 || M32R || MIPS || PARISC || PPC || S390 || SUPERH || SPARC || X86_64) && !UML help OProfile is a profiling system capable of profiling the whole system, include the kernel, kernel modules, libraries, @@ -32,7 +32,7 @@ config OPROFILE config KPROBES bool "Kprobes" depends on KALLSYMS && MODULES - depends on X86_32 || IA64 || PPC || S390 || SPARC64 || X86_64 || AVR32 + depends on (X86_32 || IA64 || PPC || S390 || SPARC64 || X86_64 || AVR32) && !UML help Kprobes allows you to trap at almost any kernel address and execute a callback function. register_kprobe() establishes diff --git a/kernel/Makefile b/kernel/Makefile index f60afe7..dfa9695 100644 --- a/kernel/Makefile +++ b/kernel/Makefile @@ -40,7 +40,6 @@ obj-$(CONFIG_COMPAT) += compat.o obj-$(CONFIG_CGROUPS) += cgroup.o obj-$(CONFIG_CGROUP_DEBUG) += cgroup_debug.o obj-$(CONFIG_CPUSETS) += cpuset.o -obj-$(CONFIG_CGROUP_CPUACCT) += cpu_acct.o obj-$(CONFIG_CGROUP_NS) += ns_cgroup.o obj-$(CONFIG_IKCONFIG) += configs.o obj-$(CONFIG_STOP_MACHINE) += stop_machine.o diff --git a/kernel/acct.c b/kernel/acct.c index fce53d8..cf19547 100644 --- a/kernel/acct.c +++ b/kernel/acct.c @@ -413,7 +413,7 @@ static u32 encode_float(u64 value) * The acct_process() call is the workhorse of the process * accounting system. The struct acct is built here and then written * into the accounting file. This function should only be called from - * do_exit(). + * do_exit() or when switching to a different output file. */ /* diff --git a/kernel/cgroup.c b/kernel/cgroup.c index 3fe21e1..1a3c239 100644 --- a/kernel/cgroup.c +++ b/kernel/cgroup.c @@ -1,6 +1,4 @@ /* - * kernel/cgroup.c - * * Generic process-grouping system. * * Based originally on the cpuset system, extracted by Paul Menage @@ -2200,7 +2198,8 @@ static void cgroup_init_subsys(struct cgroup_subsys *ss) { struct cgroup_subsys_state *css; struct list_head *l; - printk(KERN_ERR "Initializing cgroup subsys %s\n", ss->name); + + printk(KERN_INFO "Initializing cgroup subsys %s\n", ss->name); /* Create the top cgroup state for this subsystem */ ss->root = &rootnode; @@ -2273,7 +2272,7 @@ int __init cgroup_init_early(void) BUG_ON(!ss->create); BUG_ON(!ss->destroy); if (ss->subsys_id != i) { - printk(KERN_ERR "Subsys %s id == %d\n", + printk(KERN_ERR "cgroup: Subsys %s id == %d\n", ss->name, ss->subsys_id); BUG(); } @@ -2605,7 +2604,7 @@ int cgroup_clone(struct task_struct *tsk, struct cgroup_subsys *subsys) dentry = lookup_one_len(nodename, parent->dentry, strlen(nodename)); if (IS_ERR(dentry)) { printk(KERN_INFO - "Couldn't allocate dentry for %s: %ld\n", nodename, + "cgroup: Couldn't allocate dentry for %s: %ld\n", nodename, PTR_ERR(dentry)); ret = PTR_ERR(dentry); goto out_release; diff --git a/kernel/cpu_acct.c b/kernel/cpu_acct.c deleted file mode 100644 index 731e47e..0000000 --- a/kernel/cpu_acct.c +++ /dev/null @@ -1,186 +0,0 @@ -/* - * kernel/cpu_acct.c - CPU accounting cgroup subsystem - * - * Copyright (C) Google Inc, 2006 - * - * Developed by Paul Menage (menage@google.com) and Balbir Singh - * (balbir@in.ibm.com) - * - */ - -/* - * Example cgroup subsystem for reporting total CPU usage of tasks in a - * cgroup, along with percentage load over a time interval - */ - -#include <linux/module.h> -#include <linux/cgroup.h> -#include <linux/fs.h> -#include <linux/rcupdate.h> - -#include <asm/div64.h> - -struct cpuacct { - struct cgroup_subsys_state css; - spinlock_t lock; - /* total time used by this class */ - cputime64_t time; - - /* time when next load calculation occurs */ - u64 next_interval_check; - - /* time used in current period */ - cputime64_t current_interval_time; - - /* time used in last period */ - cputime64_t last_interval_time; -}; - -struct cgroup_subsys cpuacct_subsys; - -static inline struct cpuacct *cgroup_ca(struct cgroup *cont) -{ - return container_of(cgroup_subsys_state(cont, cpuacct_subsys_id), - struct cpuacct, css); -} - -static inline struct cpuacct *task_ca(struct task_struct *task) -{ - return container_of(task_subsys_state(task, cpuacct_subsys_id), - struct cpuacct, css); -} - -#define INTERVAL (HZ * 10) - -static inline u64 next_interval_boundary(u64 now) -{ - /* calculate the next interval boundary beyond the - * current time */ - do_div(now, INTERVAL); - return (now + 1) * INTERVAL; -} - -static struct cgroup_subsys_state *cpuacct_create( - struct cgroup_subsys *ss, struct cgroup *cont) -{ - struct cpuacct *ca = kzalloc(sizeof(*ca), GFP_KERNEL); - - if (!ca) - return ERR_PTR(-ENOMEM); - spin_lock_init(&ca->lock); - ca->next_interval_check = next_interval_boundary(get_jiffies_64()); - return &ca->css; -} - -static void cpuacct_destroy(struct cgroup_subsys *ss, - struct cgroup *cont) -{ - kfree(cgroup_ca(cont)); -} - -/* Lazily update the load calculation if necessary. Called with ca locked */ -static void cpuusage_update(struct cpuacct *ca) -{ - u64 now = get_jiffies_64(); - - /* If we're not due for an update, return */ - if (ca->next_interval_check > now) - return; - - if (ca->next_interval_check <= (now - INTERVAL)) { - /* If it's been more than an interval since the last - * check, then catch up - the last interval must have - * been zero load */ - ca->last_interval_time = 0; - ca->next_interval_check = next_interval_boundary(now); - } else { - /* If a steal takes the last interval time negative, - * then we just ignore it */ - if ((s64)ca->current_interval_time > 0) - ca->last_interval_time = ca->current_interval_time; - else - ca->last_interval_time = 0; - ca->next_interval_check += INTERVAL; - } - ca->current_interval_time = 0; -} - -static u64 cpuusage_read(struct cgroup *cont, struct cftype *cft) -{ - struct cpuacct *ca = cgroup_ca(cont); - u64 time; - - spin_lock_irq(&ca->lock); - cpuusage_update(ca); - time = cputime64_to_jiffies64(ca->time); - spin_unlock_irq(&ca->lock); - - /* Convert 64-bit jiffies to seconds */ - time *= 1000; - do_div(time, HZ); - return time; -} - -static u64 load_read(struct cgroup *cont, struct cftype *cft) -{ - struct cpuacct *ca = cgroup_ca(cont); - u64 time; - - /* Find the time used in the previous interval */ - spin_lock_irq(&ca->lock); - cpuusage_update(ca); - time = cputime64_to_jiffies64(ca->last_interval_time); - spin_unlock_irq(&ca->lock); - - /* Convert time to a percentage, to give the load in the - * previous period */ - time *= 100; - do_div(time, INTERVAL); - - return time; -} - -static struct cftype files[] = { - { - .name = "usage", - .read_uint = cpuusage_read, - }, - { - .name = "load", - .read_uint = load_read, - } -}; - -static int cpuacct_populate(struct cgroup_subsys *ss, struct cgroup *cont) -{ - return cgroup_add_files(cont, ss, files, ARRAY_SIZE(files)); -} - -void cpuacct_charge(struct task_struct *task, cputime_t cputime) -{ - - struct cpuacct *ca; - unsigned long flags; - - if (!cpuacct_subsys.active) - return; - rcu_read_lock(); - ca = task_ca(task); - if (ca) { - spin_lock_irqsave(&ca->lock, flags); - cpuusage_update(ca); - ca->time = cputime64_add(ca->time, cputime); - ca->current_interval_time = - cputime64_add(ca->current_interval_time, cputime); - spin_unlock_irqrestore(&ca->lock, flags); - } - rcu_read_unlock(); -} - -struct cgroup_subsys cpuacct_subsys = { - .name = "cpuacct", - .create = cpuacct_create, - .destroy = cpuacct_destroy, - .populate = cpuacct_populate, - .subsys_id = cpuacct_subsys_id, -}; diff --git a/kernel/exit.c b/kernel/exit.c index f1aec27..549c055 100644 --- a/kernel/exit.c +++ b/kernel/exit.c @@ -1357,7 +1357,7 @@ static int wait_task_stopped(struct task_struct *p, int delayed_group_leader, int __user *stat_addr, struct rusage __user *ru) { int retval, exit_code; - struct pid_namespace *ns; + pid_t pid; if (!p->exit_code) return 0; @@ -1376,21 +1376,19 @@ static int wait_task_stopped(struct task_struct *p, int delayed_group_leader, * keep holding onto the tasklist_lock while we call getrusage and * possibly take page faults for user memory. */ - ns = current->nsproxy->pid_ns; + pid = task_pid_nr_ns(p, current->nsproxy->pid_ns); get_task_struct(p); read_unlock(&tasklist_lock); if (unlikely(noreap)) { - pid_t pid = task_pid_nr_ns(p, ns); uid_t uid = p->uid; int why = (p->ptrace & PT_PTRACED) ? CLD_TRAPPED : CLD_STOPPED; exit_code = p->exit_code; - if (unlikely(!exit_code) || - unlikely(p->state & TASK_TRACED)) + if (unlikely(!exit_code) || unlikely(p->exit_state)) goto bail_ref; return wait_noreap_copyout(p, pid, uid, - why, (exit_code << 8) | 0x7f, + why, exit_code, infop, ru); } @@ -1452,11 +1450,11 @@ bail_ref: if (!retval && infop) retval = put_user(exit_code, &infop->si_status); if (!retval && infop) - retval = put_user(task_pid_nr_ns(p, ns), &infop->si_pid); + retval = put_user(pid, &infop->si_pid); if (!retval && infop) retval = put_user(p->uid, &infop->si_uid); if (!retval) - retval = task_pid_nr_ns(p, ns); + retval = pid; put_task_struct(p); BUG_ON(!retval); diff --git a/kernel/fork.c b/kernel/fork.c index 28a7401..8ca1a14 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -1123,6 +1123,9 @@ static struct task_struct *copy_process(unsigned long clone_flags, p->blocked_on = NULL; /* not blocked yet */ #endif + /* Perform scheduler related setup. Assign this task to a CPU. */ + sched_fork(p, clone_flags); + if ((retval = security_task_alloc(p))) goto bad_fork_cleanup_policy; if ((retval = audit_alloc(p))) @@ -1212,9 +1215,6 @@ static struct task_struct *copy_process(unsigned long clone_flags, INIT_LIST_HEAD(&p->ptrace_children); INIT_LIST_HEAD(&p->ptrace_list); - /* Perform scheduler related setup. Assign this task to a CPU. */ - sched_fork(p, clone_flags); - /* Now that the task is set up, run cgroup callbacks if * necessary. We need to run them before the task is visible * on the tasklist. */ diff --git a/kernel/futex_compat.c b/kernel/futex_compat.c index 00b5726..0a43def 100644 --- a/kernel/futex_compat.c +++ b/kernel/futex_compat.c @@ -30,6 +30,15 @@ fetch_robust_entry(compat_uptr_t *uentry, struct robust_list __user **entry, return 0; } +static void __user *futex_uaddr(struct robust_list *entry, + compat_long_t futex_offset) +{ + compat_uptr_t base = ptr_to_compat(entry); + void __user *uaddr = compat_ptr(base + futex_offset); + + return uaddr; +} + /* * Walk curr->robust_list (very carefully, it's a userspace list!) * and mark any locks found there dead, and notify any waiters. @@ -76,11 +85,12 @@ void compat_exit_robust_list(struct task_struct *curr) * A pending lock might already be on the list, so * dont process it twice: */ - if (entry != pending) - if (handle_futex_death((void __user *)entry + futex_offset, - curr, pi)) - return; + if (entry != pending) { + void __user *uaddr = futex_uaddr(entry, futex_offset); + if (handle_futex_death(uaddr, curr, pi)) + return; + } if (rc) return; uentry = next_uentry; @@ -94,9 +104,11 @@ void compat_exit_robust_list(struct task_struct *curr) cond_resched(); } - if (pending) - handle_futex_death((void __user *)pending + futex_offset, - curr, pip); + if (pending) { + void __user *uaddr = futex_uaddr(pending, futex_offset); + + handle_futex_death(uaddr, curr, pip); + } } asmlinkage long diff --git a/kernel/irq/handle.c b/kernel/irq/handle.c index e391cbb..dc335ad 100644 --- a/kernel/irq/handle.c +++ b/kernel/irq/handle.c @@ -178,9 +178,11 @@ fastcall unsigned int __do_IRQ(unsigned int irq) */ if (desc->chip->ack) desc->chip->ack(irq); - action_ret = handle_IRQ_event(irq, desc->action); - if (!noirqdebug) - note_interrupt(irq, desc, action_ret); + if (likely(!(desc->status & IRQ_DISABLED))) { + action_ret = handle_IRQ_event(irq, desc->action); + if (!noirqdebug) + note_interrupt(irq, desc, action_ret); + } desc->chip->end(irq); return 1; } diff --git a/kernel/kallsyms.c b/kernel/kallsyms.c index 474219a..2fc2581 100644 --- a/kernel/kallsyms.c +++ b/kernel/kallsyms.c @@ -32,9 +32,14 @@ /* These will be re-linked against their real values during the second link stage */ extern const unsigned long kallsyms_addresses[] __attribute__((weak)); -extern const unsigned long kallsyms_num_syms __attribute__((weak)); extern const u8 kallsyms_names[] __attribute__((weak)); +/* tell the compiler that the count isn't in the small data section if the arch + * has one (eg: FRV) + */ +extern const unsigned long kallsyms_num_syms +__attribute__((weak, section(".rodata"))); + extern const u8 kallsyms_token_table[] __attribute__((weak)); extern const u16 kallsyms_token_index[] __attribute__((weak)); diff --git a/kernel/marker.c b/kernel/marker.c index ccb48d9..5323cfa 100644 --- a/kernel/marker.c +++ b/kernel/marker.c @@ -28,7 +28,7 @@ extern struct marker __start___markers[]; extern struct marker __stop___markers[]; /* - * module_mutex nests inside markers_mutex. Markers mutex protects the builtin + * markers_mutex nests inside module_mutex. Markers mutex protects the builtin * and module markers, the hash table and deferred_sync. */ static DEFINE_MUTEX(markers_mutex); @@ -257,7 +257,6 @@ static void disable_marker(struct marker *elem) * @refcount: number of references left to the given probe_module (out) * * Updates the probe callback corresponding to a range of markers. - * Must be called with markers_mutex held. */ void marker_update_probe_range(struct marker *begin, struct marker *end, struct module *probe_module, @@ -266,6 +265,7 @@ void marker_update_probe_range(struct marker *begin, struct marker *iter; struct marker_entry *mark_entry; + mutex_lock(&markers_mutex); for (iter = begin; iter < end; iter++) { mark_entry = get_marker(iter->name); if (mark_entry && mark_entry->refcount) { @@ -281,6 +281,7 @@ void marker_update_probe_range(struct marker *begin, disable_marker(iter); } } + mutex_unlock(&markers_mutex); } /* @@ -293,7 +294,6 @@ static void marker_update_probes(struct module *probe_module) { int refcount = 0; - mutex_lock(&markers_mutex); /* Core kernel markers */ marker_update_probe_range(__start___markers, __stop___markers, probe_module, &refcount); @@ -303,7 +303,6 @@ static void marker_update_probes(struct module *probe_module) synchronize_sched(); deferred_sync = 0; } - mutex_unlock(&markers_mutex); } /** @@ -320,7 +319,7 @@ int marker_probe_register(const char *name, const char *format, marker_probe_func *probe, void *private) { struct marker_entry *entry; - int ret = 0, need_update = 0; + int ret = 0; mutex_lock(&markers_mutex); entry = get_marker(name); @@ -335,11 +334,11 @@ int marker_probe_register(const char *name, const char *format, ret = add_marker(name, format, probe, private); if (ret) goto end; - need_update = 1; + mutex_unlock(&markers_mutex); + marker_update_probes(NULL); + return ret; end: mutex_unlock(&markers_mutex); - if (need_update) - marker_update_probes(NULL); return ret; } EXPORT_SYMBOL_GPL(marker_probe_register); @@ -355,7 +354,6 @@ void *marker_probe_unregister(const char *name) struct module *probe_module; struct marker_entry *entry; void *private; - int need_update = 0; mutex_lock(&markers_mutex); entry = get_marker(name); @@ -368,11 +366,11 @@ void *marker_probe_unregister(const char *name) probe_module = __module_text_address((unsigned long)entry->probe); private = remove_marker(name); deferred_sync = 1; - need_update = 1; + mutex_unlock(&markers_mutex); + marker_update_probes(probe_module); + return private; end: mutex_unlock(&markers_mutex); - if (need_update) - marker_update_probes(probe_module); return private; } EXPORT_SYMBOL_GPL(marker_probe_unregister); @@ -392,7 +390,6 @@ void *marker_probe_unregister_private_data(void *private) struct marker_entry *entry; int found = 0; unsigned int i; - int need_update = 0; mutex_lock(&markers_mutex); for (i = 0; i < MARKER_TABLE_SIZE; i++) { @@ -414,11 +411,11 @@ iter_end: probe_module = __module_text_address((unsigned long)entry->probe); private = remove_marker(entry->name); deferred_sync = 1; - need_update = 1; + mutex_unlock(&markers_mutex); + marker_update_probes(probe_module); + return private; end: mutex_unlock(&markers_mutex); - if (need_update) - marker_update_probes(probe_module); return private; } EXPORT_SYMBOL_GPL(marker_probe_unregister_private_data); @@ -434,7 +431,7 @@ EXPORT_SYMBOL_GPL(marker_probe_unregister_private_data); int marker_arm(const char *name) { struct marker_entry *entry; - int ret = 0, need_update = 0; + int ret = 0; mutex_lock(&markers_mutex); entry = get_marker(name); @@ -447,11 +444,9 @@ int marker_arm(const char *name) */ if (entry->refcount++) goto end; - need_update = 1; end: mutex_unlock(&markers_mutex); - if (need_update) - marker_update_probes(NULL); + marker_update_probes(NULL); return ret; } EXPORT_SYMBOL_GPL(marker_arm); @@ -467,7 +462,7 @@ EXPORT_SYMBOL_GPL(marker_arm); int marker_disarm(const char *name) { struct marker_entry *entry; - int ret = 0, need_update = 0; + int ret = 0; mutex_lock(&markers_mutex); entry = get_marker(name); @@ -486,11 +481,9 @@ int marker_disarm(const char *name) ret = -EPERM; goto end; } - need_update = 1; end: mutex_unlock(&markers_mutex); - if (need_update) - marker_update_probes(NULL); + marker_update_probes(NULL); return ret; } EXPORT_SYMBOL_GPL(marker_disarm); diff --git a/kernel/module.c b/kernel/module.c index 3202c99..91fe695 100644 --- a/kernel/module.c +++ b/kernel/module.c @@ -81,7 +81,8 @@ int unregister_module_notifier(struct notifier_block * nb) } EXPORT_SYMBOL(unregister_module_notifier); -/* We require a truly strong try_module_get() */ +/* We require a truly strong try_module_get(): 0 means failure due to + ongoing or failed initialization etc. */ static inline int strong_try_module_get(struct module *mod) { if (mod && mod->state == MODULE_STATE_COMING) @@ -952,7 +953,8 @@ static unsigned long resolve_symbol(Elf_Shdr *sechdrs, ret = __find_symbol(name, &owner, &crc, !(mod->taints & TAINT_PROPRIETARY_MODULE)); if (ret) { - /* use_module can fail due to OOM, or module unloading */ + /* use_module can fail due to OOM, + or module initialization or unloading */ if (!check_version(sechdrs, versindex, name, mod, crc) || !use_module(mod, owner)) ret = 0; @@ -1369,7 +1371,7 @@ dup: return ret; } -/* Change all symbols so that sh_value encodes the pointer directly. */ +/* Change all symbols so that st_value encodes the pointer directly. */ static int simplify_symbols(Elf_Shdr *sechdrs, unsigned int symindex, const char *strtab, diff --git a/kernel/params.c b/kernel/params.c index 16f269e..2a4c514 100644 --- a/kernel/params.c +++ b/kernel/params.c @@ -592,19 +592,16 @@ static void __init param_sysfs_builtin(void) for (i=0; i < __stop___param - __start___param; i++) { char *dot; - size_t kplen; + size_t max_name_len; kp = &__start___param[i]; - kplen = strlen(kp->name); + max_name_len = + min_t(size_t, MAX_KBUILD_MODNAME, strlen(kp->name)); - /* We do not handle args without periods. */ - if (kplen > MAX_KBUILD_MODNAME) { - DEBUGP("kernel parameter name is too long: %s\n", kp->name); - continue; - } - dot = memchr(kp->name, '.', kplen); + dot = memchr(kp->name, '.', max_name_len); if (!dot) { - DEBUGP("couldn't find period in %s\n", kp->name); + DEBUGP("couldn't find period in first %d characters " + "of %s\n", MAX_KBUILD_MODNAME, kp->name); continue; } name_len = dot - kp->name; diff --git a/kernel/pid.c b/kernel/pid.c index d1db36b..f815455 100644 --- a/kernel/pid.c +++ b/kernel/pid.c @@ -537,6 +537,7 @@ err_alloc: return NULL; } +#ifdef CONFIG_PID_NS static struct pid_namespace *create_pid_namespace(int level) { struct pid_namespace *ns; @@ -621,6 +622,7 @@ void free_pid_ns(struct kref *kref) if (parent != NULL) put_pid_ns(parent); } +#endif /* CONFIG_PID_NS */ void zap_pid_ns_processes(struct pid_namespace *pid_ns) { diff --git a/kernel/power/disk.c b/kernel/power/disk.c index 8b15f77..05b6479 100644 --- a/kernel/power/disk.c +++ b/kernel/power/disk.c @@ -456,7 +456,17 @@ static int software_resume(void) int error; unsigned int flags; - mutex_lock(&pm_mutex); + /* + * name_to_dev_t() below takes a sysfs buffer mutex when sysfs + * is configured into the kernel. Since the regular hibernate + * trigger path is via sysfs which takes a buffer mutex before + * calling hibernate functions (which take pm_mutex) this can + * cause lockdep to complain about a possible ABBA deadlock + * which cannot happen since we're in the boot code here and + * sysfs can't be invoked yet. Therefore, we use a subclass + * here to avoid lockdep complaining. + */ + mutex_lock_nested(&pm_mutex, SINGLE_DEPTH_NESTING); if (!swsusp_resume_device) { if (!strlen(resume_file)) { mutex_unlock(&pm_mutex); diff --git a/kernel/resource.c b/kernel/resource.c index a358142..2eb553d 100644 --- a/kernel/resource.c +++ b/kernel/resource.c @@ -277,7 +277,7 @@ walk_memory_resource(unsigned long start_pfn, unsigned long nr_pages, void *arg, int ret = -1; res.start = (u64) start_pfn << PAGE_SHIFT; res.end = ((u64)(start_pfn + nr_pages) << PAGE_SHIFT) - 1; - res.flags = IORESOURCE_MEM; + res.flags = IORESOURCE_MEM | IORESOURCE_BUSY; orig_end = res.end; while ((res.start < res.end) && (find_next_system_ram(&res) >= 0)) { pfn = (unsigned long)(res.start >> PAGE_SHIFT); diff --git a/kernel/sched.c b/kernel/sched.c index 3f6bd11..98dcdf2 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -52,7 +52,6 @@ #include <linux/cpu.h> #include <linux/cpuset.h> #include <linux/percpu.h> -#include <linux/cpu_acct.h> #include <linux/kthread.h> #include <linux/seq_file.h> #include <linux/sysctl.h> @@ -75,7 +74,7 @@ */ unsigned long long __attribute__((weak)) sched_clock(void) { - return (unsigned long long)jiffies * (1000000000 / HZ); + return (unsigned long long)jiffies * (NSEC_PER_SEC / HZ); } /* @@ -99,8 +98,8 @@ unsigned long long __attribute__((weak)) sched_clock(void) /* * Some helpers for converting nanosecond timing to jiffy resolution */ -#define NS_TO_JIFFIES(TIME) ((unsigned long)(TIME) / (1000000000 / HZ)) -#define JIFFIES_TO_NS(TIME) ((TIME) * (1000000000 / HZ)) +#define NS_TO_JIFFIES(TIME) ((unsigned long)(TIME) / (NSEC_PER_SEC / HZ)) +#define JIFFIES_TO_NS(TIME) ((TIME) * (NSEC_PER_SEC / HZ)) #define NICE_0_LOAD SCHED_LOAD_SCALE #define NICE_0_SHIFT SCHED_LOAD_SHIFT @@ -217,15 +216,15 @@ static inline struct task_group *task_group(struct task_struct *p) } /* Change a task's cfs_rq and parent entity if it moves across CPUs/groups */ -static inline void set_task_cfs_rq(struct task_struct *p) +static inline void set_task_cfs_rq(struct task_struct *p, unsigned int cpu) { - p->se.cfs_rq = task_group(p)->cfs_rq[task_cpu(p)]; - p->se.parent = task_group(p)->se[task_cpu(p)]; + p->se.cfs_rq = task_group(p)->cfs_rq[cpu]; + p->se.parent = task_group(p)->se[cpu]; } #else -static inline void set_task_cfs_rq(struct task_struct *p) { } +static inline void set_task_cfs_rq(struct task_struct *p, unsigned int cpu) { } #endif /* CONFIG_FAIR_GROUP_SCHED */ @@ -456,24 +455,28 @@ static void update_rq_clock(struct rq *rq) */ enum { SCHED_FEAT_NEW_FAIR_SLEEPERS = 1, - SCHED_FEAT_START_DEBIT = 2, - SCHED_FEAT_TREE_AVG = 4, - SCHED_FEAT_APPROX_AVG = 8, - SCHED_FEAT_WAKEUP_PREEMPT = 16, - SCHED_FEAT_PREEMPT_RESTRICT = 32, + SCHED_FEAT_WAKEUP_PREEMPT = 2, + SCHED_FEAT_START_DEBIT = 4, + SCHED_FEAT_TREE_AVG = 8, + SCHED_FEAT_APPROX_AVG = 16, }; const_debug unsigned int sysctl_sched_features = SCHED_FEAT_NEW_FAIR_SLEEPERS * 1 | + SCHED_FEAT_WAKEUP_PREEMPT * 1 | SCHED_FEAT_START_DEBIT * 1 | SCHED_FEAT_TREE_AVG * 0 | - SCHED_FEAT_APPROX_AVG * 0 | - SCHED_FEAT_WAKEUP_PREEMPT * 1 | - SCHED_FEAT_PREEMPT_RESTRICT * 1; + SCHED_FEAT_APPROX_AVG * 0; #define sched_feat(x) (sysctl_sched_features & SCHED_FEAT_##x) /* + * Number of tasks to iterate in a single balance run. + * Limited because this is done with IRQs disabled. + */ +const_debug unsigned int sysctl_sched_nr_migrate = 32; + +/* * For kernel-internal use: high-speed (but slightly incorrect) per-cpu * clock constructed from sched_clock(): */ @@ -1019,10 +1022,16 @@ unsigned long weighted_cpuload(const int cpu) static inline void __set_task_cpu(struct task_struct *p, unsigned int cpu) { + set_task_cfs_rq(p, cpu); #ifdef CONFIG_SMP + /* + * After ->cpu is set up to a new value, task_rq_lock(p, ...) can be + * successfuly executed on another CPU. We must ensure that updates of + * per-task data have been completed by this moment. + */ + smp_wmb(); task_thread_info(p)->cpu = cpu; #endif - set_task_cfs_rq(p); } #ifdef CONFIG_SMP @@ -2237,7 +2246,7 @@ balance_tasks(struct rq *this_rq, int this_cpu, struct rq *busiest, enum cpu_idle_type idle, int *all_pinned, int *this_best_prio, struct rq_iterator *iterator) { - int pulled = 0, pinned = 0, skip_for_load; + int loops = 0, pulled = 0, pinned = 0, skip_for_load; struct task_struct *p; long rem_load_move = max_load_move; @@ -2251,10 +2260,10 @@ balance_tasks(struct rq *this_rq, int this_cpu, struct rq *busiest, */ p = iterator->start(iterator->arg); next: - if (!p) + if (!p || loops++ > sysctl_sched_nr_migrate) goto out; /* - * To help distribute high priority tasks accross CPUs we don't + * To help distribute high priority tasks across CPUs we don't * skip a task if it will be the highest priority task (i.e. smallest * prio value) on its new queue regardless of its load weight */ @@ -2271,8 +2280,7 @@ next: rem_load_move -= p->se.load.weight; /* - * We only want to steal up to the prescribed number of tasks - * and the prescribed amount of weighted load. + * We only want to steal up to the prescribed amount of weighted load. */ if (rem_load_move > 0) { if (p->prio < *this_best_prio) @@ -3335,13 +3343,9 @@ void account_user_time(struct task_struct *p, cputime_t cputime) { struct cpu_usage_stat *cpustat = &kstat_this_cpu.cpustat; cputime64_t tmp; - struct rq *rq = this_rq(); p->utime = cputime_add(p->utime, cputime); - if (p != rq->idle) - cpuacct_charge(p, cputime); - /* Add user time to cpustat. */ tmp = cputime_to_cputime64(cputime); if (TASK_NICE(p) > 0) @@ -3392,10 +3396,8 @@ void account_system_time(struct task_struct *p, int hardirq_offset, struct rq *rq = this_rq(); cputime64_t tmp; - if (p->flags & PF_VCPU) { - account_guest_time(p, cputime); - return; - } + if ((p->flags & PF_VCPU) && (irq_count() - hardirq_offset == 0)) + return account_guest_time(p, cputime); p->stime = cputime_add(p->stime, cputime); @@ -3405,10 +3407,9 @@ void account_system_time(struct task_struct *p, int hardirq_offset, cpustat->irq = cputime64_add(cpustat->irq, tmp); else if (softirq_count()) cpustat->softirq = cputime64_add(cpustat->softirq, tmp); - else if (p != rq->idle) { + else if (p != rq->idle) cpustat->system = cputime64_add(cpustat->system, tmp); - cpuacct_charge(p, cputime); - } else if (atomic_read(&rq->nr_iowait) > 0) + else if (atomic_read(&rq->nr_iowait) > 0) cpustat->iowait = cputime64_add(cpustat->iowait, tmp); else cpustat->idle = cputime64_add(cpustat->idle, tmp); @@ -3444,10 +3445,8 @@ void account_steal_time(struct task_struct *p, cputime_t steal) cpustat->iowait = cputime64_add(cpustat->iowait, tmp); else cpustat->idle = cputime64_add(cpustat->idle, tmp); - } else { + } else cpustat->steal = cputime64_add(cpustat->steal, tmp); - cpuacct_charge(p, -tmp); - } } /* @@ -4992,6 +4991,32 @@ void __cpuinit init_idle(struct task_struct *idle, int cpu) */ cpumask_t nohz_cpu_mask = CPU_MASK_NONE; +/* + * Increase the granularity value when there are more CPUs, + * because with more CPUs the 'effective latency' as visible + * to users decreases. But the relationship is not linear, + * so pick a second-best guess by going with the log2 of the + * number of CPUs. + * + * This idea comes from the SD scheduler of Con Kolivas: + */ +static inline void sched_init_granularity(void) +{ + unsigned int factor = 1 + ilog2(num_online_cpus()); + const unsigned long limit = 200000000; + + sysctl_sched_min_granularity *= factor; + if (sysctl_sched_min_granularity > limit) + sysctl_sched_min_granularity = limit; + + sysctl_sched_latency *= factor; + if (sysctl_sched_latency > limit) + sysctl_sched_latency = limit; + + sysctl_sched_wakeup_granularity *= factor; + sysctl_sched_batch_wakeup_granularity *= factor; +} + #ifdef CONFIG_SMP /* * This is how migration works: @@ -5257,23 +5282,9 @@ static void migrate_live_tasks(int src_cpu) } /* - * activate_idle_task - move idle task to the _front_ of runqueue. - */ -static void activate_idle_task(struct task_struct *p, struct rq *rq) -{ - update_rq_clock(rq); - - if (p->state == TASK_UNINTERRUPTIBLE) - rq->nr_uninterruptible--; - - enqueue_task(rq, p, 0); - inc_nr_running(p, rq); -} - -/* * Schedules idle task to be the next runnable task on current CPU. - * It does so by boosting its priority to highest possible and adding it to - * the _front_ of the runqueue. Used by CPU offline code. + * It does so by boosting its priority to highest possible. + * Used by CPU offline code. */ void sched_idle_next(void) { @@ -5293,8 +5304,8 @@ void sched_idle_next(void) __setscheduler(rq, p, SCHED_FIFO, MAX_RT_PRIO-1); - /* Add idle task to the _front_ of its priority queue: */ - activate_idle_task(p, rq); + update_rq_clock(rq); + activate_task(rq, p, 0); spin_unlock_irqrestore(&rq->lock, flags); } @@ -5455,7 +5466,7 @@ sd_alloc_ctl_domain_table(struct sched_domain *sd) return table; } -static ctl_table * sd_alloc_ctl_cpu_table(int cpu) +static ctl_table *sd_alloc_ctl_cpu_table(int cpu) { struct ctl_table *entry, *table; struct sched_domain *sd; @@ -5621,7 +5632,7 @@ static struct notifier_block __cpuinitdata migration_notifier = { .priority = 10 }; -int __init migration_init(void) +void __init migration_init(void) { void *cpu = (void *)(long)smp_processor_id(); int err; @@ -5631,8 +5642,6 @@ int __init migration_init(void) BUG_ON(err == NOTIFY_BAD); migration_call(&migration_notifier, CPU_ONLINE, cpu); register_cpu_notifier(&migration_notifier); - - return 0; } #endif @@ -6688,18 +6697,17 @@ void __init sched_init_smp(void) /* Move init over to a non-isolated CPU */ if (set_cpus_allowed(current, non_isolated_cpus) < 0) BUG(); + sched_init_granularity(); } #else void __init sched_init_smp(void) { + sched_init_granularity(); } #endif /* CONFIG_SMP */ int in_sched_functions(unsigned long addr) { - /* Linker adds these: start and end of __sched functions */ - extern char __sched_text_start[], __sched_text_end[]; - return in_lock_functions(addr) || (addr >= (unsigned long)__sched_text_start && addr < (unsigned long)__sched_text_end); @@ -7068,8 +7076,10 @@ void sched_move_task(struct task_struct *tsk) rq = task_rq_lock(tsk, &flags); - if (tsk->sched_class != &fair_sched_class) + if (tsk->sched_class != &fair_sched_class) { + set_task_cfs_rq(tsk, task_cpu(tsk)); goto done; + } update_rq_clock(rq); @@ -7082,7 +7092,7 @@ void sched_move_task(struct task_struct *tsk) tsk->sched_class->put_prev_task(rq, tsk); } - set_task_cfs_rq(tsk); + set_task_cfs_rq(tsk, task_cpu(tsk)); if (on_rq) { if (unlikely(running)) @@ -7228,7 +7238,7 @@ static u64 cpu_usage_read(struct cgroup *cgrp, struct cftype *cft) spin_unlock_irqrestore(&cpu_rq(i)->lock, flags); } /* Convert from ns to ms */ - do_div(res, 1000000); + do_div(res, NSEC_PER_MSEC); return res; } diff --git a/kernel/sched_debug.c b/kernel/sched_debug.c index 415e5c3..d30467b 100644 --- a/kernel/sched_debug.c +++ b/kernel/sched_debug.c @@ -199,7 +199,7 @@ static int sched_debug_show(struct seq_file *m, void *v) u64 now = ktime_to_ns(ktime_get()); int cpu; - SEQ_printf(m, "Sched Debug Version: v0.06-v22, %s %.*s\n", + SEQ_printf(m, "Sched Debug Version: v0.07, %s %.*s\n", init_utsname()->release, (int)strcspn(init_utsname()->version, " "), init_utsname()->version); @@ -211,7 +211,7 @@ static int sched_debug_show(struct seq_file *m, void *v) #define PN(x) \ SEQ_printf(m, " .%-40s: %Ld.%06ld\n", #x, SPLIT_NS(x)) PN(sysctl_sched_latency); - PN(sysctl_sched_nr_latency); + PN(sysctl_sched_min_granularity); PN(sysctl_sched_wakeup_granularity); PN(sysctl_sched_batch_wakeup_granularity); PN(sysctl_sched_child_runs_first); @@ -327,10 +327,12 @@ void proc_sched_show_task(struct task_struct *p, struct seq_file *m) avg_atom = -1LL; avg_per_cpu = p->se.sum_exec_runtime; - if (p->se.nr_migrations) - avg_per_cpu = div64_64(avg_per_cpu, p->se.nr_migrations); - else + if (p->se.nr_migrations) { + avg_per_cpu = div64_64(avg_per_cpu, + p->se.nr_migrations); + } else { avg_per_cpu = -1LL; + } __PN(avg_atom); __PN(avg_per_cpu); diff --git a/kernel/sched_fair.c b/kernel/sched_fair.c index 01859f6..2f16e15 100644 --- a/kernel/sched_fair.c +++ b/kernel/sched_fair.c @@ -22,7 +22,7 @@ /* * Targeted preemption latency for CPU-bound tasks: - * (default: 20ms, units: nanoseconds) + * (default: 20ms * (1 + ilog(ncpus)), units: nanoseconds) * * NOTE: this latency value is not the same as the concept of * 'timeslice length' - timeslices in CFS are of variable length @@ -32,19 +32,24 @@ * (to see the precise effective timeslice length of your workload, * run vmstat and monitor the context-switches (cs) field) */ -const_debug unsigned int sysctl_sched_latency = 20000000ULL; +unsigned int sysctl_sched_latency = 20000000ULL; /* - * After fork, child runs first. (default) If set to 0 then - * parent will (try to) run first. + * Minimal preemption granularity for CPU-bound tasks: + * (default: 4 msec * (1 + ilog(ncpus)), units: nanoseconds) */ -const_debug unsigned int sysctl_sched_child_runs_first = 1; +unsigned int sysctl_sched_min_granularity = 4000000ULL; /* - * Minimal preemption granularity for CPU-bound tasks: - * (default: 2 msec, units: nanoseconds) + * is kept at sysctl_sched_latency / sysctl_sched_min_granularity + */ +static unsigned int sched_nr_latency = 5; + +/* + * After fork, child runs first. (default) If set to 0 then + * parent will (try to) run first. */ -const_debug unsigned int sysctl_sched_nr_latency = 20; +const_debug unsigned int sysctl_sched_child_runs_first = 1; /* * sys_sched_yield() compat mode @@ -56,23 +61,23 @@ unsigned int __read_mostly sysctl_sched_compat_yield; /* * SCHED_BATCH wake-up granularity. - * (default: 10 msec, units: nanoseconds) + * (default: 10 msec * (1 + ilog(ncpus)), units: nanoseconds) * * This option delays the preemption effects of decoupled workloads * and reduces their over-scheduling. Synchronous workloads will still * have immediate wakeup/sleep latencies. */ -const_debug unsigned int sysctl_sched_batch_wakeup_granularity = 10000000UL; +unsigned int sysctl_sched_batch_wakeup_granularity = 10000000UL; /* * SCHED_OTHER wake-up granularity. - * (default: 10 msec, units: nanoseconds) + * (default: 10 msec * (1 + ilog(ncpus)), units: nanoseconds) * * This option delays the preemption effects of decoupled workloads * and reduces their over-scheduling. Synchronous workloads will still * have immediate wakeup/sleep latencies. */ -const_debug unsigned int sysctl_sched_wakeup_granularity = 10000000UL; +unsigned int sysctl_sched_wakeup_granularity = 10000000UL; const_debug unsigned int sysctl_sched_migration_cost = 500000UL; @@ -212,6 +217,22 @@ static inline struct sched_entity *__pick_last_entity(struct cfs_rq *cfs_rq) * Scheduling class statistics methods: */ +#ifdef CONFIG_SCHED_DEBUG +int sched_nr_latency_handler(struct ctl_table *table, int write, + struct file *filp, void __user *buffer, size_t *lenp, + loff_t *ppos) +{ + int ret = proc_dointvec_minmax(table, write, filp, buffer, lenp, ppos); + + if (ret || !write) + return ret; + + sched_nr_latency = DIV_ROUND_UP(sysctl_sched_latency, + sysctl_sched_min_granularity); + + return 0; +} +#endif /* * The idea is to set a period in which each task runs once. @@ -224,7 +245,7 @@ static inline struct sched_entity *__pick_last_entity(struct cfs_rq *cfs_rq) static u64 __sched_period(unsigned long nr_running) { u64 period = sysctl_sched_latency; - unsigned long nr_latency = sysctl_sched_nr_latency; + unsigned long nr_latency = sched_nr_latency; if (unlikely(nr_running > nr_latency)) { period *= nr_running; @@ -259,6 +280,7 @@ static u64 __sched_vslice(unsigned long rq_weight, unsigned long nr_running) { u64 vslice = __sched_period(nr_running); + vslice *= NICE_0_LOAD; do_div(vslice, rq_weight); return vslice; @@ -472,19 +494,26 @@ place_entity(struct cfs_rq *cfs_rq, struct sched_entity *se, int initial) } else if (sched_feat(APPROX_AVG) && cfs_rq->nr_running) vruntime += sched_vslice(cfs_rq)/2; + /* + * The 'current' period is already promised to the current tasks, + * however the extra weight of the new task will slow them down a + * little, place the new task so that it fits in the slot that + * stays open at the end. + */ if (initial && sched_feat(START_DEBIT)) vruntime += sched_vslice_add(cfs_rq, se); if (!initial) { + /* sleeps upto a single latency don't count. */ if (sched_feat(NEW_FAIR_SLEEPERS) && entity_is_task(se) && task_of(se)->policy != SCHED_BATCH) vruntime -= sysctl_sched_latency; - vruntime = max_t(s64, vruntime, se->vruntime); + /* ensure we never gain time by being placed backwards. */ + vruntime = max_vruntime(se->vruntime, vruntime); } se->vruntime = vruntime; - } static void @@ -517,7 +546,6 @@ dequeue_entity(struct cfs_rq *cfs_rq, struct sched_entity *se, int sleep) update_stats_dequeue(cfs_rq, se); if (sleep) { - se->peer_preempt = 0; #ifdef CONFIG_SCHEDSTATS if (entity_is_task(se)) { struct task_struct *tsk = task_of(se); @@ -545,10 +573,8 @@ check_preempt_tick(struct cfs_rq *cfs_rq, struct sched_entity *curr) ideal_runtime = sched_slice(cfs_rq, curr); delta_exec = curr->sum_exec_runtime - curr->prev_sum_exec_runtime; - if (delta_exec > ideal_runtime || - (sched_feat(PREEMPT_RESTRICT) && curr->peer_preempt)) + if (delta_exec > ideal_runtime) resched_task(rq_of(cfs_rq)->curr); - curr->peer_preempt = 0; } static void @@ -811,7 +837,7 @@ static void check_preempt_wakeup(struct rq *rq, struct task_struct *p) struct task_struct *curr = rq->curr; struct cfs_rq *cfs_rq = task_cfs_rq(curr); struct sched_entity *se = &curr->se, *pse = &p->se; - s64 delta, gran; + unsigned long gran; if (unlikely(rt_prio(p->prio))) { update_rq_clock(rq); @@ -826,24 +852,20 @@ static void check_preempt_wakeup(struct rq *rq, struct task_struct *p) if (unlikely(p->policy == SCHED_BATCH)) return; - if (sched_feat(WAKEUP_PREEMPT)) { - while (!is_same_group(se, pse)) { - se = parent_entity(se); - pse = parent_entity(pse); - } + if (!sched_feat(WAKEUP_PREEMPT)) + return; - delta = se->vruntime - pse->vruntime; - gran = sysctl_sched_wakeup_granularity; - if (unlikely(se->load.weight != NICE_0_LOAD)) - gran = calc_delta_fair(gran, &se->load); + while (!is_same_group(se, pse)) { + se = parent_entity(se); + pse = parent_entity(pse); + } - if (delta > gran) { - int now = !sched_feat(PREEMPT_RESTRICT); + gran = sysctl_sched_wakeup_granularity; + if (unlikely(se->load.weight != NICE_0_LOAD)) + gran = calc_delta_fair(gran, &se->load); - if (now || p->prio < curr->prio || !se->peer_preempt++) - resched_task(curr); - } - } + if (pse->vruntime + gran < se->vruntime) + resched_task(curr); } static struct task_struct *pick_next_task_fair(struct rq *rq) @@ -1045,8 +1067,9 @@ static void task_new_fair(struct rq *rq, struct task_struct *p) update_curr(cfs_rq); place_entity(cfs_rq, se, 1); + /* 'curr' will be NULL if the child belongs to a different group */ if (sysctl_sched_child_runs_first && this_cpu == task_cpu(p) && - curr->vruntime < se->vruntime) { + curr && curr->vruntime < se->vruntime) { /* * Upon rescheduling, sched_class::put_prev_task() will place * 'current' within the tree based on its new key value. @@ -1054,7 +1077,6 @@ static void task_new_fair(struct rq *rq, struct task_struct *p) swap(curr->vruntime, se->vruntime); } - se->peer_preempt = 0; enqueue_task_fair(rq, p, 0); resched_task(rq->curr); } diff --git a/kernel/sched_stats.h b/kernel/sched_stats.h index ef1a7df..5b32433 100644 --- a/kernel/sched_stats.h +++ b/kernel/sched_stats.h @@ -52,7 +52,8 @@ static int show_schedstat(struct seq_file *seq, void *v) sd->lb_nobusyq[itype], sd->lb_nobusyg[itype]); } - seq_printf(seq, " %u %u %u %u %u %u %u %u %u %u %u %u\n", + seq_printf(seq, + " %u %u %u %u %u %u %u %u %u %u %u %u\n", sd->alb_count, sd->alb_failed, sd->alb_pushed, sd->sbe_count, sd->sbe_balanced, sd->sbe_pushed, sd->sbf_count, sd->sbf_balanced, sd->sbf_pushed, @@ -127,7 +128,7 @@ rq_sched_info_depart(struct rq *rq, unsigned long long delta) # define schedstat_set(var, val) do { } while (0) #endif -#ifdef CONFIG_SCHEDSTATS +#if defined(CONFIG_SCHEDSTATS) || defined(CONFIG_TASK_DELAY_ACCT) /* * Called when a process is dequeued from the active array and given * the cpu. We should note that with the exception of interactive @@ -155,7 +156,7 @@ static inline void sched_info_dequeued(struct task_struct *t) */ static void sched_info_arrive(struct task_struct *t) { - unsigned long long now = sched_clock(), delta = 0; + unsigned long long now = task_rq(t)->clock, delta = 0; if (t->sched_info.last_queued) delta = now - t->sched_info.last_queued; @@ -186,7 +187,7 @@ static inline void sched_info_queued(struct task_struct *t) { if (unlikely(sched_info_on())) if (!t->sched_info.last_queued) - t->sched_info.last_queued = sched_clock(); + t->sched_info.last_queued = task_rq(t)->clock; } /* @@ -195,7 +196,8 @@ static inline void sched_info_queued(struct task_struct *t) */ static inline void sched_info_depart(struct task_struct *t) { - unsigned long long delta = sched_clock() - t->sched_info.last_arrival; + unsigned long long delta = task_rq(t)->clock - + t->sched_info.last_arrival; t->sched_info.cpu_time += delta; rq_sched_info_depart(task_rq(t), delta); @@ -231,5 +233,5 @@ sched_info_switch(struct task_struct *prev, struct task_struct *next) #else #define sched_info_queued(t) do { } while (0) #define sched_info_switch(t, next) do { } while (0) -#endif /* CONFIG_SCHEDSTATS */ +#endif /* CONFIG_SCHEDSTATS || CONFIG_TASK_DELAY_ACCT */ diff --git a/kernel/signal.c b/kernel/signal.c index 909a0cc..afa4f78 100644 --- a/kernel/signal.c +++ b/kernel/signal.c @@ -55,7 +55,7 @@ static int sig_ignored(struct task_struct *t, int sig) * signal handler may change by the time it is * unblocked. */ - if (sigismember(&t->blocked, sig)) + if (sigismember(&t->blocked, sig) || sigismember(&t->real_blocked, sig)) return 0; /* Is it explicitly or implicitly ignored? */ diff --git a/kernel/sys.c b/kernel/sys.c index 304b541..d1fe71e 100644 --- a/kernel/sys.c +++ b/kernel/sys.c @@ -1750,7 +1750,7 @@ asmlinkage long sys_prctl(int option, unsigned long arg2, unsigned long arg3, } asmlinkage long sys_getcpu(unsigned __user *cpup, unsigned __user *nodep, - struct getcpu_cache __user *cache) + struct getcpu_cache __user *unused) { int err = 0; int cpu = raw_smp_processor_id(); @@ -1758,24 +1758,6 @@ asmlinkage long sys_getcpu(unsigned __user *cpup, unsigned __user *nodep, err |= put_user(cpu, cpup); if (nodep) err |= put_user(cpu_to_node(cpu), nodep); - if (cache) { - /* - * The cache is not needed for this implementation, - * but make sure user programs pass something - * valid. vsyscall implementations can instead make - * good use of the cache. Only use t0 and t1 because - * these are available in both 32bit and 64bit ABI (no - * need for a compat_getcpu). 32bit has enough - * padding - */ - unsigned long t0, t1; - get_user(t0, &cache->blob[0]); - get_user(t1, &cache->blob[1]); - t0++; - t1++; - put_user(t0, &cache->blob[0]); - put_user(t1, &cache->blob[1]); - } return err ? -EFAULT : 0; } diff --git a/kernel/sysctl.c b/kernel/sysctl.c index 3b4efbe..0deed82 100644 --- a/kernel/sysctl.c +++ b/kernel/sysctl.c @@ -226,20 +226,23 @@ static struct ctl_table root_table[] = { #ifdef CONFIG_SCHED_DEBUG static unsigned long min_sched_granularity_ns = 100000; /* 100 usecs */ -static unsigned long max_sched_granularity_ns = 1000000000; /* 1 second */ +static unsigned long max_sched_granularity_ns = NSEC_PER_SEC; /* 1 second */ static unsigned long min_wakeup_granularity_ns; /* 0 usecs */ -static unsigned long max_wakeup_granularity_ns = 1000000000; /* 1 second */ +static unsigned long max_wakeup_granularity_ns = NSEC_PER_SEC; /* 1 second */ #endif static struct ctl_table kern_table[] = { #ifdef CONFIG_SCHED_DEBUG { .ctl_name = CTL_UNNUMBERED, - .procname = "sched_nr_latency", - .data = &sysctl_sched_nr_latency, + .procname = "sched_min_granularity_ns", + .data = &sysctl_sched_min_granularity, .maxlen = sizeof(unsigned int), .mode = 0644, - .proc_handler = &proc_dointvec, + .proc_handler = &sched_nr_latency_handler, + .strategy = &sysctl_intvec, + .extra1 = &min_sched_granularity_ns, + .extra2 = &max_sched_granularity_ns, }, { .ctl_name = CTL_UNNUMBERED, @@ -247,7 +250,7 @@ static struct ctl_table kern_table[] = { .data = &sysctl_sched_latency, .maxlen = sizeof(unsigned int), .mode = 0644, - .proc_handler = &proc_dointvec_minmax, + .proc_handler = &sched_nr_latency_handler, .strategy = &sysctl_intvec, .extra1 = &min_sched_granularity_ns, .extra2 = &max_sched_granularity_ns, @@ -298,6 +301,14 @@ static struct ctl_table kern_table[] = { .mode = 0644, .proc_handler = &proc_dointvec, }, + { + .ctl_name = CTL_UNNUMBERED, + .procname = "sched_nr_migrate", + .data = &sysctl_sched_nr_migrate, + .maxlen = sizeof(unsigned int), + .mode = 644, + .proc_handler = &proc_dointvec, + }, #endif { .ctl_name = CTL_UNNUMBERED, @@ -2609,6 +2620,10 @@ static int deprecated_sysctl_warning(struct __sysctl_args *args) int name[CTL_MAXNAME]; int i; + /* Check args->nlen. */ + if (args->nlen < 0 || args->nlen > CTL_MAXNAME) + return -ENOTDIR; + /* Read in the sysctl name for better debug message logging */ for (i = 0; i < args->nlen; i++) if (get_user(name[i], args->name + i)) diff --git a/kernel/sysctl_check.c b/kernel/sysctl_check.c index 5a2f2b2..6972f26 100644 --- a/kernel/sysctl_check.c +++ b/kernel/sysctl_check.c @@ -140,9 +140,6 @@ static struct trans_ctl_table trans_vm_table[] = { { VM_PANIC_ON_OOM, "panic_on_oom" }, { VM_VDSO_ENABLED, "vdso_enabled" }, { VM_MIN_SLAB, "min_slab_ratio" }, - { VM_CMM_PAGES, "cmm_pages" }, - { VM_CMM_TIMED_PAGES, "cmm_timed_pages" }, - { VM_CMM_TIMEOUT, "cmm_timeout" }, {} }; @@ -237,36 +234,6 @@ static struct trans_ctl_table trans_net_ipv4_conf_table[] = { {} }; - -static struct trans_ctl_table trans_net_ipv4_vs_table[] = { - { NET_IPV4_VS_AMEMTHRESH, "amemthresh" }, - { NET_IPV4_VS_DEBUG_LEVEL, "debug_level" }, - { NET_IPV4_VS_AMDROPRATE, "am_droprate" }, - { NET_IPV4_VS_DROP_ENTRY, "drop_entry" }, - { NET_IPV4_VS_DROP_PACKET, "drop_packet" }, - { NET_IPV4_VS_SECURE_TCP, "secure_tcp" }, - { NET_IPV4_VS_TO_ES, "timeout_established" }, - { NET_IPV4_VS_TO_SS, "timeout_synsent" }, - { NET_IPV4_VS_TO_SR, "timeout_synrecv" }, - { NET_IPV4_VS_TO_FW, "timeout_finwait" }, - { NET_IPV4_VS_TO_TW, "timeout_timewait" }, - { NET_IPV4_VS_TO_CL, "timeout_close" }, - { NET_IPV4_VS_TO_CW, "timeout_closewait" }, - { NET_IPV4_VS_TO_LA, "timeout_lastack" }, - { NET_IPV4_VS_TO_LI, "timeout_listen" }, - { NET_IPV4_VS_TO_SA, "timeout_synack" }, - { NET_IPV4_VS_TO_UDP, "timeout_udp" }, - { NET_IPV4_VS_TO_ICMP, "timeout_icmp" }, - { NET_IPV4_VS_CACHE_BYPASS, "cache_bypass" }, - { NET_IPV4_VS_EXPIRE_NODEST_CONN, "expire_nodest_conn" }, - { NET_IPV4_VS_EXPIRE_QUIESCENT_TEMPLATE, "expire_quiescent_template" }, - { NET_IPV4_VS_SYNC_THRESHOLD, "sync_threshold" }, - { NET_IPV4_VS_NAT_ICMP_SEND, "nat_icmp_send" }, - { NET_IPV4_VS_LBLC_EXPIRE, "lblc_expiration" }, - { NET_IPV4_VS_LBLCR_EXPIRE, "lblcr_expiration" }, - {} -}; - static struct trans_ctl_table trans_net_neigh_vars_table[] = { { NET_NEIGH_MCAST_SOLICIT, "mcast_solicit" }, { NET_NEIGH_UCAST_SOLICIT, "ucast_solicit" }, @@ -341,7 +308,6 @@ static struct trans_ctl_table trans_net_ipv4_table[] = { { NET_IPV4_ROUTE, "route", trans_net_ipv4_route_table }, /* NET_IPV4_FIB_HASH unused */ { NET_IPV4_NETFILTER, "netfilter", trans_net_ipv4_netfilter_table }, - { NET_IPV4_VS, "vs", trans_net_ipv4_vs_table }, { NET_IPV4_TCP_TIMESTAMPS, "tcp_timestamps" }, { NET_IPV4_TCP_WINDOW_SCALING, "tcp_window_scaling" }, @@ -738,7 +704,7 @@ static struct trans_ctl_table trans_net_table[] = { { NET_ROSE, "rose", trans_net_rose_table }, { NET_IPV6, "ipv6", trans_net_ipv6_table }, { NET_X25, "x25", trans_net_x25_table }, - { NET_TR, "tr", trans_net_tr_table }, + { NET_TR, "token-ring", trans_net_tr_table }, { NET_DECNET, "decnet", trans_net_decnet_table }, /* NET_ECONET not used */ { NET_SCTP, "sctp", trans_net_sctp_table }, @@ -1219,16 +1185,6 @@ static struct trans_ctl_table trans_arlan_table[] = { {} }; -static struct trans_ctl_table trans_appldata_table[] = { - { CTL_APPLDATA_TIMER, "timer" }, - { CTL_APPLDATA_INTERVAL, "interval" }, - { CTL_APPLDATA_OS, "os" }, - { CTL_APPLDATA_NET_SUM, "net_sum" }, - { CTL_APPLDATA_MEM, "mem" }, - {} - -}; - static struct trans_ctl_table trans_s390dbf_table[] = { { 5678 /* CTL_S390DBF_STOPPABLE */, "debug_stoppable" }, { 5679 /* CTL_S390DBF_ACTIVE */, "debug_active" }, @@ -1273,7 +1229,6 @@ static struct trans_ctl_table trans_root_table[] = { { CTL_ABI, "abi" }, /* CTL_CPU not used */ { CTL_ARLAN, "arlan", trans_arlan_table }, - { CTL_APPLDATA, "appldata", trans_appldata_table }, { CTL_S390DBF, "s390dbf", trans_s390dbf_table }, { CTL_SUNRPC, "sunrpc", trans_sunrpc_table }, { CTL_PM, "pm", trans_pm_table }, diff --git a/kernel/taskstats.c b/kernel/taskstats.c index 354e74b..07e86a8 100644 --- a/kernel/taskstats.c +++ b/kernel/taskstats.c @@ -398,31 +398,31 @@ static int cgroupstats_user_cmd(struct sk_buff *skb, struct genl_info *info) fd = nla_get_u32(info->attrs[CGROUPSTATS_CMD_ATTR_FD]); file = fget_light(fd, &fput_needed); - if (file) { - size = nla_total_size(sizeof(struct cgroupstats)); + if (!file) + return 0; - rc = prepare_reply(info, CGROUPSTATS_CMD_NEW, &rep_skb, - size); - if (rc < 0) - goto err; + size = nla_total_size(sizeof(struct cgroupstats)); - na = nla_reserve(rep_skb, CGROUPSTATS_TYPE_CGROUP_STATS, - sizeof(struct cgroupstats)); - stats = nla_data(na); - memset(stats, 0, sizeof(*stats)); + rc = prepare_reply(info, CGROUPSTATS_CMD_NEW, &rep_skb, + size); + if (rc < 0) + goto err; - rc = cgroupstats_build(stats, file->f_dentry); - if (rc < 0) - goto err; + na = nla_reserve(rep_skb, CGROUPSTATS_TYPE_CGROUP_STATS, + sizeof(struct cgroupstats)); + stats = nla_data(na); + memset(stats, 0, sizeof(*stats)); - fput_light(file, fput_needed); - return send_reply(rep_skb, info->snd_pid); + rc = cgroupstats_build(stats, file->f_dentry); + if (rc < 0) { + nlmsg_free(rep_skb); + goto err; } + rc = send_reply(rep_skb, info->snd_pid); + err: - if (file) - fput_light(file, fput_needed); - nlmsg_free(rep_skb); + fput_light(file, fput_needed); return rc; } diff --git a/kernel/time/ntp.c b/kernel/time/ntp.c index de6a2d6..e64efaf 100644 --- a/kernel/time/ntp.c +++ b/kernel/time/ntp.c @@ -205,7 +205,7 @@ static void sync_cmos_clock(unsigned long dummy) return; getnstimeofday(&now); - if (abs(xtime.tv_nsec - (NSEC_PER_SEC / 2)) <= tick_nsec / 2) + if (abs(now.tv_nsec - (NSEC_PER_SEC / 2)) <= tick_nsec / 2) fail = update_persistent_clock(now); next.tv_nsec = (NSEC_PER_SEC / 2) - now.tv_nsec; @@ -249,10 +249,12 @@ int do_adjtimex(struct timex *txc) /* Now we validate the data before disabling interrupts */ - if ((txc->modes & ADJ_OFFSET_SINGLESHOT) == ADJ_OFFSET_SINGLESHOT) + if ((txc->modes & ADJ_OFFSET_SINGLESHOT) == ADJ_OFFSET_SINGLESHOT) { /* singleshot must not be used with any other mode bits */ - if (txc->modes != ADJ_OFFSET_SINGLESHOT) + if (txc->modes != ADJ_OFFSET_SINGLESHOT && + txc->modes != ADJ_OFFSET_SS_READ) return -EINVAL; + } if (txc->modes != ADJ_OFFSET_SINGLESHOT && (txc->modes & ADJ_OFFSET)) /* adjustment Offset limited to +- .512 seconds */ @@ -372,7 +374,8 @@ int do_adjtimex(struct timex *txc) leave: if ((time_status & (STA_UNSYNC|STA_CLOCKERR)) != 0) result = TIME_ERROR; - if ((txc->modes & ADJ_OFFSET_SINGLESHOT) == ADJ_OFFSET_SINGLESHOT) + if ((txc->modes == ADJ_OFFSET_SINGLESHOT) || + (txc->modes == ADJ_OFFSET_SS_READ)) txc->offset = save_adjust; else txc->offset = ((long)shift_right(time_offset, SHIFT_UPDATE)) * diff --git a/kernel/time/tick-sched.c b/kernel/time/tick-sched.c index 27a2338..cb89fa8 100644 --- a/kernel/time/tick-sched.c +++ b/kernel/time/tick-sched.c @@ -133,6 +133,8 @@ void tick_nohz_update_jiffies(void) if (!ts->tick_stopped) return; + touch_softlockup_watchdog(); + cpu_clear(cpu, nohz_cpu_mask); now = ktime_get(); diff --git a/kernel/timer.c b/kernel/timer.c index 00e44e2..a05817c 100644 --- a/kernel/timer.c +++ b/kernel/timer.c @@ -817,6 +817,19 @@ unsigned long next_timer_interrupt(void) #endif +#ifndef CONFIG_VIRT_CPU_ACCOUNTING +void account_process_tick(struct task_struct *p, int user_tick) +{ + if (user_tick) { + account_user_time(p, jiffies_to_cputime(1)); + account_user_time_scaled(p, jiffies_to_cputime(1)); + } else { + account_system_time(p, HARDIRQ_OFFSET, jiffies_to_cputime(1)); + account_system_time_scaled(p, jiffies_to_cputime(1)); + } +} +#endif + /* * Called from the timer interrupt handler to charge one tick to the current * process. user_tick is 1 if the tick is user time, 0 for system. @@ -827,13 +840,7 @@ void update_process_times(int user_tick) int cpu = smp_processor_id(); /* Note: this timer irq context must be accounted for as well. */ - if (user_tick) { - account_user_time(p, jiffies_to_cputime(1)); - account_user_time_scaled(p, jiffies_to_cputime(1)); - } else { - account_system_time(p, HARDIRQ_OFFSET, jiffies_to_cputime(1)); - account_system_time_scaled(p, jiffies_to_cputime(1)); - } + account_process_tick(p, user_tick); run_local_timers(); if (rcu_pending(cpu)) rcu_check_callbacks(cpu, user_tick); diff --git a/kernel/user.c b/kernel/user.c index 0f3aa02..8320a87 100644 --- a/kernel/user.c +++ b/kernel/user.c @@ -337,8 +337,11 @@ struct user_struct * alloc_uid(struct user_namespace *ns, uid_t uid) struct user_struct *new; new = kmem_cache_alloc(uid_cachep, GFP_KERNEL); - if (!new) + if (!new) { + uids_mutex_unlock(); return NULL; + } + new->uid = uid; atomic_set(&new->__count, 1); atomic_set(&new->processes, 0); @@ -355,6 +358,7 @@ struct user_struct * alloc_uid(struct user_namespace *ns, uid_t uid) if (alloc_uid_keyring(new, current) < 0) { kmem_cache_free(uid_cachep, new); + uids_mutex_unlock(); return NULL; } @@ -362,6 +366,7 @@ struct user_struct * alloc_uid(struct user_namespace *ns, uid_t uid) key_put(new->uid_keyring); key_put(new->session_keyring); kmem_cache_free(uid_cachep, new); + uids_mutex_unlock(); return NULL; } diff --git a/kernel/utsname_sysctl.c b/kernel/utsname_sysctl.c index c76c064..fe3a56c 100644 --- a/kernel/utsname_sysctl.c +++ b/kernel/utsname_sysctl.c @@ -18,6 +18,10 @@ static void *get_uts(ctl_table *table, int write) { char *which = table->data; + struct uts_namespace *uts_ns; + + uts_ns = current->nsproxy->uts_ns; + which = (which - (char *)&init_uts_ns) + (char *)uts_ns; if (!write) down_read(&uts_sem); diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug index 1e5f207..a601093 100644 --- a/lib/Kconfig.debug +++ b/lib/Kconfig.debug @@ -359,7 +359,7 @@ config DEBUG_HIGHMEM config DEBUG_BUGVERBOSE bool "Verbose BUG() reporting (adds 70K)" if DEBUG_KERNEL && EMBEDDED depends on BUG - depends on ARM || AVR32 || M32R || M68K || SPARC32 || SPARC64 || FRV || SUPERH || GENERIC_BUG || BFIN + depends on ARM || AVR32 || M32R || M68K || SPARC32 || SPARC64 || FRV || SUPERH || GENERIC_BUG || BLACKFIN default !EMBEDDED help Say Y here to make BUG() panics output the file name and line number @@ -409,7 +409,7 @@ config DEBUG_SG config FRAME_POINTER bool "Compile the kernel with frame pointers" - depends on DEBUG_KERNEL && (X86 || CRIS || M68K || M68KNOMMU || FRV || UML || S390 || AVR32 || SUPERH || BFIN) + depends on DEBUG_KERNEL && (X86 || CRIS || M68K || M68KNOMMU || FRV || UML || S390 || AVR32 || SUPERH || BLACKFIN) default y if DEBUG_INFO && UML help If you say Y here the resulting kernel image will be slightly larger diff --git a/lib/Makefile b/lib/Makefile index 3a0983b..b6793ed 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -4,7 +4,7 @@ lib-y := ctype.o string.o vsprintf.o cmdline.o \ rbtree.o radix-tree.o dump_stack.o \ - idr.o int_sqrt.o bitmap.o extable.o prio_tree.o \ + idr.o int_sqrt.o extable.o prio_tree.o \ sha1.o irq_regs.o reciprocal_div.o argv_split.o \ proportions.o prio_heap.o @@ -14,7 +14,7 @@ lib-$(CONFIG_SMP) += cpumask.o lib-y += kobject.o kref.o klist.o obj-y += div64.o sort.o parser.o halfmd4.o debug_locks.o random32.o \ - bust_spinlocks.o hexdump.o kasprintf.o + bust_spinlocks.o hexdump.o kasprintf.o bitmap.o ifeq ($(CONFIG_DEBUG_KOBJECT),y) CFLAGS_kobject.o += -DDEBUG diff --git a/lib/hexdump.c b/lib/hexdump.c index bd5edae..3435465 100644 --- a/lib/hexdump.c +++ b/lib/hexdump.c @@ -106,7 +106,8 @@ void hex_dump_to_buffer(const void *buf, size_t len, int rowsize, while (lx < (linebuflen - 1) && lx < (ascii_column - 1)) linebuf[lx++] = ' '; for (j = 0; (j < rowsize) && (j < len) && (lx + 2) < linebuflen; j++) - linebuf[lx++] = isprint(ptr[j]) ? ptr[j] : '.'; + linebuf[lx++] = (isascii(ptr[j]) && isprint(ptr[j])) ? ptr[j] + : '.'; nil: linebuf[lx++] = '\0'; } diff --git a/lib/kobject.c b/lib/kobject.c index a7e3bf4..b52e9f4 100644 --- a/lib/kobject.c +++ b/lib/kobject.c @@ -313,8 +313,8 @@ int kobject_rename(struct kobject * kobj, const char *new_name) struct kobject *temp_kobj; temp_kobj = kset_find_obj(kobj->kset, new_name); if (temp_kobj) { - printk(KERN_WARNING "kobject '%s' can not be renamed " - "to '%s' as '%s' is already in existance.\n", + printk(KERN_WARNING "kobject '%s' cannot be renamed " + "to '%s' as '%s' is already in existence.\n", kobject_name(kobj), new_name, new_name); kobject_put(temp_kobj); return -EINVAL; diff --git a/lib/libcrc32c.c b/lib/libcrc32c.c index 802f11f..b5c3287 100644 --- a/lib/libcrc32c.c +++ b/lib/libcrc32c.c @@ -33,7 +33,6 @@ #include <linux/crc32c.h> #include <linux/compiler.h> #include <linux/module.h> -#include <asm/byteorder.h> MODULE_AUTHOR("Clay Haapala <chaapala@cisco.com>"); MODULE_DESCRIPTION("CRC32c (Castagnoli) calculations"); @@ -161,15 +160,13 @@ static const u32 crc32c_table[256] = { */ u32 __pure -crc32c_le(u32 seed, unsigned char const *data, size_t length) +crc32c_le(u32 crc, unsigned char const *data, size_t length) { - u32 crc = __cpu_to_le32(seed); - while (length--) crc = crc32c_table[(crc ^ *data++) & 0xFFL] ^ (crc >> 8); - return __le32_to_cpu(crc); + return crc; } #endif /* CRC_LE_BITS == 8 */ diff --git a/lib/textsearch.c b/lib/textsearch.c index 88c98a2..be8bda3 100644 --- a/lib/textsearch.c +++ b/lib/textsearch.c @@ -7,7 +7,7 @@ * 2 of the License, or (at your option) any later version. * * Authors: Thomas Graf <tgraf@suug.ch> - * Pablo Neira Ayuso <pablo@eurodev.net> + * Pablo Neira Ayuso <pablo@netfilter.org> * * ========================================================================== * @@ -250,7 +250,8 @@ unsigned int textsearch_find_continuous(struct ts_config *conf, * the various search algorithms. * * Returns a new textsearch configuration according to the specified - * parameters or a ERR_PTR(). + * parameters or a ERR_PTR(). If a zero length pattern is passed, this + * function returns EINVAL. */ struct ts_config *textsearch_prepare(const char *algo, const void *pattern, unsigned int len, gfp_t gfp_mask, int flags) @@ -259,6 +260,9 @@ struct ts_config *textsearch_prepare(const char *algo, const void *pattern, struct ts_config *conf; struct ts_ops *ops; + if (len == 0) + return ERR_PTR(-EINVAL); + ops = lookup_ts_algo(algo); #ifdef CONFIG_KMOD /* diff --git a/mm/hugetlb.c b/mm/hugetlb.c index 8b809ec..6121b57 100644 --- a/mm/hugetlb.c +++ b/mm/hugetlb.c @@ -116,7 +116,9 @@ static void update_and_free_page(struct page *page) static void free_huge_page(struct page *page) { int nid = page_to_nid(page); + struct address_space *mapping; + mapping = (struct address_space *) page_private(page); BUG_ON(page_count(page)); INIT_LIST_HEAD(&page->lru); @@ -129,6 +131,9 @@ static void free_huge_page(struct page *page) enqueue_huge_page(page); } spin_unlock(&hugetlb_lock); + if (mapping) + hugetlb_put_quota(mapping, 1); + set_page_private(page, 0); } /* @@ -323,7 +328,7 @@ free: * allocated to satisfy the reservation must be explicitly freed if they were * never used. */ -void return_unused_surplus_pages(unsigned long unused_resv_pages) +static void return_unused_surplus_pages(unsigned long unused_resv_pages) { static int nid = -1; struct page *page; @@ -353,35 +358,50 @@ void return_unused_surplus_pages(unsigned long unused_resv_pages) } } -static struct page *alloc_huge_page(struct vm_area_struct *vma, - unsigned long addr) + +static struct page *alloc_huge_page_shared(struct vm_area_struct *vma, + unsigned long addr) { - struct page *page = NULL; - int use_reserved_page = vma->vm_flags & VM_MAYSHARE; + struct page *page; spin_lock(&hugetlb_lock); - if (!use_reserved_page && (free_huge_pages <= resv_huge_pages)) - goto fail; - page = dequeue_huge_page(vma, addr); - if (!page) - goto fail; - spin_unlock(&hugetlb_lock); - set_page_refcounted(page); - return page; + return page ? page : ERR_PTR(-VM_FAULT_OOM); +} -fail: - spin_unlock(&hugetlb_lock); +static struct page *alloc_huge_page_private(struct vm_area_struct *vma, + unsigned long addr) +{ + struct page *page = NULL; - /* - * Private mappings do not use reserved huge pages so the allocation - * may have failed due to an undersized hugetlb pool. Try to grab a - * surplus huge page from the buddy allocator. - */ - if (!use_reserved_page) + if (hugetlb_get_quota(vma->vm_file->f_mapping, 1)) + return ERR_PTR(-VM_FAULT_SIGBUS); + + spin_lock(&hugetlb_lock); + if (free_huge_pages > resv_huge_pages) + page = dequeue_huge_page(vma, addr); + spin_unlock(&hugetlb_lock); + if (!page) page = alloc_buddy_huge_page(vma, addr); + return page ? page : ERR_PTR(-VM_FAULT_OOM); +} + +static struct page *alloc_huge_page(struct vm_area_struct *vma, + unsigned long addr) +{ + struct page *page; + struct address_space *mapping = vma->vm_file->f_mapping; + if (vma->vm_flags & VM_MAYSHARE) + page = alloc_huge_page_shared(vma, addr); + else + page = alloc_huge_page_private(vma, addr); + + if (!IS_ERR(page)) { + set_page_refcounted(page); + set_page_private(page, (unsigned long) mapping); + } return page; } @@ -726,9 +746,9 @@ static int hugetlb_cow(struct mm_struct *mm, struct vm_area_struct *vma, page_cache_get(old_page); new_page = alloc_huge_page(vma, address); - if (!new_page) { + if (IS_ERR(new_page)) { page_cache_release(old_page); - return VM_FAULT_OOM; + return -PTR_ERR(new_page); } spin_unlock(&mm->page_table_lock); @@ -772,27 +792,28 @@ retry: size = i_size_read(mapping->host) >> HPAGE_SHIFT; if (idx >= size) goto out; - if (hugetlb_get_quota(mapping)) - goto out; page = alloc_huge_page(vma, address); - if (!page) { - hugetlb_put_quota(mapping); - ret = VM_FAULT_OOM; + if (IS_ERR(page)) { + ret = -PTR_ERR(page); goto out; } clear_huge_page(page, address); if (vma->vm_flags & VM_SHARED) { int err; + struct inode *inode = mapping->host; err = add_to_page_cache(page, mapping, idx, GFP_KERNEL); if (err) { put_page(page); - hugetlb_put_quota(mapping); if (err == -EEXIST) goto retry; goto out; } + + spin_lock(&inode->i_lock); + inode->i_blocks += BLOCKS_PER_HUGEPAGE; + spin_unlock(&inode->i_lock); } else lock_page(page); } @@ -822,7 +843,6 @@ out: backout: spin_unlock(&mm->page_table_lock); - hugetlb_put_quota(mapping); unlock_page(page); put_page(page); goto out; @@ -868,7 +888,8 @@ int hugetlb_fault(struct mm_struct *mm, struct vm_area_struct *vma, int follow_hugetlb_page(struct mm_struct *mm, struct vm_area_struct *vma, struct page **pages, struct vm_area_struct **vmas, - unsigned long *position, int *length, int i) + unsigned long *position, int *length, int i, + int write) { unsigned long pfn_offset; unsigned long vaddr = *position; @@ -890,7 +911,7 @@ int follow_hugetlb_page(struct mm_struct *mm, struct vm_area_struct *vma, int ret; spin_unlock(&mm->page_table_lock); - ret = hugetlb_fault(mm, vma, vaddr, 0); + ret = hugetlb_fault(mm, vma, vaddr, write); spin_lock(&mm->page_table_lock); if (!(ret & VM_FAULT_ERROR)) continue; @@ -1132,6 +1153,8 @@ int hugetlb_reserve_pages(struct inode *inode, long from, long to) if (chg < 0) return chg; + if (hugetlb_get_quota(inode->i_mapping, chg)) + return -ENOSPC; ret = hugetlb_acct_memory(chg); if (ret < 0) return ret; @@ -1142,5 +1165,11 @@ int hugetlb_reserve_pages(struct inode *inode, long from, long to) void hugetlb_unreserve_pages(struct inode *inode, long offset, long freed) { long chg = region_truncate(&inode->i_mapping->private_list, offset); - hugetlb_acct_memory(freed - chg); + + spin_lock(&inode->i_lock); + inode->i_blocks -= BLOCKS_PER_HUGEPAGE * freed; + spin_unlock(&inode->i_lock); + + hugetlb_put_quota(inode->i_mapping, (chg - freed)); + hugetlb_acct_memory(-(chg - freed)); } diff --git a/mm/memory.c b/mm/memory.c index 9791e47..4bf0b6d 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -1036,7 +1036,7 @@ int get_user_pages(struct task_struct *tsk, struct mm_struct *mm, if (is_vm_hugetlb_page(vma)) { i = follow_hugetlb_page(mm, vma, pages, vmas, - &start, &len, i); + &start, &len, i, write); continue; } @@ -2084,9 +2084,9 @@ static int do_swap_page(struct mm_struct *mm, struct vm_area_struct *vma, count_vm_event(PGMAJFAULT); } - delayacct_clear_flag(DELAYACCT_PF_SWAPIN); mark_page_accessed(page); lock_page(page); + delayacct_clear_flag(DELAYACCT_PF_SWAPIN); /* * Back out if somebody else already faulted in this pte. diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c index 3a47871..9512a54 100644 --- a/mm/memory_hotplug.c +++ b/mm/memory_hotplug.c @@ -39,7 +39,7 @@ static struct resource *register_memory_resource(u64 start, u64 size) res->name = "System RAM"; res->start = start; res->end = start + size - 1; - res->flags = IORESOURCE_MEM; + res->flags = IORESOURCE_MEM | IORESOURCE_BUSY; if (request_resource(&iomem_resource, res) < 0) { printk("System RAM resource %llx - %llx cannot be added\n", (unsigned long long)res->start, (unsigned long long)res->end); @@ -574,8 +574,8 @@ repeat: /* Ok, all of our target is islaoted. We cannot do rollback at this point. */ offline_isolated_pages(start_pfn, end_pfn); - /* reset pagetype flags */ - start_isolate_page_range(start_pfn, end_pfn); + /* reset pagetype flags and makes migrate type to be MOVABLE */ + undo_isolate_page_range(start_pfn, end_pfn); /* removal success */ zone->present_pages -= offlined_pages; zone->zone_pgdat->node_present_pages -= offlined_pages; diff --git a/mm/mempolicy.c b/mm/mempolicy.c index c1592a9..83c69f8 100644 --- a/mm/mempolicy.c +++ b/mm/mempolicy.c @@ -722,12 +722,29 @@ out: } +/* + * Allocate a new page for page migration based on vma policy. + * Start assuming that page is mapped by vma pointed to by @private. + * Search forward from there, if not. N.B., this assumes that the + * list of pages handed to migrate_pages()--which is how we get here-- + * is in virtual address order. + */ static struct page *new_vma_page(struct page *page, unsigned long private, int **x) { struct vm_area_struct *vma = (struct vm_area_struct *)private; + unsigned long uninitialized_var(address); - return alloc_page_vma(GFP_HIGHUSER_MOVABLE, vma, - page_address_in_vma(page, vma)); + while (vma) { + address = page_address_in_vma(page, vma); + if (address != -EFAULT) + break; + vma = vma->vm_next; + } + + /* + * if !vma, alloc_page_vma() will use task or system default policy + */ + return alloc_page_vma(GFP_HIGHUSER_MOVABLE, vma, address); } #else diff --git a/mm/page-writeback.c b/mm/page-writeback.c index 838a5e3..d55cfca 100644 --- a/mm/page-writeback.c +++ b/mm/page-writeback.c @@ -297,20 +297,12 @@ get_dirty_limits(long *pbackground, long *pdirty, long *pbdi_dirty, { int background_ratio; /* Percentages */ int dirty_ratio; - int unmapped_ratio; long background; long dirty; unsigned long available_memory = determine_dirtyable_memory(); struct task_struct *tsk; - unmapped_ratio = 100 - ((global_page_state(NR_FILE_MAPPED) + - global_page_state(NR_ANON_PAGES)) * 100) / - available_memory; - dirty_ratio = vm_dirty_ratio; - if (dirty_ratio > unmapped_ratio / 2) - dirty_ratio = unmapped_ratio / 2; - if (dirty_ratio < 5) dirty_ratio = 5; @@ -355,8 +347,8 @@ get_dirty_limits(long *pbackground, long *pdirty, long *pbdi_dirty, */ static void balance_dirty_pages(struct address_space *mapping) { - long bdi_nr_reclaimable; - long bdi_nr_writeback; + long nr_reclaimable, bdi_nr_reclaimable; + long nr_writeback, bdi_nr_writeback; long background_thresh; long dirty_thresh; long bdi_thresh; @@ -376,11 +368,26 @@ static void balance_dirty_pages(struct address_space *mapping) get_dirty_limits(&background_thresh, &dirty_thresh, &bdi_thresh, bdi); + + nr_reclaimable = global_page_state(NR_FILE_DIRTY) + + global_page_state(NR_UNSTABLE_NFS); + nr_writeback = global_page_state(NR_WRITEBACK); + bdi_nr_reclaimable = bdi_stat(bdi, BDI_RECLAIMABLE); bdi_nr_writeback = bdi_stat(bdi, BDI_WRITEBACK); + if (bdi_nr_reclaimable + bdi_nr_writeback <= bdi_thresh) break; + /* + * Throttle it only when the background writeback cannot + * catch-up. This avoids (excessively) small writeouts + * when the bdi limits are ramping up. + */ + if (nr_reclaimable + nr_writeback < + (background_thresh + dirty_thresh) / 2) + break; + if (!bdi->dirty_exceeded) bdi->dirty_exceeded = 1; diff --git a/mm/page_alloc.c b/mm/page_alloc.c index da69d83..b5a58d4 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -305,7 +305,6 @@ static inline void prep_zero_page(struct page *page, int order, gfp_t gfp_flags) { int i; - VM_BUG_ON((gfp_flags & (__GFP_WAIT | __GFP_HIGHMEM)) == __GFP_HIGHMEM); /* * clear_highpage() will use KM_USER0, so it's a bug to use __GFP_ZERO * and __GFP_HIGHMEM from hard or soft interrupt context. @@ -749,23 +748,6 @@ int move_freepages_block(struct zone *zone, struct page *page, int migratetype) return move_freepages(zone, start_page, end_page, migratetype); } -/* Return the page with the lowest PFN in the list */ -static struct page *min_page(struct list_head *list) -{ - unsigned long min_pfn = -1UL; - struct page *min_page = NULL, *page;; - - list_for_each_entry(page, list, lru) { - unsigned long pfn = page_to_pfn(page); - if (pfn < min_pfn) { - min_pfn = pfn; - min_page = page; - } - } - - return min_page; -} - /* Remove an element from the buddy allocator from the fallback list */ static struct page *__rmqueue_fallback(struct zone *zone, int order, int start_migratetype) @@ -789,11 +771,8 @@ static struct page *__rmqueue_fallback(struct zone *zone, int order, if (list_empty(&area->free_list[migratetype])) continue; - /* Bias kernel allocations towards low pfns */ page = list_entry(area->free_list[migratetype].next, struct page, lru); - if (unlikely(start_migratetype != MIGRATE_MOVABLE)) - page = min_page(&area->free_list[migratetype]); area->nr_free--; /* @@ -3286,6 +3265,16 @@ static void inline setup_usemap(struct pglist_data *pgdat, #endif /* CONFIG_SPARSEMEM */ #ifdef CONFIG_HUGETLB_PAGE_SIZE_VARIABLE + +/* Return a sensible default order for the pageblock size. */ +static inline int pageblock_default_order(void) +{ + if (HPAGE_SHIFT > PAGE_SHIFT) + return HUGETLB_PAGE_ORDER; + + return MAX_ORDER-1; +} + /* Initialise the number of pages represented by NR_PAGEBLOCK_BITS */ static inline void __init set_pageblock_order(unsigned int order) { @@ -3301,7 +3290,16 @@ static inline void __init set_pageblock_order(unsigned int order) } #else /* CONFIG_HUGETLB_PAGE_SIZE_VARIABLE */ -/* Defined this way to avoid accidently referencing HUGETLB_PAGE_ORDER */ +/* + * When CONFIG_HUGETLB_PAGE_SIZE_VARIABLE is not set, set_pageblock_order() + * and pageblock_default_order() are unused as pageblock_order is set + * at compile-time. See include/linux/pageblock-flags.h for the values of + * pageblock_order based on the kernel config + */ +static inline int pageblock_default_order(unsigned int order) +{ + return MAX_ORDER-1; +} #define set_pageblock_order(x) do {} while (0) #endif /* CONFIG_HUGETLB_PAGE_SIZE_VARIABLE */ @@ -3386,7 +3384,7 @@ static void __meminit free_area_init_core(struct pglist_data *pgdat, if (!size) continue; - set_pageblock_order(HUGETLB_PAGE_ORDER); + set_pageblock_order(pageblock_default_order()); setup_usemap(pgdat, zone, size); ret = init_currently_empty_zone(zone, zone_start_pfn, size, MEMMAP_EARLY); diff --git a/mm/page_isolation.c b/mm/page_isolation.c index 8f92a29..3444b58 100644 --- a/mm/page_isolation.c +++ b/mm/page_isolation.c @@ -55,7 +55,7 @@ start_isolate_page_range(unsigned long start_pfn, unsigned long end_pfn) return 0; undo: for (pfn = start_pfn; - pfn <= undo_pfn; + pfn < undo_pfn; pfn += pageblock_nr_pages) unset_migratetype_isolate(pfn_to_page(pfn)); @@ -76,7 +76,7 @@ undo_isolate_page_range(unsigned long start_pfn, unsigned long end_pfn) pfn < end_pfn; pfn += pageblock_nr_pages) { page = __first_valid_page(pfn, pageblock_nr_pages); - if (!page || get_pageblock_flags(page) != MIGRATE_ISOLATE) + if (!page || get_pageblock_migratetype(page) != MIGRATE_ISOLATE) continue; unset_migratetype_isolate(page); } @@ -126,7 +126,7 @@ int test_pages_isolated(unsigned long start_pfn, unsigned long end_pfn) */ for (pfn = start_pfn; pfn < end_pfn; pfn += pageblock_nr_pages) { page = __first_valid_page(pfn, pageblock_nr_pages); - if (page && get_pageblock_flags(page) != MIGRATE_ISOLATE) + if (page && get_pageblock_migratetype(page) != MIGRATE_ISOLATE) break; } if (pfn < end_pfn) @@ -183,7 +183,9 @@ static void page_unlock_anon_vma(struct anon_vma *anon_vma) } /* - * At what user virtual address is page expected in vma? + * At what user virtual address is page expected in @vma? + * Returns virtual address or -EFAULT if page's index/offset is not + * within the range mapped the @vma. */ static inline unsigned long vma_address(struct page *page, struct vm_area_struct *vma) @@ -193,8 +195,7 @@ vma_address(struct page *page, struct vm_area_struct *vma) address = vma->vm_start + ((pgoff - vma->vm_pgoff) << PAGE_SHIFT); if (unlikely(address < vma->vm_start || address >= vma->vm_end)) { - /* page should be within any vma from prio_tree_next */ - BUG_ON(!PageAnon(page)); + /* page should be within @vma mapping range */ return -EFAULT; } return address; @@ -470,11 +471,12 @@ int page_mkclean(struct page *page) if (page_mapped(page)) { struct address_space *mapping = page_mapping(page); - if (mapping) + if (mapping) { ret = page_mkclean_file(mapping, page); - if (page_test_dirty(page)) { - page_clear_dirty(page); - ret = 1; + if (page_test_dirty(page)) { + page_clear_dirty(page); + ret = 1; + } } } @@ -1072,7 +1072,7 @@ shmem_alloc_page(gfp_t gfp, struct shmem_inode_info *info, pvma.vm_policy = mpol_shared_policy_lookup(&info->policy, idx); pvma.vm_pgoff = idx; pvma.vm_end = PAGE_SIZE; - page = alloc_page_vma(gfp | __GFP_ZERO, &pvma, 0); + page = alloc_page_vma(gfp, &pvma, 0); mpol_free(pvma.vm_policy); return page; } @@ -1093,7 +1093,7 @@ shmem_swapin(struct shmem_inode_info *info,swp_entry_t entry,unsigned long idx) static inline struct page * shmem_alloc_page(gfp_t gfp,struct shmem_inode_info *info, unsigned long idx) { - return alloc_page(gfp | __GFP_ZERO); + return alloc_page(gfp); } #endif @@ -1306,6 +1306,7 @@ repeat: info->alloced++; spin_unlock(&info->lock); + clear_highpage(filepage); flush_dcache_page(filepage); SetPageUptodate(filepage); } @@ -1043,7 +1043,7 @@ static struct array_cache **alloc_alien_cache(int node, int limit) } ac_ptr[i] = alloc_arraycache(node, limit, 0xbaadf00d); if (!ac_ptr[i]) { - for (i--; i <= 0; i--) + for (i--; i >= 0; i--) kfree(ac_ptr[i]); kfree(ac_ptr); return NULL; @@ -2881,6 +2881,8 @@ static void *cache_free_debugcheck(struct kmem_cache *cachep, void *objp, unsigned int objnr; struct slab *slabp; + BUG_ON(virt_to_cache(objp) != cachep); + objp -= obj_offset(cachep); kfree_debugcheck(objp); page = virt_to_head_page(objp); @@ -3759,8 +3761,6 @@ void kmem_cache_free(struct kmem_cache *cachep, void *objp) { unsigned long flags; - BUG_ON(virt_to_cache(objp) != cachep); - local_irq_save(flags); debug_check_no_locks_freed(objp, obj_size(cachep)); __cache_free(cachep, objp); @@ -321,7 +321,8 @@ static void *slob_alloc(size_t size, gfp_t gfp, int align, int node) /* Improve fragment distribution and reduce our average * search time by starting our next search here. (see * Knuth vol 1, sec 2.5, pg 449) */ - if (free_slob_pages.next != prev->next) + if (prev != free_slob_pages.prev && + free_slob_pages.next != prev->next) list_move_tail(&free_slob_pages, prev->next); break; } @@ -1080,7 +1080,6 @@ static struct page *new_slab(struct kmem_cache *s, gfp_t flags, int node) struct page *page; struct kmem_cache_node *n; void *start; - void *end; void *last; void *p; @@ -1101,7 +1100,6 @@ static struct page *new_slab(struct kmem_cache *s, gfp_t flags, int node) SetSlabDebug(page); start = page_address(page); - end = start + s->objects * s->size; if (unlikely(s->flags & SLAB_POISON)) memset(start, POISON_INUSE, PAGE_SIZE << s->order); diff --git a/mm/sparse-vmemmap.c b/mm/sparse-vmemmap.c index 22620f6..cd75b21 100644 --- a/mm/sparse-vmemmap.c +++ b/mm/sparse-vmemmap.c @@ -34,6 +34,16 @@ * or to back the page tables that are used to create the mapping. * Uses the main allocators if they are available, else bootmem. */ + +static void * __init_refok __earlyonly_bootmem_alloc(int node, + unsigned long size, + unsigned long align, + unsigned long goal) +{ + return __alloc_bootmem_node(NODE_DATA(node), size, align, goal); +} + + void * __meminit vmemmap_alloc_block(unsigned long size, int node) { /* If the main allocator is up use that, fallback to bootmem. */ @@ -44,7 +54,7 @@ void * __meminit vmemmap_alloc_block(unsigned long size, int node) return page_address(page); return NULL; } else - return __alloc_bootmem_node(NODE_DATA(node), size, size, + return __earlyonly_bootmem_alloc(node, size, size, __pa(MAX_DMA_ADDRESS)); } @@ -95,8 +95,8 @@ void *krealloc(const void *p, size_t new_size, gfp_t flags) return (void *)p; ret = kmalloc_track_caller(new_size, flags); - if (ret) { - memcpy(ret, p, min(new_size, ks)); + if (ret && p) { + memcpy(ret, p, ks); kfree(p); } return ret; diff --git a/mm/vmstat.c b/mm/vmstat.c index 4651bf1..e8d846f 100644 --- a/mm/vmstat.c +++ b/mm/vmstat.c @@ -803,7 +803,7 @@ static void vmstat_update(struct work_struct *w) sysctl_stat_interval); } -static void __devinit start_cpu_timer(int cpu) +static void __cpuinit start_cpu_timer(int cpu) { struct delayed_work *vmstat_work = &per_cpu(vmstat_work, cpu); diff --git a/net/8021q/vlan.c b/net/8021q/vlan.c index 3fe4fc8..6567213 100644 --- a/net/8021q/vlan.c +++ b/net/8021q/vlan.c @@ -376,6 +376,7 @@ void vlan_setup(struct net_device *new_dev) new_dev->init = vlan_dev_init; new_dev->open = vlan_dev_open; new_dev->stop = vlan_dev_stop; + new_dev->set_mac_address = vlan_set_mac_address; new_dev->set_multicast_list = vlan_dev_set_multicast_list; new_dev->change_rx_flags = vlan_change_rx_flags; new_dev->destructor = free_netdev; @@ -636,6 +637,10 @@ static int vlan_device_event(struct notifier_block *unused, unsigned long event, if (!vlandev) continue; + flgs = vlandev->flags; + if (!(flgs & IFF_UP)) + continue; + vlan_sync_address(dev, vlandev); } break; @@ -747,6 +752,7 @@ static int vlan_ioctl_handler(struct net *net, void __user *arg) vlan_dev_set_ingress_priority(dev, args.u.skb_priority, args.vlan_qos); + err = 0; break; case SET_VLAN_EGRESS_PRIORITY_CMD: diff --git a/net/8021q/vlan.h b/net/8021q/vlan.h index cf4a80d..2cd139307 100644 --- a/net/8021q/vlan.h +++ b/net/8021q/vlan.h @@ -60,6 +60,7 @@ int vlan_dev_hwaccel_hard_start_xmit(struct sk_buff *skb, struct net_device *dev int vlan_dev_change_mtu(struct net_device *dev, int new_mtu); int vlan_dev_open(struct net_device* dev); int vlan_dev_stop(struct net_device* dev); +int vlan_set_mac_address(struct net_device *dev, void *p); int vlan_dev_ioctl(struct net_device* dev, struct ifreq *ifr, int cmd); void vlan_dev_set_ingress_priority(const struct net_device *dev, u32 skb_prio, short vlan_prio); diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c index 1a1740a..4f99bb8 100644 --- a/net/8021q/vlan_dev.c +++ b/net/8021q/vlan_dev.c @@ -462,7 +462,8 @@ int vlan_dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) * OTHER THINGS LIKE FDDI/TokenRing/802.3 SNAPs... */ - if (veth->h_vlan_proto != htons(ETH_P_8021Q)) { + if (veth->h_vlan_proto != htons(ETH_P_8021Q) || + VLAN_DEV_INFO(dev)->flags & VLAN_FLAG_REORDER_HDR) { int orig_headroom = skb_headroom(skb); unsigned short veth_TCI; @@ -665,6 +666,32 @@ int vlan_dev_stop(struct net_device *dev) return 0; } +int vlan_set_mac_address(struct net_device *dev, void *p) +{ + struct net_device *real_dev = VLAN_DEV_INFO(dev)->real_dev; + struct sockaddr *addr = p; + int err; + + if (!is_valid_ether_addr(addr->sa_data)) + return -EADDRNOTAVAIL; + + if (!(dev->flags & IFF_UP)) + goto out; + + if (compare_ether_addr(addr->sa_data, real_dev->dev_addr)) { + err = dev_unicast_add(real_dev, addr->sa_data, ETH_ALEN); + if (err < 0) + return err; + } + + if (compare_ether_addr(dev->dev_addr, real_dev->dev_addr)) + dev_unicast_delete(real_dev, dev->dev_addr, ETH_ALEN); + +out: + memcpy(dev->dev_addr, addr->sa_data, ETH_ALEN); + return 0; +} + int vlan_dev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) { struct net_device *real_dev = VLAN_DEV_INFO(dev)->real_dev; diff --git a/net/bridge/br.c b/net/bridge/br.c index 93867bb..a901828 100644 --- a/net/bridge/br.c +++ b/net/bridge/br.c @@ -39,7 +39,7 @@ static int __init br_init(void) err = br_fdb_init(); if (err) - goto err_out1; + goto err_out; err = br_netfilter_init(); if (err) @@ -65,6 +65,8 @@ err_out3: err_out2: br_netfilter_fini(); err_out1: + br_fdb_fini(); +err_out: llc_sap_put(br_stp_sap); return err; } diff --git a/net/bridge/br_input.c b/net/bridge/br_input.c index 3cedd4e..0ee79a7 100644 --- a/net/bridge/br_input.c +++ b/net/bridge/br_input.c @@ -122,6 +122,7 @@ static inline int is_link_local(const unsigned char *dest) struct sk_buff *br_handle_frame(struct net_bridge_port *p, struct sk_buff *skb) { const unsigned char *dest = eth_hdr(skb)->h_dest; + int (*rhook)(struct sk_buff *skb); if (!is_valid_ether_addr(eth_hdr(skb)->h_source)) goto drop; @@ -147,9 +148,9 @@ struct sk_buff *br_handle_frame(struct net_bridge_port *p, struct sk_buff *skb) switch (p->state) { case BR_STATE_FORWARDING: - - if (br_should_route_hook) { - if (br_should_route_hook(skb)) + rhook = rcu_dereference(br_should_route_hook); + if (rhook != NULL) { + if (rhook(skb)) return skb; dest = eth_hdr(skb)->h_dest; } diff --git a/net/bridge/br_netfilter.c b/net/bridge/br_netfilter.c index da22f90..c1757c7 100644 --- a/net/bridge/br_netfilter.c +++ b/net/bridge/br_netfilter.c @@ -766,6 +766,9 @@ static unsigned int br_nf_post_routing(unsigned int hook, struct sk_buff *skb, if (!nf_bridge) return NF_ACCEPT; + if (!(nf_bridge->mask & (BRNF_BRIDGED | BRNF_BRIDGED_DNAT))) + return NF_ACCEPT; + if (!realoutdev) return NF_DROP; diff --git a/net/bridge/netfilter/ebt_among.c b/net/bridge/netfilter/ebt_among.c index 392d877..6436d30 100644 --- a/net/bridge/netfilter/ebt_among.c +++ b/net/bridge/netfilter/ebt_among.c @@ -187,7 +187,7 @@ static int ebt_among_check(const char *tablename, unsigned int hookmask, if (datalen != EBT_ALIGN(expected_length)) { printk(KERN_WARNING - "ebtables: among: wrong size: %d" + "ebtables: among: wrong size: %d " "against expected %d, rounded to %Zd\n", datalen, expected_length, EBT_ALIGN(expected_length)); diff --git a/net/bridge/netfilter/ebt_arp.c b/net/bridge/netfilter/ebt_arp.c index 1a46952..1814139 100644 --- a/net/bridge/netfilter/ebt_arp.c +++ b/net/bridge/netfilter/ebt_arp.c @@ -34,7 +34,7 @@ static int ebt_filter_arp(const struct sk_buff *skb, const struct net_device *in ah->ar_pro, EBT_ARP_PTYPE)) return EBT_NOMATCH; - if (info->bitmask & (EBT_ARP_SRC_IP | EBT_ARP_DST_IP)) { + if (info->bitmask & (EBT_ARP_SRC_IP | EBT_ARP_DST_IP | EBT_ARP_GRAT)) { __be32 saddr, daddr, *sap, *dap; if (ah->ar_pln != sizeof(__be32) || ah->ar_pro != htons(ETH_P_IP)) diff --git a/net/bridge/netfilter/ebtable_broute.c b/net/bridge/netfilter/ebtable_broute.c index e44519e..be6f186 100644 --- a/net/bridge/netfilter/ebtable_broute.c +++ b/net/bridge/netfilter/ebtable_broute.c @@ -70,13 +70,13 @@ static int __init ebtable_broute_init(void) if (ret < 0) return ret; /* see br_input.c */ - br_should_route_hook = ebt_broute; + rcu_assign_pointer(br_should_route_hook, ebt_broute); return ret; } static void __exit ebtable_broute_fini(void) { - br_should_route_hook = NULL; + rcu_assign_pointer(br_should_route_hook, NULL); synchronize_net(); ebt_unregister_table(&broute_table); } diff --git a/net/core/dev.c b/net/core/dev.c index be6ceda..86d6261 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -1171,6 +1171,8 @@ rollback: nb->notifier_call(nb, NETDEV_UNREGISTER, dev); } } + + raw_notifier_chain_unregister(&netdev_chain, nb); goto unlock; } @@ -2688,7 +2690,7 @@ static void __net_exit dev_proc_net_exit(struct net *net) proc_net_remove(net, "dev"); } -static struct pernet_operations dev_proc_ops = { +static struct pernet_operations __net_initdata dev_proc_ops = { .init = dev_proc_net_init, .exit = dev_proc_net_exit, }; @@ -4330,7 +4332,6 @@ static struct hlist_head *netdev_create_hash(void) static int __net_init netdev_init(struct net *net) { INIT_LIST_HEAD(&net->dev_base_head); - rwlock_init(&dev_base_lock); net->dev_name_head = netdev_create_hash(); if (net->dev_name_head == NULL) @@ -4354,7 +4355,7 @@ static void __net_exit netdev_exit(struct net *net) kfree(net->dev_index_head); } -static struct pernet_operations netdev_net_ops = { +static struct pernet_operations __net_initdata netdev_net_ops = { .init = netdev_init, .exit = netdev_exit, }; @@ -4385,7 +4386,7 @@ static void __net_exit default_device_exit(struct net *net) rtnl_unlock(); } -static struct pernet_operations default_device_ops = { +static struct pernet_operations __net_initdata default_device_ops = { .exit = default_device_exit, }; diff --git a/net/core/dev_mcast.c b/net/core/dev_mcast.c index ae35405..69fff16 100644 --- a/net/core/dev_mcast.c +++ b/net/core/dev_mcast.c @@ -168,13 +168,13 @@ void dev_mc_unsync(struct net_device *to, struct net_device *from) da = from->mc_list; while (da != NULL) { next = da->next; - if (!da->da_synced) - continue; - __dev_addr_delete(&to->mc_list, &to->mc_count, - da->da_addr, da->da_addrlen, 0); - da->da_synced = 0; - __dev_addr_delete(&from->mc_list, &from->mc_count, - da->da_addr, da->da_addrlen, 0); + if (da->da_synced) { + __dev_addr_delete(&to->mc_list, &to->mc_count, + da->da_addr, da->da_addrlen, 0); + da->da_synced = 0; + __dev_addr_delete(&from->mc_list, &from->mc_count, + da->da_addr, da->da_addrlen, 0); + } da = next; } __dev_set_rx_mode(to); @@ -285,7 +285,7 @@ static void __net_exit dev_mc_net_exit(struct net *net) proc_net_remove(net, "dev_mcast"); } -static struct pernet_operations dev_mc_net_ops = { +static struct pernet_operations __net_initdata dev_mc_net_ops = { .init = dev_mc_net_init, .exit = dev_mc_net_exit, }; diff --git a/net/core/dst.c b/net/core/dst.c index 16958e6..03daead 100644 --- a/net/core/dst.c +++ b/net/core/dst.c @@ -18,7 +18,6 @@ #include <linux/types.h> #include <net/net_namespace.h> -#include <net/net_namespace.h> #include <net/dst.h> /* diff --git a/net/core/fib_rules.c b/net/core/fib_rules.c index 13de6f5..848132b 100644 --- a/net/core/fib_rules.c +++ b/net/core/fib_rules.c @@ -18,6 +18,28 @@ static LIST_HEAD(rules_ops); static DEFINE_SPINLOCK(rules_mod_lock); +int fib_default_rule_add(struct fib_rules_ops *ops, + u32 pref, u32 table, u32 flags) +{ + struct fib_rule *r; + + r = kzalloc(ops->rule_size, GFP_KERNEL); + if (r == NULL) + return -ENOMEM; + + atomic_set(&r->refcnt, 1); + r->action = FR_ACT_TO_TBL; + r->pref = pref; + r->table = table; + r->flags = flags; + + /* The lock is not required here, the list in unreacheable + * at the moment this function is called */ + list_add_tail(&r->list, &ops->rules_list); + return 0; +} +EXPORT_SYMBOL(fib_default_rule_add); + static void notify_rule_change(int event, struct fib_rule *rule, struct fib_rules_ops *ops, struct nlmsghdr *nlh, u32 pid); diff --git a/net/core/neighbour.c b/net/core/neighbour.c index 05979e3..29b8ee4 100644 --- a/net/core/neighbour.c +++ b/net/core/neighbour.c @@ -1435,6 +1435,8 @@ int neigh_table_clear(struct neigh_table *tbl) kfree(tbl->phash_buckets); tbl->phash_buckets = NULL; + remove_proc_entry(tbl->id, init_net.proc_net_stat); + free_percpu(tbl->stats); tbl->stats = NULL; diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c index e9f0964..383252b 100644 --- a/net/core/net_namespace.c +++ b/net/core/net_namespace.c @@ -64,6 +64,20 @@ static struct net *net_alloc(void) return kmem_cache_zalloc(net_cachep, GFP_KERNEL); } +static void net_free(struct net *net) +{ + if (!net) + return; + + if (unlikely(atomic_read(&net->use_count) != 0)) { + printk(KERN_EMERG "network namespace not free! Usage: %d\n", + atomic_read(&net->use_count)); + return; + } + + kmem_cache_free(net_cachep, net); +} + struct net *copy_net_ns(unsigned long flags, struct net *old_net) { struct net *new_net = NULL; @@ -100,20 +114,6 @@ out: return new_net; } -static void net_free(struct net *net) -{ - if (!net) - return; - - if (unlikely(atomic_read(&net->use_count) != 0)) { - printk(KERN_EMERG "network namespace not free! Usage: %d\n", - atomic_read(&net->use_count)); - return; - } - - kmem_cache_free(net_cachep, net); -} - static void cleanup_net(struct work_struct *work) { struct pernet_operations *ops; @@ -188,6 +188,7 @@ static int __init net_ns_init(void) pure_initcall(net_ns_init); +#ifdef CONFIG_NET_NS static int register_pernet_operations(struct list_head *list, struct pernet_operations *ops) { @@ -228,6 +229,23 @@ static void unregister_pernet_operations(struct pernet_operations *ops) ops->exit(net); } +#else + +static int register_pernet_operations(struct list_head *list, + struct pernet_operations *ops) +{ + if (ops->init == NULL) + return 0; + return ops->init(&init_net); +} + +static void unregister_pernet_operations(struct pernet_operations *ops) +{ + if (ops->exit) + ops->exit(&init_net); +} +#endif + /** * register_pernet_subsys - register a network namespace subsystem * @ops: pernet operations structure for the subsystem diff --git a/net/core/pktgen.c b/net/core/pktgen.c index de33f36..285ec3e 100644 --- a/net/core/pktgen.c +++ b/net/core/pktgen.c @@ -2463,8 +2463,6 @@ static int pktgen_output_ipsec(struct sk_buff *skb, struct pktgen_dev *pkt_dev) x->curlft.bytes +=skb->len; x->curlft.packets++; - spin_unlock(&x->lock); - error: spin_unlock(&x->lock); return err; diff --git a/net/core/request_sock.c b/net/core/request_sock.c index 5f0818d..45aed75 100644 --- a/net/core/request_sock.c +++ b/net/core/request_sock.c @@ -71,6 +71,41 @@ int reqsk_queue_alloc(struct request_sock_queue *queue, EXPORT_SYMBOL(reqsk_queue_alloc); +void __reqsk_queue_destroy(struct request_sock_queue *queue) +{ + struct listen_sock *lopt; + size_t lopt_size; + + /* + * this is an error recovery path only + * no locking needed and the lopt is not NULL + */ + + lopt = queue->listen_opt; + lopt_size = sizeof(struct listen_sock) + + lopt->nr_table_entries * sizeof(struct request_sock *); + + if (lopt_size > PAGE_SIZE) + vfree(lopt); + else + kfree(lopt); +} + +EXPORT_SYMBOL(__reqsk_queue_destroy); + +static inline struct listen_sock *reqsk_queue_yank_listen_sk( + struct request_sock_queue *queue) +{ + struct listen_sock *lopt; + + write_lock_bh(&queue->syn_wait_lock); + lopt = queue->listen_opt; + queue->listen_opt = NULL; + write_unlock_bh(&queue->syn_wait_lock); + + return lopt; +} + void reqsk_queue_destroy(struct request_sock_queue *queue) { /* make all the listen_opt local to us */ diff --git a/net/core/skbuff.c b/net/core/skbuff.c index 32d5826..5b4ce9b 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c @@ -275,12 +275,11 @@ static void skb_release_data(struct sk_buff *skb) /* * Free an skbuff by memory without cleaning the state. */ -void kfree_skbmem(struct sk_buff *skb) +static void kfree_skbmem(struct sk_buff *skb) { struct sk_buff *other; atomic_t *fclone_ref; - skb_release_data(skb); switch (skb->fclone) { case SKB_FCLONE_UNAVAILABLE: kmem_cache_free(skbuff_head_cache, skb); @@ -307,16 +306,8 @@ void kfree_skbmem(struct sk_buff *skb) } } -/** - * __kfree_skb - private function - * @skb: buffer - * - * Free an sk_buff. Release anything attached to the buffer. - * Clean the state. This is an internal helper function. Users should - * always call kfree_skb - */ - -void __kfree_skb(struct sk_buff *skb) +/* Free everything but the sk_buff shell. */ +static void skb_release_all(struct sk_buff *skb) { dst_release(skb->dst); #ifdef CONFIG_XFRM @@ -340,7 +331,21 @@ void __kfree_skb(struct sk_buff *skb) skb->tc_verd = 0; #endif #endif + skb_release_data(skb); +} + +/** + * __kfree_skb - private function + * @skb: buffer + * + * Free an sk_buff. Release anything attached to the buffer. + * Clean the state. This is an internal helper function. Users should + * always call kfree_skb + */ +void __kfree_skb(struct sk_buff *skb) +{ + skb_release_all(skb); kfree_skbmem(skb); } @@ -441,7 +446,7 @@ static struct sk_buff *__skb_clone(struct sk_buff *n, struct sk_buff *skb) */ struct sk_buff *skb_morph(struct sk_buff *dst, struct sk_buff *src) { - skb_release_data(dst); + skb_release_all(dst); return __skb_clone(dst, src); } EXPORT_SYMBOL_GPL(skb_morph); diff --git a/net/core/sock.c b/net/core/sock.c index 12ad206..c519b43 100644 --- a/net/core/sock.c +++ b/net/core/sock.c @@ -1801,11 +1801,65 @@ EXPORT_SYMBOL(sk_common_release); static DEFINE_RWLOCK(proto_list_lock); static LIST_HEAD(proto_list); +#ifdef CONFIG_SMP +/* + * Define default functions to keep track of inuse sockets per protocol + * Note that often used protocols use dedicated functions to get a speed increase. + * (see DEFINE_PROTO_INUSE/REF_PROTO_INUSE) + */ +static void inuse_add(struct proto *prot, int inc) +{ + per_cpu_ptr(prot->inuse_ptr, smp_processor_id())[0] += inc; +} + +static int inuse_get(const struct proto *prot) +{ + int res = 0, cpu; + for_each_possible_cpu(cpu) + res += per_cpu_ptr(prot->inuse_ptr, cpu)[0]; + return res; +} + +static int inuse_init(struct proto *prot) +{ + if (!prot->inuse_getval || !prot->inuse_add) { + prot->inuse_ptr = alloc_percpu(int); + if (prot->inuse_ptr == NULL) + return -ENOBUFS; + + prot->inuse_getval = inuse_get; + prot->inuse_add = inuse_add; + } + return 0; +} + +static void inuse_fini(struct proto *prot) +{ + if (prot->inuse_ptr != NULL) { + free_percpu(prot->inuse_ptr); + prot->inuse_ptr = NULL; + prot->inuse_getval = NULL; + prot->inuse_add = NULL; + } +} +#else +static inline int inuse_init(struct proto *prot) +{ + return 0; +} + +static inline void inuse_fini(struct proto *prot) +{ +} +#endif + int proto_register(struct proto *prot, int alloc_slab) { char *request_sock_slab_name = NULL; char *timewait_sock_slab_name; - int rc = -ENOBUFS; + + if (inuse_init(prot)) + goto out; if (alloc_slab) { prot->slab = kmem_cache_create(prot->name, prot->obj_size, 0, @@ -1814,7 +1868,7 @@ int proto_register(struct proto *prot, int alloc_slab) if (prot->slab == NULL) { printk(KERN_CRIT "%s: Can't create sock SLAB cache!\n", prot->name); - goto out; + goto out_free_inuse; } if (prot->rsk_prot != NULL) { @@ -1858,9 +1912,8 @@ int proto_register(struct proto *prot, int alloc_slab) write_lock(&proto_list_lock); list_add(&prot->node, &proto_list); write_unlock(&proto_list_lock); - rc = 0; -out: - return rc; + return 0; + out_free_timewait_sock_slab_name: kfree(timewait_sock_slab_name); out_free_request_sock_slab: @@ -1873,7 +1926,10 @@ out_free_request_sock_slab_name: out_free_sock_slab: kmem_cache_destroy(prot->slab); prot->slab = NULL; - goto out; +out_free_inuse: + inuse_fini(prot); +out: + return -ENOBUFS; } EXPORT_SYMBOL(proto_register); @@ -1884,6 +1940,7 @@ void proto_unregister(struct proto *prot) list_del(&prot->node); write_unlock(&proto_list_lock); + inuse_fini(prot); if (prot->slab != NULL) { kmem_cache_destroy(prot->slab); prot->slab = NULL; @@ -2040,7 +2097,3 @@ EXPORT_SYMBOL(sock_wmalloc); EXPORT_SYMBOL(sock_i_uid); EXPORT_SYMBOL(sock_i_ino); EXPORT_SYMBOL(sysctl_optmem_max); -#ifdef CONFIG_SYSCTL -EXPORT_SYMBOL(sysctl_rmem_max); -EXPORT_SYMBOL(sysctl_wmem_max); -#endif diff --git a/net/dccp/ccids/lib/loss_interval.c b/net/dccp/ccids/lib/loss_interval.c index 40ad428..d26b88d 100644 --- a/net/dccp/ccids/lib/loss_interval.c +++ b/net/dccp/ccids/lib/loss_interval.c @@ -166,7 +166,7 @@ static u32 dccp_li_calc_first_li(struct sock *sk, } if (unlikely(interval == 0)) { - DCCP_WARN("%s(%p), Could not find a win_count interval > 0." + DCCP_WARN("%s(%p), Could not find a win_count interval > 0. " "Defaulting to 1\n", dccp_role(sk), sk); interval = 1; } diff --git a/net/dccp/ipv4.c b/net/dccp/ipv4.c index 01a6a80..db17b83 100644 --- a/net/dccp/ipv4.c +++ b/net/dccp/ipv4.c @@ -922,6 +922,8 @@ static struct timewait_sock_ops dccp_timewait_sock_ops = { .twsk_obj_size = sizeof(struct inet_timewait_sock), }; +DEFINE_PROTO_INUSE(dccp_v4) + static struct proto dccp_v4_prot = { .name = "DCCP", .owner = THIS_MODULE, @@ -950,6 +952,7 @@ static struct proto dccp_v4_prot = { .compat_setsockopt = compat_dccp_setsockopt, .compat_getsockopt = compat_dccp_getsockopt, #endif + REF_PROTO_INUSE(dccp_v4) }; static struct net_protocol dccp_v4_protocol = { diff --git a/net/dccp/ipv6.c b/net/dccp/ipv6.c index 62428ff..87c98fb 100644 --- a/net/dccp/ipv6.c +++ b/net/dccp/ipv6.c @@ -1107,6 +1107,8 @@ static struct timewait_sock_ops dccp6_timewait_sock_ops = { .twsk_obj_size = sizeof(struct dccp6_timewait_sock), }; +DEFINE_PROTO_INUSE(dccp_v6) + static struct proto dccp_v6_prot = { .name = "DCCPv6", .owner = THIS_MODULE, @@ -1135,6 +1137,7 @@ static struct proto dccp_v6_prot = { .compat_setsockopt = compat_dccp_setsockopt, .compat_getsockopt = compat_dccp_getsockopt, #endif + REF_PROTO_INUSE(dccp_v6) }; static struct inet6_protocol dccp_v6_protocol = { diff --git a/net/dccp/proto.c b/net/dccp/proto.c index d849739..7a3bea9 100644 --- a/net/dccp/proto.c +++ b/net/dccp/proto.c @@ -1072,11 +1072,13 @@ static int __init dccp_init(void) } for (i = 0; i < dccp_hashinfo.ehash_size; i++) { - rwlock_init(&dccp_hashinfo.ehash[i].lock); INIT_HLIST_HEAD(&dccp_hashinfo.ehash[i].chain); INIT_HLIST_HEAD(&dccp_hashinfo.ehash[i].twchain); } + if (inet_ehash_locks_alloc(&dccp_hashinfo)) + goto out_free_dccp_ehash; + bhash_order = ehash_order; do { @@ -1091,7 +1093,7 @@ static int __init dccp_init(void) if (!dccp_hashinfo.bhash) { DCCP_CRIT("Failed to allocate DCCP bind hash table"); - goto out_free_dccp_ehash; + goto out_free_dccp_locks; } for (i = 0; i < dccp_hashinfo.bhash_size; i++) { @@ -1121,6 +1123,8 @@ out_free_dccp_mib: out_free_dccp_bhash: free_pages((unsigned long)dccp_hashinfo.bhash, bhash_order); dccp_hashinfo.bhash = NULL; +out_free_dccp_locks: + inet_ehash_locks_free(&dccp_hashinfo); out_free_dccp_ehash: free_pages((unsigned long)dccp_hashinfo.ehash, ehash_order); dccp_hashinfo.ehash = NULL; @@ -1139,6 +1143,7 @@ static void __exit dccp_fini(void) free_pages((unsigned long)dccp_hashinfo.ehash, get_order(dccp_hashinfo.ehash_size * sizeof(struct inet_ehash_bucket))); + inet_ehash_locks_free(&dccp_hashinfo); kmem_cache_destroy(dccp_hashinfo.bind_bucket_cachep); dccp_ackvec_exit(); dccp_sysctl_exit(); diff --git a/net/decnet/dn_dev.c b/net/decnet/dn_dev.c index 26130af..3bc82dc 100644 --- a/net/decnet/dn_dev.c +++ b/net/decnet/dn_dev.c @@ -651,16 +651,18 @@ static int dn_nl_deladdr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) struct dn_dev *dn_db; struct ifaddrmsg *ifm; struct dn_ifaddr *ifa, **ifap; - int err = -EADDRNOTAVAIL; + int err; err = nlmsg_parse(nlh, sizeof(*ifm), tb, IFA_MAX, dn_ifa_policy); if (err < 0) goto errout; + err = -ENODEV; ifm = nlmsg_data(nlh); if ((dn_db = dn_dev_by_index(ifm->ifa_index)) == NULL) goto errout; + err = -EADDRNOTAVAIL; for (ifap = &dn_db->ifa_list; (ifa = *ifap); ifap = &ifa->ifa_next) { if (tb[IFA_LOCAL] && nla_memcmp(tb[IFA_LOCAL], &ifa->ifa_local, 2)) @@ -1439,7 +1441,7 @@ static const struct file_operations dn_dev_seq_fops = { #endif /* CONFIG_PROC_FS */ -static int __initdata addr[2]; +static int addr[2]; module_param_array(addr, int, NULL, 0444); MODULE_PARM_DESC(addr, "The DECnet address of this machine: area,node"); diff --git a/net/decnet/dn_route.c b/net/decnet/dn_route.c index 97eee5e..66663e5 100644 --- a/net/decnet/dn_route.c +++ b/net/decnet/dn_route.c @@ -293,9 +293,7 @@ static int dn_insert_route(struct dn_route *rt, unsigned hash, struct dn_route * dn_rt_hash_table[hash].chain); rcu_assign_pointer(dn_rt_hash_table[hash].chain, rth); - rth->u.dst.__use++; - dst_hold(&rth->u.dst); - rth->u.dst.lastuse = now; + dst_use(&rth->u.dst, now); spin_unlock_bh(&dn_rt_hash_table[hash].lock); dnrt_drop(rt); @@ -308,9 +306,7 @@ static int dn_insert_route(struct dn_route *rt, unsigned hash, struct dn_route * rcu_assign_pointer(rt->u.dst.dn_next, dn_rt_hash_table[hash].chain); rcu_assign_pointer(dn_rt_hash_table[hash].chain, rt); - dst_hold(&rt->u.dst); - rt->u.dst.__use++; - rt->u.dst.lastuse = now; + dst_use(&rt->u.dst, now); spin_unlock_bh(&dn_rt_hash_table[hash].lock); *rp = rt; return 0; @@ -1182,9 +1178,7 @@ static int __dn_route_output_key(struct dst_entry **pprt, const struct flowi *fl (flp->mark == rt->fl.mark) && (rt->fl.iif == 0) && (rt->fl.oif == flp->oif)) { - rt->u.dst.lastuse = jiffies; - dst_hold(&rt->u.dst); - rt->u.dst.__use++; + dst_use(&rt->u.dst, jiffies); rcu_read_unlock_bh(); *pprt = &rt->u.dst; return 0; @@ -1456,9 +1450,7 @@ int dn_route_input(struct sk_buff *skb) (rt->fl.oif == 0) && (rt->fl.mark == skb->mark) && (rt->fl.iif == cb->iif)) { - rt->u.dst.lastuse = jiffies; - dst_hold(&rt->u.dst); - rt->u.dst.__use++; + dst_use(&rt->u.dst, jiffies); rcu_read_unlock(); skb->dst = (struct dst_entry *)rt; return 0; diff --git a/net/decnet/dn_rules.c b/net/decnet/dn_rules.c index ddd3f04..ffebea0 100644 --- a/net/decnet/dn_rules.c +++ b/net/decnet/dn_rules.c @@ -48,15 +48,6 @@ struct dn_fib_rule u8 flags; }; -static struct dn_fib_rule default_rule = { - .common = { - .refcnt = ATOMIC_INIT(2), - .pref = 0x7fff, - .table = RT_TABLE_MAIN, - .action = FR_ACT_TO_TBL, - }, -}; - int dn_fib_lookup(struct flowi *flp, struct dn_fib_res *res) { @@ -262,8 +253,8 @@ static struct fib_rules_ops dn_fib_rules_ops = { void __init dn_fib_rules_init(void) { - list_add_tail(&default_rule.common.list, - &dn_fib_rules_ops.rules_list); + BUG_ON(fib_default_rule_add(&dn_fib_rules_ops, 0x7fff, + RT_TABLE_MAIN, 0)); fib_rules_register(&dn_fib_rules_ops); } diff --git a/net/ieee80211/ieee80211_crypt_ccmp.c b/net/ieee80211/ieee80211_crypt_ccmp.c index c6d760d..208bf35 100644 --- a/net/ieee80211/ieee80211_crypt_ccmp.c +++ b/net/ieee80211/ieee80211_crypt_ccmp.c @@ -338,7 +338,7 @@ static int ieee80211_ccmp_decrypt(struct sk_buff *skb, int hdr_len, void *priv) pos += 8; if (ccmp_replay_check(pn, key->rx_pn)) { - if (net_ratelimit()) { + if (ieee80211_ratelimit_debug(IEEE80211_DL_DROP)) { IEEE80211_DEBUG_DROP("CCMP: replay detected: STA=%s " "previous PN %02x%02x%02x%02x%02x%02x " "received PN %02x%02x%02x%02x%02x%02x\n", diff --git a/net/ieee80211/ieee80211_crypt_tkip.c b/net/ieee80211/ieee80211_crypt_tkip.c index 4cce353..8e14694 100644 --- a/net/ieee80211/ieee80211_crypt_tkip.c +++ b/net/ieee80211/ieee80211_crypt_tkip.c @@ -25,7 +25,6 @@ #include <net/ieee80211.h> #include <linux/crypto.h> -#include <linux/scatterlist.h> #include <linux/crc32.h> MODULE_AUTHOR("Jouni Malinen"); @@ -465,7 +464,7 @@ static int ieee80211_tkip_decrypt(struct sk_buff *skb, int hdr_len, void *priv) pos += 8; if (tkip_replay_check(iv32, iv16, tkey->rx_iv32, tkey->rx_iv16)) { - if (net_ratelimit()) { + if (ieee80211_ratelimit_debug(IEEE80211_DL_DROP)) { IEEE80211_DEBUG_DROP("TKIP: replay detected: STA=%s" " previous TSC %08x%04x received TSC " "%08x%04x\n", print_mac(mac, hdr->addr2), @@ -505,7 +504,7 @@ static int ieee80211_tkip_decrypt(struct sk_buff *skb, int hdr_len, void *priv) * it needs to be recalculated for the next packet. */ tkey->rx_phase1_done = 0; } - if (net_ratelimit()) { + if (ieee80211_ratelimit_debug(IEEE80211_DL_DROP)) { IEEE80211_DEBUG_DROP("TKIP: ICV error detected: STA=" "%s\n", print_mac(mac, hdr->addr2)); } diff --git a/net/ieee80211/ieee80211_crypt_wep.c b/net/ieee80211/ieee80211_crypt_wep.c index 866fc04..3fa30c4 100644 --- a/net/ieee80211/ieee80211_crypt_wep.c +++ b/net/ieee80211/ieee80211_crypt_wep.c @@ -22,7 +22,6 @@ #include <net/ieee80211.h> #include <linux/crypto.h> -#include <linux/scatterlist.h> #include <linux/crc32.h> MODULE_AUTHOR("Jouni Malinen"); diff --git a/net/ieee80211/ieee80211_tx.c b/net/ieee80211/ieee80211_tx.c index a4c3c51..6d06f13 100644 --- a/net/ieee80211/ieee80211_tx.c +++ b/net/ieee80211/ieee80211_tx.c @@ -144,7 +144,8 @@ static int ieee80211_copy_snap(u8 * data, u16 h_proto) snap->oui[1] = oui[1]; snap->oui[2] = oui[2]; - *(u16 *) (data + SNAP_SIZE) = htons(h_proto); + h_proto = htons(h_proto); + memcpy(data + SNAP_SIZE, &h_proto, sizeof(u16)); return SNAP_SIZE + sizeof(u16); } diff --git a/net/ieee80211/softmac/ieee80211softmac_wx.c b/net/ieee80211/softmac/ieee80211softmac_wx.c index ac36767..e01b59a 100644 --- a/net/ieee80211/softmac/ieee80211softmac_wx.c +++ b/net/ieee80211/softmac/ieee80211softmac_wx.c @@ -470,7 +470,7 @@ ieee80211softmac_wx_set_mlme(struct net_device *dev, { struct ieee80211softmac_device *mac = ieee80211_priv(dev); struct iw_mlme *mlme = (struct iw_mlme *)extra; - u16 reason = cpu_to_le16(mlme->reason_code); + u16 reason = mlme->reason_code; struct ieee80211softmac_network *net; int err = -EINVAL; diff --git a/net/ipv4/arp.c b/net/ipv4/arp.c index 36d6798..b3f366a 100644 --- a/net/ipv4/arp.c +++ b/net/ipv4/arp.c @@ -111,12 +111,8 @@ #include <net/tcp.h> #include <net/sock.h> #include <net/arp.h> -#if defined(CONFIG_AX25) || defined(CONFIG_AX25_MODULE) #include <net/ax25.h> -#if defined(CONFIG_NETROM) || defined(CONFIG_NETROM_MODULE) #include <net/netrom.h> -#endif -#endif #if defined(CONFIG_ATM_CLIP) || defined(CONFIG_ATM_CLIP_MODULE) #include <net/atmclip.h> struct neigh_table *clip_tbl_hook; @@ -731,20 +727,10 @@ static int arp_process(struct sk_buff *skb) htons(dev_type) != arp->ar_hrd) goto out; break; -#ifdef CONFIG_NET_ETHERNET case ARPHRD_ETHER: -#endif -#ifdef CONFIG_TR case ARPHRD_IEEE802_TR: -#endif -#ifdef CONFIG_FDDI case ARPHRD_FDDI: -#endif -#ifdef CONFIG_NET_FC case ARPHRD_IEEE802: -#endif -#if defined(CONFIG_NET_ETHERNET) || defined(CONFIG_TR) || \ - defined(CONFIG_FDDI) || defined(CONFIG_NET_FC) /* * ETHERNET, Token Ring and Fibre Channel (which are IEEE 802 * devices, according to RFC 2625) devices will accept ARP @@ -759,21 +745,16 @@ static int arp_process(struct sk_buff *skb) arp->ar_pro != htons(ETH_P_IP)) goto out; break; -#endif -#if defined(CONFIG_AX25) || defined(CONFIG_AX25_MODULE) case ARPHRD_AX25: if (arp->ar_pro != htons(AX25_P_IP) || arp->ar_hrd != htons(ARPHRD_AX25)) goto out; break; -#if defined(CONFIG_NETROM) || defined(CONFIG_NETROM_MODULE) case ARPHRD_NETROM: if (arp->ar_pro != htons(AX25_P_IP) || arp->ar_hrd != htons(ARPHRD_NETROM)) goto out; break; -#endif -#endif } /* Understand only these message types */ @@ -828,7 +809,8 @@ static int arp_process(struct sk_buff *skb) if (arp->ar_op == htons(ARPOP_REQUEST) && inet_addr_type(tip) == RTN_LOCAL && !arp_ignore(in_dev,dev,sip,tip)) - arp_send(ARPOP_REPLY,ETH_P_ARP,tip,dev,tip,sha,dev->dev_addr,dev->dev_addr); + arp_send(ARPOP_REPLY, ETH_P_ARP, sip, dev, tip, sha, + dev->dev_addr, sha); goto out; } diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c index 6012390..732d8f0 100644 --- a/net/ipv4/fib_frontend.c +++ b/net/ipv4/fib_frontend.c @@ -59,6 +59,13 @@ struct fib_table *ip_fib_main_table; #define FIB_TABLE_HASHSZ 1 static struct hlist_head fib_table_hash[FIB_TABLE_HASHSZ]; +static void __init fib4_rules_init(void) +{ + ip_fib_local_table = fib_hash_init(RT_TABLE_LOCAL); + hlist_add_head_rcu(&ip_fib_local_table->tb_hlist, &fib_table_hash[0]); + ip_fib_main_table = fib_hash_init(RT_TABLE_MAIN); + hlist_add_head_rcu(&ip_fib_main_table->tb_hlist, &fib_table_hash[0]); +} #else #define FIB_TABLE_HASHSZ 256 @@ -905,14 +912,8 @@ void __init ip_fib_init(void) for (i = 0; i < FIB_TABLE_HASHSZ; i++) INIT_HLIST_HEAD(&fib_table_hash[i]); -#ifndef CONFIG_IP_MULTIPLE_TABLES - ip_fib_local_table = fib_hash_init(RT_TABLE_LOCAL); - hlist_add_head_rcu(&ip_fib_local_table->tb_hlist, &fib_table_hash[0]); - ip_fib_main_table = fib_hash_init(RT_TABLE_MAIN); - hlist_add_head_rcu(&ip_fib_main_table->tb_hlist, &fib_table_hash[0]); -#else + fib4_rules_init(); -#endif register_netdevice_notifier(&fib_netdev_notifier); register_inetaddr_notifier(&fib_inetaddr_notifier); diff --git a/net/ipv4/fib_rules.c b/net/ipv4/fib_rules.c index f16839c..a0ada3a 100644 --- a/net/ipv4/fib_rules.c +++ b/net/ipv4/fib_rules.c @@ -49,33 +49,6 @@ struct fib4_rule #endif }; -static struct fib4_rule default_rule = { - .common = { - .refcnt = ATOMIC_INIT(2), - .pref = 0x7FFF, - .table = RT_TABLE_DEFAULT, - .action = FR_ACT_TO_TBL, - }, -}; - -static struct fib4_rule main_rule = { - .common = { - .refcnt = ATOMIC_INIT(2), - .pref = 0x7FFE, - .table = RT_TABLE_MAIN, - .action = FR_ACT_TO_TBL, - }, -}; - -static struct fib4_rule local_rule = { - .common = { - .refcnt = ATOMIC_INIT(2), - .table = RT_TABLE_LOCAL, - .action = FR_ACT_TO_TBL, - .flags = FIB_RULE_PERMANENT, - }, -}; - #ifdef CONFIG_NET_CLS_ROUTE u32 fib_rules_tclass(struct fib_result *res) { @@ -319,11 +292,27 @@ static struct fib_rules_ops fib4_rules_ops = { .owner = THIS_MODULE, }; -void __init fib4_rules_init(void) +static int __init fib_default_rules_init(void) { - list_add_tail(&local_rule.common.list, &fib4_rules_ops.rules_list); - list_add_tail(&main_rule.common.list, &fib4_rules_ops.rules_list); - list_add_tail(&default_rule.common.list, &fib4_rules_ops.rules_list); + int err; + + err = fib_default_rule_add(&fib4_rules_ops, 0, + RT_TABLE_LOCAL, FIB_RULE_PERMANENT); + if (err < 0) + return err; + err = fib_default_rule_add(&fib4_rules_ops, 0x7FFE, + RT_TABLE_MAIN, 0); + if (err < 0) + return err; + err = fib_default_rule_add(&fib4_rules_ops, 0x7FFF, + RT_TABLE_DEFAULT, 0); + if (err < 0) + return err; + return 0; +} +void __init fib4_rules_init(void) +{ + BUG_ON(fib_default_rules_init()); fib_rules_register(&fib4_rules_ops); } diff --git a/net/ipv4/inet_diag.c b/net/ipv4/inet_diag.c index dc429b6..e468e7a 100644 --- a/net/ipv4/inet_diag.c +++ b/net/ipv4/inet_diag.c @@ -51,6 +51,29 @@ static struct sock *idiagnl; #define INET_DIAG_PUT(skb, attrtype, attrlen) \ RTA_DATA(__RTA_PUT(skb, attrtype, attrlen)) +static DEFINE_MUTEX(inet_diag_table_mutex); + +static const struct inet_diag_handler *inet_diag_lock_handler(int type) +{ +#ifdef CONFIG_KMOD + if (!inet_diag_table[type]) + request_module("net-pf-%d-proto-%d-type-%d", PF_NETLINK, + NETLINK_INET_DIAG, type); +#endif + + mutex_lock(&inet_diag_table_mutex); + if (!inet_diag_table[type]) + return ERR_PTR(-ENOENT); + + return inet_diag_table[type]; +} + +static inline void inet_diag_unlock_handler( + const struct inet_diag_handler *handler) +{ + mutex_unlock(&inet_diag_table_mutex); +} + static int inet_csk_diag_fill(struct sock *sk, struct sk_buff *skb, int ext, u32 pid, u32 seq, u16 nlmsg_flags, @@ -235,9 +258,12 @@ static int inet_diag_get_exact(struct sk_buff *in_skb, struct inet_hashinfo *hashinfo; const struct inet_diag_handler *handler; - handler = inet_diag_table[nlh->nlmsg_type]; - BUG_ON(handler == NULL); + handler = inet_diag_lock_handler(nlh->nlmsg_type); + if (!handler) + return -ENOENT; + hashinfo = handler->idiag_hashinfo; + err = -EINVAL; if (req->idiag_family == AF_INET) { sk = inet_lookup(hashinfo, req->id.idiag_dst[0], @@ -255,11 +281,12 @@ static int inet_diag_get_exact(struct sk_buff *in_skb, } #endif else { - return -EINVAL; + goto unlock; } + err = -ENOENT; if (sk == NULL) - return -ENOENT; + goto unlock; err = -ESTALE; if ((req->id.idiag_cookie[0] != INET_DIAG_NOCOOKIE || @@ -296,6 +323,8 @@ out: else sock_put(sk); } +unlock: + inet_diag_unlock_handler(handler); return err; } @@ -678,8 +707,10 @@ static int inet_diag_dump(struct sk_buff *skb, struct netlink_callback *cb) const struct inet_diag_handler *handler; struct inet_hashinfo *hashinfo; - handler = inet_diag_table[cb->nlh->nlmsg_type]; - BUG_ON(handler == NULL); + handler = inet_diag_lock_handler(cb->nlh->nlmsg_type); + if (!handler) + goto no_handler; + hashinfo = handler->idiag_hashinfo; s_i = cb->args[1]; @@ -743,17 +774,18 @@ skip_listen_ht: } if (!(r->idiag_states & ~(TCPF_LISTEN | TCPF_SYN_RECV))) - return skb->len; + goto unlock; for (i = s_i; i < hashinfo->ehash_size; i++) { struct inet_ehash_bucket *head = &hashinfo->ehash[i]; + rwlock_t *lock = inet_ehash_lockp(hashinfo, i); struct sock *sk; struct hlist_node *node; if (i > s_i) s_num = 0; - read_lock_bh(&head->lock); + read_lock_bh(lock); num = 0; sk_for_each(sk, node, &head->chain) { struct inet_sock *inet = inet_sk(sk); @@ -769,7 +801,7 @@ skip_listen_ht: r->id.idiag_dport) goto next_normal; if (inet_csk_diag_dump(sk, skb, cb) < 0) { - read_unlock_bh(&head->lock); + read_unlock_bh(lock); goto done; } next_normal: @@ -791,19 +823,22 @@ next_normal: r->id.idiag_dport) goto next_dying; if (inet_twsk_diag_dump(tw, skb, cb) < 0) { - read_unlock_bh(&head->lock); + read_unlock_bh(lock); goto done; } next_dying: ++num; } } - read_unlock_bh(&head->lock); + read_unlock_bh(lock); } done: cb->args[1] = i; cb->args[2] = num; +unlock: + inet_diag_unlock_handler(handler); +no_handler: return skb->len; } @@ -815,15 +850,6 @@ static int inet_diag_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh) nlmsg_len(nlh) < hdrlen) return -EINVAL; -#ifdef CONFIG_KMOD - if (inet_diag_table[nlh->nlmsg_type] == NULL) - request_module("net-pf-%d-proto-%d-type-%d", PF_NETLINK, - NETLINK_INET_DIAG, nlh->nlmsg_type); -#endif - - if (inet_diag_table[nlh->nlmsg_type] == NULL) - return -ENOENT; - if (nlh->nlmsg_flags & NLM_F_DUMP) { if (nlmsg_attrlen(nlh, hdrlen)) { struct nlattr *attr; @@ -852,8 +878,6 @@ static void inet_diag_rcv(struct sk_buff *skb) mutex_unlock(&inet_diag_mutex); } -static DEFINE_SPINLOCK(inet_diag_register_lock); - int inet_diag_register(const struct inet_diag_handler *h) { const __u16 type = h->idiag_type; @@ -862,13 +886,13 @@ int inet_diag_register(const struct inet_diag_handler *h) if (type >= INET_DIAG_GETSOCK_MAX) goto out; - spin_lock(&inet_diag_register_lock); + mutex_lock(&inet_diag_table_mutex); err = -EEXIST; if (inet_diag_table[type] == NULL) { inet_diag_table[type] = h; err = 0; } - spin_unlock(&inet_diag_register_lock); + mutex_unlock(&inet_diag_table_mutex); out: return err; } @@ -881,11 +905,9 @@ void inet_diag_unregister(const struct inet_diag_handler *h) if (type >= INET_DIAG_GETSOCK_MAX) return; - spin_lock(&inet_diag_register_lock); + mutex_lock(&inet_diag_table_mutex); inet_diag_table[type] = NULL; - spin_unlock(&inet_diag_register_lock); - - synchronize_rcu(); + mutex_unlock(&inet_diag_table_mutex); } EXPORT_SYMBOL_GPL(inet_diag_unregister); diff --git a/net/ipv4/inet_hashtables.c b/net/ipv4/inet_hashtables.c index 16eecc7..67704da 100644 --- a/net/ipv4/inet_hashtables.c +++ b/net/ipv4/inet_hashtables.c @@ -204,12 +204,13 @@ static int __inet_check_established(struct inet_timewait_death_row *death_row, const __portpair ports = INET_COMBINED_PORTS(inet->dport, lport); unsigned int hash = inet_ehashfn(daddr, lport, saddr, inet->dport); struct inet_ehash_bucket *head = inet_ehash_bucket(hinfo, hash); + rwlock_t *lock = inet_ehash_lockp(hinfo, hash); struct sock *sk2; const struct hlist_node *node; struct inet_timewait_sock *tw; prefetch(head->chain.first); - write_lock(&head->lock); + write_lock(lock); /* Check TIME-WAIT sockets first. */ sk_for_each(sk2, node, &head->twchain) { @@ -239,7 +240,7 @@ unique: BUG_TRAP(sk_unhashed(sk)); __sk_add_node(sk, &head->chain); sock_prot_inc_use(sk->sk_prot); - write_unlock(&head->lock); + write_unlock(lock); if (twp) { *twp = tw; @@ -255,7 +256,7 @@ unique: return 0; not_unique: - write_unlock(&head->lock); + write_unlock(lock); return -EADDRNOTAVAIL; } diff --git a/net/ipv4/inet_timewait_sock.c b/net/ipv4/inet_timewait_sock.c index 4e189e2..a60b99e 100644 --- a/net/ipv4/inet_timewait_sock.c +++ b/net/ipv4/inet_timewait_sock.c @@ -20,16 +20,16 @@ static void __inet_twsk_kill(struct inet_timewait_sock *tw, struct inet_bind_hashbucket *bhead; struct inet_bind_bucket *tb; /* Unlink from established hashes. */ - struct inet_ehash_bucket *ehead = inet_ehash_bucket(hashinfo, tw->tw_hash); + rwlock_t *lock = inet_ehash_lockp(hashinfo, tw->tw_hash); - write_lock(&ehead->lock); + write_lock(lock); if (hlist_unhashed(&tw->tw_node)) { - write_unlock(&ehead->lock); + write_unlock(lock); return; } __hlist_del(&tw->tw_node); sk_node_init(&tw->tw_node); - write_unlock(&ehead->lock); + write_unlock(lock); /* Disassociate with bind bucket. */ bhead = &hashinfo->bhash[inet_bhashfn(tw->tw_num, hashinfo->bhash_size)]; @@ -59,6 +59,7 @@ void __inet_twsk_hashdance(struct inet_timewait_sock *tw, struct sock *sk, const struct inet_sock *inet = inet_sk(sk); const struct inet_connection_sock *icsk = inet_csk(sk); struct inet_ehash_bucket *ehead = inet_ehash_bucket(hashinfo, sk->sk_hash); + rwlock_t *lock = inet_ehash_lockp(hashinfo, sk->sk_hash); struct inet_bind_hashbucket *bhead; /* Step 1: Put TW into bind hash. Original socket stays there too. Note, that any socket with inet->num != 0 MUST be bound in @@ -71,7 +72,7 @@ void __inet_twsk_hashdance(struct inet_timewait_sock *tw, struct sock *sk, inet_twsk_add_bind_node(tw, &tw->tw_tb->owners); spin_unlock(&bhead->lock); - write_lock(&ehead->lock); + write_lock(lock); /* Step 2: Remove SK from established hash. */ if (__sk_del_node_init(sk)) @@ -81,7 +82,7 @@ void __inet_twsk_hashdance(struct inet_timewait_sock *tw, struct sock *sk, inet_twsk_add_node(tw, &ehead->twchain); atomic_inc(&tw->tw_refcnt); - write_unlock(&ehead->lock); + write_unlock(lock); } EXPORT_SYMBOL_GPL(__inet_twsk_hashdance); diff --git a/net/ipv4/inetpeer.c b/net/ipv4/inetpeer.c index 771031d..af99519 100644 --- a/net/ipv4/inetpeer.c +++ b/net/ipv4/inetpeer.c @@ -61,7 +61,7 @@ * 4. Global variable peer_total is modified under the pool lock. * 5. struct inet_peer fields modification: * avl_left, avl_right, avl_parent, avl_height: pool lock - * unused_next, unused_prevp: unused node list lock + * unused: unused node list lock * refcnt: atomically against modifications on other CPU; * usually under some other lock to prevent node disappearing * dtime: unused node list lock @@ -94,8 +94,7 @@ int inet_peer_maxttl __read_mostly = 10 * 60 * HZ; /* usual time to live: 10 min int inet_peer_gc_mintime __read_mostly = 10 * HZ; int inet_peer_gc_maxtime __read_mostly = 120 * HZ; -static struct inet_peer *inet_peer_unused_head; -static struct inet_peer **inet_peer_unused_tailp = &inet_peer_unused_head; +static LIST_HEAD(unused_peers); static DEFINE_SPINLOCK(inet_peer_unused_lock); static void peer_check_expire(unsigned long dummy); @@ -138,15 +137,7 @@ void __init inet_initpeers(void) static void unlink_from_unused(struct inet_peer *p) { spin_lock_bh(&inet_peer_unused_lock); - if (p->unused_prevp != NULL) { - /* On unused list. */ - *p->unused_prevp = p->unused_next; - if (p->unused_next != NULL) - p->unused_next->unused_prevp = p->unused_prevp; - else - inet_peer_unused_tailp = p->unused_prevp; - p->unused_prevp = NULL; /* mark it as removed */ - } + list_del_init(&p->unused); spin_unlock_bh(&inet_peer_unused_lock); } @@ -337,24 +328,24 @@ static void unlink_from_pool(struct inet_peer *p) /* May be called with local BH enabled. */ static int cleanup_once(unsigned long ttl) { - struct inet_peer *p; + struct inet_peer *p = NULL; /* Remove the first entry from the list of unused nodes. */ spin_lock_bh(&inet_peer_unused_lock); - p = inet_peer_unused_head; - if (p != NULL) { - __u32 delta = (__u32)jiffies - p->dtime; + if (!list_empty(&unused_peers)) { + __u32 delta; + + p = list_first_entry(&unused_peers, struct inet_peer, unused); + delta = (__u32)jiffies - p->dtime; + if (delta < ttl) { /* Do not prune fresh entries. */ spin_unlock_bh(&inet_peer_unused_lock); return -1; } - inet_peer_unused_head = p->unused_next; - if (p->unused_next != NULL) - p->unused_next->unused_prevp = p->unused_prevp; - else - inet_peer_unused_tailp = p->unused_prevp; - p->unused_prevp = NULL; /* mark as not on the list */ + + list_del_init(&p->unused); + /* Grab an extra reference to prevent node disappearing * before unlink_from_pool() call. */ atomic_inc(&p->refcnt); @@ -412,7 +403,7 @@ struct inet_peer *inet_getpeer(__be32 daddr, int create) /* Link the node. */ link_to_pool(n); - n->unused_prevp = NULL; /* not on the list */ + INIT_LIST_HEAD(&n->unused); peer_total++; write_unlock_bh(&peer_pool_lock); @@ -467,10 +458,7 @@ void inet_putpeer(struct inet_peer *p) { spin_lock_bh(&inet_peer_unused_lock); if (atomic_dec_and_test(&p->refcnt)) { - p->unused_prevp = inet_peer_unused_tailp; - p->unused_next = NULL; - *inet_peer_unused_tailp = p; - inet_peer_unused_tailp = &p->unused_next; + list_add_tail(&p->unused, &unused_peers); p->dtime = (__u32)jiffies; } spin_unlock_bh(&inet_peer_unused_lock); diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c index e5f7dc2..fd99fbd 100644 --- a/net/ipv4/ip_output.c +++ b/net/ipv4/ip_output.c @@ -1183,6 +1183,17 @@ error: return err; } +static void ip_cork_release(struct inet_sock *inet) +{ + inet->cork.flags &= ~IPCORK_OPT; + kfree(inet->cork.opt); + inet->cork.opt = NULL; + if (inet->cork.rt) { + ip_rt_put(inet->cork.rt); + inet->cork.rt = NULL; + } +} + /* * Combined all pending IP fragments on the socket as one IP datagram * and push them out. @@ -1276,13 +1287,7 @@ int ip_push_pending_frames(struct sock *sk) } out: - inet->cork.flags &= ~IPCORK_OPT; - kfree(inet->cork.opt); - inet->cork.opt = NULL; - if (inet->cork.rt) { - ip_rt_put(inet->cork.rt); - inet->cork.rt = NULL; - } + ip_cork_release(inet); return err; error: @@ -1295,19 +1300,12 @@ error: */ void ip_flush_pending_frames(struct sock *sk) { - struct inet_sock *inet = inet_sk(sk); struct sk_buff *skb; while ((skb = __skb_dequeue_tail(&sk->sk_write_queue)) != NULL) kfree_skb(skb); - inet->cork.flags &= ~IPCORK_OPT; - kfree(inet->cork.opt); - inet->cork.opt = NULL; - if (inet->cork.rt) { - ip_rt_put(inet->cork.rt); - inet->cork.rt = NULL; - } + ip_cork_release(inet_sk(sk)); } diff --git a/net/ipv4/ip_sockglue.c b/net/ipv4/ip_sockglue.c index f51f20e..82817e5 100644 --- a/net/ipv4/ip_sockglue.c +++ b/net/ipv4/ip_sockglue.c @@ -437,10 +437,8 @@ static int do_ip_setsockopt(struct sock *sk, int level, /* If optlen==0, it is equivalent to val == 0 */ -#ifdef CONFIG_IP_MROUTE - if (optname >= MRT_BASE && optname <= (MRT_BASE + 10)) + if (ip_mroute_opt(optname)) return ip_mroute_setsockopt(sk,optname,optval,optlen); -#endif err = 0; lock_sock(sk); @@ -909,11 +907,9 @@ int ip_setsockopt(struct sock *sk, int level, #ifdef CONFIG_NETFILTER /* we need to exclude all possible ENOPROTOOPTs except default case */ if (err == -ENOPROTOOPT && optname != IP_HDRINCL && - optname != IP_IPSEC_POLICY && optname != IP_XFRM_POLICY -#ifdef CONFIG_IP_MROUTE - && (optname < MRT_BASE || optname > (MRT_BASE + 10)) -#endif - ) { + optname != IP_IPSEC_POLICY && + optname != IP_XFRM_POLICY && + !ip_mroute_opt(optname)) { lock_sock(sk); err = nf_setsockopt(sk, PF_INET, optname, optval, optlen); release_sock(sk); @@ -935,11 +931,9 @@ int compat_ip_setsockopt(struct sock *sk, int level, int optname, #ifdef CONFIG_NETFILTER /* we need to exclude all possible ENOPROTOOPTs except default case */ if (err == -ENOPROTOOPT && optname != IP_HDRINCL && - optname != IP_IPSEC_POLICY && optname != IP_XFRM_POLICY -#ifdef CONFIG_IP_MROUTE - && (optname < MRT_BASE || optname > (MRT_BASE + 10)) -#endif - ) { + optname != IP_IPSEC_POLICY && + optname != IP_XFRM_POLICY && + !ip_mroute_opt(optname)) { lock_sock(sk); err = compat_nf_setsockopt(sk, PF_INET, optname, optval, optlen); @@ -967,11 +961,8 @@ static int do_ip_getsockopt(struct sock *sk, int level, int optname, if (level != SOL_IP) return -EOPNOTSUPP; -#ifdef CONFIG_IP_MROUTE - if (optname >= MRT_BASE && optname <= MRT_BASE+10) { + if (ip_mroute_opt(optname)) return ip_mroute_getsockopt(sk,optname,optval,optlen); - } -#endif if (get_user(len,optlen)) return -EFAULT; @@ -1171,11 +1162,8 @@ int ip_getsockopt(struct sock *sk, int level, err = do_ip_getsockopt(sk, level, optname, optval, optlen); #ifdef CONFIG_NETFILTER /* we need to exclude all possible ENOPROTOOPTs except default case */ - if (err == -ENOPROTOOPT && optname != IP_PKTOPTIONS -#ifdef CONFIG_IP_MROUTE - && (optname < MRT_BASE || optname > MRT_BASE+10) -#endif - ) { + if (err == -ENOPROTOOPT && optname != IP_PKTOPTIONS && + !ip_mroute_opt(optname)) { int len; if (get_user(len,optlen)) @@ -1200,11 +1188,8 @@ int compat_ip_getsockopt(struct sock *sk, int level, int optname, int err = do_ip_getsockopt(sk, level, optname, optval, optlen); #ifdef CONFIG_NETFILTER /* we need to exclude all possible ENOPROTOOPTs except default case */ - if (err == -ENOPROTOOPT && optname != IP_PKTOPTIONS -#ifdef CONFIG_IP_MROUTE - && (optname < MRT_BASE || optname > MRT_BASE+10) -#endif - ) { + if (err == -ENOPROTOOPT && optname != IP_PKTOPTIONS && + !ip_mroute_opt(optname)) { int len; if (get_user(len, optlen)) diff --git a/net/ipv4/ipcomp.c b/net/ipv4/ipcomp.c index ca1b5fd..2c44a94 100644 --- a/net/ipv4/ipcomp.c +++ b/net/ipv4/ipcomp.c @@ -16,6 +16,7 @@ #include <linux/module.h> #include <asm/semaphore.h> #include <linux/crypto.h> +#include <linux/err.h> #include <linux/pfkeyv2.h> #include <linux/percpu.h> #include <linux/smp.h> @@ -344,7 +345,7 @@ static struct crypto_comp **ipcomp_alloc_tfms(const char *alg_name) for_each_possible_cpu(cpu) { struct crypto_comp *tfm = crypto_alloc_comp(alg_name, 0, CRYPTO_ALG_ASYNC); - if (!tfm) + if (IS_ERR(tfm)) goto error; *per_cpu_ptr(tfms, cpu) = tfm; } diff --git a/net/ipv4/ipvs/ip_vs_conn.c b/net/ipv4/ipvs/ip_vs_conn.c index 4b702f7..0a9f3c3 100644 --- a/net/ipv4/ipvs/ip_vs_conn.c +++ b/net/ipv4/ipvs/ip_vs_conn.c @@ -426,6 +426,24 @@ ip_vs_bind_dest(struct ip_vs_conn *cp, struct ip_vs_dest *dest) /* + * Check if there is a destination for the connection, if so + * bind the connection to the destination. + */ +struct ip_vs_dest *ip_vs_try_bind_dest(struct ip_vs_conn *cp) +{ + struct ip_vs_dest *dest; + + if ((cp) && (!cp->dest)) { + dest = ip_vs_find_dest(cp->daddr, cp->dport, + cp->vaddr, cp->vport, cp->protocol); + ip_vs_bind_dest(cp, dest); + return dest; + } else + return NULL; +} + + +/* * Unbind a connection entry with its VS destination * Called by the ip_vs_conn_expire function. */ diff --git a/net/ipv4/ipvs/ip_vs_core.c b/net/ipv4/ipvs/ip_vs_core.c index c6ed765..8fba202 100644 --- a/net/ipv4/ipvs/ip_vs_core.c +++ b/net/ipv4/ipvs/ip_vs_core.c @@ -637,7 +637,7 @@ static int ip_vs_out_icmp(struct sk_buff *skb, int *related) verdict = NF_DROP; if (IP_VS_FWD_METHOD(cp) != 0) { - IP_VS_ERR("shouldn't reach here, because the box is on the" + IP_VS_ERR("shouldn't reach here, because the box is on the " "half connection in the tun/dr module.\n"); } @@ -979,15 +979,23 @@ ip_vs_in(unsigned int hooknum, struct sk_buff *skb, ret = NF_ACCEPT; } - /* increase its packet counter and check if it is needed - to be synchronized */ + /* Increase its packet counter and check if it is needed + * to be synchronized + * + * Sync connection if it is about to close to + * encorage the standby servers to update the connections timeout + */ atomic_inc(&cp->in_pkts); if ((ip_vs_sync_state & IP_VS_STATE_MASTER) && - (cp->protocol != IPPROTO_TCP || - cp->state == IP_VS_TCP_S_ESTABLISHED) && - (atomic_read(&cp->in_pkts) % sysctl_ip_vs_sync_threshold[1] - == sysctl_ip_vs_sync_threshold[0])) + (((cp->protocol != IPPROTO_TCP || + cp->state == IP_VS_TCP_S_ESTABLISHED) && + (atomic_read(&cp->in_pkts) % sysctl_ip_vs_sync_threshold[1] + == sysctl_ip_vs_sync_threshold[0])) || + ((cp->protocol == IPPROTO_TCP) && (cp->old_state != cp->state) && + ((cp->state == IP_VS_TCP_S_FIN_WAIT) || + (cp->state == IP_VS_TCP_S_CLOSE))))) ip_vs_sync_conn(cp); + cp->old_state = cp->state; ip_vs_conn_put(cp); return ret; diff --git a/net/ipv4/ipvs/ip_vs_ctl.c b/net/ipv4/ipvs/ip_vs_ctl.c index 7345fc2..693d924 100644 --- a/net/ipv4/ipvs/ip_vs_ctl.c +++ b/net/ipv4/ipvs/ip_vs_ctl.c @@ -579,6 +579,31 @@ ip_vs_lookup_dest(struct ip_vs_service *svc, __be32 daddr, __be16 dport) return NULL; } +/* + * Find destination by {daddr,dport,vaddr,protocol} + * Cretaed to be used in ip_vs_process_message() in + * the backup synchronization daemon. It finds the + * destination to be bound to the received connection + * on the backup. + * + * ip_vs_lookup_real_service() looked promissing, but + * seems not working as expected. + */ +struct ip_vs_dest *ip_vs_find_dest(__be32 daddr, __be16 dport, + __be32 vaddr, __be16 vport, __u16 protocol) +{ + struct ip_vs_dest *dest; + struct ip_vs_service *svc; + + svc = ip_vs_service_get(0, protocol, vaddr, vport); + if (!svc) + return NULL; + dest = ip_vs_lookup_dest(svc, daddr, dport); + if (dest) + atomic_inc(&dest->refcnt); + ip_vs_service_put(svc); + return dest; +} /* * Lookup dest by {svc,addr,port} in the destination trash. @@ -1399,7 +1424,6 @@ proc_do_sync_threshold(ctl_table *table, int write, struct file *filp, static struct ctl_table vs_vars[] = { { - .ctl_name = NET_IPV4_VS_AMEMTHRESH, .procname = "amemthresh", .data = &sysctl_ip_vs_amemthresh, .maxlen = sizeof(int), @@ -1408,7 +1432,6 @@ static struct ctl_table vs_vars[] = { }, #ifdef CONFIG_IP_VS_DEBUG { - .ctl_name = NET_IPV4_VS_DEBUG_LEVEL, .procname = "debug_level", .data = &sysctl_ip_vs_debug_level, .maxlen = sizeof(int), @@ -1417,7 +1440,6 @@ static struct ctl_table vs_vars[] = { }, #endif { - .ctl_name = NET_IPV4_VS_AMDROPRATE, .procname = "am_droprate", .data = &sysctl_ip_vs_am_droprate, .maxlen = sizeof(int), @@ -1425,7 +1447,6 @@ static struct ctl_table vs_vars[] = { .proc_handler = &proc_dointvec, }, { - .ctl_name = NET_IPV4_VS_DROP_ENTRY, .procname = "drop_entry", .data = &sysctl_ip_vs_drop_entry, .maxlen = sizeof(int), @@ -1433,7 +1454,6 @@ static struct ctl_table vs_vars[] = { .proc_handler = &proc_do_defense_mode, }, { - .ctl_name = NET_IPV4_VS_DROP_PACKET, .procname = "drop_packet", .data = &sysctl_ip_vs_drop_packet, .maxlen = sizeof(int), @@ -1441,7 +1461,6 @@ static struct ctl_table vs_vars[] = { .proc_handler = &proc_do_defense_mode, }, { - .ctl_name = NET_IPV4_VS_SECURE_TCP, .procname = "secure_tcp", .data = &sysctl_ip_vs_secure_tcp, .maxlen = sizeof(int), @@ -1450,7 +1469,6 @@ static struct ctl_table vs_vars[] = { }, #if 0 { - .ctl_name = NET_IPV4_VS_TO_ES, .procname = "timeout_established", .data = &vs_timeout_table_dos.timeout[IP_VS_S_ESTABLISHED], .maxlen = sizeof(int), @@ -1458,7 +1476,6 @@ static struct ctl_table vs_vars[] = { .proc_handler = &proc_dointvec_jiffies, }, { - .ctl_name = NET_IPV4_VS_TO_SS, .procname = "timeout_synsent", .data = &vs_timeout_table_dos.timeout[IP_VS_S_SYN_SENT], .maxlen = sizeof(int), @@ -1466,7 +1483,6 @@ static struct ctl_table vs_vars[] = { .proc_handler = &proc_dointvec_jiffies, }, { - .ctl_name = NET_IPV4_VS_TO_SR, .procname = "timeout_synrecv", .data = &vs_timeout_table_dos.timeout[IP_VS_S_SYN_RECV], .maxlen = sizeof(int), @@ -1474,7 +1490,6 @@ static struct ctl_table vs_vars[] = { .proc_handler = &proc_dointvec_jiffies, }, { - .ctl_name = NET_IPV4_VS_TO_FW, .procname = "timeout_finwait", .data = &vs_timeout_table_dos.timeout[IP_VS_S_FIN_WAIT], .maxlen = sizeof(int), @@ -1482,7 +1497,6 @@ static struct ctl_table vs_vars[] = { .proc_handler = &proc_dointvec_jiffies, }, { - .ctl_name = NET_IPV4_VS_TO_TW, .procname = "timeout_timewait", .data = &vs_timeout_table_dos.timeout[IP_VS_S_TIME_WAIT], .maxlen = sizeof(int), @@ -1490,7 +1504,6 @@ static struct ctl_table vs_vars[] = { .proc_handler = &proc_dointvec_jiffies, }, { - .ctl_name = NET_IPV4_VS_TO_CL, .procname = "timeout_close", .data = &vs_timeout_table_dos.timeout[IP_VS_S_CLOSE], .maxlen = sizeof(int), @@ -1498,7 +1511,6 @@ static struct ctl_table vs_vars[] = { .proc_handler = &proc_dointvec_jiffies, }, { - .ctl_name = NET_IPV4_VS_TO_CW, .procname = "timeout_closewait", .data = &vs_timeout_table_dos.timeout[IP_VS_S_CLOSE_WAIT], .maxlen = sizeof(int), @@ -1506,7 +1518,6 @@ static struct ctl_table vs_vars[] = { .proc_handler = &proc_dointvec_jiffies, }, { - .ctl_name = NET_IPV4_VS_TO_LA, .procname = "timeout_lastack", .data = &vs_timeout_table_dos.timeout[IP_VS_S_LAST_ACK], .maxlen = sizeof(int), @@ -1514,7 +1525,6 @@ static struct ctl_table vs_vars[] = { .proc_handler = &proc_dointvec_jiffies, }, { - .ctl_name = NET_IPV4_VS_TO_LI, .procname = "timeout_listen", .data = &vs_timeout_table_dos.timeout[IP_VS_S_LISTEN], .maxlen = sizeof(int), @@ -1522,7 +1532,6 @@ static struct ctl_table vs_vars[] = { .proc_handler = &proc_dointvec_jiffies, }, { - .ctl_name = NET_IPV4_VS_TO_SA, .procname = "timeout_synack", .data = &vs_timeout_table_dos.timeout[IP_VS_S_SYNACK], .maxlen = sizeof(int), @@ -1530,7 +1539,6 @@ static struct ctl_table vs_vars[] = { .proc_handler = &proc_dointvec_jiffies, }, { - .ctl_name = NET_IPV4_VS_TO_UDP, .procname = "timeout_udp", .data = &vs_timeout_table_dos.timeout[IP_VS_S_UDP], .maxlen = sizeof(int), @@ -1538,7 +1546,6 @@ static struct ctl_table vs_vars[] = { .proc_handler = &proc_dointvec_jiffies, }, { - .ctl_name = NET_IPV4_VS_TO_ICMP, .procname = "timeout_icmp", .data = &vs_timeout_table_dos.timeout[IP_VS_S_ICMP], .maxlen = sizeof(int), @@ -1547,7 +1554,6 @@ static struct ctl_table vs_vars[] = { }, #endif { - .ctl_name = NET_IPV4_VS_CACHE_BYPASS, .procname = "cache_bypass", .data = &sysctl_ip_vs_cache_bypass, .maxlen = sizeof(int), @@ -1555,7 +1561,6 @@ static struct ctl_table vs_vars[] = { .proc_handler = &proc_dointvec, }, { - .ctl_name = NET_IPV4_VS_EXPIRE_NODEST_CONN, .procname = "expire_nodest_conn", .data = &sysctl_ip_vs_expire_nodest_conn, .maxlen = sizeof(int), @@ -1563,7 +1568,6 @@ static struct ctl_table vs_vars[] = { .proc_handler = &proc_dointvec, }, { - .ctl_name = NET_IPV4_VS_EXPIRE_QUIESCENT_TEMPLATE, .procname = "expire_quiescent_template", .data = &sysctl_ip_vs_expire_quiescent_template, .maxlen = sizeof(int), @@ -1571,7 +1575,6 @@ static struct ctl_table vs_vars[] = { .proc_handler = &proc_dointvec, }, { - .ctl_name = NET_IPV4_VS_SYNC_THRESHOLD, .procname = "sync_threshold", .data = &sysctl_ip_vs_sync_threshold, .maxlen = sizeof(sysctl_ip_vs_sync_threshold), @@ -1579,7 +1582,6 @@ static struct ctl_table vs_vars[] = { .proc_handler = &proc_do_sync_threshold, }, { - .ctl_name = NET_IPV4_VS_NAT_ICMP_SEND, .procname = "nat_icmp_send", .data = &sysctl_ip_vs_nat_icmp_send, .maxlen = sizeof(int), @@ -1591,7 +1593,6 @@ static struct ctl_table vs_vars[] = { static ctl_table vs_table[] = { { - .ctl_name = NET_IPV4_VS, .procname = "vs", .mode = 0555, .child = vs_vars diff --git a/net/ipv4/ipvs/ip_vs_lblc.c b/net/ipv4/ipvs/ip_vs_lblc.c index 052f4ed..b843a11 100644 --- a/net/ipv4/ipvs/ip_vs_lblc.c +++ b/net/ipv4/ipvs/ip_vs_lblc.c @@ -114,7 +114,6 @@ struct ip_vs_lblc_table { static ctl_table vs_vars_table[] = { { - .ctl_name = NET_IPV4_VS_LBLC_EXPIRE, .procname = "lblc_expiration", .data = &sysctl_ip_vs_lblc_expiration, .maxlen = sizeof(int), @@ -126,7 +125,6 @@ static ctl_table vs_vars_table[] = { static ctl_table vs_table[] = { { - .ctl_name = NET_IPV4_VS, .procname = "vs", .mode = 0555, .child = vs_vars_table diff --git a/net/ipv4/ipvs/ip_vs_lblcr.c b/net/ipv4/ipvs/ip_vs_lblcr.c index 427b593..e5b323a 100644 --- a/net/ipv4/ipvs/ip_vs_lblcr.c +++ b/net/ipv4/ipvs/ip_vs_lblcr.c @@ -302,7 +302,6 @@ struct ip_vs_lblcr_table { static ctl_table vs_vars_table[] = { { - .ctl_name = NET_IPV4_VS_LBLCR_EXPIRE, .procname = "lblcr_expiration", .data = &sysctl_ip_vs_lblcr_expiration, .maxlen = sizeof(int), @@ -314,7 +313,6 @@ static ctl_table vs_vars_table[] = { static ctl_table vs_table[] = { { - .ctl_name = NET_IPV4_VS, .procname = "vs", .mode = 0555, .child = vs_vars_table diff --git a/net/ipv4/ipvs/ip_vs_proto.c b/net/ipv4/ipvs/ip_vs_proto.c index e844ddb..c0e11ec 100644 --- a/net/ipv4/ipvs/ip_vs_proto.c +++ b/net/ipv4/ipvs/ip_vs_proto.c @@ -45,7 +45,7 @@ static struct ip_vs_protocol *ip_vs_proto_table[IP_VS_PROTO_TAB_SIZE]; /* * register an ipvs protocol */ -static int register_ip_vs_protocol(struct ip_vs_protocol *pp) +static int __used register_ip_vs_protocol(struct ip_vs_protocol *pp) { unsigned hash = IP_VS_PROTO_HASH(pp->protocol); diff --git a/net/ipv4/ipvs/ip_vs_sync.c b/net/ipv4/ipvs/ip_vs_sync.c index 0d4d972..bd930ef 100644 --- a/net/ipv4/ipvs/ip_vs_sync.c +++ b/net/ipv4/ipvs/ip_vs_sync.c @@ -284,6 +284,7 @@ static void ip_vs_process_message(const char *buffer, const size_t buflen) struct ip_vs_sync_conn_options *opt; struct ip_vs_conn *cp; struct ip_vs_protocol *pp; + struct ip_vs_dest *dest; char *p; int i; @@ -317,20 +318,34 @@ static void ip_vs_process_message(const char *buffer, const size_t buflen) s->caddr, s->cport, s->vaddr, s->vport); if (!cp) { + /* + * Find the appropriate destination for the connection. + * If it is not found the connection will remain unbound + * but still handled. + */ + dest = ip_vs_find_dest(s->daddr, s->dport, + s->vaddr, s->vport, + s->protocol); cp = ip_vs_conn_new(s->protocol, s->caddr, s->cport, s->vaddr, s->vport, s->daddr, s->dport, - flags, NULL); + flags, dest); + if (dest) + atomic_dec(&dest->refcnt); if (!cp) { IP_VS_ERR("ip_vs_conn_new failed\n"); return; } cp->state = ntohs(s->state); } else if (!cp->dest) { - /* it is an entry created by the synchronization */ - cp->state = ntohs(s->state); - cp->flags = flags | IP_VS_CONN_F_HASHED; + dest = ip_vs_try_bind_dest(cp); + if (!dest) { + /* it is an unbound entry created by + * synchronization */ + cp->flags = flags | IP_VS_CONN_F_HASHED; + } else + atomic_dec(&dest->refcnt); } /* Note that we don't touch its state and flags if it is a normal entry. */ @@ -342,6 +357,7 @@ static void ip_vs_process_message(const char *buffer, const size_t buflen) p += SIMPLE_CONN_SIZE; atomic_set(&cp->in_pkts, sysctl_ip_vs_sync_threshold[0]); + cp->state = ntohs(s->state); pp = ip_vs_proto_get(s->protocol); cp->timeout = pp->timeout_table[cp->state]; ip_vs_conn_put(cp); diff --git a/net/ipv4/netfilter/Makefile b/net/ipv4/netfilter/Makefile index 409d273..7456833 100644 --- a/net/ipv4/netfilter/Makefile +++ b/net/ipv4/netfilter/Makefile @@ -41,27 +41,27 @@ obj-$(CONFIG_NF_NAT) += iptable_nat.o obj-$(CONFIG_IP_NF_RAW) += iptable_raw.o # matches +obj-$(CONFIG_IP_NF_MATCH_ADDRTYPE) += ipt_addrtype.o +obj-$(CONFIG_IP_NF_MATCH_AH) += ipt_ah.o +obj-$(CONFIG_IP_NF_MATCH_ECN) += ipt_ecn.o obj-$(CONFIG_IP_NF_MATCH_IPRANGE) += ipt_iprange.o obj-$(CONFIG_IP_NF_MATCH_OWNER) += ipt_owner.o -obj-$(CONFIG_IP_NF_MATCH_TOS) += ipt_tos.o obj-$(CONFIG_IP_NF_MATCH_RECENT) += ipt_recent.o -obj-$(CONFIG_IP_NF_MATCH_ECN) += ipt_ecn.o -obj-$(CONFIG_IP_NF_MATCH_AH) += ipt_ah.o +obj-$(CONFIG_IP_NF_MATCH_TOS) += ipt_tos.o obj-$(CONFIG_IP_NF_MATCH_TTL) += ipt_ttl.o -obj-$(CONFIG_IP_NF_MATCH_ADDRTYPE) += ipt_addrtype.o # targets -obj-$(CONFIG_IP_NF_TARGET_REJECT) += ipt_REJECT.o -obj-$(CONFIG_IP_NF_TARGET_TOS) += ipt_TOS.o +obj-$(CONFIG_IP_NF_TARGET_CLUSTERIP) += ipt_CLUSTERIP.o obj-$(CONFIG_IP_NF_TARGET_ECN) += ipt_ECN.o +obj-$(CONFIG_IP_NF_TARGET_LOG) += ipt_LOG.o obj-$(CONFIG_IP_NF_TARGET_MASQUERADE) += ipt_MASQUERADE.o -obj-$(CONFIG_IP_NF_TARGET_REDIRECT) += ipt_REDIRECT.o obj-$(CONFIG_IP_NF_TARGET_NETMAP) += ipt_NETMAP.o +obj-$(CONFIG_IP_NF_TARGET_REDIRECT) += ipt_REDIRECT.o +obj-$(CONFIG_IP_NF_TARGET_REJECT) += ipt_REJECT.o obj-$(CONFIG_IP_NF_TARGET_SAME) += ipt_SAME.o -obj-$(CONFIG_IP_NF_TARGET_LOG) += ipt_LOG.o -obj-$(CONFIG_IP_NF_TARGET_ULOG) += ipt_ULOG.o -obj-$(CONFIG_IP_NF_TARGET_CLUSTERIP) += ipt_CLUSTERIP.o +obj-$(CONFIG_IP_NF_TARGET_TOS) += ipt_TOS.o obj-$(CONFIG_IP_NF_TARGET_TTL) += ipt_TTL.o +obj-$(CONFIG_IP_NF_TARGET_ULOG) += ipt_ULOG.o # generic ARP tables obj-$(CONFIG_IP_NF_ARPTABLES) += arp_tables.o diff --git a/net/ipv4/netfilter/ip_queue.c b/net/ipv4/netfilter/ip_queue.c index 10a2ce0..14d64a3 100644 --- a/net/ipv4/netfilter/ip_queue.c +++ b/net/ipv4/netfilter/ip_queue.c @@ -22,6 +22,7 @@ #include <linux/spinlock.h> #include <linux/sysctl.h> #include <linux/proc_fs.h> +#include <linux/seq_file.h> #include <linux/security.h> #include <linux/mutex.h> #include <net/net_namespace.h> @@ -607,15 +608,11 @@ static ctl_table ipq_root_table[] = { { .ctl_name = 0 } }; -#ifdef CONFIG_PROC_FS -static int -ipq_get_info(char *buffer, char **start, off_t offset, int length) +static int ip_queue_show(struct seq_file *m, void *v) { - int len; - read_lock_bh(&queue_lock); - len = sprintf(buffer, + seq_printf(m, "Peer PID : %d\n" "Copy mode : %hu\n" "Copy range : %u\n" @@ -632,16 +629,21 @@ ipq_get_info(char *buffer, char **start, off_t offset, int length) queue_user_dropped); read_unlock_bh(&queue_lock); + return 0; +} - *start = buffer + offset; - len -= offset; - if (len > length) - len = length; - else if (len < 0) - len = 0; - return len; +static int ip_queue_open(struct inode *inode, struct file *file) +{ + return single_open(file, ip_queue_show, NULL); } -#endif /* CONFIG_PROC_FS */ + +static const struct file_operations ip_queue_proc_fops = { + .open = ip_queue_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, + .owner = THIS_MODULE, +}; static struct nf_queue_handler nfqh = { .name = "ip_queue", @@ -661,10 +663,11 @@ static int __init ip_queue_init(void) goto cleanup_netlink_notifier; } - proc = proc_net_create(&init_net, IPQ_PROC_FS_NAME, 0, ipq_get_info); - if (proc) + proc = create_proc_entry(IPQ_PROC_FS_NAME, 0, init_net.proc_net); + if (proc) { proc->owner = THIS_MODULE; - else { + proc->proc_fops = &ip_queue_proc_fops; + } else { printk(KERN_ERR "ip_queue: failed to create proc entry\n"); goto cleanup_ipqnl; } diff --git a/net/ipv4/netfilter/iptable_raw.c b/net/ipv4/netfilter/iptable_raw.c index 5de6e57..f867865 100644 --- a/net/ipv4/netfilter/iptable_raw.c +++ b/net/ipv4/netfilter/iptable_raw.c @@ -66,7 +66,7 @@ ipt_local_hook(unsigned int hook, if (skb->len < sizeof(struct iphdr) || ip_hdrlen(skb) < sizeof(struct iphdr)) { if (net_ratelimit()) - printk("iptable_raw: ignoring short SOCK_RAW" + printk("iptable_raw: ignoring short SOCK_RAW " "packet.\n"); return NF_ACCEPT; } diff --git a/net/ipv4/netfilter/nf_nat_amanda.c b/net/ipv4/netfilter/nf_nat_amanda.c index 35a5aa6..c31b876 100644 --- a/net/ipv4/netfilter/nf_nat_amanda.c +++ b/net/ipv4/netfilter/nf_nat_amanda.c @@ -69,7 +69,7 @@ static void __exit nf_nat_amanda_fini(void) static int __init nf_nat_amanda_init(void) { - BUG_ON(rcu_dereference(nf_nat_amanda_hook)); + BUG_ON(nf_nat_amanda_hook != NULL); rcu_assign_pointer(nf_nat_amanda_hook, help); return 0; } diff --git a/net/ipv4/netfilter/nf_nat_core.c b/net/ipv4/netfilter/nf_nat_core.c index 56e93f6..86b465b 100644 --- a/net/ipv4/netfilter/nf_nat_core.c +++ b/net/ipv4/netfilter/nf_nat_core.c @@ -607,13 +607,10 @@ static void nf_nat_move_storage(struct nf_conn *conntrack, void *old) struct nf_conn_nat *new_nat = nf_ct_ext_find(conntrack, NF_CT_EXT_NAT); struct nf_conn_nat *old_nat = (struct nf_conn_nat *)old; struct nf_conn *ct = old_nat->ct; - unsigned int srchash; - if (!(ct->status & IPS_NAT_DONE_MASK)) + if (!ct || !(ct->status & IPS_NAT_DONE_MASK)) return; - srchash = hash_by_src(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple); - write_lock_bh(&nf_nat_lock); hlist_replace_rcu(&old_nat->bysource, &new_nat->bysource); new_nat->ct = ct; @@ -681,7 +678,7 @@ static int clean_nat(struct nf_conn *i, void *data) if (!nat) return 0; - memset(nat, 0, sizeof(nat)); + memset(nat, 0, sizeof(*nat)); i->status &= ~(IPS_NAT_MASK | IPS_NAT_DONE_MASK | IPS_SEQ_ADJUST); return 0; } diff --git a/net/ipv4/netfilter/nf_nat_ftp.c b/net/ipv4/netfilter/nf_nat_ftp.c index e1a16d3..a1d5d58 100644 --- a/net/ipv4/netfilter/nf_nat_ftp.c +++ b/net/ipv4/netfilter/nf_nat_ftp.c @@ -147,7 +147,7 @@ static void __exit nf_nat_ftp_fini(void) static int __init nf_nat_ftp_init(void) { - BUG_ON(rcu_dereference(nf_nat_ftp_hook)); + BUG_ON(nf_nat_ftp_hook != NULL); rcu_assign_pointer(nf_nat_ftp_hook, nf_nat_ftp); return 0; } diff --git a/net/ipv4/netfilter/nf_nat_h323.c b/net/ipv4/netfilter/nf_nat_h323.c index a868c8c..93e18ef 100644 --- a/net/ipv4/netfilter/nf_nat_h323.c +++ b/net/ipv4/netfilter/nf_nat_h323.c @@ -544,15 +544,15 @@ static int nat_callforwarding(struct sk_buff *skb, struct nf_conn *ct, /****************************************************************************/ static int __init init(void) { - BUG_ON(rcu_dereference(set_h245_addr_hook) != NULL); - BUG_ON(rcu_dereference(set_h225_addr_hook) != NULL); - BUG_ON(rcu_dereference(set_sig_addr_hook) != NULL); - BUG_ON(rcu_dereference(set_ras_addr_hook) != NULL); - BUG_ON(rcu_dereference(nat_rtp_rtcp_hook) != NULL); - BUG_ON(rcu_dereference(nat_t120_hook) != NULL); - BUG_ON(rcu_dereference(nat_h245_hook) != NULL); - BUG_ON(rcu_dereference(nat_callforwarding_hook) != NULL); - BUG_ON(rcu_dereference(nat_q931_hook) != NULL); + BUG_ON(set_h245_addr_hook != NULL); + BUG_ON(set_h225_addr_hook != NULL); + BUG_ON(set_sig_addr_hook != NULL); + BUG_ON(set_ras_addr_hook != NULL); + BUG_ON(nat_rtp_rtcp_hook != NULL); + BUG_ON(nat_t120_hook != NULL); + BUG_ON(nat_h245_hook != NULL); + BUG_ON(nat_callforwarding_hook != NULL); + BUG_ON(nat_q931_hook != NULL); rcu_assign_pointer(set_h245_addr_hook, set_h245_addr); rcu_assign_pointer(set_h225_addr_hook, set_h225_addr); diff --git a/net/ipv4/netfilter/nf_nat_irc.c b/net/ipv4/netfilter/nf_nat_irc.c index 766e2c1..fe6f9ce 100644 --- a/net/ipv4/netfilter/nf_nat_irc.c +++ b/net/ipv4/netfilter/nf_nat_irc.c @@ -74,7 +74,7 @@ static void __exit nf_nat_irc_fini(void) static int __init nf_nat_irc_init(void) { - BUG_ON(rcu_dereference(nf_nat_irc_hook)); + BUG_ON(nf_nat_irc_hook != NULL); rcu_assign_pointer(nf_nat_irc_hook, help); return 0; } diff --git a/net/ipv4/netfilter/nf_nat_pptp.c b/net/ipv4/netfilter/nf_nat_pptp.c index e1385a0..6817e79 100644 --- a/net/ipv4/netfilter/nf_nat_pptp.c +++ b/net/ipv4/netfilter/nf_nat_pptp.c @@ -281,16 +281,16 @@ static int __init nf_nat_helper_pptp_init(void) { nf_nat_need_gre(); - BUG_ON(rcu_dereference(nf_nat_pptp_hook_outbound)); + BUG_ON(nf_nat_pptp_hook_outbound != NULL); rcu_assign_pointer(nf_nat_pptp_hook_outbound, pptp_outbound_pkt); - BUG_ON(rcu_dereference(nf_nat_pptp_hook_inbound)); + BUG_ON(nf_nat_pptp_hook_inbound != NULL); rcu_assign_pointer(nf_nat_pptp_hook_inbound, pptp_inbound_pkt); - BUG_ON(rcu_dereference(nf_nat_pptp_hook_exp_gre)); + BUG_ON(nf_nat_pptp_hook_exp_gre != NULL); rcu_assign_pointer(nf_nat_pptp_hook_exp_gre, pptp_exp_gre); - BUG_ON(rcu_dereference(nf_nat_pptp_hook_expectfn)); + BUG_ON(nf_nat_pptp_hook_expectfn != NULL); rcu_assign_pointer(nf_nat_pptp_hook_expectfn, pptp_nat_expected); return 0; } diff --git a/net/ipv4/netfilter/nf_nat_sip.c b/net/ipv4/netfilter/nf_nat_sip.c index ce9edbc..3ca9897 100644 --- a/net/ipv4/netfilter/nf_nat_sip.c +++ b/net/ipv4/netfilter/nf_nat_sip.c @@ -293,8 +293,8 @@ static void __exit nf_nat_sip_fini(void) static int __init nf_nat_sip_init(void) { - BUG_ON(rcu_dereference(nf_nat_sip_hook)); - BUG_ON(rcu_dereference(nf_nat_sdp_hook)); + BUG_ON(nf_nat_sip_hook != NULL); + BUG_ON(nf_nat_sdp_hook != NULL); rcu_assign_pointer(nf_nat_sip_hook, ip_nat_sip); rcu_assign_pointer(nf_nat_sdp_hook, ip_nat_sdp); return 0; diff --git a/net/ipv4/netfilter/nf_nat_tftp.c b/net/ipv4/netfilter/nf_nat_tftp.c index 0ecec70..1360a94 100644 --- a/net/ipv4/netfilter/nf_nat_tftp.c +++ b/net/ipv4/netfilter/nf_nat_tftp.c @@ -43,7 +43,7 @@ static void __exit nf_nat_tftp_fini(void) static int __init nf_nat_tftp_init(void) { - BUG_ON(rcu_dereference(nf_nat_tftp_hook)); + BUG_ON(nf_nat_tftp_hook != NULL); rcu_assign_pointer(nf_nat_tftp_hook, help); return 0; } diff --git a/net/ipv4/proc.c b/net/ipv4/proc.c index ffdccc0..ce34b28 100644 --- a/net/ipv4/proc.c +++ b/net/ipv4/proc.c @@ -46,17 +46,6 @@ #include <net/sock.h> #include <net/raw.h> -static int fold_prot_inuse(struct proto *proto) -{ - int res = 0; - int cpu; - - for_each_possible_cpu(cpu) - res += proto->stats[cpu].inuse; - - return res; -} - /* * Report socket allocation statistics [mea@utu.fi] */ @@ -64,12 +53,12 @@ static int sockstat_seq_show(struct seq_file *seq, void *v) { socket_seq_show(seq); seq_printf(seq, "TCP: inuse %d orphan %d tw %d alloc %d mem %d\n", - fold_prot_inuse(&tcp_prot), atomic_read(&tcp_orphan_count), + sock_prot_inuse(&tcp_prot), atomic_read(&tcp_orphan_count), tcp_death_row.tw_count, atomic_read(&tcp_sockets_allocated), atomic_read(&tcp_memory_allocated)); - seq_printf(seq, "UDP: inuse %d\n", fold_prot_inuse(&udp_prot)); - seq_printf(seq, "UDPLITE: inuse %d\n", fold_prot_inuse(&udplite_prot)); - seq_printf(seq, "RAW: inuse %d\n", fold_prot_inuse(&raw_prot)); + seq_printf(seq, "UDP: inuse %d\n", sock_prot_inuse(&udp_prot)); + seq_printf(seq, "UDPLITE: inuse %d\n", sock_prot_inuse(&udplite_prot)); + seq_printf(seq, "RAW: inuse %d\n", sock_prot_inuse(&raw_prot)); seq_printf(seq, "FRAG: inuse %d memory %d\n", ip_frag_nqueues(), ip_frag_mem()); return 0; diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c index 3916fac..66b42f5 100644 --- a/net/ipv4/raw.c +++ b/net/ipv4/raw.c @@ -760,6 +760,8 @@ static int raw_ioctl(struct sock *sk, int cmd, unsigned long arg) } } +DEFINE_PROTO_INUSE(raw) + struct proto raw_prot = { .name = "RAW", .owner = THIS_MODULE, @@ -781,6 +783,7 @@ struct proto raw_prot = { .compat_setsockopt = compat_raw_setsockopt, .compat_getsockopt = compat_raw_getsockopt, #endif + REF_PROTO_INUSE(raw) }; #ifdef CONFIG_PROC_FS diff --git a/net/ipv4/route.c b/net/ipv4/route.c index 21b12de..c426dec 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c @@ -578,6 +578,9 @@ static void rt_check_expire(struct work_struct *work) i = (i + 1) & rt_hash_mask; rthp = &rt_hash_table[i].chain; + if (need_resched()) + cond_resched(); + if (*rthp == NULL) continue; spin_lock_bh(rt_hash_lock_addr(i)); @@ -851,9 +854,7 @@ restart: */ rcu_assign_pointer(rt_hash_table[hash].chain, rth); - rth->u.dst.__use++; - dst_hold(&rth->u.dst); - rth->u.dst.lastuse = now; + dst_use(&rth->u.dst, now); spin_unlock_bh(rt_hash_lock_addr(hash)); rt_drop(rt); @@ -1813,11 +1814,6 @@ static int ip_route_input_slow(struct sk_buff *skb, __be32 daddr, __be32 saddr, goto martian_destination; err = ip_mkroute_input(skb, &res, &fl, in_dev, daddr, saddr, tos); - if (err == -ENOBUFS) - goto e_nobufs; - if (err == -EINVAL) - goto e_inval; - done: in_dev_put(in_dev); if (free_res) @@ -1935,9 +1931,7 @@ int ip_route_input(struct sk_buff *skb, __be32 daddr, __be32 saddr, rth->fl.oif == 0 && rth->fl.mark == skb->mark && rth->fl.fl4_tos == tos) { - rth->u.dst.lastuse = jiffies; - dst_hold(&rth->u.dst); - rth->u.dst.__use++; + dst_use(&rth->u.dst, jiffies); RT_CACHE_STAT_INC(in_hit); rcu_read_unlock(); skb->dst = (struct dst_entry*)rth; @@ -2331,9 +2325,7 @@ int __ip_route_output_key(struct rtable **rp, const struct flowi *flp) rth->fl.mark == flp->mark && !((rth->fl.fl4_tos ^ flp->fl4_tos) & (IPTOS_RT_MASK | RTO_ONLINK))) { - rth->u.dst.lastuse = jiffies; - dst_hold(&rth->u.dst); - rth->u.dst.__use++; + dst_use(&rth->u.dst, jiffies); RT_CACHE_STAT_INC(out_hit); rcu_read_unlock_bh(); *rp = rth; @@ -2896,18 +2888,14 @@ static int ip_rt_acct_read(char *buffer, char **start, off_t offset, offset /= sizeof(u32); if (length > 0) { - u32 *src = ((u32 *) IP_RT_ACCT_CPU(0)) + offset; u32 *dst = (u32 *) buffer; - /* Copy first cpu. */ *start = buffer; - memcpy(dst, src, length); + memset(dst, 0, length); - /* Add the other cpus in, one int at a time */ for_each_possible_cpu(i) { unsigned int j; - - src = ((u32 *) IP_RT_ACCT_CPU(i)) + offset; + u32 *src = ((u32 *) IP_RT_ACCT_CPU(i)) + offset; for (j = 0; j < length/4; j++) dst[j] += src[j]; diff --git a/net/ipv4/sysctl_net_ipv4.c b/net/ipv4/sysctl_net_ipv4.c index ffddd2b..bec6fe8 100644 --- a/net/ipv4/sysctl_net_ipv4.c +++ b/net/ipv4/sysctl_net_ipv4.c @@ -191,7 +191,7 @@ static int sysctl_tcp_congestion_control(ctl_table *table, int __user *name, tcp_get_default_congestion_control(val); ret = sysctl_string(&tbl, name, nlen, oldval, oldlenp, newval, newlen); - if (ret == 0 && newval && newlen) + if (ret == 1 && newval && newlen) ret = tcp_set_default_congestion_control(val); return ret; } diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index c64072b..8e65182 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c @@ -2456,11 +2456,11 @@ void __init tcp_init(void) thash_entries ? 0 : 512 * 1024); tcp_hashinfo.ehash_size = 1 << tcp_hashinfo.ehash_size; for (i = 0; i < tcp_hashinfo.ehash_size; i++) { - rwlock_init(&tcp_hashinfo.ehash[i].lock); INIT_HLIST_HEAD(&tcp_hashinfo.ehash[i].chain); INIT_HLIST_HEAD(&tcp_hashinfo.ehash[i].twchain); } - + if (inet_ehash_locks_alloc(&tcp_hashinfo)) + panic("TCP: failed to alloc ehash_locks"); tcp_hashinfo.bhash = alloc_large_system_hash("TCP bind", sizeof(struct inet_bind_hashbucket), diff --git a/net/ipv4/tcp_illinois.c b/net/ipv4/tcp_illinois.c index 64f1cba..5aa5f54 100644 --- a/net/ipv4/tcp_illinois.c +++ b/net/ipv4/tcp_illinois.c @@ -298,7 +298,7 @@ static u32 tcp_illinois_ssthresh(struct sock *sk) struct illinois *ca = inet_csk_ca(sk); /* Multiplicative decrease */ - return max((tp->snd_cwnd * ca->beta) >> BETA_SHIFT, 2U); + return max(tp->snd_cwnd - ((tp->snd_cwnd * ca->beta) >> BETA_SHIFT), 2U); } diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index ca9590f..0f0c1c9 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -1269,6 +1269,9 @@ tcp_sacktag_write_queue(struct sock *sk, struct sk_buff *ack_skb, u32 prior_snd_ if (before(TCP_SKB_CB(ack_skb)->ack_seq, prior_snd_una - tp->max_window)) return 0; + if (!tp->packets_out) + goto out; + /* SACK fastpath: * if the only SACK change is the increase of the end_seq of * the first block then only apply that SACK block @@ -1400,11 +1403,9 @@ tcp_sacktag_write_queue(struct sock *sk, struct sk_buff *ack_skb, u32 prior_snd_ /* DSACK info lost if out-of-mem, try SACK still */ if (in_sack <= 0) in_sack = tcp_match_skb_to_sack(sk, skb, start_seq, end_seq); - if (in_sack < 0) + if (unlikely(in_sack < 0)) break; - fack_count += tcp_skb_pcount(skb); - sacked = TCP_SKB_CB(skb)->sacked; /* Account D-SACK for retransmitted packet. */ @@ -1419,19 +1420,17 @@ tcp_sacktag_write_queue(struct sock *sk, struct sk_buff *ack_skb, u32 prior_snd_ if ((dup_sack && in_sack) && (sacked&TCPCB_SACKED_ACKED)) reord = min(fack_count, reord); - } else { - /* If it was in a hole, we detected reordering. */ - if (fack_count < prior_fackets && - !(sacked&TCPCB_SACKED_ACKED)) - reord = min(fack_count, reord); } /* Nothing to do; acked frame is about to be dropped. */ + fack_count += tcp_skb_pcount(skb); continue; } - if (!in_sack) + if (!in_sack) { + fack_count += tcp_skb_pcount(skb); continue; + } if (!(sacked&TCPCB_SACKED_ACKED)) { if (sacked & TCPCB_SACKED_RETRANS) { @@ -1448,12 +1447,17 @@ tcp_sacktag_write_queue(struct sock *sk, struct sk_buff *ack_skb, u32 prior_snd_ tp->retransmit_skb_hint = NULL; } } else { - /* New sack for not retransmitted frame, - * which was in hole. It is reordering. - */ - if (!(sacked & TCPCB_RETRANS) && - fack_count < prior_fackets) - reord = min(fack_count, reord); + if (!(sacked & TCPCB_RETRANS)) { + /* New sack for not retransmitted frame, + * which was in hole. It is reordering. + */ + if (fack_count < prior_fackets) + reord = min(fack_count, reord); + + /* SACK enhanced F-RTO (RFC4138; Appendix B) */ + if (!after(TCP_SKB_CB(skb)->end_seq, tp->frto_highmark)) + flag |= FLAG_ONLY_ORIG_SACKED; + } if (sacked & TCPCB_LOST) { TCP_SKB_CB(skb)->sacked &= ~TCPCB_LOST; @@ -1462,24 +1466,13 @@ tcp_sacktag_write_queue(struct sock *sk, struct sk_buff *ack_skb, u32 prior_snd_ /* clear lost hint */ tp->retransmit_skb_hint = NULL; } - /* SACK enhanced F-RTO detection. - * Set flag if and only if non-rexmitted - * segments below frto_highmark are - * SACKed (RFC4138; Appendix B). - * Clearing correct due to in-order walk - */ - if (after(end_seq, tp->frto_highmark)) { - flag &= ~FLAG_ONLY_ORIG_SACKED; - } else { - if (!(sacked & TCPCB_RETRANS)) - flag |= FLAG_ONLY_ORIG_SACKED; - } } TCP_SKB_CB(skb)->sacked |= TCPCB_SACKED_ACKED; flag |= FLAG_DATA_SACKED; tp->sacked_out += tcp_skb_pcount(skb); + fack_count += tcp_skb_pcount(skb); if (fack_count > tp->fackets_out) tp->fackets_out = fack_count; @@ -1490,6 +1483,8 @@ tcp_sacktag_write_queue(struct sock *sk, struct sk_buff *ack_skb, u32 prior_snd_ } else { if (dup_sack && (sacked&TCPCB_RETRANS)) reord = min(fack_count, reord); + + fack_count += tcp_skb_pcount(skb); } /* D-SACK. We can detect redundant retransmission @@ -1504,6 +1499,12 @@ tcp_sacktag_write_queue(struct sock *sk, struct sk_buff *ack_skb, u32 prior_snd_ tp->retransmit_skb_hint = NULL; } } + + /* SACK enhanced FRTO (RFC4138, Appendix B): Clearing correct + * due to in-order walk + */ + if (after(end_seq, tp->frto_highmark)) + flag &= ~FLAG_ONLY_ORIG_SACKED; } if (tp->retrans_out && @@ -1515,7 +1516,9 @@ tcp_sacktag_write_queue(struct sock *sk, struct sk_buff *ack_skb, u32 prior_snd_ if ((reord < tp->fackets_out) && icsk->icsk_ca_state != TCP_CA_Loss && (!tp->frto_highmark || after(tp->snd_una, tp->frto_highmark))) - tcp_update_reordering(sk, ((tp->fackets_out + 1) - reord), 0); + tcp_update_reordering(sk, tp->fackets_out - reord, 0); + +out: #if FASTRETRANS_DEBUG > 0 BUG_TRAP((int)tp->sacked_out >= 0); @@ -1671,6 +1674,9 @@ void tcp_enter_frto(struct sock *sk) } tcp_verify_left_out(tp); + /* Too bad if TCP was application limited */ + tp->snd_cwnd = min(tp->snd_cwnd, tcp_packets_in_flight(tp) + 1); + /* Earlier loss recovery underway (see RFC4138; Appendix B). * The last condition is necessary at least in tp->frto_counter case. */ @@ -1703,6 +1709,8 @@ static void tcp_enter_frto_loss(struct sock *sk, int allowed_segments, int flag) tcp_for_write_queue(skb, sk) { if (skb == tcp_send_head(sk)) break; + + TCP_SKB_CB(skb)->sacked &= ~TCPCB_LOST; /* * Count the retransmission made on RTO correctly (only when * waiting for the first ACK and did not get it)... @@ -1716,7 +1724,7 @@ static void tcp_enter_frto_loss(struct sock *sk, int allowed_segments, int flag) } else { if (TCP_SKB_CB(skb)->sacked & TCPCB_RETRANS) tp->undo_marker = 0; - TCP_SKB_CB(skb)->sacked &= ~(TCPCB_LOST|TCPCB_SACKED_RETRANS); + TCP_SKB_CB(skb)->sacked &= ~TCPCB_SACKED_RETRANS; } /* Don't lost mark skbs that were fwd transmitted after RTO */ @@ -2630,7 +2638,8 @@ static u32 tcp_tso_acked(struct sock *sk, struct sk_buff *skb) * is before the ack sequence we can discard it as it's confirmed to have * arrived at the other end. */ -static int tcp_clean_rtx_queue(struct sock *sk, s32 *seq_rtt_p) +static int tcp_clean_rtx_queue(struct sock *sk, s32 *seq_rtt_p, + int prior_fackets) { struct tcp_sock *tp = tcp_sk(sk); const struct inet_connection_sock *icsk = inet_csk(sk); @@ -2639,6 +2648,8 @@ static int tcp_clean_rtx_queue(struct sock *sk, s32 *seq_rtt_p) int fully_acked = 1; int flag = 0; int prior_packets = tp->packets_out; + u32 cnt = 0; + u32 reord = tp->packets_out; s32 seq_rtt = -1; ktime_t last_ackt = net_invalid_timestamp(); @@ -2679,10 +2690,14 @@ static int tcp_clean_rtx_queue(struct sock *sk, s32 *seq_rtt_p) if ((flag & FLAG_DATA_ACKED) || (packets_acked > 1)) flag |= FLAG_NONHEAD_RETRANS_ACKED; - } else if (seq_rtt < 0) { - seq_rtt = now - scb->when; - if (fully_acked) - last_ackt = skb->tstamp; + } else { + if (seq_rtt < 0) { + seq_rtt = now - scb->when; + if (fully_acked) + last_ackt = skb->tstamp; + } + if (!(sacked & TCPCB_SACKED_ACKED)) + reord = min(cnt, reord); } if (sacked & TCPCB_SACKED_ACKED) @@ -2693,12 +2708,16 @@ static int tcp_clean_rtx_queue(struct sock *sk, s32 *seq_rtt_p) if ((sacked & TCPCB_URG) && tp->urg_mode && !before(end_seq, tp->snd_up)) tp->urg_mode = 0; - } else if (seq_rtt < 0) { - seq_rtt = now - scb->when; - if (fully_acked) - last_ackt = skb->tstamp; + } else { + if (seq_rtt < 0) { + seq_rtt = now - scb->when; + if (fully_acked) + last_ackt = skb->tstamp; + } + reord = min(cnt, reord); } tp->packets_out -= packets_acked; + cnt += packets_acked; /* Initial outgoing SYN's get put onto the write_queue * just like anything else we transmit. It is not @@ -2730,13 +2749,18 @@ static int tcp_clean_rtx_queue(struct sock *sk, s32 *seq_rtt_p) tcp_ack_update_rtt(sk, flag, seq_rtt); tcp_rearm_rto(sk); + if (tcp_is_reno(tp)) { + tcp_remove_reno_sacks(sk, pkts_acked); + } else { + /* Non-retransmitted hole got filled? That's reordering */ + if (reord < prior_fackets) + tcp_update_reordering(sk, tp->fackets_out - reord, 0); + } + tp->fackets_out -= min(pkts_acked, tp->fackets_out); /* hint's skb might be NULL but we don't need to care */ tp->fastpath_cnt_hint -= min_t(u32, pkts_acked, tp->fastpath_cnt_hint); - if (tcp_is_reno(tp)) - tcp_remove_reno_sacks(sk, pkts_acked); - if (ca_ops->pkts_acked) { s32 rtt_us = -1; @@ -3019,6 +3043,7 @@ static int tcp_ack(struct sock *sk, struct sk_buff *skb, int flag) u32 ack_seq = TCP_SKB_CB(skb)->seq; u32 ack = TCP_SKB_CB(skb)->ack_seq; u32 prior_in_flight; + u32 prior_fackets; s32 seq_rtt; int prior_packets; int frto_cwnd = 0; @@ -3043,6 +3068,8 @@ static int tcp_ack(struct sock *sk, struct sk_buff *skb, int flag) tp->bytes_acked += min(ack - prior_snd_una, tp->mss_cache); } + prior_fackets = tp->fackets_out; + if (!(flag&FLAG_SLOWPATH) && after(ack, prior_snd_una)) { /* Window is constant, pure forward advance. * No more checks are required. @@ -3084,13 +3111,13 @@ static int tcp_ack(struct sock *sk, struct sk_buff *skb, int flag) prior_in_flight = tcp_packets_in_flight(tp); /* See if we can take anything off of the retransmit queue. */ - flag |= tcp_clean_rtx_queue(sk, &seq_rtt); + flag |= tcp_clean_rtx_queue(sk, &seq_rtt, prior_fackets); + if (tp->frto_counter) + frto_cwnd = tcp_process_frto(sk, flag); /* Guarantee sacktag reordering detection against wrap-arounds */ if (before(tp->frto_highmark, tp->snd_una)) tp->frto_highmark = 0; - if (tp->frto_counter) - frto_cwnd = tcp_process_frto(sk, flag); if (tcp_ack_is_dubious(sk, flag)) { /* Advance CWND, if state allows this. */ diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index d438dfb..652c323 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -900,8 +900,7 @@ int tcp_v4_md5_do_add(struct sock *sk, __be32 addr, sizeof(*keys) * md5sig->entries4); /* Free old key list, and reference new one */ - if (md5sig->keys4) - kfree(md5sig->keys4); + kfree(md5sig->keys4); md5sig->keys4 = keys; md5sig->alloced4++; } @@ -939,10 +938,10 @@ int tcp_v4_md5_do_del(struct sock *sk, __be32 addr) tp->md5sig_info->alloced4 = 0; } else if (tp->md5sig_info->entries4 != i) { /* Need to do some manipulation */ - memcpy(&tp->md5sig_info->keys4[i], - &tp->md5sig_info->keys4[i+1], - (tp->md5sig_info->entries4 - i) * - sizeof(struct tcp4_md5sig_key)); + memmove(&tp->md5sig_info->keys4[i], + &tp->md5sig_info->keys4[i+1], + (tp->md5sig_info->entries4 - i) * + sizeof(struct tcp4_md5sig_key)); } tcp_free_md5sig_pool(); return 0; @@ -2049,8 +2048,9 @@ static void *established_get_first(struct seq_file *seq) struct sock *sk; struct hlist_node *node; struct inet_timewait_sock *tw; + rwlock_t *lock = inet_ehash_lockp(&tcp_hashinfo, st->bucket); - read_lock_bh(&tcp_hashinfo.ehash[st->bucket].lock); + read_lock_bh(lock); sk_for_each(sk, node, &tcp_hashinfo.ehash[st->bucket].chain) { if (sk->sk_family != st->family) { continue; @@ -2067,7 +2067,7 @@ static void *established_get_first(struct seq_file *seq) rc = tw; goto out; } - read_unlock_bh(&tcp_hashinfo.ehash[st->bucket].lock); + read_unlock_bh(lock); st->state = TCP_SEQ_STATE_ESTABLISHED; } out: @@ -2094,11 +2094,11 @@ get_tw: cur = tw; goto out; } - read_unlock_bh(&tcp_hashinfo.ehash[st->bucket].lock); + read_unlock_bh(inet_ehash_lockp(&tcp_hashinfo, st->bucket)); st->state = TCP_SEQ_STATE_ESTABLISHED; if (++st->bucket < tcp_hashinfo.ehash_size) { - read_lock_bh(&tcp_hashinfo.ehash[st->bucket].lock); + read_lock_bh(inet_ehash_lockp(&tcp_hashinfo, st->bucket)); sk = sk_head(&tcp_hashinfo.ehash[st->bucket].chain); } else { cur = NULL; @@ -2206,7 +2206,7 @@ static void tcp_seq_stop(struct seq_file *seq, void *v) case TCP_SEQ_STATE_TIME_WAIT: case TCP_SEQ_STATE_ESTABLISHED: if (v) - read_unlock_bh(&tcp_hashinfo.ehash[st->bucket].lock); + read_unlock_bh(inet_ehash_lockp(&tcp_hashinfo, st->bucket)); break; } } @@ -2417,6 +2417,8 @@ void tcp4_proc_exit(void) } #endif /* CONFIG_PROC_FS */ +DEFINE_PROTO_INUSE(tcp) + struct proto tcp_prot = { .name = "TCP", .owner = THIS_MODULE, @@ -2451,6 +2453,7 @@ struct proto tcp_prot = { .compat_setsockopt = compat_tcp_setsockopt, .compat_getsockopt = compat_tcp_getsockopt, #endif + REF_PROTO_INUSE(tcp) }; void __init tcp_v4_init(struct net_proto_family *ops) diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index 324b420..e5130a7 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c @@ -1295,6 +1295,7 @@ static int tcp_mtu_probe(struct sock *sk) struct sk_buff *skb, *nskb, *next; int len; int probe_size; + int size_needed; unsigned int pif; int copy; int mss_now; @@ -1313,27 +1314,20 @@ static int tcp_mtu_probe(struct sock *sk) /* Very simple search strategy: just double the MSS. */ mss_now = tcp_current_mss(sk, 0); probe_size = 2*tp->mss_cache; + size_needed = probe_size + (tp->reordering + 1) * tp->mss_cache; if (probe_size > tcp_mtu_to_mss(sk, icsk->icsk_mtup.search_high)) { /* TODO: set timer for probe_converge_event */ return -1; } /* Have enough data in the send queue to probe? */ - len = 0; - if ((skb = tcp_send_head(sk)) == NULL) - return -1; - while ((len += skb->len) < probe_size && !tcp_skb_is_last(sk, skb)) - skb = tcp_write_queue_next(sk, skb); - if (len < probe_size) + if (tp->write_seq - tp->snd_nxt < size_needed) return -1; - /* Receive window check. */ - if (after(TCP_SKB_CB(skb)->seq + probe_size, tp->snd_una + tp->snd_wnd)) { - if (tp->snd_wnd < probe_size) - return -1; - else - return 0; - } + if (tp->snd_wnd < size_needed) + return -1; + if (after(tp->snd_nxt + size_needed, tp->snd_una + tp->snd_wnd)) + return 0; /* Do we need to wait to drain cwnd? */ pif = tcp_packets_in_flight(tp); @@ -1352,7 +1346,6 @@ static int tcp_mtu_probe(struct sock *sk) skb = tcp_send_head(sk); tcp_insert_write_queue_before(nskb, skb, sk); - tcp_advance_send_head(sk, skb); TCP_SKB_CB(nskb)->seq = TCP_SKB_CB(skb)->seq; TCP_SKB_CB(nskb)->end_seq = TCP_SKB_CB(skb)->seq + probe_size; diff --git a/net/ipv4/tunnel4.c b/net/ipv4/tunnel4.c index a794a8c..978b3fd 100644 --- a/net/ipv4/tunnel4.c +++ b/net/ipv4/tunnel4.c @@ -17,6 +17,11 @@ static struct xfrm_tunnel *tunnel4_handlers; static struct xfrm_tunnel *tunnel64_handlers; static DEFINE_MUTEX(tunnel4_mutex); +static inline struct xfrm_tunnel **fam_handlers(unsigned short family) +{ + return (family == AF_INET) ? &tunnel4_handlers : &tunnel64_handlers; +} + int xfrm4_tunnel_register(struct xfrm_tunnel *handler, unsigned short family) { struct xfrm_tunnel **pprev; @@ -25,8 +30,7 @@ int xfrm4_tunnel_register(struct xfrm_tunnel *handler, unsigned short family) mutex_lock(&tunnel4_mutex); - for (pprev = (family == AF_INET) ? &tunnel4_handlers : &tunnel64_handlers; - *pprev; pprev = &(*pprev)->next) { + for (pprev = fam_handlers(family); *pprev; pprev = &(*pprev)->next) { if ((*pprev)->priority > priority) break; if ((*pprev)->priority == priority) @@ -53,8 +57,7 @@ int xfrm4_tunnel_deregister(struct xfrm_tunnel *handler, unsigned short family) mutex_lock(&tunnel4_mutex); - for (pprev = (family == AF_INET) ? &tunnel4_handlers : &tunnel64_handlers; - *pprev; pprev = &(*pprev)->next) { + for (pprev = fam_handlers(family); *pprev; pprev = &(*pprev)->next) { if (*pprev == handler) { *pprev = handler->next; ret = 0; @@ -118,6 +121,17 @@ static void tunnel4_err(struct sk_buff *skb, u32 info) break; } +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) +static void tunnel64_err(struct sk_buff *skb, u32 info) +{ + struct xfrm_tunnel *handler; + + for (handler = tunnel64_handlers; handler; handler = handler->next) + if (!handler->err_handler(skb, info)) + break; +} +#endif + static struct net_protocol tunnel4_protocol = { .handler = tunnel4_rcv, .err_handler = tunnel4_err, @@ -127,7 +141,7 @@ static struct net_protocol tunnel4_protocol = { #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) static struct net_protocol tunnel64_protocol = { .handler = tunnel64_rcv, - .err_handler = tunnel4_err, + .err_handler = tunnel64_err, .no_policy = 1, }; #endif diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index 4bc25b4..03c400c 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c @@ -1430,6 +1430,8 @@ unsigned int udp_poll(struct file *file, struct socket *sock, poll_table *wait) } +DEFINE_PROTO_INUSE(udp) + struct proto udp_prot = { .name = "UDP", .owner = THIS_MODULE, @@ -1452,6 +1454,7 @@ struct proto udp_prot = { .compat_setsockopt = compat_udp_setsockopt, .compat_getsockopt = compat_udp_getsockopt, #endif + REF_PROTO_INUSE(udp) }; /* ------------------------------------------------------------------------ */ diff --git a/net/ipv4/udplite.c b/net/ipv4/udplite.c index 9497720..f5baeb3 100644 --- a/net/ipv4/udplite.c +++ b/net/ipv4/udplite.c @@ -44,6 +44,8 @@ static struct net_protocol udplite_protocol = { .no_policy = 1, }; +DEFINE_PROTO_INUSE(udplite) + struct proto udplite_prot = { .name = "UDP-Lite", .owner = THIS_MODULE, @@ -67,6 +69,7 @@ struct proto udplite_prot = { .compat_setsockopt = compat_udp_setsockopt, .compat_getsockopt = compat_udp_getsockopt, #endif + REF_PROTO_INUSE(udplite) }; static struct inet_protosw udplite4_protosw = { diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index 1bd8d81..e8c3475 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c @@ -967,7 +967,7 @@ int ipv6_dev_get_saddr(struct net_device *daddr_dev, if (unlikely(score.addr_type == IPV6_ADDR_ANY || score.addr_type & IPV6_ADDR_MULTICAST)) { LIMIT_NETDEBUG(KERN_DEBUG - "ADDRCONF: unspecified / multicast address" + "ADDRCONF: unspecified / multicast address " "assigned as unicast address on %s", dev->name); continue; @@ -2293,6 +2293,9 @@ static int addrconf_notify(struct notifier_block *this, unsigned long event, break; } + if (!idev && dev->mtu >= IPV6_MIN_MTU) + idev = ipv6_add_dev(dev); + if (idev) idev->if_flags |= IF_READY; } else { @@ -2357,12 +2360,18 @@ static int addrconf_notify(struct notifier_block *this, unsigned long event, break; case NETDEV_CHANGEMTU: - if ( idev && dev->mtu >= IPV6_MIN_MTU) { + if (idev && dev->mtu >= IPV6_MIN_MTU) { rt6_mtu_change(dev, dev->mtu); idev->cnf.mtu6 = dev->mtu; break; } + if (!idev && dev->mtu >= IPV6_MIN_MTU) { + idev = ipv6_add_dev(dev); + if (idev) + break; + } + /* MTU falled under IPV6_MIN_MTU. Stop IPv6 on this interface. */ case NETDEV_DOWN: diff --git a/net/ipv6/fib6_rules.c b/net/ipv6/fib6_rules.c index 706622a..428c6b0 100644 --- a/net/ipv6/fib6_rules.c +++ b/net/ipv6/fib6_rules.c @@ -31,25 +31,6 @@ struct fib6_rule static struct fib_rules_ops fib6_rules_ops; -static struct fib6_rule main_rule = { - .common = { - .refcnt = ATOMIC_INIT(2), - .pref = 0x7FFE, - .action = FR_ACT_TO_TBL, - .table = RT6_TABLE_MAIN, - }, -}; - -static struct fib6_rule local_rule = { - .common = { - .refcnt = ATOMIC_INIT(2), - .pref = 0, - .action = FR_ACT_TO_TBL, - .table = RT6_TABLE_LOCAL, - .flags = FIB_RULE_PERMANENT, - }, -}; - struct dst_entry *fib6_rule_lookup(struct flowi *fl, int flags, pol_lookup_t lookup) { @@ -270,11 +251,23 @@ static struct fib_rules_ops fib6_rules_ops = { .owner = THIS_MODULE, }; -void __init fib6_rules_init(void) +static int __init fib6_default_rules_init(void) { - list_add_tail(&local_rule.common.list, &fib6_rules_ops.rules_list); - list_add_tail(&main_rule.common.list, &fib6_rules_ops.rules_list); + int err; + + err = fib_default_rule_add(&fib6_rules_ops, 0, + RT6_TABLE_LOCAL, FIB_RULE_PERMANENT); + if (err < 0) + return err; + err = fib_default_rule_add(&fib6_rules_ops, 0x7FFE, RT6_TABLE_MAIN, 0); + if (err < 0) + return err; + return 0; +} +void __init fib6_rules_init(void) +{ + BUG_ON(fib6_default_rules_init()); fib_rules_register(&fib6_rules_ops); } diff --git a/net/ipv6/inet6_hashtables.c b/net/ipv6/inet6_hashtables.c index d6f1026..adc73ad 100644 --- a/net/ipv6/inet6_hashtables.c +++ b/net/ipv6/inet6_hashtables.c @@ -37,9 +37,8 @@ void __inet6_hash(struct inet_hashinfo *hashinfo, } else { unsigned int hash; sk->sk_hash = hash = inet6_sk_ehashfn(sk); - hash &= (hashinfo->ehash_size - 1); - list = &hashinfo->ehash[hash].chain; - lock = &hashinfo->ehash[hash].lock; + list = &inet_ehash_bucket(hashinfo, hash)->chain; + lock = inet_ehash_lockp(hashinfo, hash); write_lock(lock); } @@ -70,9 +69,10 @@ struct sock *__inet6_lookup_established(struct inet_hashinfo *hashinfo, */ unsigned int hash = inet6_ehashfn(daddr, hnum, saddr, sport); struct inet_ehash_bucket *head = inet_ehash_bucket(hashinfo, hash); + rwlock_t *lock = inet_ehash_lockp(hashinfo, hash); prefetch(head->chain.first); - read_lock(&head->lock); + read_lock(lock); sk_for_each(sk, node, &head->chain) { /* For IPV6 do the cheaper port and family tests first. */ if (INET6_MATCH(sk, hash, saddr, daddr, ports, dif)) @@ -92,12 +92,12 @@ struct sock *__inet6_lookup_established(struct inet_hashinfo *hashinfo, goto hit; } } - read_unlock(&head->lock); + read_unlock(lock); return NULL; hit: sock_hold(sk); - read_unlock(&head->lock); + read_unlock(lock); return sk; } EXPORT_SYMBOL(__inet6_lookup_established); @@ -175,12 +175,13 @@ static int __inet6_check_established(struct inet_timewait_death_row *death_row, const unsigned int hash = inet6_ehashfn(daddr, lport, saddr, inet->dport); struct inet_ehash_bucket *head = inet_ehash_bucket(hinfo, hash); + rwlock_t *lock = inet_ehash_lockp(hinfo, hash); struct sock *sk2; const struct hlist_node *node; struct inet_timewait_sock *tw; prefetch(head->chain.first); - write_lock(&head->lock); + write_lock(lock); /* Check TIME-WAIT sockets first. */ sk_for_each(sk2, node, &head->twchain) { @@ -216,7 +217,7 @@ unique: __sk_add_node(sk, &head->chain); sk->sk_hash = hash; sock_prot_inc_use(sk->sk_prot); - write_unlock(&head->lock); + write_unlock(lock); if (twp != NULL) { *twp = tw; @@ -231,7 +232,7 @@ unique: return 0; not_unique: - write_unlock(&head->lock); + write_unlock(lock); return -EADDRNOTAVAIL; } diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index 653fc0a..86e1835 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c @@ -1339,6 +1339,19 @@ error: return err; } +static void ip6_cork_release(struct inet_sock *inet, struct ipv6_pinfo *np) +{ + inet->cork.flags &= ~IPCORK_OPT; + kfree(np->cork.opt); + np->cork.opt = NULL; + if (np->cork.rt) { + dst_release(&np->cork.rt->u.dst); + np->cork.rt = NULL; + inet->cork.flags &= ~IPCORK_ALLFRAG; + } + memset(&inet->cork.fl, 0, sizeof(inet->cork.fl)); +} + int ip6_push_pending_frames(struct sock *sk) { struct sk_buff *skb, *tmp_skb; @@ -1415,15 +1428,7 @@ int ip6_push_pending_frames(struct sock *sk) } out: - inet->cork.flags &= ~IPCORK_OPT; - kfree(np->cork.opt); - np->cork.opt = NULL; - if (np->cork.rt) { - dst_release(&np->cork.rt->u.dst); - np->cork.rt = NULL; - inet->cork.flags &= ~IPCORK_ALLFRAG; - } - memset(&inet->cork.fl, 0, sizeof(inet->cork.fl)); + ip6_cork_release(inet, np); return err; error: goto out; @@ -1431,8 +1436,6 @@ error: void ip6_flush_pending_frames(struct sock *sk) { - struct inet_sock *inet = inet_sk(sk); - struct ipv6_pinfo *np = inet6_sk(sk); struct sk_buff *skb; while ((skb = __skb_dequeue_tail(&sk->sk_write_queue)) != NULL) { @@ -1442,14 +1445,5 @@ void ip6_flush_pending_frames(struct sock *sk) kfree_skb(skb); } - inet->cork.flags &= ~IPCORK_OPT; - - kfree(np->cork.opt); - np->cork.opt = NULL; - if (np->cork.rt) { - dst_release(&np->cork.rt->u.dst); - np->cork.rt = NULL; - inet->cork.flags &= ~IPCORK_ALLFRAG; - } - memset(&inet->cork.fl, 0, sizeof(inet->cork.fl)); + ip6_cork_release(inet_sk(sk), inet6_sk(sk)); } diff --git a/net/ipv6/ipcomp6.c b/net/ipv6/ipcomp6.c index 85eb479..0cd4056 100644 --- a/net/ipv6/ipcomp6.c +++ b/net/ipv6/ipcomp6.c @@ -36,6 +36,7 @@ #include <net/ipcomp.h> #include <asm/semaphore.h> #include <linux/crypto.h> +#include <linux/err.h> #include <linux/pfkeyv2.h> #include <linux/random.h> #include <linux/percpu.h> @@ -358,7 +359,7 @@ static struct crypto_comp **ipcomp6_alloc_tfms(const char *alg_name) for_each_possible_cpu(cpu) { struct crypto_comp *tfm = crypto_alloc_comp(alg_name, 0, CRYPTO_ALG_ASYNC); - if (!tfm) + if (IS_ERR(tfm)) goto error; *per_cpu_ptr(tfms, cpu) = tfm; } diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c index 36f7dbf..67997a7 100644 --- a/net/ipv6/ndisc.c +++ b/net/ipv6/ndisc.c @@ -1037,6 +1037,7 @@ static void ndisc_ra_useropt(struct sk_buff *ra, struct nd_opt_hdr *opt) ndmsg = nlmsg_data(nlh); ndmsg->nduseropt_family = AF_INET6; + ndmsg->nduseropt_ifindex = ra->dev->ifindex; ndmsg->nduseropt_icmp_type = icmp6h->icmp6_type; ndmsg->nduseropt_icmp_code = icmp6h->icmp6_code; ndmsg->nduseropt_opts_len = opt->nd_opt_len << 3; diff --git a/net/ipv6/netfilter/Makefile b/net/ipv6/netfilter/Makefile index 4513eab..e789ec4 100644 --- a/net/ipv6/netfilter/Makefile +++ b/net/ipv6/netfilter/Makefile @@ -4,25 +4,29 @@ # Link order matters here. obj-$(CONFIG_IP6_NF_IPTABLES) += ip6_tables.o -obj-$(CONFIG_IP6_NF_MATCH_RT) += ip6t_rt.o -obj-$(CONFIG_IP6_NF_MATCH_OPTS) += ip6t_hbh.o -obj-$(CONFIG_IP6_NF_MATCH_IPV6HEADER) += ip6t_ipv6header.o -obj-$(CONFIG_IP6_NF_MATCH_FRAG) += ip6t_frag.o -obj-$(CONFIG_IP6_NF_MATCH_AH) += ip6t_ah.o -obj-$(CONFIG_IP6_NF_MATCH_EUI64) += ip6t_eui64.o -obj-$(CONFIG_IP6_NF_MATCH_OWNER) += ip6t_owner.o obj-$(CONFIG_IP6_NF_FILTER) += ip6table_filter.o obj-$(CONFIG_IP6_NF_MANGLE) += ip6table_mangle.o -obj-$(CONFIG_IP6_NF_TARGET_HL) += ip6t_HL.o obj-$(CONFIG_IP6_NF_QUEUE) += ip6_queue.o -obj-$(CONFIG_IP6_NF_TARGET_LOG) += ip6t_LOG.o obj-$(CONFIG_IP6_NF_RAW) += ip6table_raw.o -obj-$(CONFIG_IP6_NF_MATCH_HL) += ip6t_hl.o -obj-$(CONFIG_IP6_NF_TARGET_REJECT) += ip6t_REJECT.o -obj-$(CONFIG_IP6_NF_MATCH_MH) += ip6t_mh.o # objects for l3 independent conntrack nf_conntrack_ipv6-objs := nf_conntrack_l3proto_ipv6.o nf_conntrack_proto_icmpv6.o nf_conntrack_reasm.o # l3 independent conntrack obj-$(CONFIG_NF_CONNTRACK_IPV6) += nf_conntrack_ipv6.o + +# matches +obj-$(CONFIG_IP6_NF_MATCH_AH) += ip6t_ah.o +obj-$(CONFIG_IP6_NF_MATCH_EUI64) += ip6t_eui64.o +obj-$(CONFIG_IP6_NF_MATCH_FRAG) += ip6t_frag.o +obj-$(CONFIG_IP6_NF_MATCH_HL) += ip6t_hl.o +obj-$(CONFIG_IP6_NF_MATCH_IPV6HEADER) += ip6t_ipv6header.o +obj-$(CONFIG_IP6_NF_MATCH_MH) += ip6t_mh.o +obj-$(CONFIG_IP6_NF_MATCH_OPTS) += ip6t_hbh.o +obj-$(CONFIG_IP6_NF_MATCH_OWNER) += ip6t_owner.o +obj-$(CONFIG_IP6_NF_MATCH_RT) += ip6t_rt.o + +# targets +obj-$(CONFIG_IP6_NF_TARGET_HL) += ip6t_HL.o +obj-$(CONFIG_IP6_NF_TARGET_LOG) += ip6t_LOG.o +obj-$(CONFIG_IP6_NF_TARGET_REJECT) += ip6t_REJECT.o diff --git a/net/ipv6/netfilter/ip6_queue.c b/net/ipv6/netfilter/ip6_queue.c index 6413a30..e273605 100644 --- a/net/ipv6/netfilter/ip6_queue.c +++ b/net/ipv6/netfilter/ip6_queue.c @@ -23,6 +23,7 @@ #include <linux/spinlock.h> #include <linux/sysctl.h> #include <linux/proc_fs.h> +#include <linux/seq_file.h> #include <linux/mutex.h> #include <net/net_namespace.h> #include <net/sock.h> @@ -596,15 +597,11 @@ static ctl_table ipq_root_table[] = { { .ctl_name = 0 } }; -#ifdef CONFIG_PROC_FS -static int -ipq_get_info(char *buffer, char **start, off_t offset, int length) +static int ip6_queue_show(struct seq_file *m, void *v) { - int len; - read_lock_bh(&queue_lock); - len = sprintf(buffer, + seq_printf(m, "Peer PID : %d\n" "Copy mode : %hu\n" "Copy range : %u\n" @@ -621,16 +618,21 @@ ipq_get_info(char *buffer, char **start, off_t offset, int length) queue_user_dropped); read_unlock_bh(&queue_lock); + return 0; +} - *start = buffer + offset; - len -= offset; - if (len > length) - len = length; - else if (len < 0) - len = 0; - return len; +static int ip6_queue_open(struct inode *inode, struct file *file) +{ + return single_open(file, ip6_queue_show, NULL); } -#endif /* CONFIG_PROC_FS */ + +static const struct file_operations ip6_queue_proc_fops = { + .open = ip6_queue_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, + .owner = THIS_MODULE, +}; static struct nf_queue_handler nfqh = { .name = "ip6_queue", @@ -650,10 +652,11 @@ static int __init ip6_queue_init(void) goto cleanup_netlink_notifier; } - proc = proc_net_create(&init_net, IPQ_PROC_FS_NAME, 0, ipq_get_info); - if (proc) + proc = create_proc_entry(IPQ_PROC_FS_NAME, 0, init_net.proc_net); + if (proc) { proc->owner = THIS_MODULE; - else { + proc->proc_fops = &ip6_queue_proc_fops; + } else { printk(KERN_ERR "ip6_queue: failed to create proc entry\n"); goto cleanup_ipqnl; } diff --git a/net/ipv6/proc.c b/net/ipv6/proc.c index be526ad..8631ed7 100644 --- a/net/ipv6/proc.c +++ b/net/ipv6/proc.c @@ -32,27 +32,16 @@ static struct proc_dir_entry *proc_net_devsnmp6; -static int fold_prot_inuse(struct proto *proto) -{ - int res = 0; - int cpu; - - for_each_possible_cpu(cpu) - res += proto->stats[cpu].inuse; - - return res; -} - static int sockstat6_seq_show(struct seq_file *seq, void *v) { seq_printf(seq, "TCP6: inuse %d\n", - fold_prot_inuse(&tcpv6_prot)); + sock_prot_inuse(&tcpv6_prot)); seq_printf(seq, "UDP6: inuse %d\n", - fold_prot_inuse(&udpv6_prot)); + sock_prot_inuse(&udpv6_prot)); seq_printf(seq, "UDPLITE6: inuse %d\n", - fold_prot_inuse(&udplitev6_prot)); + sock_prot_inuse(&udplitev6_prot)); seq_printf(seq, "RAW6: inuse %d\n", - fold_prot_inuse(&rawv6_prot)); + sock_prot_inuse(&rawv6_prot)); seq_printf(seq, "FRAG6: inuse %d memory %d\n", ip6_frag_nqueues(), ip6_frag_mem()); return 0; diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c index ca24ef1..807260d 100644 --- a/net/ipv6/raw.c +++ b/net/ipv6/raw.c @@ -1144,6 +1144,8 @@ static int rawv6_init_sk(struct sock *sk) return(0); } +DEFINE_PROTO_INUSE(rawv6) + struct proto rawv6_prot = { .name = "RAWv6", .owner = THIS_MODULE, @@ -1166,6 +1168,7 @@ struct proto rawv6_prot = { .compat_setsockopt = compat_rawv6_setsockopt, .compat_getsockopt = compat_rawv6_getsockopt, #endif + REF_PROTO_INUSE(rawv6) }; #ifdef CONFIG_PROC_FS diff --git a/net/ipv6/route.c b/net/ipv6/route.c index 95f8e4a..6ecb5e6 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c @@ -38,12 +38,8 @@ #include <linux/in6.h> #include <linux/init.h> #include <linux/if_arp.h> - -#ifdef CONFIG_PROC_FS #include <linux/proc_fs.h> #include <linux/seq_file.h> -#endif - #include <net/net_namespace.h> #include <net/snmp.h> #include <net/ipv6.h> @@ -548,12 +544,8 @@ restart: rt = rt6_device_match(rt, fl->oif, flags); BACKTRACK(&fl->fl6_src); out: - dst_hold(&rt->u.dst); + dst_use(&rt->u.dst, jiffies); read_unlock_bh(&table->tb6_lock); - - rt->u.dst.lastuse = jiffies; - rt->u.dst.__use++; - return rt; } @@ -2288,71 +2280,50 @@ struct rt6_proc_arg static int rt6_info_route(struct rt6_info *rt, void *p_arg) { - struct rt6_proc_arg *arg = (struct rt6_proc_arg *) p_arg; - - if (arg->skip < arg->offset / RT6_INFO_LEN) { - arg->skip++; - return 0; - } - - if (arg->len >= arg->length) - return 0; + struct seq_file *m = p_arg; - arg->len += sprintf(arg->buffer + arg->len, - NIP6_SEQFMT " %02x ", - NIP6(rt->rt6i_dst.addr), - rt->rt6i_dst.plen); + seq_printf(m, NIP6_SEQFMT " %02x ", NIP6(rt->rt6i_dst.addr), + rt->rt6i_dst.plen); #ifdef CONFIG_IPV6_SUBTREES - arg->len += sprintf(arg->buffer + arg->len, - NIP6_SEQFMT " %02x ", - NIP6(rt->rt6i_src.addr), - rt->rt6i_src.plen); + seq_printf(m, NIP6_SEQFMT " %02x ", NIP6(rt->rt6i_src.addr), + rt->rt6i_src.plen); #else - arg->len += sprintf(arg->buffer + arg->len, - "00000000000000000000000000000000 00 "); + seq_puts(m, "00000000000000000000000000000000 00 "); #endif if (rt->rt6i_nexthop) { - arg->len += sprintf(arg->buffer + arg->len, - NIP6_SEQFMT, - NIP6(*((struct in6_addr *)rt->rt6i_nexthop->primary_key))); + seq_printf(m, NIP6_SEQFMT, + NIP6(*((struct in6_addr *)rt->rt6i_nexthop->primary_key))); } else { - arg->len += sprintf(arg->buffer + arg->len, - "00000000000000000000000000000000"); + seq_puts(m, "00000000000000000000000000000000"); } - arg->len += sprintf(arg->buffer + arg->len, - " %08x %08x %08x %08x %8s\n", - rt->rt6i_metric, atomic_read(&rt->u.dst.__refcnt), - rt->u.dst.__use, rt->rt6i_flags, - rt->rt6i_dev ? rt->rt6i_dev->name : ""); + seq_printf(m, " %08x %08x %08x %08x %8s\n", + rt->rt6i_metric, atomic_read(&rt->u.dst.__refcnt), + rt->u.dst.__use, rt->rt6i_flags, + rt->rt6i_dev ? rt->rt6i_dev->name : ""); return 0; } -static int rt6_proc_info(char *buffer, char **start, off_t offset, int length) +static int ipv6_route_show(struct seq_file *m, void *v) { - struct rt6_proc_arg arg = { - .buffer = buffer, - .offset = offset, - .length = length, - }; - - fib6_clean_all(rt6_info_route, 0, &arg); - - *start = buffer; - if (offset) - *start += offset % RT6_INFO_LEN; - - arg.len -= offset % RT6_INFO_LEN; - - if (arg.len > length) - arg.len = length; - if (arg.len < 0) - arg.len = 0; + fib6_clean_all(rt6_info_route, 0, m); + return 0; +} - return arg.len; +static int ipv6_route_open(struct inode *inode, struct file *file) +{ + return single_open(file, ipv6_route_show, NULL); } +static const struct file_operations ipv6_route_proc_fops = { + .owner = THIS_MODULE, + .open = ipv6_route_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + static int rt6_stats_seq_show(struct seq_file *seq, void *v) { seq_printf(seq, "%04x %04x %04x %04x %04x %04x %04x\n", @@ -2489,22 +2460,14 @@ ctl_table ipv6_route_table[] = { void __init ip6_route_init(void) { -#ifdef CONFIG_PROC_FS - struct proc_dir_entry *p; -#endif ip6_dst_ops.kmem_cachep = kmem_cache_create("ip6_dst_cache", sizeof(struct rt6_info), 0, SLAB_HWCACHE_ALIGN|SLAB_PANIC, NULL); ip6_dst_blackhole_ops.kmem_cachep = ip6_dst_ops.kmem_cachep; fib6_init(); -#ifdef CONFIG_PROC_FS - p = proc_net_create(&init_net, "ipv6_route", 0, rt6_proc_info); - if (p) - p->owner = THIS_MODULE; - + proc_net_fops_create(&init_net, "ipv6_route", 0, &ipv6_route_proc_fops); proc_net_fops_create(&init_net, "rt6_stats", S_IRUGO, &rt6_stats_seq_fops); -#endif #ifdef CONFIG_XFRM xfrm6_init(); #endif diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index 06be2a1..93980c3 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c @@ -581,7 +581,10 @@ static int tcp_v6_md5_do_add(struct sock *sk, struct in6_addr *peer, } sk->sk_route_caps &= ~NETIF_F_GSO_MASK; } - tcp_alloc_md5sig_pool(); + if (tcp_alloc_md5sig_pool() == NULL) { + kfree(newkey); + return -ENOMEM; + } if (tp->md5sig_info->alloced6 == tp->md5sig_info->entries6) { keys = kmalloc((sizeof (tp->md5sig_info->keys6[0]) * (tp->md5sig_info->entries6 + 1)), GFP_ATOMIC); @@ -634,10 +637,6 @@ static int tcp_v6_md5_do_del(struct sock *sk, struct in6_addr *peer) kfree(tp->md5sig_info->keys6); tp->md5sig_info->keys6 = NULL; tp->md5sig_info->alloced6 = 0; - - tcp_free_md5sig_pool(); - - return 0; } else { /* shrink the database */ if (tp->md5sig_info->entries6 != i) @@ -646,6 +645,8 @@ static int tcp_v6_md5_do_del(struct sock *sk, struct in6_addr *peer) (tp->md5sig_info->entries6 - i) * sizeof (tp->md5sig_info->keys6[0])); } + tcp_free_md5sig_pool(); + return 0; } } return -ENOENT; @@ -2107,6 +2108,8 @@ void tcp6_proc_exit(void) } #endif +DEFINE_PROTO_INUSE(tcpv6) + struct proto tcpv6_prot = { .name = "TCPv6", .owner = THIS_MODULE, @@ -2141,6 +2144,7 @@ struct proto tcpv6_prot = { .compat_setsockopt = compat_tcp_setsockopt, .compat_getsockopt = compat_tcp_getsockopt, #endif + REF_PROTO_INUSE(tcpv6) }; static struct inet6_protocol tcpv6_protocol = { diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c index caebad6..ee1cc3f 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c @@ -205,12 +205,11 @@ out: return err; csum_copy_err: + UDP6_INC_STATS_USER(UDP_MIB_INERRORS, is_udplite); skb_kill_datagram(sk, skb, flags); - if (flags & MSG_DONTWAIT) { - UDP6_INC_STATS_USER(UDP_MIB_INERRORS, is_udplite); + if (flags & MSG_DONTWAIT) return -EAGAIN; - } goto try_again; } @@ -971,6 +970,8 @@ void udp6_proc_exit(void) { /* ------------------------------------------------------------------------ */ +DEFINE_PROTO_INUSE(udpv6) + struct proto udpv6_prot = { .name = "UDPv6", .owner = THIS_MODULE, @@ -992,6 +993,7 @@ struct proto udpv6_prot = { .compat_setsockopt = compat_udpv6_setsockopt, .compat_getsockopt = compat_udpv6_getsockopt, #endif + REF_PROTO_INUSE(udpv6) }; static struct inet_protosw udpv6_protosw = { diff --git a/net/ipv6/udplite.c b/net/ipv6/udplite.c index 766566f..5a0379f 100644 --- a/net/ipv6/udplite.c +++ b/net/ipv6/udplite.c @@ -40,6 +40,8 @@ static int udplite_v6_get_port(struct sock *sk, unsigned short snum) return udplite_get_port(sk, snum, ipv6_rcv_saddr_equal); } +DEFINE_PROTO_INUSE(udplitev6) + struct proto udplitev6_prot = { .name = "UDPLITEv6", .owner = THIS_MODULE, @@ -62,6 +64,7 @@ struct proto udplitev6_prot = { .compat_setsockopt = compat_udpv6_setsockopt, .compat_getsockopt = compat_udpv6_getsockopt, #endif + REF_PROTO_INUSE(udplitev6) }; static struct inet_protosw udplite6_protosw = { diff --git a/net/ipx/af_ipx.c b/net/ipx/af_ipx.c index a195a66..c76a952 100644 --- a/net/ipx/af_ipx.c +++ b/net/ipx/af_ipx.c @@ -92,11 +92,6 @@ extern int ipxrtr_route_skb(struct sk_buff *skb); extern struct ipx_route *ipxrtr_lookup(__be32 net); extern int ipxrtr_ioctl(unsigned int cmd, void __user *arg); -#undef IPX_REFCNT_DEBUG -#ifdef IPX_REFCNT_DEBUG -atomic_t ipx_sock_nr; -#endif - struct ipx_interface *ipx_interfaces_head(void) { struct ipx_interface *rc = NULL; @@ -151,14 +146,7 @@ static void ipx_destroy_socket(struct sock *sk) { ipx_remove_socket(sk); skb_queue_purge(&sk->sk_receive_queue); -#ifdef IPX_REFCNT_DEBUG - atomic_dec(&ipx_sock_nr); - printk(KERN_DEBUG "IPX socket %p released, %d are still alive\n", sk, - atomic_read(&ipx_sock_nr)); - if (atomic_read(&sk->sk_refcnt) != 1) - printk(KERN_DEBUG "Destruction sock ipx %p delayed, cnt=%d\n", - sk, atomic_read(&sk->sk_refcnt)); -#endif + sk_refcnt_debug_dec(sk); sock_put(sk); } @@ -1384,11 +1372,8 @@ static int ipx_create(struct net *net, struct socket *sock, int protocol) sk = sk_alloc(net, PF_IPX, GFP_KERNEL, &ipx_proto); if (!sk) goto out; -#ifdef IPX_REFCNT_DEBUG - atomic_inc(&ipx_sock_nr); - printk(KERN_DEBUG "IPX socket %p created, now we have %d alive\n", sk, - atomic_read(&ipx_sock_nr)); -#endif + + sk_refcnt_debug_inc(sk); sock_init_data(sock, sk); sk->sk_no_check = 1; /* Checksum off by default */ sock->ops = &ipx_dgram_ops; @@ -1409,6 +1394,7 @@ static int ipx_release(struct socket *sock) sock_set_flag(sk, SOCK_DEAD); sock->sk = NULL; + sk_refcnt_debug_release(sk); ipx_destroy_socket(sk); out: return 0; diff --git a/net/irda/iriap.c b/net/irda/iriap.c index dc5e34a..a86a5d8 100644 --- a/net/irda/iriap.c +++ b/net/irda/iriap.c @@ -928,7 +928,7 @@ void iriap_call_indication(struct iriap_cb *self, struct sk_buff *skb) opcode = fp[0]; if (~opcode & 0x80) { - IRDA_WARNING("%s: IrIAS multiframe commands or results" + IRDA_WARNING("%s: IrIAS multiframe commands or results " "is not implemented yet!\n", __FUNCTION__); return; } diff --git a/net/irda/irlan/irlan_eth.c b/net/irda/irlan/irlan_eth.c index 7f9c854..c682207 100644 --- a/net/irda/irlan/irlan_eth.c +++ b/net/irda/irlan/irlan_eth.c @@ -296,6 +296,7 @@ void irlan_eth_flow_indication(void *instance, void *sap, LOCAL_FLOW flow) */ void irlan_eth_send_gratuitous_arp(struct net_device *dev) { +#ifdef CONFIG_INET struct in_device *in_dev; /* @@ -303,7 +304,6 @@ void irlan_eth_send_gratuitous_arp(struct net_device *dev) * is useful if we have changed access points on the same * subnet. */ -#ifdef CONFIG_INET IRDA_DEBUG(4, "IrLAN: Sending gratuitous ARP\n"); rcu_read_lock(); in_dev = __in_dev_get_rcu(dev); diff --git a/net/iucv/iucv.c b/net/iucv/iucv.c index a2f5a6e..7698f6c 100644 --- a/net/iucv/iucv.c +++ b/net/iucv/iucv.c @@ -97,7 +97,7 @@ struct iucv_irq_list { struct iucv_irq_data data; }; -static struct iucv_irq_data *iucv_irq_data; +static struct iucv_irq_data *iucv_irq_data[NR_CPUS]; static cpumask_t iucv_buffer_cpumask = CPU_MASK_NONE; static cpumask_t iucv_irq_cpumask = CPU_MASK_NONE; @@ -277,7 +277,7 @@ union iucv_param { /* * Anchor for per-cpu IUCV command parameter block. */ -static union iucv_param *iucv_param; +static union iucv_param *iucv_param[NR_CPUS]; /** * iucv_call_b2f0 @@ -356,7 +356,7 @@ static void iucv_allow_cpu(void *data) * 0x10 - Flag to allow priority message completion interrupts * 0x08 - Flag to allow IUCV control interrupts */ - parm = percpu_ptr(iucv_param, smp_processor_id()); + parm = iucv_param[cpu]; memset(parm, 0, sizeof(union iucv_param)); parm->set_mask.ipmask = 0xf8; iucv_call_b2f0(IUCV_SETMASK, parm); @@ -377,7 +377,7 @@ static void iucv_block_cpu(void *data) union iucv_param *parm; /* Disable all iucv interrupts. */ - parm = percpu_ptr(iucv_param, smp_processor_id()); + parm = iucv_param[cpu]; memset(parm, 0, sizeof(union iucv_param)); iucv_call_b2f0(IUCV_SETMASK, parm); @@ -401,9 +401,9 @@ static void iucv_declare_cpu(void *data) return; /* Declare interrupt buffer. */ - parm = percpu_ptr(iucv_param, cpu); + parm = iucv_param[cpu]; memset(parm, 0, sizeof(union iucv_param)); - parm->db.ipbfadr1 = virt_to_phys(percpu_ptr(iucv_irq_data, cpu)); + parm->db.ipbfadr1 = virt_to_phys(iucv_irq_data[cpu]); rc = iucv_call_b2f0(IUCV_DECLARE_BUFFER, parm); if (rc) { char *err = "Unknown"; @@ -458,7 +458,7 @@ static void iucv_retrieve_cpu(void *data) iucv_block_cpu(NULL); /* Retrieve interrupt buffer. */ - parm = percpu_ptr(iucv_param, cpu); + parm = iucv_param[cpu]; iucv_call_b2f0(IUCV_RETRIEVE_BUFFER, parm); /* Clear indication that an iucv buffer exists for this cpu. */ @@ -558,22 +558,23 @@ static int __cpuinit iucv_cpu_notify(struct notifier_block *self, switch (action) { case CPU_UP_PREPARE: case CPU_UP_PREPARE_FROZEN: - if (!percpu_populate(iucv_irq_data, - sizeof(struct iucv_irq_data), - GFP_KERNEL|GFP_DMA, cpu)) + iucv_irq_data[cpu] = kmalloc_node(sizeof(struct iucv_irq_data), + GFP_KERNEL|GFP_DMA, cpu_to_node(cpu)); + if (!iucv_irq_data[cpu]) return NOTIFY_BAD; - if (!percpu_populate(iucv_param, sizeof(union iucv_param), - GFP_KERNEL|GFP_DMA, cpu)) { - percpu_depopulate(iucv_irq_data, cpu); + iucv_param[cpu] = kmalloc_node(sizeof(union iucv_param), + GFP_KERNEL|GFP_DMA, cpu_to_node(cpu)); + if (!iucv_param[cpu]) return NOTIFY_BAD; - } break; case CPU_UP_CANCELED: case CPU_UP_CANCELED_FROZEN: case CPU_DEAD: case CPU_DEAD_FROZEN: - percpu_depopulate(iucv_param, cpu); - percpu_depopulate(iucv_irq_data, cpu); + kfree(iucv_param[cpu]); + iucv_param[cpu] = NULL; + kfree(iucv_irq_data[cpu]); + iucv_irq_data[cpu] = NULL; break; case CPU_ONLINE: case CPU_ONLINE_FROZEN: @@ -612,7 +613,7 @@ static int iucv_sever_pathid(u16 pathid, u8 userdata[16]) { union iucv_param *parm; - parm = percpu_ptr(iucv_param, smp_processor_id()); + parm = iucv_param[smp_processor_id()]; memset(parm, 0, sizeof(union iucv_param)); if (userdata) memcpy(parm->ctrl.ipuser, userdata, sizeof(parm->ctrl.ipuser)); @@ -755,7 +756,7 @@ int iucv_path_accept(struct iucv_path *path, struct iucv_handler *handler, local_bh_disable(); /* Prepare parameter block. */ - parm = percpu_ptr(iucv_param, smp_processor_id()); + parm = iucv_param[smp_processor_id()]; memset(parm, 0, sizeof(union iucv_param)); parm->ctrl.ippathid = path->pathid; parm->ctrl.ipmsglim = path->msglim; @@ -799,7 +800,7 @@ int iucv_path_connect(struct iucv_path *path, struct iucv_handler *handler, BUG_ON(in_atomic()); spin_lock_bh(&iucv_table_lock); iucv_cleanup_queue(); - parm = percpu_ptr(iucv_param, smp_processor_id()); + parm = iucv_param[smp_processor_id()]; memset(parm, 0, sizeof(union iucv_param)); parm->ctrl.ipmsglim = path->msglim; parm->ctrl.ipflags1 = path->flags; @@ -854,7 +855,7 @@ int iucv_path_quiesce(struct iucv_path *path, u8 userdata[16]) int rc; local_bh_disable(); - parm = percpu_ptr(iucv_param, smp_processor_id()); + parm = iucv_param[smp_processor_id()]; memset(parm, 0, sizeof(union iucv_param)); if (userdata) memcpy(parm->ctrl.ipuser, userdata, sizeof(parm->ctrl.ipuser)); @@ -881,7 +882,7 @@ int iucv_path_resume(struct iucv_path *path, u8 userdata[16]) int rc; local_bh_disable(); - parm = percpu_ptr(iucv_param, smp_processor_id()); + parm = iucv_param[smp_processor_id()]; memset(parm, 0, sizeof(union iucv_param)); if (userdata) memcpy(parm->ctrl.ipuser, userdata, sizeof(parm->ctrl.ipuser)); @@ -936,7 +937,7 @@ int iucv_message_purge(struct iucv_path *path, struct iucv_message *msg, int rc; local_bh_disable(); - parm = percpu_ptr(iucv_param, smp_processor_id()); + parm = iucv_param[smp_processor_id()]; memset(parm, 0, sizeof(union iucv_param)); parm->purge.ippathid = path->pathid; parm->purge.ipmsgid = msg->id; @@ -1003,7 +1004,7 @@ int iucv_message_receive(struct iucv_path *path, struct iucv_message *msg, } local_bh_disable(); - parm = percpu_ptr(iucv_param, smp_processor_id()); + parm = iucv_param[smp_processor_id()]; memset(parm, 0, sizeof(union iucv_param)); parm->db.ipbfadr1 = (u32)(addr_t) buffer; parm->db.ipbfln1f = (u32) size; @@ -1040,7 +1041,7 @@ int iucv_message_reject(struct iucv_path *path, struct iucv_message *msg) int rc; local_bh_disable(); - parm = percpu_ptr(iucv_param, smp_processor_id()); + parm = iucv_param[smp_processor_id()]; memset(parm, 0, sizeof(union iucv_param)); parm->db.ippathid = path->pathid; parm->db.ipmsgid = msg->id; @@ -1074,7 +1075,7 @@ int iucv_message_reply(struct iucv_path *path, struct iucv_message *msg, int rc; local_bh_disable(); - parm = percpu_ptr(iucv_param, smp_processor_id()); + parm = iucv_param[smp_processor_id()]; memset(parm, 0, sizeof(union iucv_param)); if (flags & IUCV_IPRMDATA) { parm->dpl.ippathid = path->pathid; @@ -1118,7 +1119,7 @@ int iucv_message_send(struct iucv_path *path, struct iucv_message *msg, int rc; local_bh_disable(); - parm = percpu_ptr(iucv_param, smp_processor_id()); + parm = iucv_param[smp_processor_id()]; memset(parm, 0, sizeof(union iucv_param)); if (flags & IUCV_IPRMDATA) { /* Message of 8 bytes can be placed into the parameter list. */ @@ -1172,7 +1173,7 @@ int iucv_message_send2way(struct iucv_path *path, struct iucv_message *msg, int rc; local_bh_disable(); - parm = percpu_ptr(iucv_param, smp_processor_id()); + parm = iucv_param[smp_processor_id()]; memset(parm, 0, sizeof(union iucv_param)); if (flags & IUCV_IPRMDATA) { parm->dpl.ippathid = path->pathid; @@ -1559,7 +1560,7 @@ static void iucv_external_interrupt(u16 code) struct iucv_irq_data *p; struct iucv_irq_list *work; - p = percpu_ptr(iucv_irq_data, smp_processor_id()); + p = iucv_irq_data[smp_processor_id()]; if (p->ippathid >= iucv_max_pathid) { printk(KERN_WARNING "iucv_do_int: Got interrupt with " "pathid %d > max_connections (%ld)\n", @@ -1598,6 +1599,7 @@ static void iucv_external_interrupt(u16 code) static int __init iucv_init(void) { int rc; + int cpu; if (!MACHINE_IS_VM) { rc = -EPROTONOSUPPORT; @@ -1617,19 +1619,23 @@ static int __init iucv_init(void) rc = PTR_ERR(iucv_root); goto out_bus; } - /* Note: GFP_DMA used to get memory below 2G */ - iucv_irq_data = percpu_alloc(sizeof(struct iucv_irq_data), - GFP_KERNEL|GFP_DMA); - if (!iucv_irq_data) { - rc = -ENOMEM; - goto out_root; - } - /* Allocate parameter blocks. */ - iucv_param = percpu_alloc(sizeof(union iucv_param), - GFP_KERNEL|GFP_DMA); - if (!iucv_param) { - rc = -ENOMEM; - goto out_extint; + + for_each_online_cpu(cpu) { + /* Note: GFP_DMA used to get memory below 2G */ + iucv_irq_data[cpu] = kmalloc_node(sizeof(struct iucv_irq_data), + GFP_KERNEL|GFP_DMA, cpu_to_node(cpu)); + if (!iucv_irq_data[cpu]) { + rc = -ENOMEM; + goto out_free; + } + + /* Allocate parameter blocks. */ + iucv_param[cpu] = kmalloc_node(sizeof(union iucv_param), + GFP_KERNEL|GFP_DMA, cpu_to_node(cpu)); + if (!iucv_param[cpu]) { + rc = -ENOMEM; + goto out_free; + } } register_hotcpu_notifier(&iucv_cpu_notifier); ASCEBC(iucv_error_no_listener, 16); @@ -1638,9 +1644,13 @@ static int __init iucv_init(void) iucv_available = 1; return 0; -out_extint: - percpu_free(iucv_irq_data); -out_root: +out_free: + for_each_possible_cpu(cpu) { + kfree(iucv_param[cpu]); + iucv_param[cpu] = NULL; + kfree(iucv_irq_data[cpu]); + iucv_irq_data[cpu] = NULL; + } s390_root_dev_unregister(iucv_root); out_bus: bus_unregister(&iucv_bus); @@ -1658,6 +1668,7 @@ out: static void __exit iucv_exit(void) { struct iucv_irq_list *p, *n; + int cpu; spin_lock_irq(&iucv_queue_lock); list_for_each_entry_safe(p, n, &iucv_task_queue, list) @@ -1666,8 +1677,12 @@ static void __exit iucv_exit(void) kfree(p); spin_unlock_irq(&iucv_queue_lock); unregister_hotcpu_notifier(&iucv_cpu_notifier); - percpu_free(iucv_param); - percpu_free(iucv_irq_data); + for_each_possible_cpu(cpu) { + kfree(iucv_param[cpu]); + iucv_param[cpu] = NULL; + kfree(iucv_irq_data[cpu]); + iucv_irq_data[cpu] = NULL; + } s390_root_dev_unregister(iucv_root); bus_unregister(&iucv_bus); unregister_external_interrupt(0x4000, iucv_external_interrupt); diff --git a/net/key/af_key.c b/net/key/af_key.c index 10c89d4..878039b 100644 --- a/net/key/af_key.c +++ b/net/key/af_key.c @@ -1015,9 +1015,7 @@ static inline struct sk_buff *pfkey_xfrm_state2msg(struct xfrm_state *x) { struct sk_buff *skb; - spin_lock_bh(&x->lock); skb = __pfkey_xfrm_state2msg(x, 1, 3); - spin_unlock_bh(&x->lock); return skb; } @@ -1552,7 +1550,7 @@ static int pfkey_get(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hdr, out_hdr = (struct sadb_msg *) out_skb->data; out_hdr->sadb_msg_version = hdr->sadb_msg_version; - out_hdr->sadb_msg_type = SADB_DUMP; + out_hdr->sadb_msg_type = SADB_GET; out_hdr->sadb_msg_satype = pfkey_proto2satype(proto); out_hdr->sadb_msg_errno = 0; out_hdr->sadb_msg_reserved = 0; diff --git a/net/mac80211/Kconfig b/net/mac80211/Kconfig index 6fffb38..ce176e6 100644 --- a/net/mac80211/Kconfig +++ b/net/mac80211/Kconfig @@ -13,6 +13,18 @@ config MAC80211 This option enables the hardware independent IEEE 802.11 networking stack. +config MAC80211_RCSIMPLE + bool "'simple' rate control algorithm" if EMBEDDED + default y + depends on MAC80211 + help + This option allows you to turn off the 'simple' rate + control algorithm in mac80211. If you do turn it off, + you absolutely need another rate control algorithm. + + Say Y unless you know you will have another algorithm + available. + config MAC80211_LEDS bool "Enable LED triggers" depends on MAC80211 && LEDS_TRIGGERS diff --git a/net/mac80211/Makefile b/net/mac80211/Makefile index 219cd9f..1e6237b 100644 --- a/net/mac80211/Makefile +++ b/net/mac80211/Makefile @@ -1,8 +1,9 @@ -obj-$(CONFIG_MAC80211) += mac80211.o rc80211_simple.o +obj-$(CONFIG_MAC80211) += mac80211.o mac80211-objs-$(CONFIG_MAC80211_LEDS) += ieee80211_led.o mac80211-objs-$(CONFIG_MAC80211_DEBUGFS) += debugfs.o debugfs_sta.o debugfs_netdev.o debugfs_key.o mac80211-objs-$(CONFIG_NET_SCHED) += wme.o +mac80211-objs-$(CONFIG_MAC80211_RCSIMPLE) += rc80211_simple.o mac80211-objs := \ ieee80211.o \ diff --git a/net/mac80211/ieee80211.c b/net/mac80211/ieee80211.c index f484ca7..505af1f 100644 --- a/net/mac80211/ieee80211.c +++ b/net/mac80211/ieee80211.c @@ -216,6 +216,7 @@ static int ieee80211_open(struct net_device *dev) res = local->ops->start(local_to_hw(local)); if (res) return res; + ieee80211_hw_config(local); } switch (sdata->type) { @@ -232,7 +233,6 @@ static int ieee80211_open(struct net_device *dev) netif_tx_unlock_bh(local->mdev); local->hw.conf.flags |= IEEE80211_CONF_RADIOTAP; - ieee80211_hw_config(local); } break; case IEEE80211_IF_TYPE_STA: @@ -267,6 +267,17 @@ static int ieee80211_open(struct net_device *dev) tasklet_enable(&local->tasklet); } + /* + * set_multicast_list will be invoked by the networking core + * which will check whether any increments here were done in + * error and sync them down to the hardware as filter flags. + */ + if (sdata->flags & IEEE80211_SDATA_ALLMULTI) + atomic_inc(&local->iff_allmultis); + + if (sdata->flags & IEEE80211_SDATA_PROMISC) + atomic_inc(&local->iff_promiscs); + local->open_count++; netif_start_queue(dev); @@ -284,6 +295,18 @@ static int ieee80211_stop(struct net_device *dev) netif_stop_queue(dev); + /* + * Don't count this interface for promisc/allmulti while it + * is down. dev_mc_unsync() will invoke set_multicast_list + * on the master interface which will sync these down to the + * hardware as filter flags. + */ + if (sdata->flags & IEEE80211_SDATA_ALLMULTI) + atomic_dec(&local->iff_allmultis); + + if (sdata->flags & IEEE80211_SDATA_PROMISC) + atomic_dec(&local->iff_promiscs); + dev_mc_unsync(local->mdev, dev); /* down all dependent devices, that is VLANs */ @@ -311,8 +334,7 @@ static int ieee80211_stop(struct net_device *dev) ieee80211_configure_filter(local); netif_tx_unlock_bh(local->mdev); - local->hw.conf.flags |= IEEE80211_CONF_RADIOTAP; - ieee80211_hw_config(local); + local->hw.conf.flags &= ~IEEE80211_CONF_RADIOTAP; } break; case IEEE80211_IF_TYPE_STA: @@ -334,6 +356,11 @@ static int ieee80211_stop(struct net_device *dev) cancel_delayed_work(&local->scan_work); } flush_workqueue(local->hw.workqueue); + + sdata->u.sta.flags &= ~IEEE80211_STA_PRIVACY_INVOKED; + kfree(sdata->u.sta.extra_ie); + sdata->u.sta.extra_ie = NULL; + sdata->u.sta.extra_ie_len = 0; /* fall through */ default: conf.if_id = dev->ifindex; @@ -366,8 +393,8 @@ static void ieee80211_set_multicast_list(struct net_device *dev) allmulti = !!(dev->flags & IFF_ALLMULTI); promisc = !!(dev->flags & IFF_PROMISC); - sdata_allmulti = sdata->flags & IEEE80211_SDATA_ALLMULTI; - sdata_promisc = sdata->flags & IEEE80211_SDATA_PROMISC; + sdata_allmulti = !!(sdata->flags & IEEE80211_SDATA_ALLMULTI); + sdata_promisc = !!(sdata->flags & IEEE80211_SDATA_PROMISC); if (allmulti != sdata_allmulti) { if (dev->flags & IFF_ALLMULTI) @@ -1072,7 +1099,8 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) ieee80211_debugfs_add_netdev(IEEE80211_DEV_TO_SUB_IF(local->mdev)); ieee80211_if_set_type(local->mdev, IEEE80211_IF_TYPE_AP); - result = ieee80211_init_rate_ctrl_alg(local, NULL); + result = ieee80211_init_rate_ctrl_alg(local, + hw->rate_control_algorithm); if (result < 0) { printk(KERN_DEBUG "%s: Failed to initialize rate control " "algorithm\n", wiphy_name(local->hw.wiphy)); @@ -1233,8 +1261,17 @@ static int __init ieee80211_init(void) BUILD_BUG_ON(sizeof(struct ieee80211_tx_packet_data) > sizeof(skb->cb)); +#ifdef CONFIG_MAC80211_RCSIMPLE + ret = ieee80211_rate_control_register(&mac80211_rcsimple); + if (ret) + return ret; +#endif + ret = ieee80211_wme_register(); if (ret) { +#ifdef CONFIG_MAC80211_RCSIMPLE + ieee80211_rate_control_unregister(&mac80211_rcsimple); +#endif printk(KERN_DEBUG "ieee80211_init: failed to " "initialize WME (err=%d)\n", ret); return ret; @@ -1248,6 +1285,10 @@ static int __init ieee80211_init(void) static void __exit ieee80211_exit(void) { +#ifdef CONFIG_MAC80211_RCSIMPLE + ieee80211_rate_control_unregister(&mac80211_rcsimple); +#endif + ieee80211_wme_unregister(); ieee80211_debugfs_netdev_exit(); } diff --git a/net/mac80211/ieee80211_common.h b/net/mac80211/ieee80211_common.h deleted file mode 100644 index c15295d..0000000 --- a/net/mac80211/ieee80211_common.h +++ /dev/null @@ -1,91 +0,0 @@ -/* - * IEEE 802.11 driver (80211.o) -- hostapd interface - * Copyright 2002-2004, Instant802 Networks, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#ifndef IEEE80211_COMMON_H -#define IEEE80211_COMMON_H - -#include <linux/types.h> - -/* - * This is common header information with user space. It is used on all - * frames sent to wlan#ap interface. - */ - -#define IEEE80211_FI_VERSION 0x80211001 - -struct ieee80211_frame_info { - __be32 version; - __be32 length; - __be64 mactime; - __be64 hosttime; - __be32 phytype; - __be32 channel; - __be32 datarate; - __be32 antenna; - __be32 priority; - __be32 ssi_type; - __be32 ssi_signal; - __be32 ssi_noise; - __be32 preamble; - __be32 encoding; - - /* Note: this structure is otherwise identical to capture format used - * in linux-wlan-ng, but this additional field is used to provide meta - * data about the frame to hostapd. This was the easiest method for - * providing this information, but this might change in the future. */ - __be32 msg_type; -} __attribute__ ((packed)); - - -enum ieee80211_msg_type { - ieee80211_msg_normal = 0, - ieee80211_msg_tx_callback_ack = 1, - ieee80211_msg_tx_callback_fail = 2, - /* hole at 3, was ieee80211_msg_passive_scan but unused */ - /* hole at 4, was ieee80211_msg_wep_frame_unknown_key but now unused */ - ieee80211_msg_michael_mic_failure = 5, - /* hole at 6, was monitor but never sent to userspace */ - ieee80211_msg_sta_not_assoc = 7, - /* 8 was ieee80211_msg_set_aid_for_sta */ - /* 9 was ieee80211_msg_key_threshold_notification */ - /* 11 was ieee80211_msg_radar */ -}; - -struct ieee80211_msg_key_notification { - int tx_rx_count; - char ifname[IFNAMSIZ]; - u8 addr[ETH_ALEN]; /* ff:ff:ff:ff:ff:ff for broadcast keys */ -}; - - -enum ieee80211_phytype { - ieee80211_phytype_fhss_dot11_97 = 1, - ieee80211_phytype_dsss_dot11_97 = 2, - ieee80211_phytype_irbaseband = 3, - ieee80211_phytype_dsss_dot11_b = 4, - ieee80211_phytype_pbcc_dot11_b = 5, - ieee80211_phytype_ofdm_dot11_g = 6, - ieee80211_phytype_pbcc_dot11_g = 7, - ieee80211_phytype_ofdm_dot11_a = 8, -}; - -enum ieee80211_ssi_type { - ieee80211_ssi_none = 0, - ieee80211_ssi_norm = 1, /* normalized, 0-1000 */ - ieee80211_ssi_dbm = 2, - ieee80211_ssi_raw = 3, /* raw SSI */ -}; - -struct ieee80211_radar_info { - int channel; - int radar; - int radar_type; -}; - -#endif /* IEEE80211_COMMON_H */ diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 4b4ed2a..72e1c93 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -230,6 +230,7 @@ struct ieee80211_if_vlan { #define IEEE80211_STA_AUTO_SSID_SEL BIT(10) #define IEEE80211_STA_AUTO_BSSID_SEL BIT(11) #define IEEE80211_STA_AUTO_CHANNEL_SEL BIT(12) +#define IEEE80211_STA_PRIVACY_INVOKED BIT(13) struct ieee80211_if_sta { enum { IEEE80211_DISABLED, IEEE80211_AUTHENTICATE, @@ -241,6 +242,8 @@ struct ieee80211_if_sta { u8 bssid[ETH_ALEN], prev_bssid[ETH_ALEN]; u8 ssid[IEEE80211_MAX_SSID_LEN]; size_t ssid_len; + u8 scan_ssid[IEEE80211_MAX_SSID_LEN]; + size_t scan_ssid_len; u16 aid; u16 ap_capab, capab; u8 *extra_ie; /* to be added to the end of AssocReq */ @@ -259,7 +262,6 @@ struct ieee80211_if_sta { unsigned long request; struct sk_buff_head skb_queue; - int key_management_enabled; unsigned long last_probe; #define IEEE80211_AUTH_ALG_OPEN BIT(0) diff --git a/net/mac80211/ieee80211_ioctl.c b/net/mac80211/ieee80211_ioctl.c index 6caa3ec..7027eed 100644 --- a/net/mac80211/ieee80211_ioctl.c +++ b/net/mac80211/ieee80211_ioctl.c @@ -917,7 +917,6 @@ static int ieee80211_ioctl_siwauth(struct net_device *dev, struct iw_request_info *info, struct iw_param *data, char *extra) { - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); int ret = 0; @@ -927,18 +926,21 @@ static int ieee80211_ioctl_siwauth(struct net_device *dev, case IW_AUTH_CIPHER_GROUP: case IW_AUTH_WPA_ENABLED: case IW_AUTH_RX_UNENCRYPTED_EAPOL: - break; case IW_AUTH_KEY_MGMT: + break; + case IW_AUTH_PRIVACY_INVOKED: if (sdata->type != IEEE80211_IF_TYPE_STA) ret = -EINVAL; else { + sdata->u.sta.flags &= ~IEEE80211_STA_PRIVACY_INVOKED; /* - * Key management was set by wpa_supplicant, - * we only need this to associate to a network - * that has privacy enabled regardless of not - * having a key. + * Privacy invoked by wpa_supplicant, store the + * value and allow associating to a protected + * network without having a key up front. */ - sdata->u.sta.key_management_enabled = !!data->value; + if (data->value) + sdata->u.sta.flags |= + IEEE80211_STA_PRIVACY_INVOKED; } break; case IW_AUTH_80211_AUTH_ALG: @@ -948,11 +950,6 @@ static int ieee80211_ioctl_siwauth(struct net_device *dev, else ret = -EOPNOTSUPP; break; - case IW_AUTH_PRIVACY_INVOKED: - if (local->ops->set_privacy_invoked) - ret = local->ops->set_privacy_invoked( - local_to_hw(local), data->value); - break; default: ret = -EOPNOTSUPP; break; diff --git a/net/mac80211/ieee80211_rate.c b/net/mac80211/ieee80211_rate.c index 93abb8f..7254bd6 100644 --- a/net/mac80211/ieee80211_rate.c +++ b/net/mac80211/ieee80211_rate.c @@ -25,13 +25,25 @@ int ieee80211_rate_control_register(struct rate_control_ops *ops) { struct rate_control_alg *alg; + if (!ops->name) + return -EINVAL; + + mutex_lock(&rate_ctrl_mutex); + list_for_each_entry(alg, &rate_ctrl_algs, list) { + if (!strcmp(alg->ops->name, ops->name)) { + /* don't register an algorithm twice */ + WARN_ON(1); + return -EALREADY; + } + } + alg = kzalloc(sizeof(*alg), GFP_KERNEL); if (alg == NULL) { + mutex_unlock(&rate_ctrl_mutex); return -ENOMEM; } alg->ops = ops; - mutex_lock(&rate_ctrl_mutex); list_add_tail(&alg->list, &rate_ctrl_algs); mutex_unlock(&rate_ctrl_mutex); @@ -61,9 +73,12 @@ ieee80211_try_rate_control_ops_get(const char *name) struct rate_control_alg *alg; struct rate_control_ops *ops = NULL; + if (!name) + return NULL; + mutex_lock(&rate_ctrl_mutex); list_for_each_entry(alg, &rate_ctrl_algs, list) { - if (!name || !strcmp(alg->ops->name, name)) + if (!strcmp(alg->ops->name, name)) if (try_module_get(alg->ops->module)) { ops = alg->ops; break; @@ -80,9 +95,12 @@ ieee80211_rate_control_ops_get(const char *name) { struct rate_control_ops *ops; + if (!name) + name = "simple"; + ops = ieee80211_try_rate_control_ops_get(name); if (!ops) { - request_module("rc80211_%s", name ? name : "default"); + request_module("rc80211_%s", name); ops = ieee80211_try_rate_control_ops_get(name); } return ops; diff --git a/net/mac80211/ieee80211_rate.h b/net/mac80211/ieee80211_rate.h index 7cd1eba..2368813 100644 --- a/net/mac80211/ieee80211_rate.h +++ b/net/mac80211/ieee80211_rate.h @@ -65,6 +65,9 @@ struct rate_control_ref { struct kref kref; }; +/* default 'simple' algorithm */ +extern struct rate_control_ops mac80211_rcsimple; + int ieee80211_rate_control_register(struct rate_control_ops *ops); void ieee80211_rate_control_unregister(struct rate_control_ops *ops); diff --git a/net/mac80211/ieee80211_sta.c b/net/mac80211/ieee80211_sta.c index fda0e06..16afd24 100644 --- a/net/mac80211/ieee80211_sta.c +++ b/net/mac80211/ieee80211_sta.c @@ -704,10 +704,11 @@ static int ieee80211_privacy_mismatch(struct net_device *dev, { struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); struct ieee80211_sta_bss *bss; - int res = 0; + int bss_privacy; + int wep_privacy; + int privacy_invoked; - if (!ifsta || (ifsta->flags & IEEE80211_STA_MIXED_CELL) || - ifsta->key_management_enabled) + if (!ifsta || (ifsta->flags & IEEE80211_STA_MIXED_CELL)) return 0; bss = ieee80211_rx_bss_get(dev, ifsta->bssid, local->hw.conf.channel, @@ -715,13 +716,16 @@ static int ieee80211_privacy_mismatch(struct net_device *dev, if (!bss) return 0; - if (ieee80211_sta_wep_configured(dev) != - !!(bss->capability & WLAN_CAPABILITY_PRIVACY)) - res = 1; + bss_privacy = !!(bss->capability & WLAN_CAPABILITY_PRIVACY); + wep_privacy = !!ieee80211_sta_wep_configured(dev); + privacy_invoked = !!(ifsta->flags & IEEE80211_STA_PRIVACY_INVOKED); ieee80211_rx_bss_put(dev, bss); - return res; + if ((bss_privacy == wep_privacy) || (bss_privacy == privacy_invoked)) + return 0; + + return 1; } @@ -1998,7 +2002,10 @@ void ieee80211_sta_work(struct work_struct *work) if (ifsta->state != IEEE80211_AUTHENTICATE && ifsta->state != IEEE80211_ASSOCIATE && test_and_clear_bit(IEEE80211_STA_REQ_SCAN, &ifsta->request)) { - ieee80211_sta_start_scan(dev, NULL, 0); + if (ifsta->scan_ssid_len) + ieee80211_sta_start_scan(dev, ifsta->scan_ssid, ifsta->scan_ssid_len); + else + ieee80211_sta_start_scan(dev, NULL, 0); return; } @@ -2640,7 +2647,7 @@ void ieee80211_scan_completed(struct ieee80211_hw *hw) local->sta_scanning = 0; if (ieee80211_hw_config(local)) - printk(KERN_DEBUG "%s: failed to restore operational" + printk(KERN_DEBUG "%s: failed to restore operational " "channel after scan\n", dev->name); @@ -2868,6 +2875,9 @@ int ieee80211_sta_req_scan(struct net_device *dev, u8 *ssid, size_t ssid_len) return -EBUSY; } + ifsta->scan_ssid_len = ssid_len; + if (ssid_len) + memcpy(ifsta->scan_ssid, ssid, ssid_len); set_bit(IEEE80211_STA_REQ_SCAN, &ifsta->request); queue_work(local->hw.workqueue, &ifsta->work); return 0; diff --git a/net/mac80211/rc80211_simple.c b/net/mac80211/rc80211_simple.c index 314b8de..da72737 100644 --- a/net/mac80211/rc80211_simple.c +++ b/net/mac80211/rc80211_simple.c @@ -7,7 +7,6 @@ * published by the Free Software Foundation. */ -#include <linux/module.h> #include <linux/init.h> #include <linux/netdevice.h> #include <linux/types.h> @@ -29,8 +28,6 @@ #define RATE_CONTROL_INTERVAL (HZ / 20) #define RATE_CONTROL_MIN_TX 10 -MODULE_ALIAS("rc80211_default"); - static void rate_control_rate_inc(struct ieee80211_local *local, struct sta_info *sta) { @@ -394,8 +391,7 @@ static void rate_control_simple_remove_sta_debugfs(void *priv, void *priv_sta) } #endif -static struct rate_control_ops rate_control_simple = { - .module = THIS_MODULE, +struct rate_control_ops mac80211_rcsimple = { .name = "simple", .tx_status = rate_control_simple_tx_status, .get_rate = rate_control_simple_get_rate, @@ -410,22 +406,3 @@ static struct rate_control_ops rate_control_simple = { .remove_sta_debugfs = rate_control_simple_remove_sta_debugfs, #endif }; - - -static int __init rate_control_simple_init(void) -{ - return ieee80211_rate_control_register(&rate_control_simple); -} - - -static void __exit rate_control_simple_exit(void) -{ - ieee80211_rate_control_unregister(&rate_control_simple); -} - - -subsys_initcall(rate_control_simple_init); -module_exit(rate_control_simple_exit); - -MODULE_DESCRIPTION("Simple rate control algorithm for ieee80211"); -MODULE_LICENSE("GPL"); diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index ece7776..00f908d 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -509,9 +509,11 @@ ieee80211_rx_h_decrypt(struct ieee80211_txrx_data *rx) rx->key->tx_rx_count++; /* TODO: add threshold stuff again */ } else { +#ifdef CONFIG_MAC80211_DEBUG if (net_ratelimit()) printk(KERN_DEBUG "%s: RX protected frame," " but have no key\n", rx->dev->name); +#endif /* CONFIG_MAC80211_DEBUG */ return TXRX_DROP; } @@ -995,7 +997,7 @@ ieee80211_rx_h_drop_unencrypted(struct ieee80211_txrx_data *rx) if (unlikely(!(rx->fc & IEEE80211_FCTL_PROTECTED) && (rx->fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA && (rx->fc & IEEE80211_FCTL_STYPE) != IEEE80211_STYPE_NULLFUNC && - rx->sdata->drop_unencrypted && + (rx->key || rx->sdata->drop_unencrypted) && (rx->sdata->eapol == 0 || !ieee80211_is_eapol(rx->skb)))) { if (net_ratelimit()) printk(KERN_DEBUG "%s: RX non-WEP frame, but expected " diff --git a/net/mac80211/wep.c b/net/mac80211/wep.c index a84a233..b5f3413 100644 --- a/net/mac80211/wep.c +++ b/net/mac80211/wep.c @@ -265,7 +265,8 @@ int ieee80211_wep_decrypt(struct ieee80211_local *local, struct sk_buff *skb, if (ieee80211_wep_decrypt_data(local->wep_rx_tfm, rc4key, klen, skb->data + hdrlen + WEP_IV_LEN, len)) { - printk(KERN_DEBUG "WEP decrypt failed (ICV)\n"); + if (net_ratelimit()) + printk(KERN_DEBUG "WEP decrypt failed (ICV)\n"); ret = -1; } @@ -314,9 +315,11 @@ ieee80211_crypto_wep_decrypt(struct ieee80211_txrx_data *rx) if (!(rx->u.rx.status->flag & RX_FLAG_DECRYPTED)) { if (ieee80211_wep_decrypt(rx->local, rx->skb, rx->key)) { +#ifdef CONFIG_MAC80211_DEBUG if (net_ratelimit()) printk(KERN_DEBUG "%s: RX WEP frame, decrypt " "failed\n", rx->dev->name); +#endif /* CONFIG_MAC80211_DEBUG */ return TXRX_DROP; } } else if (!(rx->u.rx.status->flag & RX_FLAG_IV_STRIPPED)) { diff --git a/net/mac80211/wpa.c b/net/mac80211/wpa.c index 6695efb..20cec1c 100644 --- a/net/mac80211/wpa.c +++ b/net/mac80211/wpa.c @@ -323,9 +323,12 @@ ieee80211_crypto_tkip_decrypt(struct ieee80211_txrx_data *rx) &rx->u.rx.tkip_iv32, &rx->u.rx.tkip_iv16); if (res != TKIP_DECRYPT_OK || wpa_test) { - printk(KERN_DEBUG "%s: TKIP decrypt failed for RX frame from " - "%s (res=%d)\n", - rx->dev->name, print_mac(mac, rx->sta->addr), res); +#ifdef CONFIG_MAC80211_DEBUG + if (net_ratelimit()) + printk(KERN_DEBUG "%s: TKIP decrypt failed for RX " + "frame from %s (res=%d)\n", rx->dev->name, + print_mac(mac, rx->sta->addr), res); +#endif /* CONFIG_MAC80211_DEBUG */ return TXRX_DROP; } @@ -594,9 +597,12 @@ ieee80211_crypto_ccmp_decrypt(struct ieee80211_txrx_data *rx) skb->data + hdrlen + CCMP_HDR_LEN, data_len, skb->data + skb->len - CCMP_MIC_LEN, skb->data + hdrlen + CCMP_HDR_LEN)) { - printk(KERN_DEBUG "%s: CCMP decrypt failed for RX " - "frame from %s\n", rx->dev->name, - print_mac(mac, rx->sta->addr)); +#ifdef CONFIG_MAC80211_DEBUG + if (net_ratelimit()) + printk(KERN_DEBUG "%s: CCMP decrypt failed " + "for RX frame from %s\n", rx->dev->name, + print_mac(mac, rx->sta->addr)); +#endif /* CONFIG_MAC80211_DEBUG */ return TXRX_DROP; } } diff --git a/net/netfilter/Makefile b/net/netfilter/Makefile index 93c58f9..ad0e36e 100644 --- a/net/netfilter/Makefile +++ b/net/netfilter/Makefile @@ -40,15 +40,15 @@ obj-$(CONFIG_NETFILTER_XTABLES) += x_tables.o xt_tcpudp.o # targets obj-$(CONFIG_NETFILTER_XT_TARGET_CLASSIFY) += xt_CLASSIFY.o obj-$(CONFIG_NETFILTER_XT_TARGET_CONNMARK) += xt_CONNMARK.o +obj-$(CONFIG_NETFILTER_XT_TARGET_CONNSECMARK) += xt_CONNSECMARK.o obj-$(CONFIG_NETFILTER_XT_TARGET_DSCP) += xt_DSCP.o obj-$(CONFIG_NETFILTER_XT_TARGET_MARK) += xt_MARK.o -obj-$(CONFIG_NETFILTER_XT_TARGET_NFQUEUE) += xt_NFQUEUE.o obj-$(CONFIG_NETFILTER_XT_TARGET_NFLOG) += xt_NFLOG.o +obj-$(CONFIG_NETFILTER_XT_TARGET_NFQUEUE) += xt_NFQUEUE.o obj-$(CONFIG_NETFILTER_XT_TARGET_NOTRACK) += xt_NOTRACK.o -obj-$(CONFIG_NETFILTER_XT_TARGET_TRACE) += xt_TRACE.o obj-$(CONFIG_NETFILTER_XT_TARGET_SECMARK) += xt_SECMARK.o obj-$(CONFIG_NETFILTER_XT_TARGET_TCPMSS) += xt_TCPMSS.o -obj-$(CONFIG_NETFILTER_XT_TARGET_CONNSECMARK) += xt_CONNSECMARK.o +obj-$(CONFIG_NETFILTER_XT_TARGET_TRACE) += xt_TRACE.o # matches obj-$(CONFIG_NETFILTER_XT_MATCH_COMMENT) += xt_comment.o @@ -59,22 +59,22 @@ obj-$(CONFIG_NETFILTER_XT_MATCH_CONNTRACK) += xt_conntrack.o obj-$(CONFIG_NETFILTER_XT_MATCH_DCCP) += xt_dccp.o obj-$(CONFIG_NETFILTER_XT_MATCH_DSCP) += xt_dscp.o obj-$(CONFIG_NETFILTER_XT_MATCH_ESP) += xt_esp.o +obj-$(CONFIG_NETFILTER_XT_MATCH_HASHLIMIT) += xt_hashlimit.o obj-$(CONFIG_NETFILTER_XT_MATCH_HELPER) += xt_helper.o obj-$(CONFIG_NETFILTER_XT_MATCH_LENGTH) += xt_length.o obj-$(CONFIG_NETFILTER_XT_MATCH_LIMIT) += xt_limit.o obj-$(CONFIG_NETFILTER_XT_MATCH_MAC) += xt_mac.o obj-$(CONFIG_NETFILTER_XT_MATCH_MARK) += xt_mark.o obj-$(CONFIG_NETFILTER_XT_MATCH_MULTIPORT) += xt_multiport.o -obj-$(CONFIG_NETFILTER_XT_MATCH_POLICY) += xt_policy.o +obj-$(CONFIG_NETFILTER_XT_MATCH_PHYSDEV) += xt_physdev.o obj-$(CONFIG_NETFILTER_XT_MATCH_PKTTYPE) += xt_pkttype.o +obj-$(CONFIG_NETFILTER_XT_MATCH_POLICY) += xt_policy.o obj-$(CONFIG_NETFILTER_XT_MATCH_QUOTA) += xt_quota.o obj-$(CONFIG_NETFILTER_XT_MATCH_REALM) += xt_realm.o obj-$(CONFIG_NETFILTER_XT_MATCH_SCTP) += xt_sctp.o obj-$(CONFIG_NETFILTER_XT_MATCH_STATE) += xt_state.o obj-$(CONFIG_NETFILTER_XT_MATCH_STATISTIC) += xt_statistic.o obj-$(CONFIG_NETFILTER_XT_MATCH_STRING) += xt_string.o -obj-$(CONFIG_NETFILTER_XT_MATCH_TIME) += xt_time.o obj-$(CONFIG_NETFILTER_XT_MATCH_TCPMSS) += xt_tcpmss.o -obj-$(CONFIG_NETFILTER_XT_MATCH_PHYSDEV) += xt_physdev.o +obj-$(CONFIG_NETFILTER_XT_MATCH_TIME) += xt_time.o obj-$(CONFIG_NETFILTER_XT_MATCH_U32) += xt_u32.o -obj-$(CONFIG_NETFILTER_XT_MATCH_HASHLIMIT) += xt_hashlimit.o diff --git a/net/netfilter/nf_conntrack_extend.c b/net/netfilter/nf_conntrack_extend.c index a1a65a1..cf6ba66 100644 --- a/net/netfilter/nf_conntrack_extend.c +++ b/net/netfilter/nf_conntrack_extend.c @@ -109,7 +109,7 @@ void *__nf_ct_ext_add(struct nf_conn *ct, enum nf_ct_ext_id id, gfp_t gfp) rcu_read_lock(); t = rcu_dereference(nf_ct_ext_types[i]); if (t && t->move) - t->move(ct, ct->ext + ct->ext->offset[id]); + t->move(ct, ct->ext + ct->ext->offset[i]); rcu_read_unlock(); } kfree(ct->ext); diff --git a/net/netfilter/nf_sockopt.c b/net/netfilter/nf_sockopt.c index aa28315..3dd4b3c 100644 --- a/net/netfilter/nf_sockopt.c +++ b/net/netfilter/nf_sockopt.c @@ -23,14 +23,13 @@ static inline int overlap(int min1, int max1, int min2, int max2) /* Functions to register sockopt ranges (exclusive). */ int nf_register_sockopt(struct nf_sockopt_ops *reg) { - struct list_head *i; + struct nf_sockopt_ops *ops; int ret = 0; if (mutex_lock_interruptible(&nf_sockopt_mutex) != 0) return -EINTR; - list_for_each(i, &nf_sockopts) { - struct nf_sockopt_ops *ops = (struct nf_sockopt_ops *)i; + list_for_each_entry(ops, &nf_sockopts, list) { if (ops->pf == reg->pf && (overlap(ops->set_optmin, ops->set_optmax, reg->set_optmin, reg->set_optmax) @@ -61,48 +60,57 @@ void nf_unregister_sockopt(struct nf_sockopt_ops *reg) } EXPORT_SYMBOL(nf_unregister_sockopt); -/* Call get/setsockopt() */ -static int nf_sockopt(struct sock *sk, int pf, int val, - char __user *opt, int *len, int get) +static struct nf_sockopt_ops *nf_sockopt_find(struct sock *sk, int pf, + int val, int get) { - struct list_head *i; struct nf_sockopt_ops *ops; - int ret; if (sk->sk_net != &init_net) - return -ENOPROTOOPT; + return ERR_PTR(-ENOPROTOOPT); if (mutex_lock_interruptible(&nf_sockopt_mutex) != 0) - return -EINTR; + return ERR_PTR(-EINTR); - list_for_each(i, &nf_sockopts) { - ops = (struct nf_sockopt_ops *)i; + list_for_each_entry(ops, &nf_sockopts, list) { if (ops->pf == pf) { if (!try_module_get(ops->owner)) goto out_nosup; + if (get) { - if (val >= ops->get_optmin - && val < ops->get_optmax) { - mutex_unlock(&nf_sockopt_mutex); - ret = ops->get(sk, val, opt, len); + if (val >= ops->get_optmin && + val < ops->get_optmax) goto out; - } } else { - if (val >= ops->set_optmin - && val < ops->set_optmax) { - mutex_unlock(&nf_sockopt_mutex); - ret = ops->set(sk, val, opt, *len); + if (val >= ops->set_optmin && + val < ops->set_optmax) goto out; - } } module_put(ops->owner); } } - out_nosup: +out_nosup: + ops = ERR_PTR(-ENOPROTOOPT); +out: mutex_unlock(&nf_sockopt_mutex); - return -ENOPROTOOPT; + return ops; +} + +/* Call get/setsockopt() */ +static int nf_sockopt(struct sock *sk, int pf, int val, + char __user *opt, int *len, int get) +{ + struct nf_sockopt_ops *ops; + int ret; + + ops = nf_sockopt_find(sk, pf, val, get); + if (IS_ERR(ops)) + return PTR_ERR(ops); + + if (get) + ret = ops->get(sk, val, opt, len); + else + ret = ops->set(sk, val, opt, *len); - out: module_put(ops->owner); return ret; } @@ -124,56 +132,25 @@ EXPORT_SYMBOL(nf_getsockopt); static int compat_nf_sockopt(struct sock *sk, int pf, int val, char __user *opt, int *len, int get) { - struct list_head *i; struct nf_sockopt_ops *ops; int ret; - if (sk->sk_net != &init_net) - return -ENOPROTOOPT; - - - if (mutex_lock_interruptible(&nf_sockopt_mutex) != 0) - return -EINTR; - - list_for_each(i, &nf_sockopts) { - ops = (struct nf_sockopt_ops *)i; - if (ops->pf == pf) { - if (!try_module_get(ops->owner)) - goto out_nosup; - - if (get) { - if (val >= ops->get_optmin - && val < ops->get_optmax) { - mutex_unlock(&nf_sockopt_mutex); - if (ops->compat_get) - ret = ops->compat_get(sk, - val, opt, len); - else - ret = ops->get(sk, - val, opt, len); - goto out; - } - } else { - if (val >= ops->set_optmin - && val < ops->set_optmax) { - mutex_unlock(&nf_sockopt_mutex); - if (ops->compat_set) - ret = ops->compat_set(sk, - val, opt, *len); - else - ret = ops->set(sk, - val, opt, *len); - goto out; - } - } - module_put(ops->owner); - } + ops = nf_sockopt_find(sk, pf, val, get); + if (IS_ERR(ops)) + return PTR_ERR(ops); + + if (get) { + if (ops->compat_get) + ret = ops->compat_get(sk, val, opt, len); + else + ret = ops->get(sk, val, opt, len); + } else { + if (ops->compat_set) + ret = ops->compat_set(sk, val, opt, *len); + else + ret = ops->set(sk, val, opt, *len); } - out_nosup: - mutex_unlock(&nf_sockopt_mutex); - return -ENOPROTOOPT; - out: module_put(ops->owner); return ret; } diff --git a/net/netfilter/xt_CONNMARK.c b/net/netfilter/xt_CONNMARK.c index 856793e..0621ca7 100644 --- a/net/netfilter/xt_CONNMARK.c +++ b/net/netfilter/xt_CONNMARK.c @@ -86,11 +86,6 @@ checkentry(const char *tablename, { const struct xt_connmark_target_info *matchinfo = targinfo; - if (nf_ct_l3proto_try_module_get(target->family) < 0) { - printk(KERN_WARNING "can't load conntrack support for " - "proto=%d\n", target->family); - return false; - } if (matchinfo->mode == XT_CONNMARK_RESTORE) { if (strcmp(tablename, "mangle") != 0) { printk(KERN_WARNING "CONNMARK: restore can only be " @@ -103,6 +98,11 @@ checkentry(const char *tablename, printk(KERN_WARNING "CONNMARK: Only supports 32bit mark\n"); return false; } + if (nf_ct_l3proto_try_module_get(target->family) < 0) { + printk(KERN_WARNING "can't load conntrack support for " + "proto=%d\n", target->family); + return false; + } return true; } diff --git a/net/netfilter/xt_CONNSECMARK.c b/net/netfilter/xt_CONNSECMARK.c index 021b5c8..d8feba9 100644 --- a/net/netfilter/xt_CONNSECMARK.c +++ b/net/netfilter/xt_CONNSECMARK.c @@ -90,11 +90,6 @@ static bool checkentry(const char *tablename, const void *entry, { const struct xt_connsecmark_target_info *info = targinfo; - if (nf_ct_l3proto_try_module_get(target->family) < 0) { - printk(KERN_WARNING "can't load conntrack support for " - "proto=%d\n", target->family); - return false; - } switch (info->mode) { case CONNSECMARK_SAVE: case CONNSECMARK_RESTORE: @@ -105,6 +100,11 @@ static bool checkentry(const char *tablename, const void *entry, return false; } + if (nf_ct_l3proto_try_module_get(target->family) < 0) { + printk(KERN_WARNING "can't load conntrack support for " + "proto=%d\n", target->family); + return false; + } return true; } diff --git a/net/netfilter/xt_TCPMSS.c b/net/netfilter/xt_TCPMSS.c index 07435a6..8e76d1f 100644 --- a/net/netfilter/xt_TCPMSS.c +++ b/net/netfilter/xt_TCPMSS.c @@ -174,10 +174,8 @@ xt_tcpmss_target6(struct sk_buff *skb, nexthdr = ipv6h->nexthdr; tcphoff = ipv6_skip_exthdr(skb, sizeof(*ipv6h), &nexthdr); - if (tcphoff < 0) { - WARN_ON(1); + if (tcphoff < 0) return NF_DROP; - } ret = tcpmss_mangle_packet(skb, targinfo, tcphoff, sizeof(*ipv6h) + sizeof(struct tcphdr)); if (ret < 0) diff --git a/net/netfilter/xt_connlimit.c b/net/netfilter/xt_connlimit.c index 06cff1d..d7becf0 100644 --- a/net/netfilter/xt_connlimit.c +++ b/net/netfilter/xt_connlimit.c @@ -4,7 +4,8 @@ * (c) 2000 Gerd Knorr <kraxel@bytesex.org> * Nov 2002: Martin Bene <martin.bene@icomedias.com>: * only ignore TIME_WAIT or gone connections - * Copyright © Jan Engelhardt <jengelh@gmx.de>, 2007 + * (C) CC Computer Consultants GmbH, 2007 + * Contact: <jengelh@computergmbh.de> * * based on ... * @@ -306,7 +307,7 @@ static void __exit xt_connlimit_exit(void) module_init(xt_connlimit_init); module_exit(xt_connlimit_exit); -MODULE_AUTHOR("Jan Engelhardt <jengelh@gmx.de>"); +MODULE_AUTHOR("Jan Engelhardt <jengelh@computergmbh.de>"); MODULE_DESCRIPTION("netfilter xt_connlimit match module"); MODULE_LICENSE("GPL"); MODULE_ALIAS("ipt_connlimit"); diff --git a/net/netfilter/xt_time.c b/net/netfilter/xt_time.c index ef48bbd..f9c55dc 100644 --- a/net/netfilter/xt_time.c +++ b/net/netfilter/xt_time.c @@ -1,6 +1,7 @@ /* * xt_time - * Copyright © Jan Engelhardt <jengelh@computergmbh.de>, 2007 + * Copyright © CC Computer Consultants GmbH, 2007 + * Contact: <jengelh@computergmbh.de> * * based on ipt_time by Fabrice MARIE <fabrice@netfilter.org> * This is a module which is used for time matching @@ -169,7 +170,7 @@ static bool xt_time_match(const struct sk_buff *skb, if (skb->tstamp.tv64 == 0) __net_timestamp((struct sk_buff *)skb); - stamp = skb->tstamp.tv64; + stamp = ktime_to_ns(skb->tstamp); do_div(stamp, NSEC_PER_SEC); if (info->flags & XT_TIME_LOCAL_TZ) diff --git a/net/netfilter/xt_u32.c b/net/netfilter/xt_u32.c index bec4279..af75b8c 100644 --- a/net/netfilter/xt_u32.c +++ b/net/netfilter/xt_u32.c @@ -2,7 +2,8 @@ * xt_u32 - kernel module to match u32 packet content * * Original author: Don Cohen <don@isis.cs3-inc.com> - * © Jan Engelhardt <jengelh@gmx.de>, 2007 + * (C) CC Computer Consultants GmbH, 2007 + * Contact: <jengelh@computergmbh.de> */ #include <linux/module.h> @@ -129,7 +130,7 @@ static void __exit xt_u32_exit(void) module_init(xt_u32_init); module_exit(xt_u32_exit); -MODULE_AUTHOR("Jan Engelhardt <jengelh@gmx.de>"); +MODULE_AUTHOR("Jan Engelhardt <jengelh@computergmbh.de>"); MODULE_DESCRIPTION("netfilter u32 match module"); MODULE_LICENSE("GPL"); MODULE_ALIAS("ipt_u32"); diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c index 2601712..de3988b 100644 --- a/net/netlink/af_netlink.c +++ b/net/netlink/af_netlink.c @@ -752,7 +752,7 @@ struct sock *netlink_getsockbyfilp(struct file *filp) * 1: repeat lookup - reference dropped while waiting for socket memory. */ int netlink_attachskb(struct sock *sk, struct sk_buff *skb, int nonblock, - long timeo, struct sock *ssk) + long *timeo, struct sock *ssk) { struct netlink_sock *nlk; @@ -761,7 +761,7 @@ int netlink_attachskb(struct sock *sk, struct sk_buff *skb, int nonblock, if (atomic_read(&sk->sk_rmem_alloc) > sk->sk_rcvbuf || test_bit(0, &nlk->state)) { DECLARE_WAITQUEUE(wait, current); - if (!timeo) { + if (!*timeo) { if (!ssk || netlink_is_kernel(ssk)) netlink_overrun(sk); sock_put(sk); @@ -775,7 +775,7 @@ int netlink_attachskb(struct sock *sk, struct sk_buff *skb, int nonblock, if ((atomic_read(&sk->sk_rmem_alloc) > sk->sk_rcvbuf || test_bit(0, &nlk->state)) && !sock_flag(sk, SOCK_DEAD)) - timeo = schedule_timeout(timeo); + *timeo = schedule_timeout(*timeo); __set_current_state(TASK_RUNNING); remove_wait_queue(&nlk->wait, &wait); @@ -783,7 +783,7 @@ int netlink_attachskb(struct sock *sk, struct sk_buff *skb, int nonblock, if (signal_pending(current)) { kfree_skb(skb); - return sock_intr_errno(timeo); + return sock_intr_errno(*timeo); } return 1; } @@ -877,7 +877,7 @@ retry: if (netlink_is_kernel(sk)) return netlink_unicast_kernel(sk, skb); - err = netlink_attachskb(sk, skb, nonblock, timeo, ssk); + err = netlink_attachskb(sk, skb, nonblock, &timeo, ssk); if (err == 1) goto retry; if (err) @@ -1888,7 +1888,7 @@ static void __net_exit netlink_net_exit(struct net *net) #endif } -static struct pernet_operations netlink_net_ops = { +static struct pernet_operations __net_initdata netlink_net_ops = { .init = netlink_net_init, .exit = netlink_net_exit, }; diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c index 4cb2dfb..8a7807d 100644 --- a/net/packet/af_packet.c +++ b/net/packet/af_packet.c @@ -139,9 +139,6 @@ dev->hard_header == NULL (ll header is added by device, we cannot control it) static HLIST_HEAD(packet_sklist); static DEFINE_RWLOCK(packet_sklist_lock); -static atomic_t packet_socks_nr; - - /* Private packet socket structures. */ struct packet_mclist @@ -236,10 +233,7 @@ static void packet_sock_destruct(struct sock *sk) return; } - atomic_dec(&packet_socks_nr); -#ifdef PACKET_REFCNT_DEBUG - printk(KERN_DEBUG "PACKET socket %p is free, %d are alive\n", sk, atomic_read(&packet_socks_nr)); -#endif + sk_refcnt_debug_dec(sk); } @@ -515,7 +509,7 @@ static int packet_rcv(struct sk_buff *skb, struct net_device *dev, struct packet sll->sll_hatype = dev->type; sll->sll_protocol = skb->protocol; sll->sll_pkttype = skb->pkt_type; - if (unlikely(po->origdev) && skb->pkt_type == PACKET_HOST) + if (unlikely(po->origdev)) sll->sll_ifindex = orig_dev->ifindex; else sll->sll_ifindex = dev->ifindex; @@ -661,7 +655,7 @@ static int tpacket_rcv(struct sk_buff *skb, struct net_device *dev, struct packe sll->sll_hatype = dev->type; sll->sll_protocol = skb->protocol; sll->sll_pkttype = skb->pkt_type; - if (unlikely(po->origdev) && skb->pkt_type == PACKET_HOST) + if (unlikely(po->origdev)) sll->sll_ifindex = orig_dev->ifindex; else sll->sll_ifindex = dev->ifindex; @@ -849,6 +843,7 @@ static int packet_release(struct socket *sock) /* Purge queues */ skb_queue_purge(&sk->sk_receive_queue); + sk_refcnt_debug_release(sk); sock_put(sk); return 0; @@ -886,20 +881,14 @@ static int packet_do_bind(struct sock *sk, struct net_device *dev, __be16 protoc if (protocol == 0) goto out_unlock; - if (dev) { - if (dev->flags&IFF_UP) { - dev_add_pack(&po->prot_hook); - sock_hold(sk); - po->running = 1; - } else { - sk->sk_err = ENETDOWN; - if (!sock_flag(sk, SOCK_DEAD)) - sk->sk_error_report(sk); - } - } else { + if (!dev || (dev->flags & IFF_UP)) { dev_add_pack(&po->prot_hook); sock_hold(sk); po->running = 1; + } else { + sk->sk_err = ENETDOWN; + if (!sock_flag(sk, SOCK_DEAD)) + sk->sk_error_report(sk); } out_unlock: @@ -1010,7 +999,7 @@ static int packet_create(struct net *net, struct socket *sock, int protocol) po->num = proto; sk->sk_destruct = packet_sock_destruct; - atomic_inc(&packet_socks_nr); + sk_refcnt_debug_inc(sk); /* * Attach a protocol block diff --git a/net/rfkill/rfkill.c b/net/rfkill/rfkill.c index 51d151c..4469a7b 100644 --- a/net/rfkill/rfkill.c +++ b/net/rfkill/rfkill.c @@ -27,6 +27,10 @@ #include <linux/mutex.h> #include <linux/rfkill.h> +/* Get declaration of rfkill_switch_all() to shut up sparse. */ +#include "rfkill-input.h" + + MODULE_AUTHOR("Ivo van Doorn <IvDoorn@gmail.com>"); MODULE_VERSION("1.0"); MODULE_DESCRIPTION("RF switch support"); @@ -56,11 +60,7 @@ static void rfkill_led_trigger(struct rfkill *rfkill, static int rfkill_toggle_radio(struct rfkill *rfkill, enum rfkill_state state) { - int retval; - - retval = mutex_lock_interruptible(&rfkill->mutex); - if (retval) - return retval; + int retval = 0; if (state != rfkill->state) { retval = rfkill->toggle_radio(rfkill->data, state); @@ -70,7 +70,6 @@ static int rfkill_toggle_radio(struct rfkill *rfkill, } } - mutex_unlock(&rfkill->mutex); return retval; } @@ -154,12 +153,13 @@ static ssize_t rfkill_state_store(struct device *dev, if (!capable(CAP_NET_ADMIN)) return -EPERM; + if (mutex_lock_interruptible(&rfkill->mutex)) + return -ERESTARTSYS; error = rfkill_toggle_radio(rfkill, state ? RFKILL_STATE_ON : RFKILL_STATE_OFF); - if (error) - return error; + mutex_unlock(&rfkill->mutex); - return count; + return error ? error : count; } static ssize_t rfkill_claim_show(struct device *dev, @@ -276,21 +276,17 @@ static struct class rfkill_class = { static int rfkill_add_switch(struct rfkill *rfkill) { - int retval; - - retval = mutex_lock_interruptible(&rfkill_mutex); - if (retval) - return retval; + int error; - retval = rfkill_toggle_radio(rfkill, rfkill_states[rfkill->type]); - if (retval) - goto out; + mutex_lock(&rfkill_mutex); - list_add_tail(&rfkill->node, &rfkill_list); + error = rfkill_toggle_radio(rfkill, rfkill_states[rfkill->type]); + if (!error) + list_add_tail(&rfkill->node, &rfkill_list); - out: mutex_unlock(&rfkill_mutex); - return retval; + + return error; } static void rfkill_remove_switch(struct rfkill *rfkill) @@ -387,20 +383,23 @@ int rfkill_register(struct rfkill *rfkill) if (!rfkill->toggle_radio) return -EINVAL; + if (rfkill->type >= RFKILL_TYPE_MAX) + return -EINVAL; + + snprintf(dev->bus_id, sizeof(dev->bus_id), + "rfkill%ld", (long)atomic_inc_return(&rfkill_no) - 1); + + rfkill_led_trigger_register(rfkill); error = rfkill_add_switch(rfkill); if (error) return error; - snprintf(dev->bus_id, sizeof(dev->bus_id), - "rfkill%ld", (long)atomic_inc_return(&rfkill_no) - 1); - error = device_add(dev); if (error) { rfkill_remove_switch(rfkill); return error; } - rfkill_led_trigger_register(rfkill); return 0; } @@ -416,9 +415,9 @@ EXPORT_SYMBOL(rfkill_register); */ void rfkill_unregister(struct rfkill *rfkill) { - rfkill_led_trigger_unregister(rfkill); device_del(&rfkill->dev); rfkill_remove_switch(rfkill); + rfkill_led_trigger_unregister(rfkill); put_device(&rfkill->dev); } EXPORT_SYMBOL(rfkill_unregister); @@ -448,5 +447,5 @@ static void __exit rfkill_exit(void) class_unregister(&rfkill_class); } -module_init(rfkill_init); +subsys_initcall(rfkill_init); module_exit(rfkill_exit); diff --git a/net/rxrpc/Kconfig b/net/rxrpc/Kconfig index e662f1d..0d3103c 100644 --- a/net/rxrpc/Kconfig +++ b/net/rxrpc/Kconfig @@ -5,6 +5,7 @@ config AF_RXRPC tristate "RxRPC session sockets" depends on INET && EXPERIMENTAL + select CRYPTO select KEYS help Say Y or M here to include support for RxRPC session sockets (just diff --git a/net/rxrpc/ar-local.c b/net/rxrpc/ar-local.c index fe03f71..f3a2bd7 100644 --- a/net/rxrpc/ar-local.c +++ b/net/rxrpc/ar-local.c @@ -114,7 +114,7 @@ static int rxrpc_create_local(struct rxrpc_local *local) return 0; error: - local->socket->ops->shutdown(local->socket, 2); + kernel_sock_shutdown(local->socket, SHUT_RDWR); local->socket->sk->sk_user_data = NULL; sock_release(local->socket); local->socket = NULL; @@ -267,7 +267,7 @@ static void rxrpc_destroy_local(struct work_struct *work) /* finish cleaning up the local descriptor */ rxrpc_purge_queue(&local->accept_queue); rxrpc_purge_queue(&local->reject_queue); - local->socket->ops->shutdown(local->socket, 2); + kernel_sock_shutdown(local->socket, SHUT_RDWR); sock_release(local->socket); up_read(&rxrpc_local_sem); diff --git a/net/sched/cls_u32.c b/net/sched/cls_u32.c index 9e98c6e..c390082 100644 --- a/net/sched/cls_u32.c +++ b/net/sched/cls_u32.c @@ -91,7 +91,7 @@ static struct tc_u_common *u32_list; static __inline__ unsigned u32_hash_fold(u32 key, struct tc_u32_sel *sel, u8 fshift) { - unsigned h = (key & sel->hmask)>>fshift; + unsigned h = ntohl(key & sel->hmask)>>fshift; return h; } @@ -613,17 +613,7 @@ static int u32_change(struct tcf_proto *tp, unsigned long base, u32 handle, memcpy(&n->sel, s, sizeof(*s) + s->nkeys*sizeof(struct tc_u32_key)); n->ht_up = ht; n->handle = handle; -{ - u8 i = 0; - u32 mask = s->hmask; - if (mask) { - while (!(mask & 1)) { - i++; - mask>>=1; - } - } - n->fshift = i; -} + n->fshift = s->hmask ? ffs(ntohl(s->hmask)) - 1 : 0; #ifdef CONFIG_CLS_U32_MARK if (tb[TCA_U32_MARK-1]) { diff --git a/net/sched/sch_generic.c b/net/sched/sch_generic.c index fa1a6f4..e595e65 100644 --- a/net/sched/sch_generic.c +++ b/net/sched/sch_generic.c @@ -134,7 +134,7 @@ static inline int qdisc_restart(struct net_device *dev) { struct Qdisc *q = dev->qdisc; struct sk_buff *skb; - int ret; + int ret = NETDEV_TX_BUSY; /* Dequeue packet */ if (unlikely((skb = dev_dequeue_skb(dev, q)) == NULL)) @@ -145,7 +145,8 @@ static inline int qdisc_restart(struct net_device *dev) spin_unlock(&dev->queue_lock); HARD_TX_LOCK(dev, smp_processor_id()); - ret = dev_hard_start_xmit(skb, dev); + if (!netif_subqueue_stopped(dev, skb)) + ret = dev_hard_start_xmit(skb, dev); HARD_TX_UNLOCK(dev); spin_lock(&dev->queue_lock); diff --git a/net/sched/sch_teql.c b/net/sched/sch_teql.c index 421281d..c0ed06d 100644 --- a/net/sched/sch_teql.c +++ b/net/sched/sch_teql.c @@ -252,6 +252,9 @@ __teql_resolve(struct sk_buff *skb, struct sk_buff *skb_res, struct net_device * static inline int teql_resolve(struct sk_buff *skb, struct sk_buff *skb_res, struct net_device *dev) { + if (dev->qdisc == &noop_qdisc) + return -ENODEV; + if (dev->header_ops == NULL || skb->dst == NULL || skb->dst->neighbour == NULL) diff --git a/net/sctp/Kconfig b/net/sctp/Kconfig index 8210f54..5390bc7 100644 --- a/net/sctp/Kconfig +++ b/net/sctp/Kconfig @@ -6,9 +6,9 @@ menuconfig IP_SCTP tristate "The SCTP Protocol (EXPERIMENTAL)" depends on INET && EXPERIMENTAL depends on IPV6 || IPV6=n - select CRYPTO if SCTP_HMAC_SHA1 || SCTP_HMAC_MD5 - select CRYPTO_HMAC if SCTP_HMAC_SHA1 || SCTP_HMAC_MD5 - select CRYPTO_SHA1 if SCTP_HMAC_SHA1 + select CRYPTO + select CRYPTO_HMAC + select CRYPTO_SHA1 select CRYPTO_MD5 if SCTP_HMAC_MD5 ---help--- Stream Control Transmission Protocol diff --git a/net/sctp/associola.c b/net/sctp/associola.c index 03158e3..013e3d3 100644 --- a/net/sctp/associola.c +++ b/net/sctp/associola.c @@ -262,10 +262,14 @@ static struct sctp_association *sctp_association_init(struct sctp_association *a */ asoc->peer.sack_needed = 1; - /* Assume that the peer recongizes ASCONF until reported otherwise - * via an ERROR chunk. + /* Assume that the peer will tell us if he recognizes ASCONF + * as part of INIT exchange. + * The sctp_addip_noauth option is there for backward compatibilty + * and will revert old behavior. */ - asoc->peer.asconf_capable = 1; + asoc->peer.asconf_capable = 0; + if (sctp_addip_noauth) + asoc->peer.asconf_capable = 1; /* Create an input queue. */ sctp_inq_init(&asoc->base.inqueue); diff --git a/net/sctp/auth.c b/net/sctp/auth.c index 6d5fa6b..97e6ebd 100644 --- a/net/sctp/auth.c +++ b/net/sctp/auth.c @@ -54,11 +54,13 @@ static struct sctp_hmac sctp_hmac_list[SCTP_AUTH_NUM_HMACS] = { /* id 2 is reserved as well */ .hmac_id = SCTP_AUTH_HMAC_ID_RESERVED_2, }, +#if defined (CONFIG_CRYPTO_SHA256) || defined (CONFIG_CRYPTO_SHA256_MODULE) { .hmac_id = SCTP_AUTH_HMAC_ID_SHA256, .hmac_name="hmac(sha256)", .hmac_len = SCTP_SHA256_SIG_SIZE, } +#endif }; @@ -631,7 +633,7 @@ static int __sctp_auth_cid(sctp_cid_t chunk, struct sctp_chunks_param *param) int found = 0; int i; - if (!param) + if (!param || param->param_hdr.length == 0) return 0; len = ntohs(param->param_hdr.length) - sizeof(sctp_paramhdr_t); diff --git a/net/sctp/bind_addr.c b/net/sctp/bind_addr.c index dfffa94..cae95af 100644 --- a/net/sctp/bind_addr.c +++ b/net/sctp/bind_addr.c @@ -180,9 +180,7 @@ int sctp_add_bind_addr(struct sctp_bind_addr *bp, union sctp_addr *new, /* Delete an address from the bind address list in the SCTP_bind_addr * structure. */ -int sctp_del_bind_addr(struct sctp_bind_addr *bp, union sctp_addr *del_addr, - void fastcall (*rcu_call)(struct rcu_head *head, - void (*func)(struct rcu_head *head))) +int sctp_del_bind_addr(struct sctp_bind_addr *bp, union sctp_addr *del_addr) { struct sctp_sockaddr_entry *addr, *temp; @@ -198,15 +196,10 @@ int sctp_del_bind_addr(struct sctp_bind_addr *bp, union sctp_addr *del_addr, } } - /* Call the rcu callback provided in the args. This function is - * called by both BH packet processing and user side socket option - * processing, but it works on different lists in those 2 contexts. - * Each context provides it's own callback, whether call_rcu_bh() - * or call_rcu(), to make sure that we wait for an appropriate time. - */ if (addr && !addr->valid) { - rcu_call(&addr->rcu, sctp_local_addr_free); + call_rcu(&addr->rcu, sctp_local_addr_free); SCTP_DBG_OBJCNT_DEC(addr); + return 0; } return -EINVAL; diff --git a/net/sctp/endpointola.c b/net/sctp/endpointola.c index 2d2d81e..de6f505 100644 --- a/net/sctp/endpointola.c +++ b/net/sctp/endpointola.c @@ -328,24 +328,35 @@ static struct sctp_association *__sctp_endpoint_lookup_assoc( const union sctp_addr *paddr, struct sctp_transport **transport) { + struct sctp_association *asoc = NULL; + struct sctp_transport *t = NULL; + struct sctp_hashbucket *head; + struct sctp_ep_common *epb; + struct hlist_node *node; + int hash; int rport; - struct sctp_association *asoc; - struct list_head *pos; + *transport = NULL; rport = ntohs(paddr->v4.sin_port); - list_for_each(pos, &ep->asocs) { - asoc = list_entry(pos, struct sctp_association, asocs); - if (rport == asoc->peer.port) { - *transport = sctp_assoc_lookup_paddr(asoc, paddr); - - if (*transport) - return asoc; + hash = sctp_assoc_hashfn(ep->base.bind_addr.port, rport); + head = &sctp_assoc_hashtable[hash]; + read_lock(&head->lock); + sctp_for_each_hentry(epb, node, &head->chain) { + asoc = sctp_assoc(epb); + if (asoc->ep != ep || rport != asoc->peer.port) + goto next; + + t = sctp_assoc_lookup_paddr(asoc, paddr); + if (t) { + *transport = t; + break; } +next: + asoc = NULL; } - - *transport = NULL; - return NULL; + read_unlock(&head->lock); + return asoc; } /* Lookup association on an endpoint based on a peer address. BH-safe. */ diff --git a/net/sctp/input.c b/net/sctp/input.c index 86503e7..91ae463 100644 --- a/net/sctp/input.c +++ b/net/sctp/input.c @@ -656,7 +656,6 @@ discard: /* Insert endpoint into the hash table. */ static void __sctp_hash_endpoint(struct sctp_endpoint *ep) { - struct sctp_ep_common **epp; struct sctp_ep_common *epb; struct sctp_hashbucket *head; @@ -666,12 +665,7 @@ static void __sctp_hash_endpoint(struct sctp_endpoint *ep) head = &sctp_ep_hashtable[epb->hashent]; sctp_write_lock(&head->lock); - epp = &head->chain; - epb->next = *epp; - if (epb->next) - (*epp)->pprev = &epb->next; - *epp = epb; - epb->pprev = epp; + hlist_add_head(&epb->node, &head->chain); sctp_write_unlock(&head->lock); } @@ -691,19 +685,15 @@ static void __sctp_unhash_endpoint(struct sctp_endpoint *ep) epb = &ep->base; + if (hlist_unhashed(&epb->node)) + return; + epb->hashent = sctp_ep_hashfn(epb->bind_addr.port); head = &sctp_ep_hashtable[epb->hashent]; sctp_write_lock(&head->lock); - - if (epb->pprev) { - if (epb->next) - epb->next->pprev = epb->pprev; - *epb->pprev = epb->next; - epb->pprev = NULL; - } - + __hlist_del(&epb->node); sctp_write_unlock(&head->lock); } @@ -721,12 +711,13 @@ static struct sctp_endpoint *__sctp_rcv_lookup_endpoint(const union sctp_addr *l struct sctp_hashbucket *head; struct sctp_ep_common *epb; struct sctp_endpoint *ep; + struct hlist_node *node; int hash; hash = sctp_ep_hashfn(ntohs(laddr->v4.sin_port)); head = &sctp_ep_hashtable[hash]; read_lock(&head->lock); - for (epb = head->chain; epb; epb = epb->next) { + sctp_for_each_hentry(epb, node, &head->chain) { ep = sctp_ep(epb); if (sctp_endpoint_is_match(ep, laddr)) goto hit; @@ -744,7 +735,6 @@ hit: /* Insert association into the hash table. */ static void __sctp_hash_established(struct sctp_association *asoc) { - struct sctp_ep_common **epp; struct sctp_ep_common *epb; struct sctp_hashbucket *head; @@ -756,12 +746,7 @@ static void __sctp_hash_established(struct sctp_association *asoc) head = &sctp_assoc_hashtable[epb->hashent]; sctp_write_lock(&head->lock); - epp = &head->chain; - epb->next = *epp; - if (epb->next) - (*epp)->pprev = &epb->next; - *epp = epb; - epb->pprev = epp; + hlist_add_head(&epb->node, &head->chain); sctp_write_unlock(&head->lock); } @@ -790,14 +775,7 @@ static void __sctp_unhash_established(struct sctp_association *asoc) head = &sctp_assoc_hashtable[epb->hashent]; sctp_write_lock(&head->lock); - - if (epb->pprev) { - if (epb->next) - epb->next->pprev = epb->pprev; - *epb->pprev = epb->next; - epb->pprev = NULL; - } - + __hlist_del(&epb->node); sctp_write_unlock(&head->lock); } @@ -822,6 +800,7 @@ static struct sctp_association *__sctp_lookup_association( struct sctp_ep_common *epb; struct sctp_association *asoc; struct sctp_transport *transport; + struct hlist_node *node; int hash; /* Optimize here for direct hit, only listening connections can @@ -830,7 +809,7 @@ static struct sctp_association *__sctp_lookup_association( hash = sctp_assoc_hashfn(ntohs(local->v4.sin_port), ntohs(peer->v4.sin_port)); head = &sctp_assoc_hashtable[hash]; read_lock(&head->lock); - for (epb = head->chain; epb; epb = epb->next) { + sctp_for_each_hentry(epb, node, &head->chain) { asoc = sctp_assoc(epb); transport = sctp_assoc_is_match(asoc, local, peer); if (transport) diff --git a/net/sctp/inqueue.c b/net/sctp/inqueue.c index f10fe7f..cf4b7eb 100644 --- a/net/sctp/inqueue.c +++ b/net/sctp/inqueue.c @@ -90,6 +90,10 @@ void sctp_inq_free(struct sctp_inq *queue) void sctp_inq_push(struct sctp_inq *q, struct sctp_chunk *chunk) { /* Directly call the packet handling routine. */ + if (chunk->rcvr->dead) { + sctp_chunk_free(chunk); + return; + } /* We are now calling this either from the soft interrupt * or from the backlog processing. diff --git a/net/sctp/outqueue.c b/net/sctp/outqueue.c index 28f4fe7..fa76f23 100644 --- a/net/sctp/outqueue.c +++ b/net/sctp/outqueue.c @@ -382,7 +382,7 @@ static void sctp_insert_list(struct list_head *head, struct list_head *new) /* Mark all the eligible packets on a transport for retransmission. */ void sctp_retransmit_mark(struct sctp_outq *q, struct sctp_transport *transport, - __u8 fast_retransmit) + __u8 reason) { struct list_head *lchunk, *ltemp; struct sctp_chunk *chunk; @@ -412,20 +412,20 @@ void sctp_retransmit_mark(struct sctp_outq *q, continue; } - /* If we are doing retransmission due to a fast retransmit, - * only the chunk's that are marked for fast retransmit - * should be added to the retransmit queue. If we are doing - * retransmission due to a timeout or pmtu discovery, only the - * chunks that are not yet acked should be added to the - * retransmit queue. + /* If we are doing retransmission due to a timeout or pmtu + * discovery, only the chunks that are not yet acked should + * be added to the retransmit queue. */ - if ((fast_retransmit && (chunk->fast_retransmit > 0)) || - (!fast_retransmit && !chunk->tsn_gap_acked)) { + if ((reason == SCTP_RTXR_FAST_RTX && + (chunk->fast_retransmit > 0)) || + (reason != SCTP_RTXR_FAST_RTX && !chunk->tsn_gap_acked)) { /* If this chunk was sent less then 1 rto ago, do not * retransmit this chunk, but give the peer time - * to acknowlege it. + * to acknowlege it. Do this only when + * retransmitting due to T3 timeout. */ - if ((jiffies - chunk->sent_at) < transport->rto) + if (reason == SCTP_RTXR_T3_RTX && + (jiffies - chunk->sent_at) < transport->last_rto) continue; /* RFC 2960 6.2.1 Processing a Received SACK @@ -467,10 +467,10 @@ void sctp_retransmit_mark(struct sctp_outq *q, } } - SCTP_DEBUG_PRINTK("%s: transport: %p, fast_retransmit: %d, " + SCTP_DEBUG_PRINTK("%s: transport: %p, reason: %d, " "cwnd: %d, ssthresh: %d, flight_size: %d, " "pba: %d\n", __FUNCTION__, - transport, fast_retransmit, + transport, reason, transport->cwnd, transport->ssthresh, transport->flight_size, transport->partial_bytes_acked); @@ -484,7 +484,6 @@ void sctp_retransmit(struct sctp_outq *q, struct sctp_transport *transport, sctp_retransmit_reason_t reason) { int error = 0; - __u8 fast_retransmit = 0; switch(reason) { case SCTP_RTXR_T3_RTX: @@ -499,16 +498,18 @@ void sctp_retransmit(struct sctp_outq *q, struct sctp_transport *transport, case SCTP_RTXR_FAST_RTX: SCTP_INC_STATS(SCTP_MIB_FAST_RETRANSMITS); sctp_transport_lower_cwnd(transport, SCTP_LOWER_CWND_FAST_RTX); - fast_retransmit = 1; break; case SCTP_RTXR_PMTUD: SCTP_INC_STATS(SCTP_MIB_PMTUD_RETRANSMITS); break; + case SCTP_RTXR_T1_RTX: + SCTP_INC_STATS(SCTP_MIB_T1_RETRANSMITS); + break; default: BUG(); } - sctp_retransmit_mark(q, transport, fast_retransmit); + sctp_retransmit_mark(q, transport, reason); /* PR-SCTP A5) Any time the T3-rtx timer expires, on any destination, * the sender SHOULD try to advance the "Advanced.Peer.Ack.Point" by @@ -641,7 +642,8 @@ static int sctp_outq_flush_rtx(struct sctp_outq *q, struct sctp_packet *pkt, /* If we are here due to a retransmit timeout or a fast * retransmit and if there are any chunks left in the retransmit - * queue that could not fit in the PMTU sized packet, they need * to be marked as ineligible for a subsequent fast retransmit. + * queue that could not fit in the PMTU sized packet, they need + * to be marked as ineligible for a subsequent fast retransmit. */ if (rtx_timeout && !lchunk) { list_for_each(lchunk1, lqueue) { @@ -660,10 +662,9 @@ static int sctp_outq_flush_rtx(struct sctp_outq *q, struct sctp_packet *pkt, int sctp_outq_uncork(struct sctp_outq *q) { int error = 0; - if (q->cork) { + if (q->cork) q->cork = 0; - error = sctp_outq_flush(q, 0); - } + error = sctp_outq_flush(q, 0); return error; } diff --git a/net/sctp/proc.c b/net/sctp/proc.c index e4cd841..2499732 100644 --- a/net/sctp/proc.c +++ b/net/sctp/proc.c @@ -225,6 +225,7 @@ static int sctp_eps_seq_show(struct seq_file *seq, void *v) struct sctp_ep_common *epb; struct sctp_endpoint *ep; struct sock *sk; + struct hlist_node *node; int hash = *(loff_t *)v; if (hash >= sctp_ep_hashsize) @@ -233,7 +234,7 @@ static int sctp_eps_seq_show(struct seq_file *seq, void *v) head = &sctp_ep_hashtable[hash]; sctp_local_bh_disable(); read_lock(&head->lock); - for (epb = head->chain; epb; epb = epb->next) { + sctp_for_each_hentry(epb, node, &head->chain) { ep = sctp_ep(epb); sk = epb->sk; seq_printf(seq, "%8p %8p %-3d %-3d %-4d %-5d %5d %5lu ", ep, sk, @@ -328,6 +329,7 @@ static int sctp_assocs_seq_show(struct seq_file *seq, void *v) struct sctp_ep_common *epb; struct sctp_association *assoc; struct sock *sk; + struct hlist_node *node; int hash = *(loff_t *)v; if (hash >= sctp_assoc_hashsize) @@ -336,7 +338,7 @@ static int sctp_assocs_seq_show(struct seq_file *seq, void *v) head = &sctp_assoc_hashtable[hash]; sctp_local_bh_disable(); read_lock(&head->lock); - for (epb = head->chain; epb; epb = epb->next) { + sctp_for_each_hentry(epb, node, &head->chain) { assoc = sctp_assoc(epb); sk = epb->sk; seq_printf(seq, diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c index 40c1a47..d50f610 100644 --- a/net/sctp/protocol.c +++ b/net/sctp/protocol.c @@ -1137,7 +1137,7 @@ SCTP_STATIC __init int sctp_init(void) } for (i = 0; i < sctp_assoc_hashsize; i++) { rwlock_init(&sctp_assoc_hashtable[i].lock); - sctp_assoc_hashtable[i].chain = NULL; + INIT_HLIST_HEAD(&sctp_assoc_hashtable[i].chain); } /* Allocate and initialize the endpoint hash table. */ @@ -1151,7 +1151,7 @@ SCTP_STATIC __init int sctp_init(void) } for (i = 0; i < sctp_ep_hashsize; i++) { rwlock_init(&sctp_ep_hashtable[i].lock); - sctp_ep_hashtable[i].chain = NULL; + INIT_HLIST_HEAD(&sctp_ep_hashtable[i].chain); } /* Allocate and initialize the SCTP port hash table. */ @@ -1170,7 +1170,7 @@ SCTP_STATIC __init int sctp_init(void) } for (i = 0; i < sctp_port_hashsize; i++) { spin_lock_init(&sctp_port_hashtable[i].lock); - sctp_port_hashtable[i].chain = NULL; + INIT_HLIST_HEAD(&sctp_port_hashtable[i].chain); } printk(KERN_INFO "SCTP: Hash tables configured " @@ -1179,6 +1179,7 @@ SCTP_STATIC __init int sctp_init(void) /* Disable ADDIP by default. */ sctp_addip_enable = 0; + sctp_addip_noauth = 0; /* Enable PR-SCTP by default. */ sctp_prsctp_enable = 1; diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c index c377e4e..f487629 100644 --- a/net/sctp/sm_make_chunk.c +++ b/net/sctp/sm_make_chunk.c @@ -77,6 +77,8 @@ static int sctp_process_param(struct sctp_association *asoc, union sctp_params param, const union sctp_addr *peer_addr, gfp_t gfp); +static void *sctp_addto_param(struct sctp_chunk *chunk, int len, + const void *data); /* What was the inbound interface for this chunk? */ int sctp_chunk_iif(const struct sctp_chunk *chunk) @@ -207,11 +209,7 @@ struct sctp_chunk *sctp_make_init(const struct sctp_association *asoc, chunksize = sizeof(init) + addrs_len + SCTP_SAT_LEN(num_types); chunksize += sizeof(ecap_param); - if (sctp_prsctp_enable) { - chunksize += sizeof(prsctp_param); - extensions[num_ext] = SCTP_CID_FWD_TSN; - num_ext += 1; - } + /* ADDIP: Section 4.2.7: * An implementation supporting this extension [ADDIP] MUST list * the ASCONF,the ASCONF-ACK, and the AUTH chunks in its INIT and @@ -243,7 +241,7 @@ struct sctp_chunk *sctp_make_init(const struct sctp_association *asoc, if (auth_chunks->length) chunksize += ntohs(auth_chunks->length); else - auth_hmacs = NULL; + auth_chunks = NULL; extensions[num_ext] = SCTP_CID_AUTH; num_ext += 1; @@ -297,7 +295,7 @@ struct sctp_chunk *sctp_make_init(const struct sctp_association *asoc, htons(sizeof(sctp_supported_ext_param_t) + num_ext); sctp_addto_chunk(retval, sizeof(sctp_supported_ext_param_t), &ext_param); - sctp_addto_chunk(retval, num_ext, extensions); + sctp_addto_param(retval, num_ext, extensions); } if (sctp_prsctp_enable) @@ -371,20 +369,12 @@ struct sctp_chunk *sctp_make_init_ack(const struct sctp_association *asoc, if (asoc->peer.ecn_capable) chunksize += sizeof(ecap_param); - /* Tell peer that we'll do PR-SCTP only if peer advertised. */ - if (asoc->peer.prsctp_capable) { - chunksize += sizeof(prsctp_param); - extensions[num_ext] = SCTP_CID_FWD_TSN; - num_ext += 1; - } - if (sctp_addip_enable) { extensions[num_ext] = SCTP_CID_ASCONF; extensions[num_ext+1] = SCTP_CID_ASCONF_ACK; num_ext += 2; } - chunksize += sizeof(ext_param) + num_ext; chunksize += sizeof(aiparam); if (asoc->peer.auth_capable) { @@ -407,6 +397,9 @@ struct sctp_chunk *sctp_make_init_ack(const struct sctp_association *asoc, num_ext += 1; } + if (num_ext) + chunksize += sizeof(sctp_supported_ext_param_t) + num_ext; + /* Now allocate and fill out the chunk. */ retval = sctp_make_chunk(asoc, SCTP_CID_INIT_ACK, 0, chunksize); if (!retval) @@ -428,7 +421,7 @@ struct sctp_chunk *sctp_make_init_ack(const struct sctp_association *asoc, htons(sizeof(sctp_supported_ext_param_t) + num_ext); sctp_addto_chunk(retval, sizeof(sctp_supported_ext_param_t), &ext_param); - sctp_addto_chunk(retval, num_ext, extensions); + sctp_addto_param(retval, num_ext, extensions); } if (asoc->peer.prsctp_capable) sctp_addto_chunk(retval, sizeof(prsctp_param), &prsctp_param); @@ -1788,9 +1781,14 @@ static int sctp_process_inv_paramlength(const struct sctp_association *asoc, sizeof(sctp_paramhdr_t); + /* This is a fatal error. Any accumulated non-fatal errors are + * not reported. + */ + if (*errp) + sctp_chunk_free(*errp); + /* Create an error chunk and fill it in with our payload. */ - if (!*errp) - *errp = sctp_make_op_error_space(asoc, chunk, payload_len); + *errp = sctp_make_op_error_space(asoc, chunk, payload_len); if (*errp) { sctp_init_cause(*errp, SCTP_ERROR_PROTO_VIOLATION, @@ -1813,9 +1811,15 @@ static int sctp_process_hn_param(const struct sctp_association *asoc, { __u16 len = ntohs(param.p->length); - /* Make an ERROR chunk. */ - if (!*errp) - *errp = sctp_make_op_error_space(asoc, chunk, len); + /* Processing of the HOST_NAME parameter will generate an + * ABORT. If we've accumulated any non-fatal errors, they + * would be unrecognized parameters and we should not include + * them in the ABORT. + */ + if (*errp) + sctp_chunk_free(*errp); + + *errp = sctp_make_op_error_space(asoc, chunk, len); if (*errp) { sctp_init_cause(*errp, SCTP_ERROR_DNS_FAILED, len); @@ -1847,7 +1851,7 @@ static void sctp_process_ext_param(struct sctp_association *asoc, break; case SCTP_CID_ASCONF: case SCTP_CID_ASCONF_ACK: - asoc->peer.addip_capable = 1; + asoc->peer.asconf_capable = 1; break; default: break; @@ -1862,56 +1866,40 @@ static void sctp_process_ext_param(struct sctp_association *asoc, * taken if the processing endpoint does not recognize the * Parameter Type. * - * 00 - Stop processing this SCTP chunk and discard it, - * do not process any further chunks within it. + * 00 - Stop processing this parameter; do not process any further + * parameters within this chunk * - * 01 - Stop processing this SCTP chunk and discard it, - * do not process any further chunks within it, and report - * the unrecognized parameter in an 'Unrecognized - * Parameter Type' (in either an ERROR or in the INIT ACK). + * 01 - Stop processing this parameter, do not process any further + * parameters within this chunk, and report the unrecognized + * parameter in an 'Unrecognized Parameter' ERROR chunk. * * 10 - Skip this parameter and continue processing. * * 11 - Skip this parameter and continue processing but * report the unrecognized parameter in an - * 'Unrecognized Parameter Type' (in either an ERROR or in - * the INIT ACK). + * 'Unrecognized Parameter' ERROR chunk. * * Return value: - * 0 - discard the chunk - * 1 - continue with the chunk + * SCTP_IERROR_NO_ERROR - continue with the chunk + * SCTP_IERROR_ERROR - stop and report an error. + * SCTP_IERROR_NOMEME - out of memory. */ -static int sctp_process_unk_param(const struct sctp_association *asoc, - union sctp_params param, - struct sctp_chunk *chunk, - struct sctp_chunk **errp) +static sctp_ierror_t sctp_process_unk_param(const struct sctp_association *asoc, + union sctp_params param, + struct sctp_chunk *chunk, + struct sctp_chunk **errp) { - int retval = 1; + int retval = SCTP_IERROR_NO_ERROR; switch (param.p->type & SCTP_PARAM_ACTION_MASK) { case SCTP_PARAM_ACTION_DISCARD: - retval = 0; - break; - case SCTP_PARAM_ACTION_DISCARD_ERR: - retval = 0; - /* Make an ERROR chunk, preparing enough room for - * returning multiple unknown parameters. - */ - if (NULL == *errp) - *errp = sctp_make_op_error_space(asoc, chunk, - ntohs(chunk->chunk_hdr->length)); - - if (*errp) { - sctp_init_cause(*errp, SCTP_ERROR_UNKNOWN_PARAM, - WORD_ROUND(ntohs(param.p->length))); - sctp_addto_chunk(*errp, - WORD_ROUND(ntohs(param.p->length)), - param.v); - } - + retval = SCTP_IERROR_ERROR; break; case SCTP_PARAM_ACTION_SKIP: break; + case SCTP_PARAM_ACTION_DISCARD_ERR: + retval = SCTP_IERROR_ERROR; + /* Fall through */ case SCTP_PARAM_ACTION_SKIP_ERR: /* Make an ERROR chunk, preparing enough room for * returning multiple unknown parameters. @@ -1932,9 +1920,8 @@ static int sctp_process_unk_param(const struct sctp_association *asoc, * to the peer and the association won't be * established. */ - retval = 0; + retval = SCTP_IERROR_NOMEM; } - break; default: break; @@ -1943,18 +1930,20 @@ static int sctp_process_unk_param(const struct sctp_association *asoc, return retval; } -/* Find unrecognized parameters in the chunk. +/* Verify variable length parameters * Return values: - * 0 - discard the chunk - * 1 - continue with the chunk + * SCTP_IERROR_ABORT - trigger an ABORT + * SCTP_IERROR_NOMEM - out of memory (abort) + * SCTP_IERROR_ERROR - stop processing, trigger an ERROR + * SCTP_IERROR_NO_ERROR - continue with the chunk */ -static int sctp_verify_param(const struct sctp_association *asoc, - union sctp_params param, - sctp_cid_t cid, - struct sctp_chunk *chunk, - struct sctp_chunk **err_chunk) +static sctp_ierror_t sctp_verify_param(const struct sctp_association *asoc, + union sctp_params param, + sctp_cid_t cid, + struct sctp_chunk *chunk, + struct sctp_chunk **err_chunk) { - int retval = 1; + int retval = SCTP_IERROR_NO_ERROR; /* FIXME - This routine is not looking at each parameter per the * chunk type, i.e., unrecognized parameters should be further @@ -1976,7 +1965,9 @@ static int sctp_verify_param(const struct sctp_association *asoc, case SCTP_PARAM_HOST_NAME_ADDRESS: /* Tell the peer, we won't support this param. */ - return sctp_process_hn_param(asoc, param, chunk, err_chunk); + sctp_process_hn_param(asoc, param, chunk, err_chunk); + retval = SCTP_IERROR_ABORT; + break; case SCTP_PARAM_FWD_TSN_SUPPORT: if (sctp_prsctp_enable) @@ -1993,9 +1984,11 @@ static int sctp_verify_param(const struct sctp_association *asoc, * cause 'Protocol Violation'. */ if (SCTP_AUTH_RANDOM_LENGTH != - ntohs(param.p->length) - sizeof(sctp_paramhdr_t)) - return sctp_process_inv_paramlength(asoc, param.p, + ntohs(param.p->length) - sizeof(sctp_paramhdr_t)) { + sctp_process_inv_paramlength(asoc, param.p, chunk, err_chunk); + retval = SCTP_IERROR_ABORT; + } break; case SCTP_PARAM_CHUNKS: @@ -2007,9 +2000,11 @@ static int sctp_verify_param(const struct sctp_association *asoc, * INIT-ACK chunk if the sender wants to receive authenticated * chunks. Its maximum length is 260 bytes. */ - if (260 < ntohs(param.p->length)) - return sctp_process_inv_paramlength(asoc, param.p, - chunk, err_chunk); + if (260 < ntohs(param.p->length)) { + sctp_process_inv_paramlength(asoc, param.p, + chunk, err_chunk); + retval = SCTP_IERROR_ABORT; + } break; case SCTP_PARAM_HMAC_ALGO: @@ -2020,8 +2015,7 @@ fallthrough: default: SCTP_DEBUG_PRINTK("Unrecognized param: %d for chunk %d.\n", ntohs(param.p->type), cid); - return sctp_process_unk_param(asoc, param, chunk, err_chunk); - + retval = sctp_process_unk_param(asoc, param, chunk, err_chunk); break; } return retval; @@ -2036,6 +2030,7 @@ int sctp_verify_init(const struct sctp_association *asoc, { union sctp_params param; int has_cookie = 0; + int result; /* Verify stream values are non-zero. */ if ((0 == peer_init->init_hdr.num_outbound_streams) || @@ -2043,8 +2038,7 @@ int sctp_verify_init(const struct sctp_association *asoc, (0 == peer_init->init_hdr.init_tag) || (SCTP_DEFAULT_MINWINDOW > ntohl(peer_init->init_hdr.a_rwnd))) { - sctp_process_inv_mandatory(asoc, chunk, errp); - return 0; + return sctp_process_inv_mandatory(asoc, chunk, errp); } /* Check for missing mandatory parameters. */ @@ -2062,29 +2056,29 @@ int sctp_verify_init(const struct sctp_association *asoc, * VIOLATION error. We build the ERROR chunk here and let the normal * error handling code build and send the packet. */ - if (param.v != (void*)chunk->chunk_end) { - sctp_process_inv_paramlength(asoc, param.p, chunk, errp); - return 0; - } + if (param.v != (void*)chunk->chunk_end) + return sctp_process_inv_paramlength(asoc, param.p, chunk, errp); /* The only missing mandatory param possible today is * the state cookie for an INIT-ACK chunk. */ - if ((SCTP_CID_INIT_ACK == cid) && !has_cookie) { - sctp_process_missing_param(asoc, SCTP_PARAM_STATE_COOKIE, - chunk, errp); - return 0; - } - - /* Find unrecognized parameters. */ + if ((SCTP_CID_INIT_ACK == cid) && !has_cookie) + return sctp_process_missing_param(asoc, SCTP_PARAM_STATE_COOKIE, + chunk, errp); + /* Verify all the variable length parameters */ sctp_walk_params(param, peer_init, init_hdr.params) { - if (!sctp_verify_param(asoc, param, cid, chunk, errp)) { - if (SCTP_PARAM_HOST_NAME_ADDRESS == param.p->type) + result = sctp_verify_param(asoc, param, cid, chunk, errp); + switch (result) { + case SCTP_IERROR_ABORT: + case SCTP_IERROR_NOMEM: return 0; - else + case SCTP_IERROR_ERROR: return 1; + case SCTP_IERROR_NO_ERROR: + default: + break; } } /* for (loop through all parameters) */ @@ -2137,11 +2131,14 @@ int sctp_process_init(struct sctp_association *asoc, sctp_cid_t cid, /* If the peer claims support for ADD-IP without support * for AUTH, disable support for ADD-IP. + * Do this only if backward compatible mode is turned off. */ - if (asoc->peer.addip_capable && !asoc->peer.auth_capable) { + if (!sctp_addip_noauth && + (asoc->peer.asconf_capable && !asoc->peer.auth_capable)) { asoc->peer.addip_disabled_mask |= (SCTP_PARAM_ADD_IP | SCTP_PARAM_DEL_IP | SCTP_PARAM_SET_PRIMARY); + asoc->peer.asconf_capable = 0; } /* Walk list of transports, removing transports in the UNKNOWN state. */ @@ -2848,10 +2845,11 @@ struct sctp_chunk *sctp_process_asconf(struct sctp_association *asoc, __be16 err_code; int length = 0; - int chunk_len = asconf->skb->len; + int chunk_len; __u32 serial; int all_param_pass = 1; + chunk_len = ntohs(asconf->chunk_hdr->length) - sizeof(sctp_chunkhdr_t); hdr = (sctp_addiphdr_t *)asconf->skb->data; serial = ntohl(hdr->serial); @@ -2952,13 +2950,17 @@ static int sctp_asconf_param_success(struct sctp_association *asoc, /* This is always done in BH context with a socket lock * held, so the list can not change. */ + local_bh_disable(); list_for_each_entry(saddr, &bp->address_list, list) { if (sctp_cmp_addr_exact(&saddr->a, &addr)) saddr->use_as_src = 1; } + local_bh_enable(); break; case SCTP_PARAM_DEL_IP: - retval = sctp_del_bind_addr(bp, &addr, call_rcu_bh); + local_bh_disable(); + retval = sctp_del_bind_addr(bp, &addr); + local_bh_enable(); list_for_each(pos, &asoc->peer.transport_addr_list) { transport = list_entry(pos, struct sctp_transport, transports); @@ -2990,7 +2992,7 @@ static __be16 sctp_get_asconf_response(struct sctp_chunk *asconf_ack, sctp_addip_param_t *asconf_ack_param; sctp_errhdr_t *err_param; int length; - int asconf_ack_len = asconf_ack->skb->len; + int asconf_ack_len; __be16 err_code; if (no_err) @@ -2998,6 +3000,9 @@ static __be16 sctp_get_asconf_response(struct sctp_chunk *asconf_ack, else err_code = SCTP_ERROR_REQ_REFUSED; + asconf_ack_len = ntohs(asconf_ack->chunk_hdr->length) - + sizeof(sctp_chunkhdr_t); + /* Skip the addiphdr from the asconf_ack chunk and store a pointer to * the first asconf_ack parameter. */ diff --git a/net/sctp/sm_sideeffect.c b/net/sctp/sm_sideeffect.c index bbdc938..78d1a8a 100644 --- a/net/sctp/sm_sideeffect.c +++ b/net/sctp/sm_sideeffect.c @@ -453,6 +453,7 @@ static void sctp_do_8_2_transport_strike(struct sctp_association *asoc, * maximum value discussed in rule C7 above (RTO.max) may be * used to provide an upper bound to this doubling operation. */ + transport->last_rto = transport->rto; transport->rto = min((transport->rto * 2), transport->asoc->rto_max); } @@ -1267,6 +1268,12 @@ static int sctp_cmd_interpreter(sctp_event_t event_type, sctp_ootb_pkt_free(packet); break; + case SCTP_CMD_T1_RETRAN: + /* Mark a transport for retransmission. */ + sctp_retransmit(&asoc->outqueue, cmd->obj.transport, + SCTP_RTXR_T1_RTX); + break; + case SCTP_CMD_RETRAN: /* Mark a transport for retransmission. */ sctp_retransmit(&asoc->outqueue, cmd->obj.transport, @@ -1393,7 +1400,8 @@ static int sctp_cmd_interpreter(sctp_event_t event_type, list_for_each(pos, &asoc->peer.transport_addr_list) { t = list_entry(pos, struct sctp_transport, transports); - sctp_retransmit_mark(&asoc->outqueue, t, 0); + sctp_retransmit_mark(&asoc->outqueue, t, + SCTP_RTXR_T1_RTX); } sctp_add_cmd_sf(commands, diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c index f01b408..5fb8477 100644 --- a/net/sctp/sm_statefuns.c +++ b/net/sctp/sm_statefuns.c @@ -959,7 +959,7 @@ sctp_disposition_t sctp_sf_sendbeat_8_3(const struct sctp_endpoint *ep, { struct sctp_transport *transport = (struct sctp_transport *) arg; - if (asoc->overall_error_count >= asoc->max_retrans) { + if (asoc->overall_error_count > asoc->max_retrans) { sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR, SCTP_ERROR(ETIMEDOUT)); /* CMD_ASSOC_FAILED calls CMD_DELETE_TCB. */ @@ -1146,7 +1146,7 @@ sctp_disposition_t sctp_sf_backbeat_8_3(const struct sctp_endpoint *ep, /* Check if the timestamp looks valid. */ if (time_after(hbinfo->sent_at, jiffies) || time_after(jiffies, hbinfo->sent_at + max_interval)) { - SCTP_DEBUG_PRINTK("%s: HEARTBEAT ACK with invalid timestamp" + SCTP_DEBUG_PRINTK("%s: HEARTBEAT ACK with invalid timestamp " "received for transport: %p\n", __FUNCTION__, link); return SCTP_DISPOSITION_DISCARD; @@ -2305,7 +2305,7 @@ static sctp_disposition_t sctp_sf_do_5_2_6_stale(const struct sctp_endpoint *ep, /* If we've sent any data bundled with COOKIE-ECHO we will need to * resend */ - sctp_add_cmd_sf(commands, SCTP_CMD_RETRAN, + sctp_add_cmd_sf(commands, SCTP_CMD_T1_RETRAN, SCTP_TRANSPORT(asoc->peer.primary_path)); /* Cast away the const modifier, as we want to just @@ -4064,11 +4064,6 @@ static sctp_disposition_t sctp_sf_abort_violation( struct sctp_chunk *chunk = arg; struct sctp_chunk *abort = NULL; - /* Make the abort chunk. */ - abort = sctp_make_abort_violation(asoc, chunk, payload, paylen); - if (!abort) - goto nomem; - /* SCTP-AUTH, Section 6.3: * It should be noted that if the receiver wants to tear * down an association in an authenticated way only, the @@ -4083,6 +4078,11 @@ static sctp_disposition_t sctp_sf_abort_violation( if (sctp_auth_recv_cid(SCTP_CID_ABORT, asoc)) goto discard; + /* Make the abort chunk. */ + abort = sctp_make_abort_violation(asoc, chunk, payload, paylen); + if (!abort) + goto nomem; + if (asoc) { sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(abort)); SCTP_INC_STATS(SCTP_MIB_OUTCTRLCHUNKS); diff --git a/net/sctp/socket.c b/net/sctp/socket.c index bd6f42a..ff8bc95 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c @@ -660,7 +660,7 @@ static int sctp_bindx_rem(struct sock *sk, struct sockaddr *addrs, int addrcnt) * socket routing and failover schemes. Refer to comments in * sctp_do_bind(). -daisy */ - retval = sctp_del_bind_addr(bp, sa_addr, call_rcu); + retval = sctp_del_bind_addr(bp, sa_addr); addr_buf += af->sockaddr_len; err_bindx_rem: @@ -5307,6 +5307,7 @@ static long sctp_get_port_local(struct sock *sk, union sctp_addr *addr) { struct sctp_bind_hashbucket *head; /* hash list */ struct sctp_bind_bucket *pp; /* hash list port iterator */ + struct hlist_node *node; unsigned short snum; int ret; @@ -5331,7 +5332,7 @@ static long sctp_get_port_local(struct sock *sk, union sctp_addr *addr) index = sctp_phashfn(rover); head = &sctp_port_hashtable[index]; sctp_spin_lock(&head->lock); - for (pp = head->chain; pp; pp = pp->next) + sctp_for_each_hentry(pp, node, &head->chain) if (pp->port == rover) goto next; break; @@ -5358,7 +5359,7 @@ static long sctp_get_port_local(struct sock *sk, union sctp_addr *addr) */ head = &sctp_port_hashtable[sctp_phashfn(snum)]; sctp_spin_lock(&head->lock); - for (pp = head->chain; pp; pp = pp->next) { + sctp_for_each_hentry(pp, node, &head->chain) { if (pp->port == snum) goto pp_found; } @@ -5702,10 +5703,7 @@ static struct sctp_bind_bucket *sctp_bucket_create( pp->port = snum; pp->fastreuse = 0; INIT_HLIST_HEAD(&pp->owner); - if ((pp->next = head->chain) != NULL) - pp->next->pprev = &pp->next; - head->chain = pp; - pp->pprev = &head->chain; + hlist_add_head(&pp->node, &head->chain); } return pp; } @@ -5714,9 +5712,7 @@ static struct sctp_bind_bucket *sctp_bucket_create( static void sctp_bucket_destroy(struct sctp_bind_bucket *pp) { if (pp && hlist_empty(&pp->owner)) { - if (pp->next) - pp->next->pprev = pp->pprev; - *(pp->pprev) = pp->next; + __hlist_del(&pp->node); kmem_cache_free(sctp_bucket_cachep, pp); SCTP_DBG_OBJCNT_DEC(bind_bucket); } @@ -6455,6 +6451,8 @@ static void sctp_sock_migrate(struct sock *oldsk, struct sock *newsk, } +DEFINE_PROTO_INUSE(sctp) + /* This proto struct describes the ULP interface for SCTP. */ struct proto sctp_prot = { .name = "SCTP", @@ -6483,9 +6481,12 @@ struct proto sctp_prot = { .memory_pressure = &sctp_memory_pressure, .enter_memory_pressure = sctp_enter_memory_pressure, .memory_allocated = &sctp_memory_allocated, + REF_PROTO_INUSE(sctp) }; #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) +DEFINE_PROTO_INUSE(sctpv6) + struct proto sctpv6_prot = { .name = "SCTPv6", .owner = THIS_MODULE, @@ -6513,5 +6514,6 @@ struct proto sctpv6_prot = { .memory_pressure = &sctp_memory_pressure, .enter_memory_pressure = sctp_enter_memory_pressure, .memory_allocated = &sctp_memory_allocated, + REF_PROTO_INUSE(sctpv6) }; #endif /* defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) */ diff --git a/net/sctp/sysctl.c b/net/sctp/sysctl.c index 0669778..da4f157 100644 --- a/net/sctp/sysctl.c +++ b/net/sctp/sysctl.c @@ -263,6 +263,15 @@ static ctl_table sctp_table[] = { .proc_handler = &proc_dointvec, .strategy = &sysctl_intvec }, + { + .ctl_name = CTL_UNNUMBERED, + .procname = "addip_noauth_enable", + .data = &sctp_addip_noauth, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = &proc_dointvec, + .strategy = &sysctl_intvec + }, { .ctl_name = 0 } }; diff --git a/net/sctp/transport.c b/net/sctp/transport.c index 5f467c9..d55ce83 100644 --- a/net/sctp/transport.c +++ b/net/sctp/transport.c @@ -74,8 +74,8 @@ static struct sctp_transport *sctp_transport_init(struct sctp_transport *peer, * given destination transport address, set RTO to the protocol * parameter 'RTO.Initial'. */ + peer->last_rto = peer->rto = msecs_to_jiffies(sctp_rto_initial); peer->rtt = 0; - peer->rto = msecs_to_jiffies(sctp_rto_initial); peer->rttvar = 0; peer->srtt = 0; peer->rto_pending = 0; @@ -385,6 +385,7 @@ void sctp_transport_update_rto(struct sctp_transport *tp, __u32 rtt) tp->rto = tp->asoc->rto_max; tp->rtt = rtt; + tp->last_rto = tp->rto; /* Reset rto_pending so that a new RTT measurement is started when a * new data chunk is sent. @@ -578,7 +579,7 @@ void sctp_transport_reset(struct sctp_transport *t) */ t->cwnd = min(4*asoc->pathmtu, max_t(__u32, 2*asoc->pathmtu, 4380)); t->ssthresh = asoc->peer.i.a_rwnd; - t->rto = asoc->rto_initial; + t->last_rto = t->rto = asoc->rto_initial; t->rtt = 0; t->srtt = 0; t->rttvar = 0; diff --git a/net/sctp/ulpqueue.c b/net/sctp/ulpqueue.c index 4be92d0..4908041 100644 --- a/net/sctp/ulpqueue.c +++ b/net/sctp/ulpqueue.c @@ -862,7 +862,7 @@ static inline void sctp_ulpq_reap_ordered(struct sctp_ulpq *ulpq, __u16 sid) continue; /* see if this ssn has been marked by skipping */ - if (!SSN_lt(cssn, sctp_ssn_peek(in, csid))) + if (!SSN_lte(cssn, sctp_ssn_peek(in, csid))) break; __skb_unlink(pos, &ulpq->lobby); diff --git a/net/socket.c b/net/socket.c index 5d879fd..74784df 100644 --- a/net/socket.c +++ b/net/socket.c @@ -2319,6 +2319,11 @@ int kernel_sock_ioctl(struct socket *sock, int cmd, unsigned long arg) return err; } +int kernel_sock_shutdown(struct socket *sock, enum sock_shutdown_cmd how) +{ + return sock->ops->shutdown(sock, how); +} + /* ABI emulation layers need these two */ EXPORT_SYMBOL(move_addr_to_kernel); EXPORT_SYMBOL(move_addr_to_user); @@ -2345,3 +2350,4 @@ EXPORT_SYMBOL(kernel_getsockopt); EXPORT_SYMBOL(kernel_setsockopt); EXPORT_SYMBOL(kernel_sendpage); EXPORT_SYMBOL(kernel_sock_ioctl); +EXPORT_SYMBOL(kernel_sock_shutdown); diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c index 53995af..a6e57d1 100644 --- a/net/sunrpc/auth_gss/auth_gss.c +++ b/net/sunrpc/auth_gss/auth_gss.c @@ -540,7 +540,7 @@ gss_pipe_downcall(struct file *filp, const char __user *src, size_t mlen) p = gss_fill_context(p, end, ctx, gss_msg->auth->mech); if (IS_ERR(p)) { err = PTR_ERR(p); - gss_msg->msg.errno = (err == -EACCES) ? -EACCES : -EAGAIN; + gss_msg->msg.errno = (err == -EAGAIN) ? -EAGAIN : -EACCES; goto err_release_msg; } gss_msg->ctx = gss_get_ctx(ctx); @@ -967,7 +967,7 @@ gss_validate(struct rpc_task *task, __be32 *p) if (maj_stat == GSS_S_CONTEXT_EXPIRED) clear_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags); if (maj_stat) { - dprintk("RPC: %5u gss_validate: gss_verify_mic returned" + dprintk("RPC: %5u gss_validate: gss_verify_mic returned " "error 0x%08x\n", task->tk_pid, maj_stat); goto out_bad; } diff --git a/net/sunrpc/auth_gss/gss_krb5_mech.c b/net/sunrpc/auth_gss/gss_krb5_mech.c index 9843eac..60c3dba 100644 --- a/net/sunrpc/auth_gss/gss_krb5_mech.c +++ b/net/sunrpc/auth_gss/gss_krb5_mech.c @@ -147,13 +147,17 @@ gss_import_sec_context_kerberos(const void *p, p = simple_get_bytes(p, end, &tmp, sizeof(tmp)); if (IS_ERR(p)) goto out_err_free_ctx; - if (tmp != SGN_ALG_DES_MAC_MD5) + if (tmp != SGN_ALG_DES_MAC_MD5) { + p = ERR_PTR(-ENOSYS); goto out_err_free_ctx; + } p = simple_get_bytes(p, end, &tmp, sizeof(tmp)); if (IS_ERR(p)) goto out_err_free_ctx; - if (tmp != SEAL_ALG_DES) + if (tmp != SEAL_ALG_DES) { + p = ERR_PTR(-ENOSYS); goto out_err_free_ctx; + } p = simple_get_bytes(p, end, &ctx->endtime, sizeof(ctx->endtime)); if (IS_ERR(p)) goto out_err_free_ctx; diff --git a/net/sunrpc/auth_gss/gss_krb5_seal.c b/net/sunrpc/auth_gss/gss_krb5_seal.c index 1c6eda5..dedcbd6 100644 --- a/net/sunrpc/auth_gss/gss_krb5_seal.c +++ b/net/sunrpc/auth_gss/gss_krb5_seal.c @@ -83,6 +83,7 @@ gss_get_mic_kerberos(struct gss_ctx *gss_ctx, struct xdr_buf *text, u32 seq_send; dprintk("RPC: gss_krb5_seal\n"); + BUG_ON(ctx == NULL); now = get_seconds(); diff --git a/net/sunrpc/rpc_pipe.c b/net/sunrpc/rpc_pipe.c index 18f0a8d..c59f3ca 100644 --- a/net/sunrpc/rpc_pipe.c +++ b/net/sunrpc/rpc_pipe.c @@ -280,7 +280,7 @@ rpc_pipe_poll(struct file *filp, struct poll_table_struct *wait) mask = POLLOUT | POLLWRNORM; if (rpci->ops == NULL) mask |= POLLERR | POLLHUP; - if (!list_empty(&rpci->pipe)) + if (filp->private_data || !list_empty(&rpci->pipe)) mask |= POLLIN | POLLRDNORM; return mask; } diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c index 282a9a2..cd641c8 100644 --- a/net/sunrpc/xprt.c +++ b/net/sunrpc/xprt.c @@ -62,7 +62,7 @@ static inline void do_xprt_reserve(struct rpc_task *); static void xprt_connect_status(struct rpc_task *task); static int __xprt_get_cong(struct rpc_xprt *, struct rpc_task *); -static spinlock_t xprt_list_lock = SPIN_LOCK_UNLOCKED; +static DEFINE_SPINLOCK(xprt_list_lock); static LIST_HEAD(xprt_list); /* diff --git a/net/sunrpc/xprtrdma/transport.c b/net/sunrpc/xprtrdma/transport.c index dc55cc9..6f2112d 100644 --- a/net/sunrpc/xprtrdma/transport.c +++ b/net/sunrpc/xprtrdma/transport.c @@ -89,7 +89,7 @@ static struct ctl_table_header *sunrpc_table_header; static ctl_table xr_tunables_table[] = { { - .ctl_name = CTL_SLOTTABLE_RDMA, + .ctl_name = CTL_UNNUMBERED, .procname = "rdma_slot_table_entries", .data = &xprt_rdma_slot_table_entries, .maxlen = sizeof(unsigned int), @@ -100,7 +100,7 @@ static ctl_table xr_tunables_table[] = { .extra2 = &max_slot_table_size }, { - .ctl_name = CTL_RDMA_MAXINLINEREAD, + .ctl_name = CTL_UNNUMBERED, .procname = "rdma_max_inline_read", .data = &xprt_rdma_max_inline_read, .maxlen = sizeof(unsigned int), @@ -109,7 +109,7 @@ static ctl_table xr_tunables_table[] = { .strategy = &sysctl_intvec, }, { - .ctl_name = CTL_RDMA_MAXINLINEWRITE, + .ctl_name = CTL_UNNUMBERED, .procname = "rdma_max_inline_write", .data = &xprt_rdma_max_inline_write, .maxlen = sizeof(unsigned int), @@ -118,7 +118,7 @@ static ctl_table xr_tunables_table[] = { .strategy = &sysctl_intvec, }, { - .ctl_name = CTL_RDMA_WRITEPADDING, + .ctl_name = CTL_UNNUMBERED, .procname = "rdma_inline_write_padding", .data = &xprt_rdma_inline_write_padding, .maxlen = sizeof(unsigned int), @@ -129,7 +129,7 @@ static ctl_table xr_tunables_table[] = { .extra2 = &max_padding, }, { - .ctl_name = CTL_RDMA_MEMREG, + .ctl_name = CTL_UNNUMBERED, .procname = "rdma_memreg_strategy", .data = &xprt_rdma_memreg_strategy, .maxlen = sizeof(unsigned int), @@ -320,9 +320,9 @@ xprt_setup_rdma(struct xprt_create *args) xprt->slot = kcalloc(xprt->max_reqs, sizeof(struct rpc_rqst), GFP_KERNEL); if (xprt->slot == NULL) { - kfree(xprt); dprintk("RPC: %s: couldn't allocate %d slots\n", __func__, xprt->max_reqs); + kfree(xprt); return ERR_PTR(-ENOMEM); } diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c index 02298f5..2f630a5 100644 --- a/net/sunrpc/xprtsock.c +++ b/net/sunrpc/xprtsock.c @@ -1828,7 +1828,7 @@ static struct rpc_xprt *xs_setup_xprt(struct xprt_create *args, * @args: rpc transport creation arguments * */ -struct rpc_xprt *xs_setup_udp(struct xprt_create *args) +static struct rpc_xprt *xs_setup_udp(struct xprt_create *args) { struct sockaddr *addr = args->dstaddr; struct rpc_xprt *xprt; @@ -1894,7 +1894,7 @@ struct rpc_xprt *xs_setup_udp(struct xprt_create *args) * @args: rpc transport creation arguments * */ -struct rpc_xprt *xs_setup_tcp(struct xprt_create *args) +static struct rpc_xprt *xs_setup_tcp(struct xprt_create *args) { struct sockaddr *addr = args->dstaddr; struct rpc_xprt *xprt; diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c index 515e7a6..060bba4 100644 --- a/net/unix/af_unix.c +++ b/net/unix/af_unix.c @@ -457,7 +457,7 @@ static int unix_release_sock (struct sock *sk, int embrion) * What the above comment does talk about? --ANK(980817) */ - if (atomic_read(&unix_tot_inflight)) + if (unix_tot_inflight) unix_gc(); /* Garbage collect fds */ return 0; @@ -599,15 +599,14 @@ static struct sock * unix_create1(struct net *net, struct socket *sock) struct sock *sk = NULL; struct unix_sock *u; - if (atomic_read(&unix_nr_socks) >= 2*get_max_files()) + atomic_inc(&unix_nr_socks); + if (atomic_read(&unix_nr_socks) > 2 * get_max_files()) goto out; sk = sk_alloc(net, PF_UNIX, GFP_KERNEL, &unix_proto); if (!sk) goto out; - atomic_inc(&unix_nr_socks); - sock_init_data(sock,sk); lockdep_set_class(&sk->sk_receive_queue.lock, &af_unix_sk_receive_queue_lock_key); @@ -625,6 +624,8 @@ static struct sock * unix_create1(struct net *net, struct socket *sock) init_waitqueue_head(&u->peer_wait); unix_insert_socket(unix_sockets_unbound, sk); out: + if (sk == NULL) + atomic_dec(&unix_nr_socks); return sk; } @@ -1636,8 +1637,15 @@ static int unix_dgram_recvmsg(struct kiocb *iocb, struct socket *sock, mutex_lock(&u->readlock); skb = skb_recv_datagram(sk, flags, noblock, &err); - if (!skb) + if (!skb) { + unix_state_lock(sk); + /* Signal EOF on disconnected non-blocking SEQPACKET socket. */ + if (sk->sk_type == SOCK_SEQPACKET && err == -EAGAIN && + (sk->sk_shutdown & RCV_SHUTDOWN)) + err = 0; + unix_state_unlock(sk); goto out_unlock; + } wake_up_interruptible_sync(&u->peer_wait); diff --git a/net/unix/garbage.c b/net/unix/garbage.c index 406b643..ebdff3d 100644 --- a/net/unix/garbage.c +++ b/net/unix/garbage.c @@ -92,7 +92,7 @@ static LIST_HEAD(gc_inflight_list); static LIST_HEAD(gc_candidates); static DEFINE_SPINLOCK(unix_gc_lock); -atomic_t unix_tot_inflight = ATOMIC_INIT(0); +unsigned int unix_tot_inflight; static struct sock *unix_get_socket(struct file *filp) @@ -133,7 +133,7 @@ void unix_inflight(struct file *fp) } else { BUG_ON(list_empty(&u->link)); } - atomic_inc(&unix_tot_inflight); + unix_tot_inflight++; spin_unlock(&unix_gc_lock); } } @@ -147,7 +147,7 @@ void unix_notinflight(struct file *fp) BUG_ON(list_empty(&u->link)); if (atomic_dec_and_test(&u->inflight)) list_del_init(&u->link); - atomic_dec(&unix_tot_inflight); + unix_tot_inflight--; spin_unlock(&unix_gc_lock); } } @@ -161,7 +161,7 @@ static inline struct sk_buff *sock_queue_head(struct sock *sk) for (skb = sock_queue_head(sk)->next, next = skb->next; \ skb != sock_queue_head(sk); skb = next, next = skb->next) -static void scan_inflight(struct sock *x, void (*func)(struct sock *), +static void scan_inflight(struct sock *x, void (*func)(struct unix_sock *), struct sk_buff_head *hitlist) { struct sk_buff *skb; @@ -185,9 +185,9 @@ static void scan_inflight(struct sock *x, void (*func)(struct sock *), * if it indeed does so */ struct sock *sk = unix_get_socket(*fp++); - if(sk) { + if (sk) { hit = true; - func(sk); + func(unix_sk(sk)); } } if (hit && hitlist != NULL) { @@ -199,7 +199,7 @@ static void scan_inflight(struct sock *x, void (*func)(struct sock *), spin_unlock(&x->sk_receive_queue.lock); } -static void scan_children(struct sock *x, void (*func)(struct sock *), +static void scan_children(struct sock *x, void (*func)(struct unix_sock *), struct sk_buff_head *hitlist) { if (x->sk_state != TCP_LISTEN) @@ -235,20 +235,18 @@ static void scan_children(struct sock *x, void (*func)(struct sock *), } } -static void dec_inflight(struct sock *sk) +static void dec_inflight(struct unix_sock *usk) { - atomic_dec(&unix_sk(sk)->inflight); + atomic_dec(&usk->inflight); } -static void inc_inflight(struct sock *sk) +static void inc_inflight(struct unix_sock *usk) { - atomic_inc(&unix_sk(sk)->inflight); + atomic_inc(&usk->inflight); } -static void inc_inflight_move_tail(struct sock *sk) +static void inc_inflight_move_tail(struct unix_sock *u) { - struct unix_sock *u = unix_sk(sk); - atomic_inc(&u->inflight); /* * If this is still a candidate, move it to the end of the diff --git a/net/wireless/wext.c b/net/wireless/wext.c index 85e5f9d..47e80cc 100644 --- a/net/wireless/wext.c +++ b/net/wireless/wext.c @@ -1094,7 +1094,7 @@ int wext_handle_ioctl(struct net *net, struct ifreq *ifr, unsigned int cmd, rtnl_lock(); ret = wireless_process_ioctl(net, ifr, cmd); rtnl_unlock(); - if (IW_IS_GET(cmd) && copy_to_user(arg, ifr, sizeof(struct ifreq))) + if (IW_IS_GET(cmd) && copy_to_user(arg, ifr, sizeof(struct iwreq))) return -EFAULT; return ret; } diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c index b702bd8..9a4cf2e 100644 --- a/net/xfrm/xfrm_policy.c +++ b/net/xfrm/xfrm_policy.c @@ -1344,6 +1344,7 @@ restart: xfrm_nr += pols[0]->xfrm_nr; switch (policy->action) { + default: case XFRM_POLICY_BLOCK: /* Prohibit the flow */ err = -EPERM; diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c index 224b44e..cf43c49 100644 --- a/net/xfrm/xfrm_state.c +++ b/net/xfrm/xfrm_state.c @@ -552,7 +552,7 @@ int __xfrm_state_delete(struct xfrm_state *x) * The xfrm_state_alloc call gives a reference, and that * is what we are dropping here. */ - __xfrm_state_put(x); + xfrm_state_put(x); err = 0; } diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c index d41588d..e75dbdc 100644 --- a/net/xfrm/xfrm_user.c +++ b/net/xfrm/xfrm_user.c @@ -507,7 +507,6 @@ static int copy_to_user_state_extra(struct xfrm_state *x, struct xfrm_usersa_info *p, struct sk_buff *skb) { - spin_lock_bh(&x->lock); copy_to_user_state(x, p); if (x->coaddr) @@ -515,7 +514,6 @@ static int copy_to_user_state_extra(struct xfrm_state *x, if (x->lastused) NLA_PUT_U64(skb, XFRMA_LASTUSED, x->lastused); - spin_unlock_bh(&x->lock); if (x->aalg) NLA_PUT(skb, XFRMA_ALG_AUTH, alg_len(x->aalg), x->aalg); diff --git a/samples/markers/marker-example.c b/samples/markers/marker-example.c index e787c6d..05e438f 100644 --- a/samples/markers/marker-example.c +++ b/samples/markers/marker-example.c @@ -19,7 +19,8 @@ static int my_open(struct inode *inode, struct file *file) { int i; - trace_mark(subsystem_event, "%d %s", 123, "example string"); + trace_mark(subsystem_event, "integer %d string %s", 123, + "example string"); for (i = 0; i < 10; i++) trace_mark(subsystem_eventb, MARK_NOARGS); return -EPERM; diff --git a/samples/markers/probe-example.c b/samples/markers/probe-example.c index 238b2e3..a367975 100644 --- a/samples/markers/probe-example.c +++ b/samples/markers/probe-example.c @@ -53,7 +53,7 @@ void probe_subsystem_eventb(const struct marker *mdata, void *private, static struct probe_data probe_array[] = { { .name = "subsystem_event", - .format = "%d %s", + .format = "integer %d string %s", .probe_func = probe_subsystem_event }, { .name = "subsystem_eventb", .format = MARK_NOARGS, diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl index cbb4258..579f50f 100755 --- a/scripts/checkpatch.pl +++ b/scripts/checkpatch.pl @@ -9,7 +9,7 @@ use strict; my $P = $0; $P =~ s@.*/@@g; -my $V = '0.11'; +my $V = '0.12'; use Getopt::Long qw(:config no_auto_abbrev); @@ -19,8 +19,11 @@ my $chk_signoff = 1; my $chk_patch = 1; my $tst_type = 0; my $emacs = 0; +my $terse = 0; my $file = 0; my $check = 0; +my $summary = 1; +my $mailback = 0; my $root; GetOptions( 'q|quiet+' => \$quiet, @@ -29,10 +32,13 @@ GetOptions( 'patch!' => \$chk_patch, 'test-type!' => \$tst_type, 'emacs!' => \$emacs, + 'terse!' => \$terse, 'file!' => \$file, 'subjective!' => \$check, 'strict!' => \$check, 'root=s' => \$root, + 'summary!' => \$summary, + 'mailback!' => \$mailback, ) or exit; my $exit = 0; @@ -42,6 +48,7 @@ if ($#ARGV < 0) { print "version: $V\n"; print "options: -q => quiet\n"; print " --no-tree => run without a kernel tree\n"; + print " --terse => one line per report\n"; print " --emacs => emacs compile window format\n"; print " --file => check a source file\n"; print " --strict => enable more subjective tests\n"; @@ -49,6 +56,11 @@ if ($#ARGV < 0) { exit(1); } +if ($terse) { + $emacs = 1; + $quiet++; +} + if ($tree) { if (defined $root) { if (!top_of_kernel_tree($root)) { @@ -90,41 +102,6 @@ our $Attribute = qr{ __(?:mem|cpu|dev|)(?:initdata|init) }x; our $Inline = qr{inline|__always_inline|noinline}; -our $NonptrType = qr{ - \b - (?:const\s+)? - (?:unsigned\s+)? - (?: - void| - char| - short| - int| - long| - unsigned| - float| - double| - bool| - long\s+int| - long\s+long| - long\s+long\s+int| - (?:__)?(?:u|s|be|le)(?:8|16|32|64)| - struct\s+$Ident| - union\s+$Ident| - enum\s+$Ident| - ${Ident}_t| - ${Ident}_handler| - ${Ident}_handler_fn - ) - (?:\s+$Sparse)* - \b - }x; - -our $Type = qr{ - \b$NonptrType\b - (?:\s*\*+\s*const|\s*\*+|(?:\s*\[\s*\])+)? - (?:\s+$Sparse|\s+$Attribute)* - }x; -our $Declare = qr{(?:$Storage\s+)?$Type}; our $Member = qr{->$Ident|\.$Ident|\[[^]]*\]}; our $Lval = qr{$Ident(?:$Member)*}; @@ -136,7 +113,50 @@ our $Operators = qr{ &&|\|\||,|\^|\+\+|--|&|\||\+|-|\*|\/ }x; -our $Bare = ''; +our $NonptrType; +our $Type; +our $Declare; + +our @typeList = ( + qr{void}, + qr{char}, + qr{short}, + qr{int}, + qr{long}, + qr{unsigned}, + qr{float}, + qr{double}, + qr{bool}, + qr{long\s+int}, + qr{long\s+long}, + qr{long\s+long\s+int}, + qr{(?:__)?(?:u|s|be|le)(?:8|16|32|64)}, + qr{struct\s+$Ident}, + qr{union\s+$Ident}, + qr{enum\s+$Ident}, + qr{${Ident}_t}, + qr{${Ident}_handler}, + qr{${Ident}_handler_fn}, +); + +sub build_types { + my $all = "(?: \n" . join("|\n ", @typeList) . "\n)"; + $NonptrType = qr{ + \b + (?:const\s+)? + (?:unsigned\s+)? + $all + (?:\s+$Sparse|\s+const)* + \b + }x; + $Type = qr{ + \b$NonptrType\b + (?:\s*\*+\s*const|\s*\*+|(?:\s*\[\s*\])+)? + (?:\s+$Sparse|\s+$Attribute)* + }x; + $Declare = qr{(?:$Storage\s+)?$Type}; +} +build_types(); $chk_signoff = 0 if ($file); @@ -278,6 +298,81 @@ sub sanitise_line { return $res; } +sub ctx_statement_block { + my ($linenr, $remain, $off) = @_; + my $line = $linenr - 1; + my $blk = ''; + my $soff = $off; + my $coff = $off - 1; + + my $type = ''; + my $level = 0; + my $c; + my $len = 0; + while (1) { + #warn "CSB: blk<$blk>\n"; + # If we are about to drop off the end, pull in more + # context. + if ($off >= $len) { + for (; $remain > 0; $line++) { + next if ($rawlines[$line] =~ /^-/); + $remain--; + $blk .= sanitise_line($rawlines[$line]) . "\n"; + $len = length($blk); + $line++; + last; + } + # Bail if there is no further context. + #warn "CSB: blk<$blk> off<$off> len<$len>\n"; + if ($off == $len) { + last; + } + } + $c = substr($blk, $off, 1); + + #warn "CSB: c<$c> type<$type> level<$level>\n"; + # Statement ends at the ';' or a close '}' at the + # outermost level. + if ($level == 0 && $c eq ';') { + last; + } + + if (($type eq '' || $type eq '(') && $c eq '(') { + $level++; + $type = '('; + } + if ($type eq '(' && $c eq ')') { + $level--; + $type = ($level != 0)? '(' : ''; + + if ($level == 0 && $coff < $soff) { + $coff = $off; + } + } + if (($type eq '' || $type eq '{') && $c eq '{') { + $level++; + $type = '{'; + } + if ($type eq '{' && $c eq '}') { + $level--; + $type = ($level != 0)? '{' : ''; + + if ($level == 0) { + last; + } + } + $off++; + } + + my $statement = substr($blk, $soff, $off - $soff + 1); + my $condition = substr($blk, $soff, $coff - $soff + 1); + + #warn "STATEMENT<$statement>\n"; + #warn "CONDITION<$condition>\n"; + + return ($statement, $condition); +} + sub ctx_block_get { my ($linenr, $remain, $outer, $open, $close, $off) = @_; my $line; @@ -421,9 +516,6 @@ sub annotate_values { my $paren = 0; my @paren_type; - # Include any user defined types we may have found as we went. - my $type_match = "(?:$Type$Bare)"; - while (length($cur)) { print " <$type> " if ($debug); if ($cur =~ /^(\s+)/o) { @@ -433,7 +525,7 @@ sub annotate_values { $type = 'N'; } - } elsif ($cur =~ /^($type_match)/) { + } elsif ($cur =~ /^($Type)/) { print "DECLARE($1)\n" if ($debug); $type = 'T'; @@ -457,7 +549,7 @@ sub annotate_values { } $type = 'N'; - } elsif ($cur =~ /^(if|while|typeof)\b/o) { + } elsif ($cur =~ /^(if|while|typeof|for)\b/o) { print "COND($1)\n" if ($debug); $paren_type[$paren] = 'N'; $type = 'N'; @@ -515,11 +607,30 @@ sub annotate_values { return $res; } +sub possible { + my ($possible) = @_; + + #print "CHECK<$possible>\n"; + if ($possible !~ /^(?:$Storage|$Type|DEFINE_\S+)$/ && + $possible ne 'goto' && $possible ne 'return' && + $possible ne 'struct' && $possible ne 'enum' && + $possible ne 'case' && $possible ne 'else' && + $possible ne 'typedef') { + #print "POSSIBLE<$possible>\n"; + push(@typeList, $possible); + build_types(); + } +} + my $prefix = ''; my @report = (); sub report { - push(@report, $prefix . $_[0]); + my $line = $prefix . $_[0]; + + $line = (split('\n', $line))[0] . "\n" if ($terse); + + push(@report, $line); } sub report_dump { @report; @@ -574,9 +685,6 @@ sub process { my $prev_values = 'N'; - # Possible bare types. - my @bare = (); - # Pre-scan the patch looking for any __setup documentation. my @setup_docs = (); my $setup_docs = 0; @@ -631,21 +739,35 @@ sub process { $realline++; $realcnt-- if ($realcnt != 0); - # track any sort of multi-line comment. Obviously if - # the added text or context do not include the whole - # comment we will not see it. Such is life. - # + # Guestimate if this is a continuing comment. Run + # the context looking for a comment "edge". If this + # edge is a close comment then we must be in a comment + # at context start. + if ($linenr == $first_line) { + my $edge; + for (my $ln = $first_line; $ln < ($linenr + $realcnt); $ln++) { + ($edge) = ($lines[$ln - 1] =~ m@(/\*|\*/)@); + last if (defined $edge); + } + if (defined $edge && $edge eq '*/') { + $in_comment = 1; + } + } + # Guestimate if this is a continuing comment. If this # is the start of a diff block and this line starts # ' *' then it is very likely a comment. if ($linenr == $first_line and $line =~ m@^.\s*\*@) { $in_comment = 1; } - if ($line =~ m@/\*@) { - $in_comment = 1; - } - if ($line =~ m@\*/@) { - $in_comment = 0; + + # Find the last comment edge on _this_ line. + while (($line =~ m@(/\*|\*/)@g)) { + if ($1 eq '/*') { + $in_comment = 1; + } else { + $in_comment = 0; + } } # Measure the line length and indent. @@ -687,7 +809,7 @@ sub process { } # Check for wrappage within a valid hunk of the file - if ($realcnt != 0 && $line !~ m{^(?:\+|-| |$)}) { + if ($realcnt != 0 && $line !~ m{^(?:\+|-| |\\ No newline|$)}) { ERROR("patch seems to be corrupt (line wrapped?)\n" . $herecurr) if (!$emitted_corrupt++); } @@ -727,6 +849,11 @@ sub process { WARN("line over 80 characters\n" . $herecurr); } +# check for adding lines without a newline. + if ($line =~ /^\+/ && defined $lines[$linenr] && $lines[$linenr] =~ /^\\ No newline at end of file/) { + WARN("adding a line without newline at end of file\n" . $herecurr); + } + # check we are in a valid source file *.[hc] if not then ignore this hunk next if ($realfile !~ /\.[hc]$/); @@ -752,30 +879,41 @@ sub process { # Check for potential 'bare' types if ($realcnt && - $line !~ /^.\s*(?:$Storage\s+)?(?:$Inline\s+)?$Type\b/ && $line !~ /$Ident:\s*$/ && - $line !~ /^.\s*$Ident\s*\(/ && - # definitions in global scope can only start with types - ($line =~ /^.(?:$Storage\s+)?(?:$Inline\s+)?($Ident)\b/ || - # declarations always start with types - $line =~ /^.\s*(?:$Storage\s+)?($Ident)\b\s*\**\s*$Ident\s*(?:;|=)/) || - # any (foo ... *) is a pointer cast, and foo is a type - $line =~ /\(($Ident)(?:\s+$Sparse)*\s*\*+\s*\)/) { - my $possible = $1; - if ($possible !~ /^(?:$Storage|$Type|DEFINE_\S+)$/ && - $possible ne 'goto' && $possible ne 'return' && - $possible ne 'struct' && $possible ne 'enum' && - $possible ne 'case' && $possible ne 'else' && - $possible ne 'typedef') { - #print "POSSIBLE<$possible>\n"; - push(@bare, $possible); - my $bare = join("|", @bare); - $Bare = '|' . qr{ - \b(?:$bare)\b - (?:\s*\*+\s*const|\s*\*+|(?:\s*\[\s*\])+)? - (?:\s+$Sparse)* - }x; + ($line =~ /^.\s*$Ident\s*\(\*+\s*$Ident\)\s*\(/ || + $line !~ /^.\s*$Ident\s*\(/)) { + # definitions in global scope can only start with types + if ($line =~ /^.(?:$Storage\s+)?(?:$Inline\s+)?(?:const\s+)?($Ident)\b/) { + possible($1); + + # declarations always start with types + } elsif ($prev_values eq 'N' && $line =~ /^.\s*(?:$Storage\s+)?($Ident)\b\s*\**\s*$Ident\s*(?:;|=)/) { + possible($1); + + # any (foo ... *) is a pointer cast, and foo is a type + } elsif ($line =~ /\(($Ident)(?:\s+$Sparse)*\s*\*+\s*\)/) { + possible($1); + } + + # Check for any sort of function declaration. + # int foo(something bar, other baz); + # void (*store_gdt)(x86_descr_ptr *); + if ($prev_values eq 'N' && $line =~ /^(.(?:(?:$Storage|$Inline)\s*)*\s*$Type\s*(?:\b$Ident|\(\*\s*$Ident\))\s*)\(/) { + my ($name_len) = length($1); + my ($level, @ctx) = ctx_statement_level($linenr, $realcnt, $name_len); + my $ctx = join("\n", @ctx); + + $ctx =~ s/\n.//; + substr($ctx, 0, $name_len + 1) = ''; + $ctx =~ s/\)[^\)]*$//; + for my $arg (split(/\s*,\s*/, $ctx)) { + if ($arg =~ /^(?:const\s+)?($Ident)(?:\s+$Sparse)*\s*\**\s*(:?\b$Ident)?$/ || $arg =~ /^($Ident)$/) { + + possible($1); + } + } } + } # @@ -935,6 +1073,10 @@ sub process { # $clean = 0; # } + if ($line =~ /\bLINUX_VERSION_CODE\b/) { + WARN("LINUX_VERSION_CODE should be avoided, code should be for the version to which it is merged" . $herecurr); + } + # printk should use KERN_* levels. Note that follow on printk's on the # same line do not need a level, so we use the current block context # to try and find and validate the current printk. In summary the current @@ -965,6 +1107,12 @@ sub process { ERROR("open brace '{' following function declarations go on the next line\n" . $herecurr); } +# open braces for enum, union and struct go on the same line. + if ($line =~ /^.\s*{/ && + $prevline =~ /^.\s*(?:typedef\s+)?(enum|union|struct)(?:\s+$Ident)?\s*$/) { + ERROR("open brace '{' following $1 go on the same line\n" . $hereprev); + } + # check for spaces between functions and their parentheses. while ($line =~ /($Ident)\s+\(/g) { if ($1 !~ /^(?:if|for|while|switch|return|volatile|__volatile__|__attribute__|format|__extension__|Copyright|case)$/ && @@ -1172,9 +1320,27 @@ sub process { } # Check for illegal assignment in if conditional. - if ($line=~/\bif\s*\(.*[^<>!=]=[^=]/) { - #next if ($line=~/\".*\Q$op\E.*\"/ or $line=~/\'\Q$op\E\'/); - ERROR("do not use assignment in if condition\n" . $herecurr); + if ($line =~ /\bif\s*\(/) { + my ($s, $c) = ctx_statement_block($linenr, $realcnt, 0); + + if ($c =~ /\bif\s*\(.*[^<>!=]=[^=].*/) { + ERROR("do not use assignment in if condition ($c)\n" . $herecurr); + } + + # Find out what is on the end of the line after the + # conditional. + substr($s, 0, length($c)) = ''; + $s =~ s/\n.*//g; + + if (length($c) && $s !~ /^\s*({|;|\/\*.*\*\/)?\s*\\*\s*$/) { + ERROR("trailing statements should be on next line\n" . $herecurr); + } + } + +# if and else should not have general statements after it + if ($line =~ /^.\s*(?:}\s*)?else\b(.*)/ && + $1 !~ /^\s*(?:\sif|{|\\|$)/) { + ERROR("trailing statements should be on next line\n" . $herecurr); } # Check for }<nl>else {, these must be at the same @@ -1205,12 +1371,6 @@ sub process { } } -# if and else should not have general statements after it - if ($line =~ /^.\s*(?:}\s*)?else\b(.*)/ && - $1 !~ /^\s*(?:\sif|{|\\|$)/) { - ERROR("trailing statements should be on next line\n" . $herecurr); - } - # multi-statement macros should be enclosed in a do while loop, grab the # first statement and ensure its the whole macro if its not enclosed # in a known goot container @@ -1233,6 +1393,10 @@ sub process { $off = length($1); $ln--; $cnt++; + while ($lines[$ln - 1] =~ /^-/) { + $ln--; + $cnt++; + } } my @ctx = ctx_statement($ln, $cnt, $off); my $ctx_ln = $ln + $#ctx + 1; @@ -1268,25 +1432,23 @@ sub process { if ($lines[$nr - 1] =~ /{\s*$/) { my ($lvl, @block) = ctx_block_level($nr, $cnt); - my $stmt = join(' ', @block); - $stmt =~ s/(^[^{]*){//; + my $stmt = join("\n", @block); + # Drop the diff line leader. + $stmt =~ s/\n./\n/g; + # Drop the code outside the block. + $stmt =~ s/(^[^{]*){\s*//; my $before = $1; - $stmt =~ s/}([^}]*$)//; + $stmt =~ s/\s*}([^}]*$)//; my $after = $1; #print "block<" . join(' ', @block) . "><" . scalar(@block) . ">\n"; #print "stmt<$stmt>\n\n"; - # Count the ;'s if there is fewer than two - # then there can only be one statement, - # if there is a brace inside we cannot - # trivially detect if its one statement. - # Also nested if's often require braces to - # disambiguate the else binding so shhh there. - my @semi = ($stmt =~ /;/g); - push(@semi, "/**/") if ($stmt =~ m@/\*@); - ##print "semi<" . scalar(@semi) . ">\n"; - if ($lvl == 0 && scalar(@semi) < 2 && + # Count the newlines, if there is only one + # then the block should not have {}'s. + my @lines = ($stmt =~ /\n/g); + #print "lines<" . scalar(@lines) . ">\n"; + if ($lvl == 0 && scalar(@lines) == 0 && $stmt !~ /{/ && $stmt !~ /\bif\b/ && $before !~ /}/ && $after !~ /{/) { my $herectx = "$here\n" . join("\n", @control, @block[1 .. $#block]) . "\n"; @@ -1372,6 +1534,11 @@ sub process { ERROR("inline keyword should sit between storage class and type\n" . $herecurr); } +# Check for __inline__ and __inline, prefer inline + if ($line =~ /\b(__inline__|__inline)\b/) { + WARN("plain inline is preferred over $1\n" . $herecurr); + } + # check for new externs in .c files. if ($line =~ /^.\s*extern\s/ && ($realfile =~ /\.c$/)) { WARN("externs should be avoided in .c files\n" . $herecurr); @@ -1392,21 +1559,33 @@ sub process { } } - if ($chk_patch && !$is_patch) { + # In mailback mode only produce a report in the negative, for + # things that appear to be patches. + if ($mailback && ($clean == 1 || !$is_patch)) { + exit(0); + } + + # This is not a patch, and we are are in 'no-patch' mode so + # just keep quiet. + if (!$chk_patch && !$is_patch) { + exit(0); + } + + if (!$is_patch) { ERROR("Does not appear to be a unified-diff format patch\n"); } if ($is_patch && $chk_signoff && $signoff == 0) { ERROR("Missing Signed-off-by: line(s)\n"); } - if ($clean == 0 && ($chk_patch || $is_patch)) { - print report_dump(); - if ($quiet < 2) { - print "total: $cnt_error errors, $cnt_warn warnings, " . - (($check)? "$cnt_chk checks, " : "") . - "$cnt_lines lines checked\n"; - } + print report_dump(); + if ($summary) { + print "total: $cnt_error errors, $cnt_warn warnings, " . + (($check)? "$cnt_chk checks, " : "") . + "$cnt_lines lines checked\n"; + print "\n" if ($quiet == 0); } + if ($clean == 1 && $quiet == 0) { print "Your patch has no obvious style problems and is ready for submission.\n" } diff --git a/scripts/kconfig/Makefile b/scripts/kconfig/Makefile index 5959412..1ad6f7f 100644 --- a/scripts/kconfig/Makefile +++ b/scripts/kconfig/Makefile @@ -4,12 +4,7 @@ PHONY += oldconfig xconfig gconfig menuconfig config silentoldconfig update-po-config -# If a arch/$(SRCARCH)/Kconfig.$(ARCH) file exist use it -ifneq ($(wildcard $(srctree)/arch/$(SRCARCH)/Kconfig.$(ARCH)),) - Kconfig := arch/$(SRCARCH)/Kconfig.$(ARCH) -else - Kconfig := arch/$(SRCARCH)/Kconfig -endif +Kconfig := arch/$(SRCARCH)/Kconfig xconfig: $(obj)/qconf $< $(Kconfig) diff --git a/scripts/kconfig/confdata.c b/scripts/kconfig/confdata.c index b2913e9..e0f402f 100644 --- a/scripts/kconfig/confdata.c +++ b/scripts/kconfig/confdata.c @@ -83,6 +83,68 @@ char *conf_get_default_confname(void) return name; } +static int conf_set_sym_val(struct symbol *sym, int def, int def_flags, char *p) +{ + char *p2; + + switch (sym->type) { + case S_TRISTATE: + if (p[0] == 'm') { + sym->def[def].tri = mod; + sym->flags |= def_flags; + break; + } + case S_BOOLEAN: + if (p[0] == 'y') { + sym->def[def].tri = yes; + sym->flags |= def_flags; + break; + } + if (p[0] == 'n') { + sym->def[def].tri = no; + sym->flags |= def_flags; + break; + } + conf_warning("symbol value '%s' invalid for %s", p, sym->name); + break; + case S_OTHER: + if (*p != '"') { + for (p2 = p; *p2 && !isspace(*p2); p2++) + ; + sym->type = S_STRING; + goto done; + } + case S_STRING: + if (*p++ != '"') + break; + for (p2 = p; (p2 = strpbrk(p2, "\"\\")); p2++) { + if (*p2 == '"') { + *p2 = 0; + break; + } + memmove(p2, p2 + 1, strlen(p2)); + } + if (!p2) { + conf_warning("invalid string found"); + return 1; + } + case S_INT: + case S_HEX: + done: + if (sym_string_valid(sym, p)) { + sym->def[def].val = strdup(p); + sym->flags |= def_flags; + } else { + conf_warning("symbol value '%s' invalid for %s", p, sym->name); + return 1; + } + break; + default: + ; + } + return 0; +} + int conf_read_simple(const char *name, int def) { FILE *in = NULL; @@ -213,61 +275,8 @@ load: conf_warning("trying to reassign symbol %s", sym->name); break; } - switch (sym->type) { - case S_TRISTATE: - if (p[0] == 'm') { - sym->def[def].tri = mod; - sym->flags |= def_flags; - break; - } - case S_BOOLEAN: - if (p[0] == 'y') { - sym->def[def].tri = yes; - sym->flags |= def_flags; - break; - } - if (p[0] == 'n') { - sym->def[def].tri = no; - sym->flags |= def_flags; - break; - } - conf_warning("symbol value '%s' invalid for %s", p, sym->name); - break; - case S_OTHER: - if (*p != '"') { - for (p2 = p; *p2 && !isspace(*p2); p2++) - ; - sym->type = S_STRING; - goto done; - } - case S_STRING: - if (*p++ != '"') - break; - for (p2 = p; (p2 = strpbrk(p2, "\"\\")); p2++) { - if (*p2 == '"') { - *p2 = 0; - break; - } - memmove(p2, p2 + 1, strlen(p2)); - } - if (!p2) { - conf_warning("invalid string found"); - continue; - } - case S_INT: - case S_HEX: - done: - if (sym_string_valid(sym, p)) { - sym->def[def].val = strdup(p); - sym->flags |= def_flags; - } else { - conf_warning("symbol value '%s' invalid for %s", p, sym->name); - continue; - } - break; - default: - ; - } + if (conf_set_sym_val(sym, def, def_flags, p)) + continue; break; case '\r': case '\n': diff --git a/security/commoncap.c b/security/commoncap.c index bf67871..5bc1895 100644 --- a/security/commoncap.c +++ b/security/commoncap.c @@ -526,6 +526,19 @@ int cap_task_kill(struct task_struct *p, struct siginfo *info, if (info != SEND_SIG_NOINFO && (is_si_special(info) || SI_FROMKERNEL(info))) return 0; + /* + * Running a setuid root program raises your capabilities. + * Killing your own setuid root processes was previously + * allowed. + * We must preserve legacy signal behavior in this case. + */ + if (p->euid == 0 && p->uid == current->uid) + return 0; + + /* sigcont is permitted within same session */ + if (sig == SIGCONT && (task_session_nr(current) == task_session_nr(p))) + return 0; + if (secid) /* * Signal sent as a particular user. diff --git a/security/selinux/ss/avtab.c b/security/selinux/ss/avtab.c index 7551af1..9e70a16 100644 --- a/security/selinux/ss/avtab.c +++ b/security/selinux/ss/avtab.c @@ -325,7 +325,7 @@ static uint16_t spec_order[] = { AVTAB_MEMBER }; -int avtab_read_item(void *fp, u32 vers, struct avtab *a, +int avtab_read_item(struct avtab *a, void *fp, struct policydb *pol, int (*insertf)(struct avtab *a, struct avtab_key *k, struct avtab_datum *d, void *p), void *p) @@ -333,10 +333,11 @@ int avtab_read_item(void *fp, u32 vers, struct avtab *a, __le16 buf16[4]; u16 enabled; __le32 buf32[7]; - u32 items, items2, val; + u32 items, items2, val, vers = pol->policyvers; struct avtab_key key; struct avtab_datum datum; int i, rc; + unsigned set; memset(&key, 0, sizeof(struct avtab_key)); memset(&datum, 0, sizeof(struct avtab_datum)); @@ -420,12 +421,35 @@ int avtab_read_item(void *fp, u32 vers, struct avtab *a, key.target_class = le16_to_cpu(buf16[items++]); key.specified = le16_to_cpu(buf16[items++]); + if (!policydb_type_isvalid(pol, key.source_type) || + !policydb_type_isvalid(pol, key.target_type) || + !policydb_class_isvalid(pol, key.target_class)) { + printk(KERN_WARNING "security: avtab: invalid type or class\n"); + return -1; + } + + set = 0; + for (i = 0; i < ARRAY_SIZE(spec_order); i++) { + if (key.specified & spec_order[i]) + set++; + } + if (!set || set > 1) { + printk(KERN_WARNING + "security: avtab: more than one specifier\n"); + return -1; + } + rc = next_entry(buf32, fp, sizeof(u32)); if (rc < 0) { printk("security: avtab: truncated entry\n"); return -1; } datum.data = le32_to_cpu(*buf32); + if ((key.specified & AVTAB_TYPE) && + !policydb_type_isvalid(pol, datum.data)) { + printk(KERN_WARNING "security: avtab: invalid type\n"); + return -1; + } return insertf(a, &key, &datum, p); } @@ -435,7 +459,7 @@ static int avtab_insertf(struct avtab *a, struct avtab_key *k, return avtab_insert(a, k, d); } -int avtab_read(struct avtab *a, void *fp, u32 vers) +int avtab_read(struct avtab *a, void *fp, struct policydb *pol) { int rc; __le32 buf[1]; @@ -459,7 +483,7 @@ int avtab_read(struct avtab *a, void *fp, u32 vers) goto bad; for (i = 0; i < nel; i++) { - rc = avtab_read_item(fp,vers, a, avtab_insertf, NULL); + rc = avtab_read_item(a, fp, pol, avtab_insertf, NULL); if (rc) { if (rc == -ENOMEM) printk(KERN_ERR "security: avtab: out of memory\n"); diff --git a/security/selinux/ss/avtab.h b/security/selinux/ss/avtab.h index d8edf8c..8da6a84 100644 --- a/security/selinux/ss/avtab.h +++ b/security/selinux/ss/avtab.h @@ -64,12 +64,13 @@ struct avtab_datum *avtab_search(struct avtab *h, struct avtab_key *k); void avtab_destroy(struct avtab *h); void avtab_hash_eval(struct avtab *h, char *tag); -int avtab_read_item(void *fp, uint32_t vers, struct avtab *a, +struct policydb; +int avtab_read_item(struct avtab *a, void *fp, struct policydb *pol, int (*insert)(struct avtab *a, struct avtab_key *k, struct avtab_datum *d, void *p), void *p); -int avtab_read(struct avtab *a, void *fp, u32 vers); +int avtab_read(struct avtab *a, void *fp, struct policydb *pol); struct avtab_node *avtab_insert_nonunique(struct avtab *h, struct avtab_key *key, struct avtab_datum *datum); diff --git a/security/selinux/ss/conditional.c b/security/selinux/ss/conditional.c index 45b93a8..50ad85d 100644 --- a/security/selinux/ss/conditional.c +++ b/security/selinux/ss/conditional.c @@ -362,7 +362,8 @@ static int cond_read_av_list(struct policydb *p, void *fp, struct cond_av_list * data.head = NULL; data.tail = NULL; for (i = 0; i < len; i++) { - rc = avtab_read_item(fp, p->policyvers, &p->te_cond_avtab, cond_insertf, &data); + rc = avtab_read_item(&p->te_cond_avtab, fp, p, cond_insertf, + &data); if (rc) return rc; diff --git a/security/selinux/ss/ebitmap.c b/security/selinux/ss/ebitmap.c index c1a6b22..920b5e3 100644 --- a/security/selinux/ss/ebitmap.c +++ b/security/selinux/ss/ebitmap.c @@ -129,8 +129,8 @@ int ebitmap_netlbl_export(struct ebitmap *ebmap, cmap_sft = delta % NETLBL_CATMAP_MAPSIZE; c_iter->bitmap[cmap_idx] |= e_iter->maps[cmap_idx] << cmap_sft; - e_iter = e_iter->next; } + e_iter = e_iter->next; } return 0; diff --git a/security/selinux/ss/mls.c b/security/selinux/ss/mls.c index 9a11dea..fb5d70a 100644 --- a/security/selinux/ss/mls.c +++ b/security/selinux/ss/mls.c @@ -157,49 +157,55 @@ void mls_sid_to_context(struct context *context, return; } +int mls_level_isvalid(struct policydb *p, struct mls_level *l) +{ + struct level_datum *levdatum; + struct ebitmap_node *node; + int i; + + if (!l->sens || l->sens > p->p_levels.nprim) + return 0; + levdatum = hashtab_search(p->p_levels.table, + p->p_sens_val_to_name[l->sens - 1]); + if (!levdatum) + return 0; + + ebitmap_for_each_positive_bit(&l->cat, node, i) { + if (i > p->p_cats.nprim) + return 0; + if (!ebitmap_get_bit(&levdatum->level->cat, i)) { + /* + * Category may not be associated with + * sensitivity. + */ + return 0; + } + } + + return 1; +} + +int mls_range_isvalid(struct policydb *p, struct mls_range *r) +{ + return (mls_level_isvalid(p, &r->level[0]) && + mls_level_isvalid(p, &r->level[1]) && + mls_level_dom(&r->level[1], &r->level[0])); +} + /* * Return 1 if the MLS fields in the security context * structure `c' are valid. Return 0 otherwise. */ int mls_context_isvalid(struct policydb *p, struct context *c) { - struct level_datum *levdatum; struct user_datum *usrdatum; - struct ebitmap_node *node; - int i, l; if (!selinux_mls_enabled) return 1; - /* - * MLS range validity checks: high must dominate low, low level must - * be valid (category set <-> sensitivity check), and high level must - * be valid (category set <-> sensitivity check) - */ - if (!mls_level_dom(&c->range.level[1], &c->range.level[0])) - /* High does not dominate low. */ + if (!mls_range_isvalid(p, &c->range)) return 0; - for (l = 0; l < 2; l++) { - if (!c->range.level[l].sens || c->range.level[l].sens > p->p_levels.nprim) - return 0; - levdatum = hashtab_search(p->p_levels.table, - p->p_sens_val_to_name[c->range.level[l].sens - 1]); - if (!levdatum) - return 0; - - ebitmap_for_each_positive_bit(&c->range.level[l].cat, node, i) { - if (i > p->p_cats.nprim) - return 0; - if (!ebitmap_get_bit(&levdatum->level->cat, i)) - /* - * Category may not be associated with - * sensitivity in low level. - */ - return 0; - } - } - if (c->role == OBJECT_R_VAL) return 1; diff --git a/security/selinux/ss/mls.h b/security/selinux/ss/mls.h index 096d1b4..ab53663 100644 --- a/security/selinux/ss/mls.h +++ b/security/selinux/ss/mls.h @@ -27,6 +27,8 @@ int mls_compute_context_len(struct context *context); void mls_sid_to_context(struct context *context, char **scontext); int mls_context_isvalid(struct policydb *p, struct context *c); +int mls_range_isvalid(struct policydb *p, struct mls_range *r); +int mls_level_isvalid(struct policydb *p, struct mls_level *l); int mls_context_to_sid(char oldc, char **scontext, diff --git a/security/selinux/ss/policydb.c b/security/selinux/ss/policydb.c index 539828b..b582aae 100644 --- a/security/selinux/ss/policydb.c +++ b/security/selinux/ss/policydb.c @@ -713,6 +713,27 @@ out: return rc; } +int policydb_class_isvalid(struct policydb *p, unsigned int class) +{ + if (!class || class > p->p_classes.nprim) + return 0; + return 1; +} + +int policydb_role_isvalid(struct policydb *p, unsigned int role) +{ + if (!role || role > p->p_roles.nprim) + return 0; + return 1; +} + +int policydb_type_isvalid(struct policydb *p, unsigned int type) +{ + if (!type || type > p->p_types.nprim) + return 0; + return 1; +} + /* * Return 1 if the fields in the security context * structure `c' are valid. Return 0 otherwise. @@ -1260,6 +1281,7 @@ static int mls_read_level(struct mls_level *lp, void *fp) "categories\n"); goto bad; } + return 0; bad: @@ -1563,7 +1585,7 @@ int policydb_read(struct policydb *p, void *fp) p->symtab[i].nprim = nprim; } - rc = avtab_read(&p->te_avtab, fp, p->policyvers); + rc = avtab_read(&p->te_avtab, fp, p); if (rc) goto bad; @@ -1595,6 +1617,12 @@ int policydb_read(struct policydb *p, void *fp) tr->role = le32_to_cpu(buf[0]); tr->type = le32_to_cpu(buf[1]); tr->new_role = le32_to_cpu(buf[2]); + if (!policydb_role_isvalid(p, tr->role) || + !policydb_type_isvalid(p, tr->type) || + !policydb_role_isvalid(p, tr->new_role)) { + rc = -EINVAL; + goto bad; + } ltr = tr; } @@ -1619,6 +1647,11 @@ int policydb_read(struct policydb *p, void *fp) goto bad; ra->role = le32_to_cpu(buf[0]); ra->new_role = le32_to_cpu(buf[1]); + if (!policydb_role_isvalid(p, ra->role) || + !policydb_role_isvalid(p, ra->new_role)) { + rc = -EINVAL; + goto bad; + } lra = ra; } @@ -1872,9 +1905,19 @@ int policydb_read(struct policydb *p, void *fp) rt->target_class = le32_to_cpu(buf[0]); } else rt->target_class = SECCLASS_PROCESS; + if (!policydb_type_isvalid(p, rt->source_type) || + !policydb_type_isvalid(p, rt->target_type) || + !policydb_class_isvalid(p, rt->target_class)) { + rc = -EINVAL; + goto bad; + } rc = mls_read_range_helper(&rt->target_range, fp); if (rc) goto bad; + if (!mls_range_isvalid(p, &rt->target_range)) { + printk(KERN_WARNING "security: rangetrans: invalid range\n"); + goto bad; + } lrt = rt; } } diff --git a/security/selinux/ss/policydb.h b/security/selinux/ss/policydb.h index 844d310..ed6fc68 100644 --- a/security/selinux/ss/policydb.h +++ b/security/selinux/ss/policydb.h @@ -251,6 +251,9 @@ struct policydb { extern void policydb_destroy(struct policydb *p); extern int policydb_load_isids(struct policydb *p, struct sidtab *s); extern int policydb_context_isvalid(struct policydb *p, struct context *c); +extern int policydb_class_isvalid(struct policydb *p, unsigned int class); +extern int policydb_type_isvalid(struct policydb *p, unsigned int type); +extern int policydb_role_isvalid(struct policydb *p, unsigned int role); extern int policydb_read(struct policydb *p, void *fp); #define PERM_SYMTAB_SIZE 32 diff --git a/security/selinux/xfrm.c b/security/selinux/xfrm.c index 36a191e..e076039 100644 --- a/security/selinux/xfrm.c +++ b/security/selinux/xfrm.c @@ -211,26 +211,27 @@ static int selinux_xfrm_sec_ctx_alloc(struct xfrm_sec_ctx **ctxp, if (uctx->ctx_doi != XFRM_SC_ALG_SELINUX) return -EINVAL; - if (uctx->ctx_len >= PAGE_SIZE) + str_len = uctx->ctx_len; + if (str_len >= PAGE_SIZE) return -ENOMEM; *ctxp = ctx = kmalloc(sizeof(*ctx) + - uctx->ctx_len + 1, + str_len + 1, GFP_KERNEL); if (!ctx) return -ENOMEM; ctx->ctx_doi = uctx->ctx_doi; - ctx->ctx_len = uctx->ctx_len; + ctx->ctx_len = str_len; ctx->ctx_alg = uctx->ctx_alg; memcpy(ctx->ctx_str, uctx+1, - ctx->ctx_len); - ctx->ctx_str[ctx->ctx_len] = 0; + str_len); + ctx->ctx_str[str_len] = 0; rc = security_context_to_sid(ctx->ctx_str, - ctx->ctx_len, + str_len, &ctx->ctx_sid); if (rc) diff --git a/sound/drivers/mpu401/mpu401_uart.c b/sound/drivers/mpu401/mpu401_uart.c index 3306ecd..b57f2d5 100644 --- a/sound/drivers/mpu401/mpu401_uart.c +++ b/sound/drivers/mpu401/mpu401_uart.c @@ -97,23 +97,27 @@ static void snd_mpu401_uart_clear_rx(struct snd_mpu401 *mpu) static void uart_interrupt_tx(struct snd_mpu401 *mpu) { + unsigned long flags; + if (test_bit(MPU401_MODE_BIT_OUTPUT, &mpu->mode) && test_bit(MPU401_MODE_BIT_OUTPUT_TRIGGER, &mpu->mode)) { - spin_lock(&mpu->output_lock); + spin_lock_irqsave(&mpu->output_lock, flags); snd_mpu401_uart_output_write(mpu); - spin_unlock(&mpu->output_lock); + spin_unlock_irqrestore(&mpu->output_lock, flags); } } static void _snd_mpu401_uart_interrupt(struct snd_mpu401 *mpu) { + unsigned long flags; + if (mpu->info_flags & MPU401_INFO_INPUT) { - spin_lock(&mpu->input_lock); + spin_lock_irqsave(&mpu->input_lock, flags); if (test_bit(MPU401_MODE_BIT_INPUT, &mpu->mode)) snd_mpu401_uart_input_read(mpu); else snd_mpu401_uart_clear_rx(mpu); - spin_unlock(&mpu->input_lock); + spin_unlock_irqrestore(&mpu->input_lock, flags); } if (! (mpu->info_flags & MPU401_INFO_TX_IRQ)) /* ok. for better Tx performance try do some output diff --git a/sound/drivers/portman2x4.c b/sound/drivers/portman2x4.c index e065b2a..1b83287 100644 --- a/sound/drivers/portman2x4.c +++ b/sound/drivers/portman2x4.c @@ -668,7 +668,7 @@ static int __devinit snd_portman_probe_port(struct parport *p) parport_release(pardev); parport_unregister_device(pardev); - return res; + return res ? -EIO : 0; } static void __devinit snd_portman_attach(struct parport *p) diff --git a/sound/pci/ca0106/ca0106_mixer.c b/sound/pci/ca0106/ca0106_mixer.c index be519a1..3f9b5c5 100644 --- a/sound/pci/ca0106/ca0106_mixer.c +++ b/sound/pci/ca0106/ca0106_mixer.c @@ -86,7 +86,7 @@ static int snd_ca0106_shared_spdif_get(struct snd_kcontrol *kcontrol, { struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol); - ucontrol->value.enumerated.item[0] = emu->spdif_enable; + ucontrol->value.integer.value[0] = emu->spdif_enable; return 0; } @@ -98,11 +98,11 @@ static int snd_ca0106_shared_spdif_put(struct snd_kcontrol *kcontrol, int change = 0; u32 mask; - val = ucontrol->value.enumerated.item[0] ; + val = !!ucontrol->value.integer.value[0]; change = (emu->spdif_enable != val); if (change) { emu->spdif_enable = val; - if (val == 1) { + if (val) { /* Digital */ snd_ca0106_ptr_write(emu, SPDIF_SELECT1, 0, 0xf); snd_ca0106_ptr_write(emu, SPDIF_SELECT2, 0, 0x0b000000); @@ -159,6 +159,8 @@ static int snd_ca0106_capture_source_put(struct snd_kcontrol *kcontrol, u32 source; val = ucontrol->value.enumerated.item[0] ; + if (val >= 6) + return -EINVAL; change = (emu->capture_source != val); if (change) { emu->capture_source = val; @@ -207,6 +209,8 @@ static int snd_ca0106_i2c_capture_source_put(struct snd_kcontrol *kcontrol, * for the particular source. */ source_id = ucontrol->value.enumerated.item[0] ; + if (source_id >= 4) + return -EINVAL; change = (emu->i2c_capture_source != source_id); if (change) { snd_ca0106_i2c_write(emu, ADC_MUX, 0); /* Mute input */ @@ -271,6 +275,8 @@ static int snd_ca0106_capture_mic_line_in_put(struct snd_kcontrol *kcontrol, u32 tmp; val = ucontrol->value.enumerated.item[0] ; + if (val > 1) + return -EINVAL; change = (emu->capture_mic_line_in != val); if (change) { emu->capture_mic_line_in = val; @@ -443,7 +449,7 @@ static int snd_ca0106_i2c_volume_put(struct snd_kcontrol *kcontrol, ogain = emu->i2c_capture_volume[source_id][0]; /* Left */ ngain = ucontrol->value.integer.value[0]; if (ngain > 0xff) - return 0; + return -EINVAL; if (ogain != ngain) { if (emu->i2c_capture_source == source_id) snd_ca0106_i2c_write(emu, ADC_ATTEN_ADCL, ((ngain) & 0xff) ); @@ -453,7 +459,7 @@ static int snd_ca0106_i2c_volume_put(struct snd_kcontrol *kcontrol, ogain = emu->i2c_capture_volume[source_id][1]; /* Right */ ngain = ucontrol->value.integer.value[1]; if (ngain > 0xff) - return 0; + return -EINVAL; if (ogain != ngain) { if (emu->i2c_capture_source == source_id) snd_ca0106_i2c_write(emu, ADC_ATTEN_ADCR, ((ngain) & 0xff)); @@ -497,7 +503,7 @@ static int spi_mute_put(struct snd_kcontrol *kcontrol, } ret = snd_ca0106_spi_write(emu, emu->spi_dac_reg[reg]); - return ret ? -1 : 1; + return ret ? -EINVAL : 1; } #define CA_VOLUME(xname,chid,reg) \ diff --git a/sound/pci/ca0106/ca0106_proc.c b/sound/pci/ca0106/ca0106_proc.c index ae80f51..61f2718 100644 --- a/sound/pci/ca0106/ca0106_proc.c +++ b/sound/pci/ca0106/ca0106_proc.c @@ -445,13 +445,11 @@ int __devinit snd_ca0106_proc_init(struct snd_ca0106 * emu) snd_info_set_text_ops(entry, emu, snd_ca0106_proc_reg_read1); entry->c.text.write = snd_ca0106_proc_reg_write; entry->mode |= S_IWUSR; -// entry->private_data = emu; } if(! snd_card_proc_new(emu->card, "ca0106_i2c", &entry)) { - snd_info_set_text_ops(entry, emu, snd_ca0106_proc_i2c_write); entry->c.text.write = snd_ca0106_proc_i2c_write; + entry->private_data = emu; entry->mode |= S_IWUSR; -// entry->private_data = emu; } if(! snd_card_proc_new(emu->card, "ca0106_regs2", &entry)) snd_info_set_text_ops(entry, emu, snd_ca0106_proc_reg_read2); diff --git a/sound/pci/cmipci.c b/sound/pci/cmipci.c index 6832649..1fa5f00 100644 --- a/sound/pci/cmipci.c +++ b/sound/pci/cmipci.c @@ -246,10 +246,9 @@ MODULE_PARM_DESC(joystick_port, "Joystick port address."); #define CM_MMODE_MASK 0x00000E00 /* model DAA interface mode */ #define CM_SPDIF_SELECT2 0x00000100 /* for model > 039 ? */ #define CM_ENCENTER 0x00000080 -#define CM_FLINKON 0x00000080 /* force modem link detection on, model 037 */ +#define CM_FLINKON 0x00000040 /* force modem link detection on, model 037 */ #define CM_MUTECH1 0x00000040 /* mute PCI ch1 to DAC */ -#define CM_FLINKOFF 0x00000040 /* force modem link detection off, model 037 */ -#define CM_UNKNOWN_18_5 0x00000020 /* ? */ +#define CM_FLINKOFF 0x00000020 /* force modem link detection off, model 037 */ #define CM_MIDSMP 0x00000010 /* 1/2 interpolation at front end DAC */ #define CM_UPDDMA_MASK 0x0000000C /* TDMA position update notification */ #define CM_UPDDMA_2048 0x00000000 diff --git a/sound/pci/emu10k1/emumixer.c b/sound/pci/emu10k1/emumixer.c index 54a2034..ccacd7b 100644 --- a/sound/pci/emu10k1/emumixer.c +++ b/sound/pci/emu10k1/emumixer.c @@ -58,6 +58,9 @@ static int snd_emu10k1_spdif_get(struct snd_kcontrol *kcontrol, unsigned int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); unsigned long flags; + /* Limit: emu->spdif_bits */ + if (idx >= 3) + return -EINVAL; spin_lock_irqsave(&emu->reg_lock, flags); ucontrol->value.iec958.status[0] = (emu->spdif_bits[idx] >> 0) & 0xff; ucontrol->value.iec958.status[1] = (emu->spdif_bits[idx] >> 8) & 0xff; @@ -272,9 +275,12 @@ static int snd_emu1010_output_source_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); - int channel; + unsigned int channel; channel = (kcontrol->private_value) & 0xff; + /* Limit: emu1010_output_dst, emu->emu1010.output_source */ + if (channel >= 24) + return -EINVAL; ucontrol->value.enumerated.item[0] = emu->emu1010.output_source[channel]; return 0; } @@ -285,11 +291,17 @@ static int snd_emu1010_output_source_put(struct snd_kcontrol *kcontrol, struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); int change = 0; unsigned int val; - int channel; + unsigned int channel; + val = ucontrol->value.enumerated.item[0]; + if (val >= 53) + return -EINVAL; channel = (kcontrol->private_value) & 0xff; - if (emu->emu1010.output_source[channel] != ucontrol->value.enumerated.item[0]) { - val = emu->emu1010.output_source[channel] = ucontrol->value.enumerated.item[0]; + /* Limit: emu1010_output_dst, emu->emu1010.output_source */ + if (channel >= 24) + return -EINVAL; + if (emu->emu1010.output_source[channel] != val) { + emu->emu1010.output_source[channel] = val; change = 1; snd_emu1010_fpga_link_dst_src_write(emu, emu1010_output_dst[channel], emu1010_src_regs[val]); @@ -301,9 +313,12 @@ static int snd_emu1010_input_source_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); - int channel; + unsigned int channel; channel = (kcontrol->private_value) & 0xff; + /* Limit: emu1010_input_dst, emu->emu1010.input_source */ + if (channel >= 22) + return -EINVAL; ucontrol->value.enumerated.item[0] = emu->emu1010.input_source[channel]; return 0; } @@ -314,11 +329,17 @@ static int snd_emu1010_input_source_put(struct snd_kcontrol *kcontrol, struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); int change = 0; unsigned int val; - int channel; + unsigned int channel; + val = ucontrol->value.enumerated.item[0]; + if (val >= 53) + return -EINVAL; channel = (kcontrol->private_value) & 0xff; - if (emu->emu1010.input_source[channel] != ucontrol->value.enumerated.item[0]) { - val = emu->emu1010.input_source[channel] = ucontrol->value.enumerated.item[0]; + /* Limit: emu1010_input_dst, emu->emu1010.input_source */ + if (channel >= 22) + return -EINVAL; + if (emu->emu1010.input_source[channel] != val) { + emu->emu1010.input_source[channel] = val; change = 1; snd_emu1010_fpga_link_dst_src_write(emu, emu1010_input_dst[channel], emu1010_src_regs[val]); @@ -533,6 +554,9 @@ static int snd_emu1010_internal_clock_put(struct snd_kcontrol *kcontrol, int change = 0; val = ucontrol->value.enumerated.item[0] ; + /* Limit: uinfo->value.enumerated.items = 4; */ + if (val >= 4) + return -EINVAL; change = (emu->emu1010.internal_clock != val); if (change) { emu->emu1010.internal_clock = val; @@ -669,7 +693,11 @@ static int snd_audigy_i2c_capture_source_put(struct snd_kcontrol *kcontrol, * update the capture volume from the cached value * for the particular source. */ - source_id = ucontrol->value.enumerated.item[0]; /* Use 2 and 3 */ + source_id = ucontrol->value.enumerated.item[0]; + /* Limit: uinfo->value.enumerated.items = 2; */ + /* emu->i2c_capture_volume */ + if (source_id >= 2) + return -EINVAL; change = (emu->i2c_capture_source != source_id); if (change) { snd_emu10k1_i2c_write(emu, ADC_MUX, 0); /* Mute input */ @@ -720,9 +748,13 @@ static int snd_audigy_i2c_volume_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); - int source_id; + unsigned int source_id; source_id = kcontrol->private_value; + /* Limit: emu->i2c_capture_volume */ + /* capture_source: uinfo->value.enumerated.items = 2 */ + if (source_id >= 2) + return -EINVAL; ucontrol->value.integer.value[0] = emu->i2c_capture_volume[source_id][0]; ucontrol->value.integer.value[1] = emu->i2c_capture_volume[source_id][1]; @@ -735,10 +767,14 @@ static int snd_audigy_i2c_volume_put(struct snd_kcontrol *kcontrol, struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); unsigned int ogain; unsigned int ngain; - int source_id; + unsigned int source_id; int change = 0; source_id = kcontrol->private_value; + /* Limit: emu->i2c_capture_volume */ + /* capture_source: uinfo->value.enumerated.items = 2 */ + if (source_id >= 2) + return -EINVAL; ogain = emu->i2c_capture_volume[source_id][0]; /* Left */ ngain = ucontrol->value.integer.value[0]; if (ngain > 0xff) @@ -746,7 +782,7 @@ static int snd_audigy_i2c_volume_put(struct snd_kcontrol *kcontrol, if (ogain != ngain) { if (emu->i2c_capture_source == source_id) snd_emu10k1_i2c_write(emu, ADC_ATTEN_ADCL, ((ngain) & 0xff) ); - emu->i2c_capture_volume[source_id][0] = ucontrol->value.integer.value[0]; + emu->i2c_capture_volume[source_id][0] = ngain; change = 1; } ogain = emu->i2c_capture_volume[source_id][1]; /* Right */ @@ -756,7 +792,7 @@ static int snd_audigy_i2c_volume_put(struct snd_kcontrol *kcontrol, if (ogain != ngain) { if (emu->i2c_capture_source == source_id) snd_emu10k1_i2c_write(emu, ADC_ATTEN_ADCR, ((ngain) & 0xff)); - emu->i2c_capture_volume[source_id][1] = ucontrol->value.integer.value[1]; + emu->i2c_capture_volume[source_id][1] = ngain; change = 1; } @@ -877,6 +913,9 @@ static int snd_emu10k1_spdif_put(struct snd_kcontrol *kcontrol, unsigned int val; unsigned long flags; + /* Limit: emu->spdif_bits */ + if (idx >= 3) + return -EINVAL; val = (ucontrol->value.iec958.status[0] << 0) | (ucontrol->value.iec958.status[1] << 8) | (ucontrol->value.iec958.status[2] << 16) | diff --git a/sound/pci/emu10k1/p16v.c b/sound/pci/emu10k1/p16v.c index d619a38..9fd3135 100644 --- a/sound/pci/emu10k1/p16v.c +++ b/sound/pci/emu10k1/p16v.c @@ -742,6 +742,8 @@ static int snd_p16v_capture_source_put(struct snd_kcontrol *kcontrol, u32 source; val = ucontrol->value.enumerated.item[0] ; + if (val > 7) + return -EINVAL; change = (emu->p16v_capture_source != val); if (change) { emu->p16v_capture_source = val; @@ -784,6 +786,8 @@ static int snd_p16v_capture_channel_put(struct snd_kcontrol *kcontrol, u32 tmp; val = ucontrol->value.enumerated.item[0] ; + if (val > 3) + return -EINVAL; change = (emu->p16v_capture_channel != val); if (change) { emu->p16v_capture_channel = val; diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index ad4cb38..8cbe3bf 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c @@ -1625,19 +1625,26 @@ static void hda_set_power_state(struct hda_codec *codec, hda_nid_t fg, nid = codec->start_nid; for (i = 0; i < codec->num_nodes; i++, nid++) { - if (get_wcaps(codec, nid) & AC_WCAP_POWER) { - unsigned int pincap; - /* - * don't power down the widget if it controls eapd - * and EAPD_BTLENABLE is set. - */ - pincap = snd_hda_param_read(codec, nid, AC_PAR_PIN_CAP); - if (pincap & AC_PINCAP_EAPD) { - int eapd = snd_hda_codec_read(codec, nid, - 0, AC_VERB_GET_EAPD_BTLENABLE, 0); - eapd &= 0x02; - if (power_state == AC_PWRST_D3 && eapd) - continue; + unsigned int wcaps = get_wcaps(codec, nid); + if (wcaps & AC_WCAP_POWER) { + unsigned int wid_type = (wcaps & AC_WCAP_TYPE) >> + AC_WCAP_TYPE_SHIFT; + if (wid_type == AC_WID_PIN) { + unsigned int pincap; + /* + * don't power down the widget if it controls + * eapd and EAPD_BTLENABLE is set. + */ + pincap = snd_hda_param_read(codec, nid, + AC_PAR_PIN_CAP); + if (pincap & AC_PINCAP_EAPD) { + int eapd = snd_hda_codec_read(codec, + nid, 0, + AC_VERB_GET_EAPD_BTLENABLE, 0); + eapd &= 0x02; + if (power_state == AC_PWRST_D3 && eapd) + continue; + } } snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_POWER_STATE, @@ -2485,13 +2492,14 @@ int snd_hda_multi_out_analog_prepare(struct hda_codec *codec, /* front */ snd_hda_codec_setup_stream(codec, nids[HDA_FRONT], stream_tag, 0, format); - if (mout->hp_nid && mout->hp_nid != nids[HDA_FRONT]) + if (!mout->no_share_stream && + mout->hp_nid && mout->hp_nid != nids[HDA_FRONT]) /* headphone out will just decode front left/right (stereo) */ snd_hda_codec_setup_stream(codec, mout->hp_nid, stream_tag, 0, format); /* extra outputs copied from front */ for (i = 0; i < ARRAY_SIZE(mout->extra_out_nid); i++) - if (mout->extra_out_nid[i]) + if (!mout->no_share_stream && mout->extra_out_nid[i]) snd_hda_codec_setup_stream(codec, mout->extra_out_nid[i], stream_tag, 0, format); @@ -2501,7 +2509,7 @@ int snd_hda_multi_out_analog_prepare(struct hda_codec *codec, if (chs >= (i + 1) * 2) /* independent out */ snd_hda_codec_setup_stream(codec, nids[i], stream_tag, i * 2, format); - else /* copy front */ + else if (!mout->no_share_stream) /* copy front */ snd_hda_codec_setup_stream(codec, nids[i], stream_tag, 0, format); } diff --git a/sound/pci/hda/hda_local.h b/sound/pci/hda/hda_local.h index 20c5e62..8c56c9c 100644 --- a/sound/pci/hda/hda_local.h +++ b/sound/pci/hda/hda_local.h @@ -220,6 +220,7 @@ struct hda_multi_out { hda_nid_t dig_out_nid; /* digital out audio widget */ int max_channels; /* currently supported analog channels */ int dig_out_used; /* current usage of digital out (HDA_DIG_XXX) */ + int no_share_stream; /* don't share a stream with multiple pins */ }; int snd_hda_multi_out_dig_open(struct hda_codec *codec, diff --git a/sound/pci/hda/patch_analog.c b/sound/pci/hda/patch_analog.c index 0ee8ae4..196ad3c 100644 --- a/sound/pci/hda/patch_analog.c +++ b/sound/pci/hda/patch_analog.c @@ -957,6 +957,14 @@ static int patch_ad1986a(struct hda_codec *codec) break; } + /* AD1986A has a hardware problem that it can't share a stream + * with multiple output pins. The copy of front to surrounds + * causes noisy or silent outputs at a certain timing, e.g. + * changing the volume. + * So, let's disable the shared stream. + */ + spec->multiout.no_share_stream = 1; + return 0; } diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index f9b2c43..0401223 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c @@ -111,7 +111,6 @@ struct sigmatel_spec { unsigned int alt_switch: 1; unsigned int hp_detect: 1; unsigned int gpio_mute: 1; - unsigned int no_vol_knob :1; unsigned int gpio_mask, gpio_data; @@ -342,42 +341,6 @@ static int stac92xx_aloopback_put(struct snd_kcontrol *kcontrol, return 1; } -static int stac92xx_volknob_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 1; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = 127; - return 0; -} - -static int stac92xx_volknob_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - ucontrol->value.integer.value[0] = kcontrol->private_value & 0xff; - return 0; -} - -static int stac92xx_volknob_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - unsigned int val = kcontrol->private_value & 0xff; - - if (val == ucontrol->value.integer.value[0]) - return 0; - - val = ucontrol->value.integer.value[0]; - kcontrol->private_value &= ~0xff; - kcontrol->private_value |= val; - - snd_hda_codec_write_cache(codec, kcontrol->private_value >> 16, 0, - AC_VERB_SET_VOLUME_KNOB_CONTROL, val | 0x80); - return 1; -} - - static struct hda_verb stac9200_core_init[] = { /* set dac0mux for dac converter */ { 0x07, AC_VERB_SET_CONNECT_SEL, 0x00}, @@ -446,18 +409,6 @@ static struct hda_verb stac9205_core_init[] = { .private_value = verb_read | (verb_write << 16), \ } -#define STAC_VOLKNOB(knob_nid) \ - { \ - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ - .name = "Master Playback Volume", \ - .count = 1, \ - .info = stac92xx_volknob_info, \ - .get = stac92xx_volknob_get, \ - .put = stac92xx_volknob_put, \ - .private_value = 127 | (knob_nid << 16), \ - } - - static struct snd_kcontrol_new stac9200_mixer[] = { HDA_CODEC_VOLUME("Master Playback Volume", 0xb, 0, HDA_OUTPUT), HDA_CODEC_MUTE("Master Playback Switch", 0xb, 0, HDA_OUTPUT), @@ -487,7 +438,6 @@ static struct snd_kcontrol_new stac9205_mixer[] = { }, STAC_INPUT_SOURCE(2), STAC_ANALOG_LOOPBACK(0xFE0, 0x7E0), - STAC_VOLKNOB(0x24), HDA_CODEC_VOLUME_IDX("Capture Volume", 0x0, 0x1b, 0x0, HDA_INPUT), HDA_CODEC_MUTE_IDX("Capture Switch", 0x0, 0x1d, 0x0, HDA_OUTPUT), @@ -503,7 +453,6 @@ static struct snd_kcontrol_new stac9205_mixer[] = { /* This needs to be generated dynamically based on sequence */ static struct snd_kcontrol_new stac922x_mixer[] = { STAC_INPUT_SOURCE(2), - STAC_VOLKNOB(0x16), HDA_CODEC_VOLUME_IDX("Capture Volume", 0x0, 0x17, 0x0, HDA_INPUT), HDA_CODEC_MUTE_IDX("Capture Switch", 0x0, 0x17, 0x0, HDA_INPUT), HDA_CODEC_VOLUME_IDX("Mux Capture Volume", 0x0, 0x12, 0x0, HDA_OUTPUT), @@ -517,7 +466,6 @@ static struct snd_kcontrol_new stac922x_mixer[] = { static struct snd_kcontrol_new stac927x_mixer[] = { STAC_INPUT_SOURCE(3), - STAC_VOLKNOB(0x24), STAC_ANALOG_LOOPBACK(0xFEB, 0x7EB), HDA_CODEC_VOLUME_IDX("Capture Volume", 0x0, 0x18, 0x0, HDA_INPUT), @@ -1931,8 +1879,7 @@ static int stac92xx_auto_create_hp_ctls(struct hda_codec *codec, } if (spec->multiout.hp_nid) { const char *pfx; - if (old_num_dacs == spec->multiout.num_dacs && - spec->no_vol_knob) + if (old_num_dacs == spec->multiout.num_dacs) pfx = "Master"; else pfx = "Headphone"; @@ -2489,7 +2436,6 @@ static int patch_stac9200(struct hda_codec *codec) codec->spec = spec; spec->num_pins = ARRAY_SIZE(stac9200_pin_nids); spec->pin_nids = stac9200_pin_nids; - spec->no_vol_knob = 1; spec->board_config = snd_hda_check_board_config(codec, STAC_9200_MODELS, stac9200_models, stac9200_cfg_tbl); @@ -2544,7 +2490,6 @@ static int patch_stac925x(struct hda_codec *codec) codec->spec = spec; spec->num_pins = ARRAY_SIZE(stac925x_pin_nids); spec->pin_nids = stac925x_pin_nids; - spec->no_vol_knob = 1; spec->board_config = snd_hda_check_board_config(codec, STAC_925x_MODELS, stac925x_models, stac925x_cfg_tbl); diff --git a/sound/soc/codecs/cs4270.c b/sound/soc/codecs/cs4270.c index 5d601ad..abac628 100644 --- a/sound/soc/codecs/cs4270.c +++ b/sound/soc/codecs/cs4270.c @@ -725,7 +725,8 @@ static int cs4270_probe(struct platform_device *pdev) codec->owner = THIS_MODULE; codec->dai = &cs4270_dai; codec->num_dai = 1; - codec->private_data = codec + ALIGN(sizeof(struct snd_soc_codec), 4); + codec->private_data = (void *) codec + + ALIGN(sizeof(struct snd_soc_codec), 4); socdev->codec = codec; diff --git a/sound/soc/s3c24xx/s3c2443-ac97.c b/sound/soc/s3c24xx/s3c2443-ac97.c index 75acf7e..758a263 100644 --- a/sound/soc/s3c24xx/s3c2443-ac97.c +++ b/sound/soc/s3c24xx/s3c2443-ac97.c @@ -32,7 +32,7 @@ #include <asm/hardware.h> #include <asm/io.h> -#include <asm/arch/regs-ac97.h> +#include <asm/plat-s3c/regs-ac97.h> #include <asm/arch/regs-gpio.h> #include <asm/arch/regs-clock.h> #include <asm/arch/audio.h> |