Merge branch 'gfar' of master.kernel.org:/pub/scm/linux/kernel/git/galak/powerpc into upstream
This commit is contained in:
commit
48c871c1f6
2243 changed files with 57344 additions and 41439 deletions
10
CREDITS
10
CREDITS
|
@ -2571,6 +2571,16 @@ S: Subiaco, 6008
|
|||
S: Perth, Western Australia
|
||||
S: Australia
|
||||
|
||||
N: Miguel Ojeda Sandonis
|
||||
E: maxextreme@gmail.com
|
||||
D: Author: Auxiliary LCD Controller driver (ks0108)
|
||||
D: Author: Auxiliary LCD driver (cfag12864b)
|
||||
D: Author: Auxiliary LCD framebuffer driver (cfag12864bfb)
|
||||
D: Maintainer: Auxiliary display drivers tree (drivers/auxdisplay/*)
|
||||
S: C/ Mieses 20, 9-B
|
||||
S: Valladolid 47009
|
||||
S: Spain
|
||||
|
||||
N: Greg Page
|
||||
E: gpage@sovereign.org
|
||||
D: IPX development and support
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
What: /debug/pktcdvd/pktcdvd[0-7]
|
||||
Date: Oct. 2006
|
||||
KernelVersion: 2.6.19
|
||||
KernelVersion: 2.6.20
|
||||
Contact: Thomas Maier <balagi@justmail.de>
|
||||
Description:
|
||||
|
||||
|
@ -11,8 +11,7 @@ The pktcdvd module (packet writing driver) creates
|
|||
these files in debugfs:
|
||||
|
||||
/debug/pktcdvd/pktcdvd[0-7]/
|
||||
info (0444) Lots of human readable driver
|
||||
statistics and infos. Multiple lines!
|
||||
info (0444) Lots of driver statistics and infos.
|
||||
|
||||
Example:
|
||||
-------
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
What: /sys/class/pktcdvd/
|
||||
Date: Oct. 2006
|
||||
KernelVersion: 2.6.19
|
||||
KernelVersion: 2.6.20
|
||||
Contact: Thomas Maier <balagi@justmail.de>
|
||||
Description:
|
||||
|
||||
|
|
|
@ -482,13 +482,13 @@ slightly.
|
|||
<para>Gadget drivers
|
||||
rely on common USB structures and constants
|
||||
defined in the
|
||||
<filename><linux/usb_ch9.h></filename>
|
||||
<filename><linux/usb/ch9.h></filename>
|
||||
header file, which is standard in Linux 2.6 kernels.
|
||||
These are the same types and constants used by host
|
||||
side drivers (and usbcore).
|
||||
</para>
|
||||
|
||||
!Iinclude/linux/usb_ch9.h
|
||||
!Iinclude/linux/usb/ch9.h
|
||||
</sect1>
|
||||
|
||||
<sect1 id="core"><title>Core Objects and Methods</title>
|
||||
|
|
|
@ -316,6 +316,9 @@ X!Earch/i386/kernel/mca.c
|
|||
<sect1><title>DMI Interfaces</title>
|
||||
!Edrivers/firmware/dmi_scan.c
|
||||
</sect1>
|
||||
<sect1><title>EDD Interfaces</title>
|
||||
!Idrivers/firmware/edd.c
|
||||
</sect1>
|
||||
</chapter>
|
||||
|
||||
<chapter id="security">
|
||||
|
|
|
@ -4,4 +4,5 @@
|
|||
<param name="funcsynopsis.style">ansi</param>
|
||||
<param name="funcsynopsis.tabular.threshold">80</param>
|
||||
<!-- <param name="paper.type">A4</param> -->
|
||||
<param name="generate.section.toc.level">2</param>
|
||||
</stylesheet>
|
||||
|
|
|
@ -187,13 +187,13 @@
|
|||
|
||||
<chapter><title>USB-Standard Types</title>
|
||||
|
||||
<para>In <filename><linux/usb_ch9.h></filename> you will find
|
||||
<para>In <filename><linux/usb/ch9.h></filename> you will find
|
||||
the USB data types defined in chapter 9 of the USB specification.
|
||||
These data types are used throughout USB, and in APIs including
|
||||
this host side API, gadget APIs, and usbfs.
|
||||
</para>
|
||||
|
||||
!Iinclude/linux/usb_ch9.h
|
||||
!Iinclude/linux/usb/ch9.h
|
||||
|
||||
</chapter>
|
||||
|
||||
|
@ -574,7 +574,7 @@ for (;;) {
|
|||
#include <asm/byteorder.h></programlisting>
|
||||
The standard USB device model requests, from "Chapter 9" of
|
||||
the USB 2.0 specification, are automatically included from
|
||||
the <filename><linux/usb_ch9.h></filename> header.
|
||||
the <filename><linux/usb/ch9.h></filename> header.
|
||||
</para>
|
||||
|
||||
<para>Unless noted otherwise, the ioctl requests
|
||||
|
|
105
Documentation/auxdisplay/cfag12864b
Normal file
105
Documentation/auxdisplay/cfag12864b
Normal file
|
@ -0,0 +1,105 @@
|
|||
===================================
|
||||
cfag12864b LCD Driver Documentation
|
||||
===================================
|
||||
|
||||
License: GPLv2
|
||||
Author & Maintainer: Miguel Ojeda Sandonis <maxextreme@gmail.com>
|
||||
Date: 2006-10-27
|
||||
|
||||
|
||||
|
||||
--------
|
||||
0. INDEX
|
||||
--------
|
||||
|
||||
1. DRIVER INFORMATION
|
||||
2. DEVICE INFORMATION
|
||||
3. WIRING
|
||||
4. USERSPACE PROGRAMMING
|
||||
|
||||
|
||||
---------------------
|
||||
1. DRIVER INFORMATION
|
||||
---------------------
|
||||
|
||||
This driver support one cfag12864b display at time.
|
||||
|
||||
|
||||
---------------------
|
||||
2. DEVICE INFORMATION
|
||||
---------------------
|
||||
|
||||
Manufacturer: Crystalfontz
|
||||
Device Name: Crystalfontz 12864b LCD Series
|
||||
Device Code: cfag12864b
|
||||
Webpage: http://www.crystalfontz.com
|
||||
Device Webpage: http://www.crystalfontz.com/products/12864b/
|
||||
Type: LCD (Liquid Crystal Display)
|
||||
Width: 128
|
||||
Height: 64
|
||||
Colors: 2 (B/N)
|
||||
Controller: ks0108
|
||||
Controllers: 2
|
||||
Pages: 8 each controller
|
||||
Addresses: 64 each page
|
||||
Data size: 1 byte each address
|
||||
Memory size: 2 * 8 * 64 * 1 = 1024 bytes = 1 Kbyte
|
||||
|
||||
|
||||
---------
|
||||
3. WIRING
|
||||
---------
|
||||
|
||||
The cfag12864b LCD Series don't have official wiring.
|
||||
|
||||
The common wiring is done to the parallel port as shown:
|
||||
|
||||
Parallel Port cfag12864b
|
||||
|
||||
Name Pin# Pin# Name
|
||||
|
||||
Strobe ( 1)------------------------------(17) Enable
|
||||
Data 0 ( 2)------------------------------( 4) Data 0
|
||||
Data 1 ( 3)------------------------------( 5) Data 1
|
||||
Data 2 ( 4)------------------------------( 6) Data 2
|
||||
Data 3 ( 5)------------------------------( 7) Data 3
|
||||
Data 4 ( 6)------------------------------( 8) Data 4
|
||||
Data 5 ( 7)------------------------------( 9) Data 5
|
||||
Data 6 ( 8)------------------------------(10) Data 6
|
||||
Data 7 ( 9)------------------------------(11) Data 7
|
||||
(10) [+5v]---( 1) Vdd
|
||||
(11) [GND]---( 2) Ground
|
||||
(12) [+5v]---(14) Reset
|
||||
(13) [GND]---(15) Read / Write
|
||||
Line (14)------------------------------(13) Controller Select 1
|
||||
(15)
|
||||
Init (16)------------------------------(12) Controller Select 2
|
||||
Select (17)------------------------------(16) Data / Instruction
|
||||
Ground (18)---[GND] [+5v]---(19) LED +
|
||||
Ground (19)---[GND]
|
||||
Ground (20)---[GND] E A Values:
|
||||
Ground (21)---[GND] [GND]---[P1]---(18) Vee · R = Resistor = 22 ohm
|
||||
Ground (22)---[GND] | · P1 = Preset = 10 Kohm
|
||||
Ground (23)---[GND] ---- S ------( 3) V0 · P2 = Preset = 1 Kohm
|
||||
Ground (24)---[GND] | |
|
||||
Ground (25)---[GND] [GND]---[P2]---[R]---(20) LED -
|
||||
|
||||
|
||||
------------------------
|
||||
4. USERSPACE PROGRAMMING
|
||||
------------------------
|
||||
|
||||
The cfag12864bfb describes a framebuffer device (/dev/fbX).
|
||||
|
||||
It has a size of 1024 bytes = 1 Kbyte.
|
||||
Each bit represents one pixel. If the bit is high, the pixel will
|
||||
turn on. If the pixel is low, the pixel will turn off.
|
||||
|
||||
You can use the framebuffer as a file: fopen, fwrite, fclose...
|
||||
Although the LCD won't get updated until the next refresh time arrives.
|
||||
|
||||
Also, you can mmap the framebuffer: open & mmap, munmap & close...
|
||||
which is the best option for most uses.
|
||||
|
||||
Check Documentation/auxdisplay/cfag12864b-example.c
|
||||
for a real working userspace complete program with usage examples.
|
282
Documentation/auxdisplay/cfag12864b-example.c
Normal file
282
Documentation/auxdisplay/cfag12864b-example.c
Normal file
|
@ -0,0 +1,282 @@
|
|||
/*
|
||||
* Filename: cfag12864b-example.c
|
||||
* Version: 0.1.0
|
||||
* Description: cfag12864b LCD userspace example program
|
||||
* License: GPLv2
|
||||
*
|
||||
* Author: Copyright (C) Miguel Ojeda Sandonis <maxextreme@gmail.com>
|
||||
* Date: 2006-10-31
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* ------------------------
|
||||
* start of cfag12864b code
|
||||
* ------------------------
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/mman.h>
|
||||
|
||||
#define CFAG12864B_WIDTH (128)
|
||||
#define CFAG12864B_HEIGHT (64)
|
||||
#define CFAG12864B_SIZE (128 * 64 / 8)
|
||||
#define CFAG12864B_BPB (8)
|
||||
#define CFAG12864B_ADDRESS(x, y) ((y) * CFAG12864B_WIDTH / \
|
||||
CFAG12864B_BPB + (x) / CFAG12864B_BPB)
|
||||
#define CFAG12864B_BIT(n) (((unsigned char) 1) << (n))
|
||||
|
||||
#undef CFAG12864B_DOCHECK
|
||||
#ifdef CFAG12864B_DOCHECK
|
||||
#define CFAG12864B_CHECK(x, y) ((x) < CFAG12864B_WIDTH && \
|
||||
(y) < CFAG12864B_HEIGHT)
|
||||
#else
|
||||
#define CFAG12864B_CHECK(x, y) (1)
|
||||
#endif
|
||||
|
||||
int cfag12864b_fd;
|
||||
unsigned char * cfag12864b_mem;
|
||||
unsigned char cfag12864b_buffer[CFAG12864B_SIZE];
|
||||
|
||||
/*
|
||||
* init a cfag12864b framebuffer device
|
||||
*
|
||||
* No error: return = 0
|
||||
* Unable to open: return = -1
|
||||
* Unable to mmap: return = -2
|
||||
*/
|
||||
int cfag12864b_init(char *path)
|
||||
{
|
||||
cfag12864b_fd = open(path, O_RDWR);
|
||||
if (cfag12864b_fd == -1)
|
||||
return -1;
|
||||
|
||||
cfag12864b_mem = mmap(0, CFAG12864B_SIZE, PROT_READ | PROT_WRITE,
|
||||
MAP_SHARED, cfag12864b_fd, 0);
|
||||
if (cfag12864b_mem == MAP_FAILED) {
|
||||
close(cfag12864b_fd);
|
||||
return -2;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* exit a cfag12864b framebuffer device
|
||||
*/
|
||||
void cfag12864b_exit(void)
|
||||
{
|
||||
munmap(cfag12864b_mem, CFAG12864B_SIZE);
|
||||
close(cfag12864b_fd);
|
||||
}
|
||||
|
||||
/*
|
||||
* set (x, y) pixel
|
||||
*/
|
||||
void cfag12864b_set(unsigned char x, unsigned char y)
|
||||
{
|
||||
if (CFAG12864B_CHECK(x, y))
|
||||
cfag12864b_buffer[CFAG12864B_ADDRESS(x, y)] |=
|
||||
CFAG12864B_BIT(x % CFAG12864B_BPB);
|
||||
}
|
||||
|
||||
/*
|
||||
* unset (x, y) pixel
|
||||
*/
|
||||
void cfag12864b_unset(unsigned char x, unsigned char y)
|
||||
{
|
||||
if (CFAG12864B_CHECK(x, y))
|
||||
cfag12864b_buffer[CFAG12864B_ADDRESS(x, y)] &=
|
||||
~CFAG12864B_BIT(x % CFAG12864B_BPB);
|
||||
}
|
||||
|
||||
/*
|
||||
* is set (x, y) pixel?
|
||||
*
|
||||
* Pixel off: return = 0
|
||||
* Pixel on: return = 1
|
||||
*/
|
||||
unsigned char cfag12864b_isset(unsigned char x, unsigned char y)
|
||||
{
|
||||
if (CFAG12864B_CHECK(x, y))
|
||||
if (cfag12864b_buffer[CFAG12864B_ADDRESS(x, y)] &
|
||||
CFAG12864B_BIT(x % CFAG12864B_BPB))
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* not (x, y) pixel
|
||||
*/
|
||||
void cfag12864b_not(unsigned char x, unsigned char y)
|
||||
{
|
||||
if (cfag12864b_isset(x, y))
|
||||
cfag12864b_unset(x, y);
|
||||
else
|
||||
cfag12864b_set(x, y);
|
||||
}
|
||||
|
||||
/*
|
||||
* fill (set all pixels)
|
||||
*/
|
||||
void cfag12864b_fill(void)
|
||||
{
|
||||
unsigned short i;
|
||||
|
||||
for (i = 0; i < CFAG12864B_SIZE; i++)
|
||||
cfag12864b_buffer[i] = 0xFF;
|
||||
}
|
||||
|
||||
/*
|
||||
* clear (unset all pixels)
|
||||
*/
|
||||
void cfag12864b_clear(void)
|
||||
{
|
||||
unsigned short i;
|
||||
|
||||
for (i = 0; i < CFAG12864B_SIZE; i++)
|
||||
cfag12864b_buffer[i] = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* format a [128*64] matrix
|
||||
*
|
||||
* Pixel off: src[i] = 0
|
||||
* Pixel on: src[i] > 0
|
||||
*/
|
||||
void cfag12864b_format(unsigned char * matrix)
|
||||
{
|
||||
unsigned char i, j, n;
|
||||
|
||||
for (i = 0; i < CFAG12864B_HEIGHT; i++)
|
||||
for (j = 0; j < CFAG12864B_WIDTH / CFAG12864B_BPB; j++) {
|
||||
cfag12864b_buffer[i * CFAG12864B_WIDTH / CFAG12864B_BPB +
|
||||
j] = 0;
|
||||
for (n = 0; n < CFAG12864B_BPB; n++)
|
||||
if (matrix[i * CFAG12864B_WIDTH +
|
||||
j * CFAG12864B_BPB + n])
|
||||
cfag12864b_buffer[i * CFAG12864B_WIDTH /
|
||||
CFAG12864B_BPB + j] |=
|
||||
CFAG12864B_BIT(n);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* blit buffer to lcd
|
||||
*/
|
||||
void cfag12864b_blit(void)
|
||||
{
|
||||
memcpy(cfag12864b_mem, cfag12864b_buffer, CFAG12864B_SIZE);
|
||||
}
|
||||
|
||||
/*
|
||||
* ----------------------
|
||||
* end of cfag12864b code
|
||||
* ----------------------
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#define EXAMPLES 6
|
||||
|
||||
void example(unsigned char n)
|
||||
{
|
||||
unsigned short i, j;
|
||||
unsigned char matrix[CFAG12864B_WIDTH * CFAG12864B_HEIGHT];
|
||||
|
||||
if (n > EXAMPLES)
|
||||
return;
|
||||
|
||||
printf("Example %i/%i - ", n, EXAMPLES);
|
||||
|
||||
switch (n) {
|
||||
case 1:
|
||||
printf("Draw points setting bits");
|
||||
cfag12864b_clear();
|
||||
for (i = 0; i < CFAG12864B_WIDTH; i += 2)
|
||||
for (j = 0; j < CFAG12864B_HEIGHT; j += 2)
|
||||
cfag12864b_set(i, j);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
printf("Clear the LCD");
|
||||
cfag12864b_clear();
|
||||
break;
|
||||
|
||||
case 3:
|
||||
printf("Draw rows formatting a [128*64] matrix");
|
||||
memset(matrix, 0, CFAG12864B_WIDTH * CFAG12864B_HEIGHT);
|
||||
for (i = 0; i < CFAG12864B_WIDTH; i++)
|
||||
for (j = 0; j < CFAG12864B_HEIGHT; j += 2)
|
||||
matrix[j * CFAG12864B_WIDTH + i] = 1;
|
||||
cfag12864b_format(matrix);
|
||||
break;
|
||||
|
||||
case 4:
|
||||
printf("Fill the lcd");
|
||||
cfag12864b_fill();
|
||||
break;
|
||||
|
||||
case 5:
|
||||
printf("Draw columns unsetting bits");
|
||||
for (i = 0; i < CFAG12864B_WIDTH; i += 2)
|
||||
for (j = 0; j < CFAG12864B_HEIGHT; j++)
|
||||
cfag12864b_unset(i, j);
|
||||
break;
|
||||
|
||||
case 6:
|
||||
printf("Do negative not-ing all bits");
|
||||
for (i = 0; i < CFAG12864B_WIDTH; i++)
|
||||
for (j = 0; j < CFAG12864B_HEIGHT; j ++)
|
||||
cfag12864b_not(i, j);
|
||||
break;
|
||||
}
|
||||
|
||||
puts(" - [Press Enter]");
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
unsigned char n;
|
||||
|
||||
if (argc != 2) {
|
||||
printf(
|
||||
"Sintax: %s fbdev\n"
|
||||
"Usually: /dev/fb0, /dev/fb1...\n", argv[0]);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (cfag12864b_init(argv[1])) {
|
||||
printf("Can't init %s fbdev\n", argv[1]);
|
||||
return -2;
|
||||
}
|
||||
|
||||
for (n = 1; n <= EXAMPLES; n++) {
|
||||
example(n);
|
||||
cfag12864b_blit();
|
||||
while (getchar() != '\n');
|
||||
}
|
||||
|
||||
cfag12864b_exit();
|
||||
|
||||
return 0;
|
||||
}
|
55
Documentation/auxdisplay/ks0108
Normal file
55
Documentation/auxdisplay/ks0108
Normal file
|
@ -0,0 +1,55 @@
|
|||
==========================================
|
||||
ks0108 LCD Controller Driver Documentation
|
||||
==========================================
|
||||
|
||||
License: GPLv2
|
||||
Author & Maintainer: Miguel Ojeda Sandonis <maxextreme@gmail.com>
|
||||
Date: 2006-10-27
|
||||
|
||||
|
||||
|
||||
--------
|
||||
0. INDEX
|
||||
--------
|
||||
|
||||
1. DRIVER INFORMATION
|
||||
2. DEVICE INFORMATION
|
||||
3. WIRING
|
||||
|
||||
|
||||
---------------------
|
||||
1. DRIVER INFORMATION
|
||||
---------------------
|
||||
|
||||
This driver support the ks0108 LCD controller.
|
||||
|
||||
|
||||
---------------------
|
||||
2. DEVICE INFORMATION
|
||||
---------------------
|
||||
|
||||
Manufacturer: Samsung
|
||||
Device Name: KS0108 LCD Controller
|
||||
Device Code: ks0108
|
||||
Webpage: -
|
||||
Device Webpage: -
|
||||
Type: LCD Controller (Liquid Crystal Display Controller)
|
||||
Width: 64
|
||||
Height: 64
|
||||
Colors: 2 (B/N)
|
||||
Pages: 8
|
||||
Addresses: 64 each page
|
||||
Data size: 1 byte each address
|
||||
Memory size: 8 * 64 * 1 = 512 bytes
|
||||
|
||||
|
||||
---------
|
||||
3. WIRING
|
||||
---------
|
||||
|
||||
The driver supports data parallel port wiring.
|
||||
|
||||
If you aren't building LCD related hardware, you should check
|
||||
your LCD specific wiring information in the same folder.
|
||||
|
||||
For example, check Documentation/auxdisplay/cfag12864b.
|
|
@ -93,7 +93,7 @@ Notes
|
|||
Using the pktcdvd sysfs interface
|
||||
---------------------------------
|
||||
|
||||
Since Linux 2.6.19, the pktcdvd module has a sysfs interface
|
||||
Since Linux 2.6.20, the pktcdvd module has a sysfs interface
|
||||
and can be controlled by it. For example the "pktcdvd" tool uses
|
||||
this interface. (see http://people.freenet.de/BalaGi#pktcdvd )
|
||||
|
||||
|
|
268
Documentation/driver-model/devres.txt
Normal file
268
Documentation/driver-model/devres.txt
Normal file
|
@ -0,0 +1,268 @@
|
|||
Devres - Managed Device Resource
|
||||
================================
|
||||
|
||||
Tejun Heo <teheo@suse.de>
|
||||
|
||||
First draft 10 January 2007
|
||||
|
||||
|
||||
1. Intro : Huh? Devres?
|
||||
2. Devres : Devres in a nutshell
|
||||
3. Devres Group : Group devres'es and release them together
|
||||
4. Details : Life time rules, calling context, ...
|
||||
5. Overhead : How much do we have to pay for this?
|
||||
6. List of managed interfaces : Currently implemented managed interfaces
|
||||
|
||||
|
||||
1. Intro
|
||||
--------
|
||||
|
||||
devres came up while trying to convert libata to use iomap. Each
|
||||
iomapped address should be kept and unmapped on driver detach. For
|
||||
example, a plain SFF ATA controller (that is, good old PCI IDE) in
|
||||
native mode makes use of 5 PCI BARs and all of them should be
|
||||
maintained.
|
||||
|
||||
As with many other device drivers, libata low level drivers have
|
||||
sufficient bugs in ->remove and ->probe failure path. Well, yes,
|
||||
that's probably because libata low level driver developers are lazy
|
||||
bunch, but aren't all low level driver developers? After spending a
|
||||
day fiddling with braindamaged hardware with no document or
|
||||
braindamaged document, if it's finally working, well, it's working.
|
||||
|
||||
For one reason or another, low level drivers don't receive as much
|
||||
attention or testing as core code, and bugs on driver detach or
|
||||
initilaization failure doesn't happen often enough to be noticeable.
|
||||
Init failure path is worse because it's much less travelled while
|
||||
needs to handle multiple entry points.
|
||||
|
||||
So, many low level drivers end up leaking resources on driver detach
|
||||
and having half broken failure path implementation in ->probe() which
|
||||
would leak resources or even cause oops when failure occurs. iomap
|
||||
adds more to this mix. So do msi and msix.
|
||||
|
||||
|
||||
2. Devres
|
||||
---------
|
||||
|
||||
devres is basically linked list of arbitrarily sized memory areas
|
||||
associated with a struct device. Each devres entry is associated with
|
||||
a release function. A devres can be released in several ways. No
|
||||
matter what, all devres entries are released on driver detach. On
|
||||
release, the associated release function is invoked and then the
|
||||
devres entry is freed.
|
||||
|
||||
Managed interface is created for resources commonly used by device
|
||||
drivers using devres. For example, coherent DMA memory is acquired
|
||||
using dma_alloc_coherent(). The managed version is called
|
||||
dmam_alloc_coherent(). It is identical to dma_alloc_coherent() except
|
||||
for the DMA memory allocated using it is managed and will be
|
||||
automatically released on driver detach. Implementation looks like
|
||||
the following.
|
||||
|
||||
struct dma_devres {
|
||||
size_t size;
|
||||
void *vaddr;
|
||||
dma_addr_t dma_handle;
|
||||
};
|
||||
|
||||
static void dmam_coherent_release(struct device *dev, void *res)
|
||||
{
|
||||
struct dma_devres *this = res;
|
||||
|
||||
dma_free_coherent(dev, this->size, this->vaddr, this->dma_handle);
|
||||
}
|
||||
|
||||
dmam_alloc_coherent(dev, size, dma_handle, gfp)
|
||||
{
|
||||
struct dma_devres *dr;
|
||||
void *vaddr;
|
||||
|
||||
dr = devres_alloc(dmam_coherent_release, sizeof(*dr), gfp);
|
||||
...
|
||||
|
||||
/* alloc DMA memory as usual */
|
||||
vaddr = dma_alloc_coherent(...);
|
||||
...
|
||||
|
||||
/* record size, vaddr, dma_handle in dr */
|
||||
dr->vaddr = vaddr;
|
||||
...
|
||||
|
||||
devres_add(dev, dr);
|
||||
|
||||
return vaddr;
|
||||
}
|
||||
|
||||
If a driver uses dmam_alloc_coherent(), the area is guaranteed to be
|
||||
freed whether initialization fails half-way or the device gets
|
||||
detached. If most resources are acquired using managed interface, a
|
||||
driver can have much simpler init and exit code. Init path basically
|
||||
looks like the following.
|
||||
|
||||
my_init_one()
|
||||
{
|
||||
struct mydev *d;
|
||||
|
||||
d = devm_kzalloc(dev, sizeof(*d), GFP_KERNEL);
|
||||
if (!d)
|
||||
return -ENOMEM;
|
||||
|
||||
d->ring = dmam_alloc_coherent(...);
|
||||
if (!d->ring)
|
||||
return -ENOMEM;
|
||||
|
||||
if (check something)
|
||||
return -EINVAL;
|
||||
...
|
||||
|
||||
return register_to_upper_layer(d);
|
||||
}
|
||||
|
||||
And exit path,
|
||||
|
||||
my_remove_one()
|
||||
{
|
||||
unregister_from_upper_layer(d);
|
||||
shutdown_my_hardware();
|
||||
}
|
||||
|
||||
As shown above, low level drivers can be simplified a lot by using
|
||||
devres. Complexity is shifted from less maintained low level drivers
|
||||
to better maintained higher layer. Also, as init failure path is
|
||||
shared with exit path, both can get more testing.
|
||||
|
||||
|
||||
3. Devres group
|
||||
---------------
|
||||
|
||||
Devres entries can be grouped using devres group. When a group is
|
||||
released, all contained normal devres entries and properly nested
|
||||
groups are released. One usage is to rollback series of acquired
|
||||
resources on failure. For example,
|
||||
|
||||
if (!devres_open_group(dev, NULL, GFP_KERNEL))
|
||||
return -ENOMEM;
|
||||
|
||||
acquire A;
|
||||
if (failed)
|
||||
goto err;
|
||||
|
||||
acquire B;
|
||||
if (failed)
|
||||
goto err;
|
||||
...
|
||||
|
||||
devres_remove_group(dev, NULL);
|
||||
return 0;
|
||||
|
||||
err:
|
||||
devres_release_group(dev, NULL);
|
||||
return err_code;
|
||||
|
||||
As resource acquision failure usually means probe failure, constructs
|
||||
like above are usually useful in midlayer driver (e.g. libata core
|
||||
layer) where interface function shouldn't have side effect on failure.
|
||||
For LLDs, just returning error code suffices in most cases.
|
||||
|
||||
Each group is identified by void *id. It can either be explicitly
|
||||
specified by @id argument to devres_open_group() or automatically
|
||||
created by passing NULL as @id as in the above example. In both
|
||||
cases, devres_open_group() returns the group's id. The returned id
|
||||
can be passed to other devres functions to select the target group.
|
||||
If NULL is given to those functions, the latest open group is
|
||||
selected.
|
||||
|
||||
For example, you can do something like the following.
|
||||
|
||||
int my_midlayer_create_something()
|
||||
{
|
||||
if (!devres_open_group(dev, my_midlayer_create_something, GFP_KERNEL))
|
||||
return -ENOMEM;
|
||||
|
||||
...
|
||||
|
||||
devres_close_group(dev, my_midlayer_something);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void my_midlayer_destroy_something()
|
||||
{
|
||||
devres_release_group(dev, my_midlayer_create_soemthing);
|
||||
}
|
||||
|
||||
|
||||
4. Details
|
||||
----------
|
||||
|
||||
Lifetime of a devres entry begins on devres allocation and finishes
|
||||
when it is released or destroyed (removed and freed) - no reference
|
||||
counting.
|
||||
|
||||
devres core guarantees atomicity to all basic devres operations and
|
||||
has support for single-instance devres types (atomic
|
||||
lookup-and-add-if-not-found). Other than that, synchronizing
|
||||
concurrent accesses to allocated devres data is caller's
|
||||
responsibility. This is usually non-issue because bus ops and
|
||||
resource allocations already do the job.
|
||||
|
||||
For an example of single-instance devres type, read pcim_iomap_table()
|
||||
in lib/iomap.c.
|
||||
|
||||
All devres interface functions can be called without context if the
|
||||
right gfp mask is given.
|
||||
|
||||
|
||||
5. Overhead
|
||||
-----------
|
||||
|
||||
Each devres bookkeeping info is allocated together with requested data
|
||||
area. With debug option turned off, bookkeeping info occupies 16
|
||||
bytes on 32bit machines and 24 bytes on 64bit (three pointers rounded
|
||||
up to ull alignment). If singly linked list is used, it can be
|
||||
reduced to two pointers (8 bytes on 32bit, 16 bytes on 64bit).
|
||||
|
||||
Each devres group occupies 8 pointers. It can be reduced to 6 if
|
||||
singly linked list is used.
|
||||
|
||||
Memory space overhead on ahci controller with two ports is between 300
|
||||
and 400 bytes on 32bit machine after naive conversion (we can
|
||||
certainly invest a bit more effort into libata core layer).
|
||||
|
||||
|
||||
6. List of managed interfaces
|
||||
-----------------------------
|
||||
|
||||
IO region
|
||||
devm_request_region()
|
||||
devm_request_mem_region()
|
||||
devm_release_region()
|
||||
devm_release_mem_region()
|
||||
|
||||
IRQ
|
||||
devm_request_irq()
|
||||
devm_free_irq()
|
||||
|
||||
DMA
|
||||
dmam_alloc_coherent()
|
||||
dmam_free_coherent()
|
||||
dmam_alloc_noncoherent()
|
||||
dmam_free_noncoherent()
|
||||
dmam_declare_coherent_memory()
|
||||
dmam_pool_create()
|
||||
dmam_pool_destroy()
|
||||
|
||||
PCI
|
||||
pcim_enable_device() : after success, all PCI ops become managed
|
||||
pcim_pin_device() : keep PCI device enabled after release
|
||||
|
||||
IOMAP
|
||||
devm_ioport_map()
|
||||
devm_ioport_unmap()
|
||||
devm_ioremap()
|
||||
devm_ioremap_nocache()
|
||||
devm_iounmap()
|
||||
pcim_iomap()
|
||||
pcim_iounmap()
|
||||
pcim_iomap_table() : array of mapped addresses indexed by BAR
|
||||
pcim_iomap_regions() : do request_region() and iomap() on multiple BARs
|
|
@ -339,7 +339,21 @@ Device Symlink:
|
|||
|
||||
'device'
|
||||
|
||||
Symlink to the memory controller device
|
||||
Symlink to the memory controller device.
|
||||
|
||||
Sdram memory scrubbing rate:
|
||||
|
||||
'sdram_scrub_rate'
|
||||
|
||||
Read/Write attribute file that controls memory scrubbing. The scrubbing
|
||||
rate is set by writing a minimum bandwith in bytes/sec to the attribute
|
||||
file. The rate will be translated to an internal value that gives at
|
||||
least the specified rate.
|
||||
|
||||
Reading the file will return the actual scrubbing rate employed.
|
||||
|
||||
If configuration fails or memory scrubbing is not implemented, the value
|
||||
of the attribute file will be -1.
|
||||
|
||||
|
||||
|
||||
|
|
78
Documentation/fb/s3fb.txt
Normal file
78
Documentation/fb/s3fb.txt
Normal file
|
@ -0,0 +1,78 @@
|
|||
|
||||
s3fb - fbdev driver for S3 Trio/Virge chips
|
||||
===========================================
|
||||
|
||||
|
||||
Supported Hardware
|
||||
==================
|
||||
|
||||
S3 Trio32
|
||||
S3 Trio64 (and variants V+, UV+, V2/DX, V2/GX)
|
||||
S3 Virge (and variants VX, DX, GX and GX2+)
|
||||
S3 Plato/PX (completely untested)
|
||||
S3 Aurora64V+ (completely untested)
|
||||
|
||||
- only PCI bus supported
|
||||
- only BIOS initialized VGA devices supported
|
||||
- probably not working on big endian
|
||||
|
||||
I tested s3fb on Trio64 (plain, V+ and V2/DX) and Virge (plain, VX, DX),
|
||||
all on i386.
|
||||
|
||||
|
||||
Supported Features
|
||||
==================
|
||||
|
||||
* 4 bpp pseudocolor modes (with 18bit palette, two variants)
|
||||
* 8 bpp pseudocolor mode (with 18bit palette)
|
||||
* 16 bpp truecolor modes (RGB 555 and RGB 565)
|
||||
* 24 bpp truecolor mode (RGB 888) on (only on Virge VX)
|
||||
* 32 bpp truecolor mode (RGB 888) on (not on Virge VX)
|
||||
* text mode (activated by bpp = 0)
|
||||
* interlaced mode variant (not available in text mode)
|
||||
* doublescan mode variant (not available in text mode)
|
||||
* panning in both directions
|
||||
* suspend/resume support
|
||||
* DPMS support
|
||||
|
||||
Text mode is supported even in higher resolutions, but there is limitation
|
||||
to lower pixclocks (maximum between 50-60 MHz, depending on specific hardware).
|
||||
This limitation is not enforced by driver. Text mode supports 8bit wide fonts
|
||||
only (hardware limitation) and 16bit tall fonts (driver limitation).
|
||||
|
||||
There are two 4 bpp modes. First mode (selected if nonstd == 0) is mode with
|
||||
packed pixels, high nibble first. Second mode (selected if nonstd == 1) is mode
|
||||
with interleaved planes (1 byte interleave), MSB first. Both modes support
|
||||
8bit wide fonts only (driver limitation).
|
||||
|
||||
Suspend/resume works on systems that initialize video card during resume and
|
||||
if device is active (for example used by fbcon).
|
||||
|
||||
|
||||
Missing Features
|
||||
================
|
||||
(alias TODO list)
|
||||
|
||||
* secondary (not initialized by BIOS) device support
|
||||
* big endian support
|
||||
* Zorro bus support
|
||||
* MMIO support
|
||||
* 24 bpp mode support on more cards
|
||||
* support for fontwidths != 8 in 4 bpp modes
|
||||
* support for fontheight != 16 in text mode
|
||||
* composite and external sync (is anyone able to test this?)
|
||||
* hardware cursor
|
||||
* video overlay support
|
||||
* vsync synchronization
|
||||
* feature connector support
|
||||
* acceleration support (8514-like 2D, Virge 3D, busmaster transfers)
|
||||
* better values for some magic registers (performance issues)
|
||||
|
||||
|
||||
Known bugs
|
||||
==========
|
||||
|
||||
* cursor disable in text mode doesn't work
|
||||
|
||||
--
|
||||
Ondrej Zajicek <santiago@crfreenet.org>
|
|
@ -215,6 +215,13 @@ Who: Jean Delvare <khali@linux-fr.org>,
|
|||
|
||||
---------------------------
|
||||
|
||||
What: drivers depending on OBSOLETE_OSS
|
||||
When: options in 2.6.22, code in 2.6.24
|
||||
Why: OSS drivers with ALSA replacements
|
||||
Who: Adrian Bunk <bunk@stusta.de>
|
||||
|
||||
---------------------------
|
||||
|
||||
What: IPv4 only connection tracking/NAT/helpers
|
||||
When: 2.6.22
|
||||
Why: The new layer 3 independant connection tracking replaces the old
|
||||
|
@ -312,3 +319,18 @@ Why: In kernel tree version of driver is unmaintained. Sk98lin driver
|
|||
replaced by the skge driver.
|
||||
Who: Stephen Hemminger <shemminger@osdl.org>
|
||||
|
||||
---------------------------
|
||||
|
||||
What: Compaq touchscreen device emulation
|
||||
When: Oct 2007
|
||||
Files: drivers/input/tsdev.c
|
||||
Why: The code says it was obsolete when it was written in 2001.
|
||||
tslib is a userspace library which does anything tsdev can do and
|
||||
much more besides in userspace where this code belongs. There is no
|
||||
longer any need for tsdev and applications should have converted to
|
||||
use tslib by now.
|
||||
The name "tsdev" is also extremely confusing and lots of people have
|
||||
it loaded when they don't need/use it.
|
||||
Who: Richard Purdie <rpurdie@rpsys.net>
|
||||
|
||||
---------------------------
|
||||
|
|
|
@ -157,7 +157,7 @@ TBD(curr. line MT:/API/)
|
|||
channel management functions:
|
||||
|
||||
relay_open(base_filename, parent, subbuf_size, n_subbufs,
|
||||
callbacks)
|
||||
callbacks, private_data)
|
||||
relay_close(chan)
|
||||
relay_flush(chan)
|
||||
relay_reset(chan)
|
||||
|
@ -251,7 +251,7 @@ static struct rchan_callbacks relay_callbacks =
|
|||
|
||||
And an example relay_open() invocation using them:
|
||||
|
||||
chan = relay_open("cpu", NULL, SUBBUF_SIZE, N_SUBBUFS, &relay_callbacks);
|
||||
chan = relay_open("cpu", NULL, SUBBUF_SIZE, N_SUBBUFS, &relay_callbacks, NULL);
|
||||
|
||||
If the create_buf_file() callback fails, or isn't defined, channel
|
||||
creation and thus relay_open() will fail.
|
||||
|
@ -289,6 +289,11 @@ they use the proper locking for such a buffer, either by wrapping
|
|||
writes in a spinlock, or by copying a write function from relay.h and
|
||||
creating a local version that internally does the proper locking.
|
||||
|
||||
The private_data passed into relay_open() allows clients to associate
|
||||
user-defined data with a channel, and is immediately available
|
||||
(including in create_buf_file()) via chan->private_data or
|
||||
buf->chan->private_data.
|
||||
|
||||
Channel 'modes'
|
||||
---------------
|
||||
|
||||
|
|
|
@ -21,7 +21,7 @@ ufstype=type_of_ufs
|
|||
supported as read-write
|
||||
|
||||
ufs2 used in FreeBSD 5.x
|
||||
supported as read-only
|
||||
supported as read-write
|
||||
|
||||
5xbsd synonym for ufs2
|
||||
|
||||
|
@ -50,12 +50,11 @@ ufstype=type_of_ufs
|
|||
POSSIBLE PROBLEMS
|
||||
=================
|
||||
|
||||
There is still bug in reallocation of fragment, in file fs/ufs/balloc.c,
|
||||
line 364. But it seems working on current buffer cache configuration.
|
||||
See next section, if you have any.
|
||||
|
||||
|
||||
BUG REPORTS
|
||||
===========
|
||||
|
||||
Any ufs bug report you can send to daniel.pirkl@email.cz (do not send
|
||||
partition tables bug reports.)
|
||||
Any ufs bug report you can send to daniel.pirkl@email.cz or
|
||||
to dushistov@mail.ru (do not send partition tables bug reports).
|
||||
|
|
271
Documentation/gpio.txt
Normal file
271
Documentation/gpio.txt
Normal file
|
@ -0,0 +1,271 @@
|
|||
GPIO Interfaces
|
||||
|
||||
This provides an overview of GPIO access conventions on Linux.
|
||||
|
||||
|
||||
What is a GPIO?
|
||||
===============
|
||||
A "General Purpose Input/Output" (GPIO) is a flexible software-controlled
|
||||
digital signal. They are provided from many kinds of chip, and are familiar
|
||||
to Linux developers working with embedded and custom hardware. Each GPIO
|
||||
represents a bit connected to a particular pin, or "ball" on Ball Grid Array
|
||||
(BGA) packages. Board schematics show which external hardware connects to
|
||||
which GPIOs. Drivers can be written generically, so that board setup code
|
||||
passes such pin configuration data to drivers.
|
||||
|
||||
System-on-Chip (SOC) processors heavily rely on GPIOs. In some cases, every
|
||||
non-dedicated pin can be configured as a GPIO; and most chips have at least
|
||||
several dozen of them. Programmable logic devices (like FPGAs) can easily
|
||||
provide GPIOs; multifunction chips like power managers, and audio codecs
|
||||
often have a few such pins to help with pin scarcity on SOCs; and there are
|
||||
also "GPIO Expander" chips that connect using the I2C or SPI serial busses.
|
||||
Most PC southbridges have a few dozen GPIO-capable pins (with only the BIOS
|
||||
firmware knowing how they're used).
|
||||
|
||||
The exact capabilities of GPIOs vary between systems. Common options:
|
||||
|
||||
- Output values are writable (high=1, low=0). Some chips also have
|
||||
options about how that value is driven, so that for example only one
|
||||
value might be driven ... supporting "wire-OR" and similar schemes
|
||||
for the other value.
|
||||
|
||||
- Input values are likewise readable (1, 0). Some chips support readback
|
||||
of pins configured as "output", which is very useful in such "wire-OR"
|
||||
cases (to support bidirectional signaling). GPIO controllers may have
|
||||
input de-glitch logic, sometimes with software controls.
|
||||
|
||||
- Inputs can often be used as IRQ signals, often edge triggered but
|
||||
sometimes level triggered. Such IRQs may be configurable as system
|
||||
wakeup events, to wake the system from a low power state.
|
||||
|
||||
- Usually a GPIO will be configurable as either input or output, as needed
|
||||
by different product boards; single direction ones exist too.
|
||||
|
||||
- Most GPIOs can be accessed while holding spinlocks, but those accessed
|
||||
through a serial bus normally can't. Some systems support both types.
|
||||
|
||||
On a given board each GPIO is used for one specific purpose like monitoring
|
||||
MMC/SD card insertion/removal, detecting card writeprotect status, driving
|
||||
a LED, configuring a transceiver, bitbanging a serial bus, poking a hardware
|
||||
watchdog, sensing a switch, and so on.
|
||||
|
||||
|
||||
GPIO conventions
|
||||
================
|
||||
Note that this is called a "convention" because you don't need to do it this
|
||||
way, and it's no crime if you don't. There **are** cases where portability
|
||||
is not the main issue; GPIOs are often used for the kind of board-specific
|
||||
glue logic that may even change between board revisions, and can't ever be
|
||||
used on a board that's wired differently. Only least-common-denominator
|
||||
functionality can be very portable. Other features are platform-specific,
|
||||
and that can be critical for glue logic.
|
||||
|
||||
Plus, this doesn't define an implementation framework, just an interface.
|
||||
One platform might implement it as simple inline functions accessing chip
|
||||
registers; another might implement it by delegating through abstractions
|
||||
used for several very different kinds of GPIO controller.
|
||||
|
||||
That said, if the convention is supported on their platform, drivers should
|
||||
use it when possible:
|
||||
|
||||
#include <asm/gpio.h>
|
||||
|
||||
If you stick to this convention then it'll be easier for other developers to
|
||||
see what your code is doing, and help maintain it.
|
||||
|
||||
|
||||
Identifying GPIOs
|
||||
-----------------
|
||||
GPIOs are identified by unsigned integers in the range 0..MAX_INT. That
|
||||
reserves "negative" numbers for other purposes like marking signals as
|
||||
"not available on this board", or indicating faults.
|
||||
|
||||
Platforms define how they use those integers, and usually #define symbols
|
||||
for the GPIO lines so that board-specific setup code directly corresponds
|
||||
to the relevant schematics. In contrast, drivers should only use GPIO
|
||||
numbers passed to them from that setup code, using platform_data to hold
|
||||
board-specific pin configuration data (along with other board specific
|
||||
data they need). That avoids portability problems.
|
||||
|
||||
So for example one platform uses numbers 32-159 for GPIOs; while another
|
||||
uses numbers 0..63 with one set of GPIO controllers, 64-79 with another
|
||||
type of GPIO controller, and on one particular board 80-95 with an FPGA.
|
||||
The numbers need not be contiguous; either of those platforms could also
|
||||
use numbers 2000-2063 to identify GPIOs in a bank of I2C GPIO expanders.
|
||||
|
||||
Whether a platform supports multiple GPIO controllers is currently a
|
||||
platform-specific implementation issue.
|
||||
|
||||
|
||||
Using GPIOs
|
||||
-----------
|
||||
One of the first things to do with a GPIO, often in board setup code when
|
||||
setting up a platform_device using the GPIO, is mark its direction:
|
||||
|
||||
/* set as input or output, returning 0 or negative errno */
|
||||
int gpio_direction_input(unsigned gpio);
|
||||
int gpio_direction_output(unsigned gpio);
|
||||
|
||||
The return value is zero for success, else a negative errno. It should
|
||||
be checked, since the get/set calls don't have error returns and since
|
||||
misconfiguration is possible. (These calls could sleep.)
|
||||
|
||||
Setting the direction can fail if the GPIO number is invalid, or when
|
||||
that particular GPIO can't be used in that mode. It's generally a bad
|
||||
idea to rely on boot firmware to have set the direction correctly, since
|
||||
it probably wasn't validated to do more than boot Linux. (Similarly,
|
||||
that board setup code probably needs to multiplex that pin as a GPIO,
|
||||
and configure pullups/pulldowns appropriately.)
|
||||
|
||||
|
||||
Spinlock-Safe GPIO access
|
||||
-------------------------
|
||||
Most GPIO controllers can be accessed with memory read/write instructions.
|
||||
That doesn't need to sleep, and can safely be done from inside IRQ handlers.
|
||||
|
||||
Use these calls to access such GPIOs:
|
||||
|
||||
/* GPIO INPUT: return zero or nonzero */
|
||||
int gpio_get_value(unsigned gpio);
|
||||
|
||||
/* GPIO OUTPUT */
|
||||
void gpio_set_value(unsigned gpio, int value);
|
||||
|
||||
The values are boolean, zero for low, nonzero for high. When reading the
|
||||
value of an output pin, the value returned should be what's seen on the
|
||||
pin ... that won't always match the specified output value, because of
|
||||
issues including wire-OR and output latencies.
|
||||
|
||||
The get/set calls have no error returns because "invalid GPIO" should have
|
||||
been reported earlier in gpio_set_direction(). However, note that not all
|
||||
platforms can read the value of output pins; those that can't should always
|
||||
return zero. Also, these calls will be ignored for GPIOs that can't safely
|
||||
be accessed wihtout sleeping (see below).
|
||||
|
||||
Platform-specific implementations are encouraged to optimise the two
|
||||
calls to access the GPIO value in cases where the GPIO number (and for
|
||||
output, value) are constant. It's normal for them to need only a couple
|
||||
of instructions in such cases (reading or writing a hardware register),
|
||||
and not to need spinlocks. Such optimized calls can make bitbanging
|
||||
applications a lot more efficient (in both space and time) than spending
|
||||
dozens of instructions on subroutine calls.
|
||||
|
||||
|
||||
GPIO access that may sleep
|
||||
--------------------------
|
||||
Some GPIO controllers must be accessed using message based busses like I2C
|
||||
or SPI. Commands to read or write those GPIO values require waiting to
|
||||
get to the head of a queue to transmit a command and get its response.
|
||||
This requires sleeping, which can't be done from inside IRQ handlers.
|
||||
|
||||
Platforms that support this type of GPIO distinguish them from other GPIOs
|
||||
by returning nonzero from this call:
|
||||
|
||||
int gpio_cansleep(unsigned gpio);
|
||||
|
||||
To access such GPIOs, a different set of accessors is defined:
|
||||
|
||||
/* GPIO INPUT: return zero or nonzero, might sleep */
|
||||
int gpio_get_value_cansleep(unsigned gpio);
|
||||
|
||||
/* GPIO OUTPUT, might sleep */
|
||||
void gpio_set_value_cansleep(unsigned gpio, int value);
|
||||
|
||||
Other than the fact that these calls might sleep, and will not be ignored
|
||||
for GPIOs that can't be accessed from IRQ handlers, these calls act the
|
||||
same as the spinlock-safe calls.
|
||||
|
||||
|
||||
Claiming and Releasing GPIOs (OPTIONAL)
|
||||
---------------------------------------
|
||||
To help catch system configuration errors, two calls are defined.
|
||||
However, many platforms don't currently support this mechanism.
|
||||
|
||||
/* request GPIO, returning 0 or negative errno.
|
||||
* non-null labels may be useful for diagnostics.
|
||||
*/
|
||||
int gpio_request(unsigned gpio, const char *label);
|
||||
|
||||
/* release previously-claimed GPIO */
|
||||
void gpio_free(unsigned gpio);
|
||||
|
||||
Passing invalid GPIO numbers to gpio_request() will fail, as will requesting
|
||||
GPIOs that have already been claimed with that call. The return value of
|
||||
gpio_request() must be checked. (These calls could sleep.)
|
||||
|
||||
These calls serve two basic purposes. One is marking the signals which
|
||||
are actually in use as GPIOs, for better diagnostics; systems may have
|
||||
several hundred potential GPIOs, but often only a dozen are used on any
|
||||
given board. Another is to catch conflicts between drivers, reporting
|
||||
errors when drivers wrongly think they have exclusive use of that signal.
|
||||
|
||||
These two calls are optional because not not all current Linux platforms
|
||||
offer such functionality in their GPIO support; a valid implementation
|
||||
could return success for all gpio_request() calls. Unlike the other calls,
|
||||
the state they represent doesn't normally match anything from a hardware
|
||||
register; it's just a software bitmap which clearly is not necessary for
|
||||
correct operation of hardware or (bug free) drivers.
|
||||
|
||||
Note that requesting a GPIO does NOT cause it to be configured in any
|
||||
way; it just marks that GPIO as in use. Separate code must handle any
|
||||
pin setup (e.g. controlling which pin the GPIO uses, pullup/pulldown).
|
||||
|
||||
|
||||
GPIOs mapped to IRQs
|
||||
--------------------
|
||||
GPIO numbers are unsigned integers; so are IRQ numbers. These make up
|
||||
two logically distinct namespaces (GPIO 0 need not use IRQ 0). You can
|
||||
map between them using calls like:
|
||||
|
||||
/* map GPIO numbers to IRQ numbers */
|
||||
int gpio_to_irq(unsigned gpio);
|
||||
|
||||
/* map IRQ numbers to GPIO numbers */
|
||||
int irq_to_gpio(unsigned irq);
|
||||
|
||||
Those return either the corresponding number in the other namespace, or
|
||||
else a negative errno code if the mapping can't be done. (For example,
|
||||
some GPIOs can't used as IRQs.) It is an unchecked error to use a GPIO
|
||||
number that hasn't been marked as an input using gpio_set_direction(), or
|
||||
to use an IRQ number that didn't originally come from gpio_to_irq().
|
||||
|
||||
These two mapping calls are expected to cost on the order of a single
|
||||
addition or subtraction. They're not allowed to sleep.
|
||||
|
||||
Non-error values returned from gpio_to_irq() can be passed to request_irq()
|
||||
or free_irq(). They will often be stored into IRQ resources for platform
|
||||
devices, by the board-specific initialization code. Note that IRQ trigger
|
||||
options are part of the IRQ interface, e.g. IRQF_TRIGGER_FALLING, as are
|
||||
system wakeup capabilities.
|
||||
|
||||
Non-error values returned from irq_to_gpio() would most commonly be used
|
||||
with gpio_get_value().
|
||||
|
||||
|
||||
|
||||
What do these conventions omit?
|
||||
===============================
|
||||
One of the biggest things these conventions omit is pin multiplexing, since
|
||||
this is highly chip-specific and nonportable. One platform might not need
|
||||
explicit multiplexing; another might have just two options for use of any
|
||||
given pin; another might have eight options per pin; another might be able
|
||||
to route a given GPIO to any one of several pins. (Yes, those examples all
|
||||
come from systems that run Linux today.)
|
||||
|
||||
Related to multiplexing is configuration and enabling of the pullups or
|
||||
pulldowns integrated on some platforms. Not all platforms support them,
|
||||
or support them in the same way; and any given board might use external
|
||||
pullups (or pulldowns) so that the on-chip ones should not be used.
|
||||
|
||||
There are other system-specific mechanisms that are not specified here,
|
||||
like the aforementioned options for input de-glitching and wire-OR output.
|
||||
Hardware may support reading or writing GPIOs in gangs, but that's usually
|
||||
configuration dependednt: for GPIOs sharing the same bank. (GPIOs are
|
||||
commonly grouped in banks of 16 or 32, with a given SOC having several such
|
||||
banks.) Code relying on such mechanisms will necessarily be nonportable.
|
||||
|
||||
Dynamic definition of GPIOs is not currently supported; for example, as
|
||||
a side effect of configuring an add-on board with some GPIO expanders.
|
||||
|
||||
These calls are purely for kernel space, but a userspace API could be built
|
||||
on top of it.
|
|
@ -94,8 +94,7 @@ Code Seq# Include File Comments
|
|||
'L' 00-1F linux/loop.h
|
||||
'L' E0-FF linux/ppdd.h encrypted disk device driver
|
||||
<http://linux01.gwdg.de/~alatham/ppdd.html>
|
||||
'M' all linux/soundcard.h conflict!
|
||||
'M' 00-1F linux/isicom.h conflict!
|
||||
'M' all linux/soundcard.h
|
||||
'N' 00-1F drivers/usb/scanner.h
|
||||
'P' all linux/soundcard.h
|
||||
'Q' all linux/soundcard.h
|
||||
|
|
|
@ -8,29 +8,33 @@ GigaSet 307x Device Driver
|
|||
This release supports the connection of the Gigaset 307x/417x family of
|
||||
ISDN DECT bases via Gigaset M101 Data, Gigaset M105 Data or direct USB
|
||||
connection. The following devices are reported to be compatible:
|
||||
307x/417x:
|
||||
Gigaset SX255isdn
|
||||
Gigaset SX353isdn
|
||||
Sinus 45 [AB] isdn (Deutsche Telekom)
|
||||
Sinus 721X/XA
|
||||
|
||||
Bases:
|
||||
Siemens Gigaset 3070/3075 isdn
|
||||
Siemens Gigaset 4170/4175 isdn
|
||||
Siemens Gigaset SX205/255
|
||||
Siemens Gigaset SX353
|
||||
T-Com Sinus 45 [AB] isdn
|
||||
T-Com Sinus 721X[A] [SE]
|
||||
Vox Chicago 390 ISDN (KPN Telecom)
|
||||
M101:
|
||||
Sinus 45 Data 1 (Telekom)
|
||||
M105:
|
||||
Gigaset USB Adapter DECT
|
||||
Sinus 45 Data 2 (Telekom)
|
||||
Sinus 721 data
|
||||
|
||||
RS232 data boxes:
|
||||
Siemens Gigaset M101 Data
|
||||
T-Com Sinus 45 Data 1
|
||||
|
||||
USB data boxes:
|
||||
Siemens Gigaset M105 Data
|
||||
Siemens Gigaset USB Adapter DECT
|
||||
T-Com Sinus 45 Data 2
|
||||
T-Com Sinus 721 data
|
||||
Chicago 390 USB (KPN)
|
||||
|
||||
See also http://www.erbze.info/sinus_gigaset.htm and
|
||||
http://gigaset307x.sourceforge.net/
|
||||
|
||||
We had also reports from users of Gigaset M105 who could use the drivers
|
||||
with SX 100 and CX 100 ISDN bases (only in unimodem mode, see section 2.4.)
|
||||
If you have another device that works with our driver, please let us know.
|
||||
For example, Gigaset SX205isdn/Sinus 721 X SE and Gigaset SX303isdn bases
|
||||
are just versions without answering machine of models known to work, so
|
||||
they should work just as well; but so far we are lacking positive reports
|
||||
on these.
|
||||
|
||||
Chances of getting an USB device to work are good if the output of
|
||||
lsusb
|
||||
|
@ -60,14 +64,28 @@ GigaSet 307x Device Driver
|
|||
To get the device working, you have to load the proper kernel module. You
|
||||
can do this using
|
||||
modprobe modulename
|
||||
where modulename is usb_gigaset (M105) or bas_gigaset (direct USB
|
||||
connection to the base).
|
||||
where modulename is ser_gigaset (M101), usb_gigaset (M105), or
|
||||
bas_gigaset (direct USB connection to the base).
|
||||
|
||||
The module ser_gigaset provides a serial line discipline N_GIGASET_M101
|
||||
which drives the device through the regular serial line driver. To use it,
|
||||
run the Gigaset M101 daemon "gigasetm101d" (also available from
|
||||
http://sourceforge.net/projects/gigaset307x/) with the device file of the
|
||||
RS232 port to the M101 as an argument, for example:
|
||||
gigasetm101d /dev/ttyS1
|
||||
This will open the device file, set its line discipline to N_GIGASET_M101,
|
||||
and then sleep in the background, keeping the device open so that the
|
||||
line discipline remains active. To deactivate it, kill the daemon, for
|
||||
example with
|
||||
killall gigasetm101d
|
||||
before disconnecting the device.
|
||||
|
||||
2.2. Device nodes for user space programs
|
||||
------------------------------------
|
||||
The device can be accessed from user space (eg. by the user space tools
|
||||
mentioned in 1.2.) through the device nodes:
|
||||
|
||||
- /dev/ttyGS0 for M101 (RS232 data boxes)
|
||||
- /dev/ttyGU0 for M105 (USB data boxes)
|
||||
- /dev/ttyGB0 for the base driver (direct USB connection)
|
||||
|
||||
|
@ -168,6 +186,19 @@ GigaSet 307x Device Driver
|
|||
You can also use /sys/class/tty/ttyGxy/cidmode for changing the CID mode
|
||||
setting (ttyGxy is ttyGU0 or ttyGB0).
|
||||
|
||||
2.6. M105 Undocumented USB Requests
|
||||
------------------------------
|
||||
|
||||
The Gigaset M105 USB data box understands a couple of useful, but
|
||||
undocumented USB commands. These requests are not used in normal
|
||||
operation (for wireless access to the base), but are needed for access
|
||||
to the M105's own configuration mode (registration to the base, baudrate
|
||||
and line format settings, device status queries) via the gigacontr
|
||||
utility. Their use is disabled in the driver by default for safety
|
||||
reasons but can be enabled by setting the kernel configuration option
|
||||
"Support for undocumented USB requests" (GIGASET_UNDOCREQ) to "Y" and
|
||||
recompiling.
|
||||
|
||||
|
||||
3. Troubleshooting
|
||||
---------------
|
||||
|
|
|
@ -311,10 +311,10 @@ Following are the arch specific command line options to be used while
|
|||
loading dump-capture kernel.
|
||||
|
||||
For i386, x86_64 and ia64:
|
||||
"init 1 irqpoll maxcpus=1"
|
||||
"1 irqpoll maxcpus=1"
|
||||
|
||||
For ppc64:
|
||||
"init 1 maxcpus=1 noirqdistrib"
|
||||
"1 maxcpus=1 noirqdistrib"
|
||||
|
||||
|
||||
Notes on loading the dump-capture kernel:
|
||||
|
@ -332,8 +332,8 @@ Notes on loading the dump-capture kernel:
|
|||
* You must specify <root-dev> in the format corresponding to the root
|
||||
device name in the output of mount command.
|
||||
|
||||
* "init 1" boots the dump-capture kernel into single-user mode without
|
||||
networking. If you want networking, use "init 3."
|
||||
* Boot parameter "1" boots the dump-capture kernel into single-user
|
||||
mode without networking. If you want networking, use "3".
|
||||
|
||||
* We generally don' have to bring up a SMP kernel just to capture the
|
||||
dump. Hence generally it is useful either to build a UP dump-capture
|
||||
|
|
|
@ -101,16 +101,20 @@ The format of the block comment is like this:
|
|||
|
||||
/**
|
||||
* function_name(:)? (- short description)?
|
||||
(* @parameterx: (description of parameter x)?)*
|
||||
(* @parameterx(space)*: (description of parameter x)?)*
|
||||
(* a blank line)?
|
||||
* (Description:)? (Description of function)?
|
||||
* (section header: (section description)? )*
|
||||
(*)?*/
|
||||
|
||||
The short function description cannot be multiline, but the other
|
||||
descriptions can be (and they can contain blank lines). Avoid putting a
|
||||
spurious blank line after the function name, or else the description will
|
||||
be repeated!
|
||||
The short function description ***cannot be multiline***, but the other
|
||||
descriptions can be (and they can contain blank lines). If you continue
|
||||
that initial short description onto a second line, that second line will
|
||||
appear further down at the beginning of the description section, which is
|
||||
almost certainly not what you had in mind.
|
||||
|
||||
Avoid putting a spurious blank line after the function name, or else the
|
||||
description will be repeated!
|
||||
|
||||
All descriptive text is further processed, scanning for the following special
|
||||
patterns, which are highlighted appropriately.
|
||||
|
@ -121,6 +125,31 @@ patterns, which are highlighted appropriately.
|
|||
'@parameter' - name of a parameter
|
||||
'%CONST' - name of a constant.
|
||||
|
||||
NOTE 1: The multi-line descriptive text you provide does *not* recognize
|
||||
line breaks, so if you try to format some text nicely, as in:
|
||||
|
||||
Return codes
|
||||
0 - cool
|
||||
1 - invalid arg
|
||||
2 - out of memory
|
||||
|
||||
this will all run together and produce:
|
||||
|
||||
Return codes 0 - cool 1 - invalid arg 2 - out of memory
|
||||
|
||||
NOTE 2: If the descriptive text you provide has lines that begin with
|
||||
some phrase followed by a colon, each of those phrases will be taken as
|
||||
a new section heading, which means you should similarly try to avoid text
|
||||
like:
|
||||
|
||||
Return codes:
|
||||
0: cool
|
||||
1: invalid arg
|
||||
2: out of memory
|
||||
|
||||
every line of which would start a new section. Again, probably not
|
||||
what you were after.
|
||||
|
||||
Take a look around the source tree for examples.
|
||||
|
||||
|
||||
|
|
|
@ -1396,6 +1396,8 @@ and is between 256 and 4096 characters. It is defined in the file
|
|||
in <PAGE_SIZE> units (needed only for swap files).
|
||||
See Documentation/power/swsusp-and-swap-files.txt
|
||||
|
||||
retain_initrd [RAM] Keep initrd memory after extraction
|
||||
|
||||
rhash_entries= [KNL,NET]
|
||||
Set number of hash buckets for route cache
|
||||
|
||||
|
|
163
Documentation/local_ops.txt
Normal file
163
Documentation/local_ops.txt
Normal file
|
@ -0,0 +1,163 @@
|
|||
Semantics and Behavior of Local Atomic Operations
|
||||
|
||||
Mathieu Desnoyers
|
||||
|
||||
|
||||
This document explains the purpose of the local atomic operations, how
|
||||
to implement them for any given architecture and shows how they can be used
|
||||
properly. It also stresses on the precautions that must be taken when reading
|
||||
those local variables across CPUs when the order of memory writes matters.
|
||||
|
||||
|
||||
|
||||
* Purpose of local atomic operations
|
||||
|
||||
Local atomic operations are meant to provide fast and highly reentrant per CPU
|
||||
counters. They minimize the performance cost of standard atomic operations by
|
||||
removing the LOCK prefix and memory barriers normally required to synchronize
|
||||
across CPUs.
|
||||
|
||||
Having fast per CPU atomic counters is interesting in many cases : it does not
|
||||
require disabling interrupts to protect from interrupt handlers and it permits
|
||||
coherent counters in NMI handlers. It is especially useful for tracing purposes
|
||||
and for various performance monitoring counters.
|
||||
|
||||
Local atomic operations only guarantee variable modification atomicity wrt the
|
||||
CPU which owns the data. Therefore, care must taken to make sure that only one
|
||||
CPU writes to the local_t data. This is done by using per cpu data and making
|
||||
sure that we modify it from within a preemption safe context. It is however
|
||||
permitted to read local_t data from any CPU : it will then appear to be written
|
||||
out of order wrt other memory writes on the owner CPU.
|
||||
|
||||
|
||||
* Implementation for a given architecture
|
||||
|
||||
It can be done by slightly modifying the standard atomic operations : only
|
||||
their UP variant must be kept. It typically means removing LOCK prefix (on
|
||||
i386 and x86_64) and any SMP sychronization barrier. If the architecture does
|
||||
not have a different behavior between SMP and UP, including asm-generic/local.h
|
||||
in your archtecture's local.h is sufficient.
|
||||
|
||||
The local_t type is defined as an opaque signed long by embedding an
|
||||
atomic_long_t inside a structure. This is made so a cast from this type to a
|
||||
long fails. The definition looks like :
|
||||
|
||||
typedef struct { atomic_long_t a; } local_t;
|
||||
|
||||
|
||||
* How to use local atomic operations
|
||||
|
||||
#include <linux/percpu.h>
|
||||
#include <asm/local.h>
|
||||
|
||||
static DEFINE_PER_CPU(local_t, counters) = LOCAL_INIT(0);
|
||||
|
||||
|
||||
* Counting
|
||||
|
||||
Counting is done on all the bits of a signed long.
|
||||
|
||||
In preemptible context, use get_cpu_var() and put_cpu_var() around local atomic
|
||||
operations : it makes sure that preemption is disabled around write access to
|
||||
the per cpu variable. For instance :
|
||||
|
||||
local_inc(&get_cpu_var(counters));
|
||||
put_cpu_var(counters);
|
||||
|
||||
If you are already in a preemption-safe context, you can directly use
|
||||
__get_cpu_var() instead.
|
||||
|
||||
local_inc(&__get_cpu_var(counters));
|
||||
|
||||
|
||||
|
||||
* Reading the counters
|
||||
|
||||
Those local counters can be read from foreign CPUs to sum the count. Note that
|
||||
the data seen by local_read across CPUs must be considered to be out of order
|
||||
relatively to other memory writes happening on the CPU that owns the data.
|
||||
|
||||
long sum = 0;
|
||||
for_each_online_cpu(cpu)
|
||||
sum += local_read(&per_cpu(counters, cpu));
|
||||
|
||||
If you want to use a remote local_read to synchronize access to a resource
|
||||
between CPUs, explicit smp_wmb() and smp_rmb() memory barriers must be used
|
||||
respectively on the writer and the reader CPUs. It would be the case if you use
|
||||
the local_t variable as a counter of bytes written in a buffer : there should
|
||||
be a smp_wmb() between the buffer write and the counter increment and also a
|
||||
smp_rmb() between the counter read and the buffer read.
|
||||
|
||||
|
||||
Here is a sample module which implements a basic per cpu counter using local.h.
|
||||
|
||||
--- BEGIN ---
|
||||
/* test-local.c
|
||||
*
|
||||
* Sample module for local.h usage.
|
||||
*/
|
||||
|
||||
|
||||
#include <asm/local.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/timer.h>
|
||||
|
||||
static DEFINE_PER_CPU(local_t, counters) = LOCAL_INIT(0);
|
||||
|
||||
static struct timer_list test_timer;
|
||||
|
||||
/* IPI called on each CPU. */
|
||||
static void test_each(void *info)
|
||||
{
|
||||
/* Increment the counter from a non preemptible context */
|
||||
printk("Increment on cpu %d\n", smp_processor_id());
|
||||
local_inc(&__get_cpu_var(counters));
|
||||
|
||||
/* This is what incrementing the variable would look like within a
|
||||
* preemptible context (it disables preemption) :
|
||||
*
|
||||
* local_inc(&get_cpu_var(counters));
|
||||
* put_cpu_var(counters);
|
||||
*/
|
||||
}
|
||||
|
||||
static void do_test_timer(unsigned long data)
|
||||
{
|
||||
int cpu;
|
||||
|
||||
/* Increment the counters */
|
||||
on_each_cpu(test_each, NULL, 0, 1);
|
||||
/* Read all the counters */
|
||||
printk("Counters read from CPU %d\n", smp_processor_id());
|
||||
for_each_online_cpu(cpu) {
|
||||
printk("Read : CPU %d, count %ld\n", cpu,
|
||||
local_read(&per_cpu(counters, cpu)));
|
||||
}
|
||||
del_timer(&test_timer);
|
||||
test_timer.expires = jiffies + 1000;
|
||||
add_timer(&test_timer);
|
||||
}
|
||||
|
||||
static int __init test_init(void)
|
||||
{
|
||||
/* initialize the timer that will increment the counter */
|
||||
init_timer(&test_timer);
|
||||
test_timer.function = do_test_timer;
|
||||
test_timer.expires = jiffies + 1;
|
||||
add_timer(&test_timer);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __exit test_exit(void)
|
||||
{
|
||||
del_timer_sync(&test_timer);
|
||||
}
|
||||
|
||||
module_init(test_init);
|
||||
module_exit(test_exit);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Mathieu Desnoyers");
|
||||
MODULE_DESCRIPTION("Local Atomic Ops");
|
||||
--- END ---
|
|
@ -67,8 +67,8 @@ nfsroot=[<server-ip>:]<root-dir>[,<nfs-options>]
|
|||
<nfs-options> Standard NFS options. All options are separated by commas.
|
||||
The following defaults are used:
|
||||
port = as given by server portmap daemon
|
||||
rsize = 1024
|
||||
wsize = 1024
|
||||
rsize = 4096
|
||||
wsize = 4096
|
||||
timeo = 7
|
||||
retrans = 3
|
||||
acregmin = 3
|
||||
|
|
192
Documentation/rbtree.txt
Normal file
192
Documentation/rbtree.txt
Normal file
|
@ -0,0 +1,192 @@
|
|||
Red-black Trees (rbtree) in Linux
|
||||
January 18, 2007
|
||||
Rob Landley <rob@landley.net>
|
||||
=============================
|
||||
|
||||
What are red-black trees, and what are they for?
|
||||
------------------------------------------------
|
||||
|
||||
Red-black trees are a type of self-balancing binary search tree, used for
|
||||
storing sortable key/value data pairs. This differs from radix trees (which
|
||||
are used to efficiently store sparse arrays and thus use long integer indexes
|
||||
to insert/access/delete nodes) and hash tables (which are not kept sorted to
|
||||
be easily traversed in order, and must be tuned for a specific size and
|
||||
hash function where rbtrees scale gracefully storing arbitrary keys).
|
||||
|
||||
Red-black trees are similar to AVL trees, but provide faster real-time bounded
|
||||
worst case performance for insertion and deletion (at most two rotations and
|
||||
three rotations, respectively, to balance the tree), with slightly slower
|
||||
(but still O(log n)) lookup time.
|
||||
|
||||
To quote Linux Weekly News:
|
||||
|
||||
There are a number of red-black trees in use in the kernel.
|
||||
The anticipatory, deadline, and CFQ I/O schedulers all employ
|
||||
rbtrees to track requests; the packet CD/DVD driver does the same.
|
||||
The high-resolution timer code uses an rbtree to organize outstanding
|
||||
timer requests. The ext3 filesystem tracks directory entries in a
|
||||
red-black tree. Virtual memory areas (VMAs) are tracked with red-black
|
||||
trees, as are epoll file descriptors, cryptographic keys, and network
|
||||
packets in the "hierarchical token bucket" scheduler.
|
||||
|
||||
This document covers use of the Linux rbtree implementation. For more
|
||||
information on the nature and implementation of Red Black Trees, see:
|
||||
|
||||
Linux Weekly News article on red-black trees
|
||||
http://lwn.net/Articles/184495/
|
||||
|
||||
Wikipedia entry on red-black trees
|
||||
http://en.wikipedia.org/wiki/Red-black_tree
|
||||
|
||||
Linux implementation of red-black trees
|
||||
---------------------------------------
|
||||
|
||||
Linux's rbtree implementation lives in the file "lib/rbtree.c". To use it,
|
||||
"#include <linux/rbtree.h>".
|
||||
|
||||
The Linux rbtree implementation is optimized for speed, and thus has one
|
||||
less layer of indirection (and better cache locality) than more traditional
|
||||
tree implementations. Instead of using pointers to separate rb_node and data
|
||||
structures, each instance of struct rb_node is embedded in the data structure
|
||||
it organizes. And instead of using a comparison callback function pointer,
|
||||
users are expected to write their own tree search and insert functions
|
||||
which call the provided rbtree functions. Locking is also left up to the
|
||||
user of the rbtree code.
|
||||
|
||||
Creating a new rbtree
|
||||
---------------------
|
||||
|
||||
Data nodes in an rbtree tree are structures containing a struct rb_node member:
|
||||
|
||||
struct mytype {
|
||||
struct rb_node node;
|
||||
char *keystring;
|
||||
};
|
||||
|
||||
When dealing with a pointer to the embedded struct rb_node, the containing data
|
||||
structure may be accessed with the standard container_of() macro. In addition,
|
||||
individual members may be accessed directly via rb_entry(node, type, member).
|
||||
|
||||
At the root of each rbtree is an rb_root structure, which is initialized to be
|
||||
empty via:
|
||||
|
||||
struct rb_root mytree = RB_ROOT;
|
||||
|
||||
Searching for a value in an rbtree
|
||||
----------------------------------
|
||||
|
||||
Writing a search function for your tree is fairly straightforward: start at the
|
||||
root, compare each value, and follow the left or right branch as necessary.
|
||||
|
||||
Example:
|
||||
|
||||
struct mytype *my_search(struct rb_root *root, char *string)
|
||||
{
|
||||
struct rb_node *node = root->rb_node;
|
||||
|
||||
while (node) {
|
||||
struct mytype *data = container_of(node, struct mytype, node);
|
||||
int result;
|
||||
|
||||
result = strcmp(string, data->keystring);
|
||||
|
||||
if (result < 0)
|
||||
node = node->rb_left;
|
||||
else if (result > 0)
|
||||
node = node->rb_right;
|
||||
else
|
||||
return data;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Inserting data into an rbtree
|
||||
-----------------------------
|
||||
|
||||
Inserting data in the tree involves first searching for the place to insert the
|
||||
new node, then inserting the node and rebalancing ("recoloring") the tree.
|
||||
|
||||
The search for insertion differs from the previous search by finding the
|
||||
location of the pointer on which to graft the new node. The new node also
|
||||
needs a link to its parent node for rebalancing purposes.
|
||||
|
||||
Example:
|
||||
|
||||
int my_insert(struct rb_root *root, struct mytype *data)
|
||||
{
|
||||
struct rb_node **new = &(root->rb_node), *parent = NULL;
|
||||
|
||||
/* Figure out where to put new node */
|
||||
while (*new) {
|
||||
struct mytype *this = container_of(*new, struct mytype, node);
|
||||
int result = strcmp(data->keystring, this->keystring);
|
||||
|
||||
parent = *new;
|
||||
if (result < 0)
|
||||
new = &((*new)->rb_left);
|
||||
else if (result > 0)
|
||||
new = &((*new)->rb_right);
|
||||
else
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Add new node and rebalance tree. */
|
||||
rb_link_node(data->node, parent, new);
|
||||
rb_insert_color(data->node, root);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
Removing or replacing existing data in an rbtree
|
||||
------------------------------------------------
|
||||
|
||||
To remove an existing node from a tree, call:
|
||||
|
||||
void rb_erase(struct rb_node *victim, struct rb_root *tree);
|
||||
|
||||
Example:
|
||||
|
||||
struct mytype *data = mysearch(mytree, "walrus");
|
||||
|
||||
if (data) {
|
||||
rb_erase(data->node, mytree);
|
||||
myfree(data);
|
||||
}
|
||||
|
||||
To replace an existing node in a tree with a new one with the same key, call:
|
||||
|
||||
void rb_replace_node(struct rb_node *old, struct rb_node *new,
|
||||
struct rb_root *tree);
|
||||
|
||||
Replacing a node this way does not re-sort the tree: If the new node doesn't
|
||||
have the same key as the old node, the rbtree will probably become corrupted.
|
||||
|
||||
Iterating through the elements stored in an rbtree (in sort order)
|
||||
------------------------------------------------------------------
|
||||
|
||||
Four functions are provided for iterating through an rbtree's contents in
|
||||
sorted order. These work on arbitrary trees, and should not need to be
|
||||
modified or wrapped (except for locking purposes):
|
||||
|
||||
struct rb_node *rb_first(struct rb_root *tree);
|
||||
struct rb_node *rb_last(struct rb_root *tree);
|
||||
struct rb_node *rb_next(struct rb_node *node);
|
||||
struct rb_node *rb_prev(struct rb_node *node);
|
||||
|
||||
To start iterating, call rb_first() or rb_last() with a pointer to the root
|
||||
of the tree, which will return a pointer to the node structure contained in
|
||||
the first or last element in the tree. To continue, fetch the next or previous
|
||||
node by calling rb_next() or rb_prev() on the current node. This will return
|
||||
NULL when there are no more nodes left.
|
||||
|
||||
The iterator functions return a pointer to the embedded struct rb_node, from
|
||||
which the containing data structure may be accessed with the container_of()
|
||||
macro, and individual members may be accessed directly via
|
||||
rb_entry(node, type, member).
|
||||
|
||||
Example:
|
||||
|
||||
struct rb_node *node;
|
||||
for (node = rb_first(&mytree); node; node = rb_next(node))
|
||||
printk("key=%s\n", rb_entry(node, int, keystring));
|
||||
|
|
@ -149,7 +149,7 @@ RTC class framework, but can't be supported by the older driver.
|
|||
is connected to an IRQ line, it can often issue an alarm IRQ up to
|
||||
24 hours in the future.
|
||||
|
||||
* RTC_WKALM_SET, RTC_WKALM_READ ... RTCs that can issue alarms beyond
|
||||
* RTC_WKALM_SET, RTC_WKALM_RD ... RTCs that can issue alarms beyond
|
||||
the next 24 hours use a slightly more powerful API, which supports
|
||||
setting the longer alarm time and enabling its IRQ using a single
|
||||
request (using the same model as EFI firmware).
|
||||
|
@ -167,6 +167,28 @@ Linux out of a low power sleep state (or hibernation) back to a fully
|
|||
operational state. For example, a system could enter a deep power saving
|
||||
state until it's time to execute some scheduled tasks.
|
||||
|
||||
Note that many of these ioctls need not actually be implemented by your
|
||||
driver. The common rtc-dev interface handles many of these nicely if your
|
||||
driver returns ENOIOCTLCMD. Some common examples:
|
||||
|
||||
* RTC_RD_TIME, RTC_SET_TIME: the read_time/set_time functions will be
|
||||
called with appropriate values.
|
||||
|
||||
* RTC_ALM_SET, RTC_ALM_READ, RTC_WKALM_SET, RTC_WKALM_RD: the
|
||||
set_alarm/read_alarm functions will be called. To differentiate
|
||||
between the ALM and WKALM, check the larger fields of the rtc_wkalrm
|
||||
struct (like tm_year). These will be set to -1 when using ALM and
|
||||
will be set to proper values when using WKALM.
|
||||
|
||||
* 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.
|
||||
|
||||
If all else fails, check out the rtc-test.c driver!
|
||||
|
||||
|
||||
-------------------- 8< ---------------- 8< -----------------------------
|
||||
|
||||
|
@ -237,7 +259,7 @@ int main(int argc, char **argv)
|
|||
"\n...Update IRQs not supported.\n");
|
||||
goto test_READ;
|
||||
}
|
||||
perror("ioctl");
|
||||
perror("RTC_UIE_ON ioctl");
|
||||
exit(errno);
|
||||
}
|
||||
|
||||
|
@ -284,7 +306,7 @@ int main(int argc, char **argv)
|
|||
/* Turn off update interrupts */
|
||||
retval = ioctl(fd, RTC_UIE_OFF, 0);
|
||||
if (retval == -1) {
|
||||
perror("ioctl");
|
||||
perror("RTC_UIE_OFF ioctl");
|
||||
exit(errno);
|
||||
}
|
||||
|
||||
|
@ -292,7 +314,7 @@ test_READ:
|
|||
/* Read the RTC time/date */
|
||||
retval = ioctl(fd, RTC_RD_TIME, &rtc_tm);
|
||||
if (retval == -1) {
|
||||
perror("ioctl");
|
||||
perror("RTC_RD_TIME ioctl");
|
||||
exit(errno);
|
||||
}
|
||||
|
||||
|
@ -320,14 +342,14 @@ test_READ:
|
|||
"\n...Alarm IRQs not supported.\n");
|
||||
goto test_PIE;
|
||||
}
|
||||
perror("ioctl");
|
||||
perror("RTC_ALM_SET ioctl");
|
||||
exit(errno);
|
||||
}
|
||||
|
||||
/* Read the current alarm settings */
|
||||
retval = ioctl(fd, RTC_ALM_READ, &rtc_tm);
|
||||
if (retval == -1) {
|
||||
perror("ioctl");
|
||||
perror("RTC_ALM_READ ioctl");
|
||||
exit(errno);
|
||||
}
|
||||
|
||||
|
@ -337,7 +359,7 @@ test_READ:
|
|||
/* Enable alarm interrupts */
|
||||
retval = ioctl(fd, RTC_AIE_ON, 0);
|
||||
if (retval == -1) {
|
||||
perror("ioctl");
|
||||
perror("RTC_AIE_ON ioctl");
|
||||
exit(errno);
|
||||
}
|
||||
|
||||
|
@ -355,7 +377,7 @@ test_READ:
|
|||
/* Disable alarm interrupts */
|
||||
retval = ioctl(fd, RTC_AIE_OFF, 0);
|
||||
if (retval == -1) {
|
||||
perror("ioctl");
|
||||
perror("RTC_AIE_OFF ioctl");
|
||||
exit(errno);
|
||||
}
|
||||
|
||||
|
@ -368,7 +390,7 @@ test_PIE:
|
|||
fprintf(stderr, "\nNo periodic IRQ support\n");
|
||||
return 0;
|
||||
}
|
||||
perror("ioctl");
|
||||
perror("RTC_IRQP_READ ioctl");
|
||||
exit(errno);
|
||||
}
|
||||
fprintf(stderr, "\nPeriodic IRQ rate is %ldHz.\n", tmp);
|
||||
|
@ -387,7 +409,7 @@ test_PIE:
|
|||
"\n...Periodic IRQ rate is fixed\n");
|
||||
goto done;
|
||||
}
|
||||
perror("ioctl");
|
||||
perror("RTC_IRQP_SET ioctl");
|
||||
exit(errno);
|
||||
}
|
||||
|
||||
|
@ -397,7 +419,7 @@ test_PIE:
|
|||
/* Enable periodic interrupts */
|
||||
retval = ioctl(fd, RTC_PIE_ON, 0);
|
||||
if (retval == -1) {
|
||||
perror("ioctl");
|
||||
perror("RTC_PIE_ON ioctl");
|
||||
exit(errno);
|
||||
}
|
||||
|
||||
|
@ -416,7 +438,7 @@ test_PIE:
|
|||
/* Disable periodic interrupts */
|
||||
retval = ioctl(fd, RTC_PIE_OFF, 0);
|
||||
if (retval == -1) {
|
||||
perror("ioctl");
|
||||
perror("RTC_PIE_OFF ioctl");
|
||||
exit(errno);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,3 +1,19 @@
|
|||
Release Date : Thu Nov 16 15:32:35 EST 2006 -
|
||||
Sumant Patro <sumant.patro@lsi.com>
|
||||
Current Version : 2.20.5.1 (scsi module), 2.20.2.6 (cmm module)
|
||||
Older Version : 2.20.4.9 (scsi module), 2.20.2.6 (cmm module)
|
||||
|
||||
1. Changes in Initialization to fix kdump failure.
|
||||
Send SYNC command on loading.
|
||||
This command clears the pending commands in the adapter
|
||||
and re-initialize its internal RAID structure.
|
||||
Without this change, megaraid driver either panics or fails to
|
||||
initialize the adapter during kdump's second kernel boot
|
||||
if there are pending commands or interrupts from other devices
|
||||
sharing the same IRQ.
|
||||
2. Authors email-id domain name changed from lsil.com to lsi.com.
|
||||
Also modified the MODULE_AUTHOR to megaraidlinux@lsi.com
|
||||
|
||||
Release Date : Fri May 19 09:31:45 EST 2006 - Seokmann Ju <sju@lsil.com>
|
||||
Current Version : 2.20.4.9 (scsi module), 2.20.2.6 (cmm module)
|
||||
Older Version : 2.20.4.8 (scsi module), 2.20.2.6 (cmm module)
|
||||
|
|
|
@ -284,7 +284,6 @@ SPI protocol drivers somewhat resemble platform device drivers:
|
|||
static struct spi_driver CHIP_driver = {
|
||||
.driver = {
|
||||
.name = "CHIP",
|
||||
.bus = &spi_bus_type,
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
|
||||
|
@ -312,7 +311,7 @@ might look like this unless you're creating a class_device:
|
|||
chip = kzalloc(sizeof *chip, GFP_KERNEL);
|
||||
if (!chip)
|
||||
return -ENOMEM;
|
||||
dev_set_drvdata(&spi->dev, chip);
|
||||
spi_set_drvdata(spi, chip);
|
||||
|
||||
... etc
|
||||
return 0;
|
||||
|
|
|
@ -64,11 +64,6 @@ On all - write a character to /proc/sysrq-trigger. e.g.:
|
|||
|
||||
* What are the 'command' keys?
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
'r' - Turns off keyboard raw mode and sets it to XLATE.
|
||||
|
||||
'k' - Secure Access Key (SAK) Kills all programs on the current virtual
|
||||
console. NOTE: See important comments below in SAK section.
|
||||
|
||||
'b' - Will immediately reboot the system without syncing or unmounting
|
||||
your disks.
|
||||
|
||||
|
@ -76,21 +71,37 @@ On all - write a character to /proc/sysrq-trigger. e.g.:
|
|||
|
||||
'd' - Shows all locks that are held.
|
||||
|
||||
'o' - Will shut your system off (if configured and supported).
|
||||
'e' - Send a SIGTERM to all processes, except for init.
|
||||
|
||||
's' - Will attempt to sync all mounted filesystems.
|
||||
'f' - Will call oom_kill to kill a memory hog process.
|
||||
|
||||
'u' - Will attempt to remount all mounted filesystems read-only.
|
||||
'g' - Used by kgdb on ppc platforms.
|
||||
|
||||
'p' - Will dump the current registers and flags to your console.
|
||||
'h' - Will display help (actually any other key than those listed
|
||||
above will display help. but 'h' is easy to remember :-)
|
||||
|
||||
't' - Will dump a list of current tasks and their information to your
|
||||
console.
|
||||
'i' - Send a SIGKILL to all processes, except for init.
|
||||
|
||||
'k' - Secure Access Key (SAK) Kills all programs on the current virtual
|
||||
console. NOTE: See important comments below in SAK section.
|
||||
|
||||
'm' - Will dump current memory info to your console.
|
||||
|
||||
'n' - Used to make RT tasks nice-able
|
||||
|
||||
'o' - Will shut your system off (if configured and supported).
|
||||
|
||||
'p' - Will dump the current registers and flags to your console.
|
||||
|
||||
'r' - Turns off keyboard raw mode and sets it to XLATE.
|
||||
|
||||
's' - Will attempt to sync all mounted filesystems.
|
||||
|
||||
't' - Will dump a list of current tasks and their information to your
|
||||
console.
|
||||
|
||||
'u' - Will attempt to remount all mounted filesystems read-only.
|
||||
|
||||
'v' - Dumps Voyager SMP processor info to your console.
|
||||
|
||||
'w' - Dumps tasks that are in uninterruptable (blocked) state.
|
||||
|
@ -102,17 +113,6 @@ On all - write a character to /proc/sysrq-trigger. e.g.:
|
|||
it so that only emergency messages like PANICs or OOPSes would
|
||||
make it to your console.)
|
||||
|
||||
'f' - Will call oom_kill to kill a memory hog process.
|
||||
|
||||
'e' - Send a SIGTERM to all processes, except for init.
|
||||
|
||||
'g' - Used by kgdb on ppc platforms.
|
||||
|
||||
'i' - Send a SIGKILL to all processes, except for init.
|
||||
|
||||
'h' - Will display help (actually any other key than those listed
|
||||
above will display help. but 'h' is easy to remember :-)
|
||||
|
||||
* Okay, so what can I use them for?
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
Well, un'R'aw is very handy when your X server or a svgalib program crashes.
|
||||
|
|
30
MAINTAINERS
30
MAINTAINERS
|
@ -635,6 +635,12 @@ W: http://people.redhat.com/sgrubb/audit/
|
|||
T: git kernel.org:/pub/scm/linux/kernel/git/dwmw2/audit-2.6.git
|
||||
S: Maintained
|
||||
|
||||
AUXILIARY DISPLAY DRIVERS
|
||||
P: Miguel Ojeda Sandonis
|
||||
M: maxextreme@gmail.com
|
||||
L: linux-kernel@vger.kernel.org
|
||||
S: Maintained
|
||||
|
||||
AVR32 ARCHITECTURE
|
||||
P: Haavard Skinnemoen
|
||||
M: hskinnemoen@atmel.com
|
||||
|
@ -836,6 +842,18 @@ L: linux-kernel@vger.kernel.org
|
|||
L: discuss@x86-64.org
|
||||
S: Maintained
|
||||
|
||||
CFAG12864B LCD DRIVER
|
||||
P: Miguel Ojeda Sandonis
|
||||
M: maxextreme@gmail.com
|
||||
L: linux-kernel@vger.kernel.org
|
||||
S: Maintained
|
||||
|
||||
CFAG12864BFB LCD FRAMEBUFFER DRIVER
|
||||
P: Miguel Ojeda Sandonis
|
||||
M: maxextreme@gmail.com
|
||||
L: linux-kernel@vger.kernel.org
|
||||
S: Maintained
|
||||
|
||||
COMMON INTERNET FILE SYSTEM (CIFS)
|
||||
P: Steve French
|
||||
M: sfrench@samba.org
|
||||
|
@ -984,14 +1002,12 @@ L: cycsyn-devel@bazar.conectiva.com.br
|
|||
S: Maintained
|
||||
|
||||
CYCLADES ASYNC MUX DRIVER
|
||||
M: async@cyclades.com
|
||||
W: http://www.cyclades.com/
|
||||
S: Supported
|
||||
S: Orphan
|
||||
|
||||
CYCLADES PC300 DRIVER
|
||||
M: pc300@cyclades.com
|
||||
W: http://www.cyclades.com/
|
||||
S: Supported
|
||||
S: Orphan
|
||||
|
||||
DAMA SLAVE for AX.25
|
||||
P: Joerg Reuter
|
||||
|
@ -1971,6 +1987,12 @@ M: davem@davemloft.net
|
|||
L: linux-kernel@vger.kernel.org
|
||||
S: Maintained
|
||||
|
||||
KS0108 LCD CONTROLLER DRIVER
|
||||
P: Miguel Ojeda Sandonis
|
||||
M: maxextreme@gmail.com
|
||||
L: linux-kernel@vger.kernel.org
|
||||
S: Maintained
|
||||
|
||||
LAPB module
|
||||
L: linux-x25@vger.kernel.org
|
||||
S: Orphan
|
||||
|
|
2
Makefile
2
Makefile
|
@ -789,7 +789,7 @@ $(vmlinux-dirs): prepare scripts
|
|||
|
||||
pattern = ".*/localversion[^~]*"
|
||||
string = $(shell cat /dev/null \
|
||||
`find $(objtree) $(srctree) -maxdepth 1 -regex $(pattern) | sort`)
|
||||
`find $(objtree) $(srctree) -maxdepth 1 -regex $(pattern) | sort -u`)
|
||||
|
||||
localver = $(subst $(space),, $(string) \
|
||||
$(patsubst "%",%,$(CONFIG_LOCALVERSION)))
|
||||
|
|
|
@ -41,6 +41,10 @@ config GENERIC_CALIBRATE_DELAY
|
|||
bool
|
||||
default y
|
||||
|
||||
config ZONE_DMA
|
||||
bool
|
||||
default y
|
||||
|
||||
config GENERIC_ISA_DMA
|
||||
bool
|
||||
default y
|
||||
|
|
|
@ -122,7 +122,7 @@ static void get_sysnames(unsigned long, unsigned long, unsigned long,
|
|||
char **, char **);
|
||||
static void determine_cpu_caches (unsigned int);
|
||||
|
||||
static char command_line[COMMAND_LINE_SIZE];
|
||||
static char __initdata command_line[COMMAND_LINE_SIZE];
|
||||
|
||||
/*
|
||||
* The format of "screen_info" is strange, and due to early
|
||||
|
@ -547,7 +547,7 @@ setup_arch(char **cmdline_p)
|
|||
} else {
|
||||
strlcpy(command_line, COMMAND_LINE, sizeof command_line);
|
||||
}
|
||||
strcpy(saved_command_line, command_line);
|
||||
strcpy(boot_command_line, command_line);
|
||||
*cmdline_p = command_line;
|
||||
|
||||
/*
|
||||
|
@ -589,7 +589,7 @@ setup_arch(char **cmdline_p)
|
|||
}
|
||||
|
||||
/* Replace the command line, now that we've killed it with strsep. */
|
||||
strcpy(command_line, saved_command_line);
|
||||
strcpy(command_line, boot_command_line);
|
||||
|
||||
/* If we want SRM console printk echoing early, do it now. */
|
||||
if (alpha_using_srm && srmcons_output) {
|
||||
|
|
|
@ -90,17 +90,6 @@ static inline __u32 rpcc(void)
|
|||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* Scheduler clock - returns current time in nanosec units.
|
||||
*
|
||||
* Copied from ARM code for expediency... ;-}
|
||||
*/
|
||||
unsigned long long sched_clock(void)
|
||||
{
|
||||
return (unsigned long long)jiffies * (1000000000 / HZ);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* timer_interrupt() needs to keep up the real-time clock,
|
||||
* as well as call the "do_timer()" routine every clocktick
|
||||
|
|
|
@ -52,10 +52,12 @@ SECTIONS
|
|||
}
|
||||
__initcall_end = .;
|
||||
|
||||
#ifdef CONFIG_BLK_DEV_INITRD
|
||||
. = ALIGN(8192);
|
||||
__initramfs_start = .;
|
||||
.init.ramfs : { *(.init.ramfs) }
|
||||
__initramfs_end = .;
|
||||
#endif
|
||||
|
||||
. = ALIGN(8);
|
||||
.con_initcall.init : {
|
||||
|
|
|
@ -29,6 +29,10 @@ config MMU
|
|||
bool
|
||||
default y
|
||||
|
||||
config NO_IOPORT
|
||||
bool
|
||||
default n
|
||||
|
||||
config EISA
|
||||
bool
|
||||
---help---
|
||||
|
@ -100,6 +104,10 @@ config GENERIC_BUST_SPINLOCK
|
|||
config ARCH_MAY_HAVE_PC_FDC
|
||||
bool
|
||||
|
||||
config ZONE_DMA
|
||||
bool
|
||||
default y
|
||||
|
||||
config GENERIC_ISA_DMA
|
||||
bool
|
||||
|
||||
|
@ -294,6 +302,7 @@ config ARCH_RPC
|
|||
select TIMER_ACORN
|
||||
select ARCH_MAY_HAVE_PC_FDC
|
||||
select ISA_DMA_API
|
||||
select NO_IOPORT
|
||||
help
|
||||
On the Acorn Risc-PC, Linux can support the internal IDE disk and
|
||||
CD-ROM interface, serial and parallel port, and the floppy drive.
|
||||
|
|
|
@ -329,7 +329,7 @@ static int rtc_fasync(int fd, struct file *file, int on)
|
|||
return fasync_helper(fd, file, on, &rtc_async_queue);
|
||||
}
|
||||
|
||||
static struct file_operations rtc_fops = {
|
||||
static const struct file_operations rtc_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.llseek = no_llseek,
|
||||
.read = rtc_read,
|
||||
|
|
|
@ -106,7 +106,7 @@ unsigned long phys_initrd_size __initdata = 0;
|
|||
static struct meminfo meminfo __initdata = { 0, };
|
||||
static const char *cpu_name;
|
||||
static const char *machine_name;
|
||||
static char command_line[COMMAND_LINE_SIZE];
|
||||
static char __initdata command_line[COMMAND_LINE_SIZE];
|
||||
|
||||
static char default_command_line[COMMAND_LINE_SIZE] __initdata = CONFIG_CMDLINE;
|
||||
static union { char c[4]; unsigned long l; } endian_test __initdata = { { 'l', '?', '?', 'b' } };
|
||||
|
@ -803,8 +803,8 @@ void __init setup_arch(char **cmdline_p)
|
|||
init_mm.end_data = (unsigned long) &_edata;
|
||||
init_mm.brk = (unsigned long) &_end;
|
||||
|
||||
memcpy(saved_command_line, from, COMMAND_LINE_SIZE);
|
||||
saved_command_line[COMMAND_LINE_SIZE-1] = '\0';
|
||||
memcpy(boot_command_line, from, COMMAND_LINE_SIZE);
|
||||
boot_command_line[COMMAND_LINE_SIZE-1] = '\0';
|
||||
parse_cmdline(cmdline_p, from);
|
||||
paging_init(&meminfo, mdesc);
|
||||
request_standard_resources(&meminfo, mdesc);
|
||||
|
|
|
@ -77,16 +77,6 @@ static unsigned long dummy_gettimeoffset(void)
|
|||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Scheduler clock - returns current time in nanosec units.
|
||||
* This is the default implementation. Sub-architecture
|
||||
* implementations can override this.
|
||||
*/
|
||||
unsigned long long __attribute__((weak)) sched_clock(void)
|
||||
{
|
||||
return (unsigned long long)jiffies * (1000000000 / HZ);
|
||||
}
|
||||
|
||||
/*
|
||||
* An implementation of printk_clock() independent from
|
||||
* sched_clock(). This avoids non-bootable kernels when
|
||||
|
|
|
@ -53,10 +53,12 @@ SECTIONS
|
|||
__security_initcall_start = .;
|
||||
*(.security_initcall.init)
|
||||
__security_initcall_end = .;
|
||||
#ifdef CONFIG_BLK_DEV_INITRD
|
||||
. = ALIGN(32);
|
||||
__initramfs_start = .;
|
||||
usr/built-in.o(.init.ramfs)
|
||||
__initramfs_end = .;
|
||||
#endif
|
||||
. = ALIGN(64);
|
||||
__per_cpu_start = .;
|
||||
*(.data.percpu)
|
||||
|
|
|
@ -407,7 +407,7 @@ static int at91_clk_open(struct inode *inode, struct file *file)
|
|||
return single_open(file, at91_clk_show, NULL);
|
||||
}
|
||||
|
||||
static struct file_operations at91_clk_operations = {
|
||||
static const struct file_operations at91_clk_operations = {
|
||||
.open = at91_clk_open,
|
||||
.read = seq_read,
|
||||
.llseek = seq_lseek,
|
||||
|
|
|
@ -64,6 +64,24 @@ static inline unsigned pin_to_mask(unsigned pin)
|
|||
*/
|
||||
|
||||
|
||||
/*
|
||||
* mux the pin to the "GPIO" peripheral role.
|
||||
*/
|
||||
int __init_or_module at91_set_GPIO_periph(unsigned pin, int use_pullup)
|
||||
{
|
||||
void __iomem *pio = pin_to_controller(pin);
|
||||
unsigned mask = pin_to_mask(pin);
|
||||
|
||||
if (!pio)
|
||||
return -EINVAL;
|
||||
__raw_writel(mask, pio + PIO_IDR);
|
||||
__raw_writel(mask, pio + (use_pullup ? PIO_PUER : PIO_PUDR));
|
||||
__raw_writel(mask, pio + PIO_PER);
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(at91_set_GPIO_periph);
|
||||
|
||||
|
||||
/*
|
||||
* mux the pin to the "A" internal peripheral role.
|
||||
*/
|
||||
|
@ -181,6 +199,36 @@ EXPORT_SYMBOL(at91_set_multi_drive);
|
|||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
/* new-style GPIO calls; these expect at91_set_GPIO_periph to have been
|
||||
* called, and maybe at91_set_multi_drive() for putout pins.
|
||||
*/
|
||||
|
||||
int gpio_direction_input(unsigned pin)
|
||||
{
|
||||
void __iomem *pio = pin_to_controller(pin);
|
||||
unsigned mask = pin_to_mask(pin);
|
||||
|
||||
if (!pio || !(__raw_readl(pio + PIO_PSR) & mask))
|
||||
return -EINVAL;
|
||||
__raw_writel(mask, pio + PIO_OER);
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(gpio_direction_input);
|
||||
|
||||
int gpio_direction_output(unsigned pin)
|
||||
{
|
||||
void __iomem *pio = pin_to_controller(pin);
|
||||
unsigned mask = pin_to_mask(pin);
|
||||
|
||||
if (!pio || !(__raw_readl(pio + PIO_PSR) & mask))
|
||||
return -EINVAL;
|
||||
__raw_writel(mask, pio + PIO_OER);
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(gpio_direction_output);
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* assuming the pin is muxed as a gpio output, set its value.
|
||||
*/
|
||||
|
|
|
@ -60,6 +60,10 @@ config GENERIC_CALIBRATE_DELAY
|
|||
config GENERIC_BUST_SPINLOCK
|
||||
bool
|
||||
|
||||
config ZONE_DMA
|
||||
bool
|
||||
default y
|
||||
|
||||
config GENERIC_ISA_DMA
|
||||
bool
|
||||
|
||||
|
|
|
@ -665,7 +665,7 @@ ecard_probe(int slot, card_type_t type)
|
|||
ec->fiqmask = 4;
|
||||
}
|
||||
|
||||
for (i = 0; i < sizeof(blacklist) / sizeof(*blacklist); i++)
|
||||
for (i = 0; i < ARRAY_SIZE(blacklist); i++)
|
||||
if (blacklist[i].manufacturer == ec->cid.manufacturer &&
|
||||
blacklist[i].product == ec->cid.product) {
|
||||
ec->card_desc = blacklist[i].type;
|
||||
|
|
|
@ -80,7 +80,7 @@ unsigned long phys_initrd_size __initdata = 0;
|
|||
static struct meminfo meminfo __initdata = { 0, };
|
||||
static struct proc_info_item proc_info;
|
||||
static const char *machine_name;
|
||||
static char command_line[COMMAND_LINE_SIZE];
|
||||
static char __initdata command_line[COMMAND_LINE_SIZE];
|
||||
|
||||
static char default_command_line[COMMAND_LINE_SIZE] __initdata = CONFIG_CMDLINE;
|
||||
|
||||
|
@ -492,8 +492,8 @@ void __init setup_arch(char **cmdline_p)
|
|||
init_mm.end_data = (unsigned long) &_edata;
|
||||
init_mm.brk = (unsigned long) &_end;
|
||||
|
||||
memcpy(saved_command_line, from, COMMAND_LINE_SIZE);
|
||||
saved_command_line[COMMAND_LINE_SIZE-1] = '\0';
|
||||
memcpy(boot_command_line, from, COMMAND_LINE_SIZE);
|
||||
boot_command_line[COMMAND_LINE_SIZE-1] = '\0';
|
||||
parse_cmdline(&meminfo, cmdline_p, from);
|
||||
bootmem_init(&meminfo);
|
||||
paging_init(&meminfo);
|
||||
|
|
|
@ -89,14 +89,6 @@ static unsigned long gettimeoffset(void)
|
|||
return (offset + LATCH/2) / LATCH;
|
||||
}
|
||||
|
||||
/*
|
||||
* Scheduler clock - returns current time in nanosec units.
|
||||
*/
|
||||
unsigned long long sched_clock(void)
|
||||
{
|
||||
return (unsigned long long)jiffies * (1000000000 / HZ);
|
||||
}
|
||||
|
||||
static unsigned long next_rtc_update;
|
||||
|
||||
/*
|
||||
|
|
|
@ -46,10 +46,12 @@ SECTIONS
|
|||
__con_initcall_start = .;
|
||||
*(.con_initcall.init)
|
||||
__con_initcall_end = .;
|
||||
#ifdef CONFIG_BLK_DEV_INITRD
|
||||
. = ALIGN(32);
|
||||
__initramfs_start = .;
|
||||
usr/built-in.o(.init.ramfs)
|
||||
__initramfs_end = .;
|
||||
#endif
|
||||
. = ALIGN(32768);
|
||||
__init_end = .;
|
||||
}
|
||||
|
|
|
@ -47,10 +47,12 @@ SECTIONS
|
|||
__con_initcall_start = .;
|
||||
*(.con_initcall.init)
|
||||
__con_initcall_end = .;
|
||||
#ifdef CONFIG_BLK_DEV_INITRD
|
||||
. = ALIGN(32);
|
||||
__initramfs_start = .;
|
||||
usr/built-in.o(.init.ramfs)
|
||||
__initramfs_end = .;
|
||||
#endif
|
||||
. = ALIGN(32768);
|
||||
__init_end = .;
|
||||
}
|
||||
|
|
|
@ -45,7 +45,7 @@ struct avr32_cpuinfo boot_cpu_data = {
|
|||
};
|
||||
EXPORT_SYMBOL(boot_cpu_data);
|
||||
|
||||
static char command_line[COMMAND_LINE_SIZE];
|
||||
static char __initdata command_line[COMMAND_LINE_SIZE];
|
||||
|
||||
/*
|
||||
* Should be more than enough, but if you have a _really_ complex
|
||||
|
@ -202,7 +202,7 @@ __tagtable(ATAG_MEM, parse_tag_mem);
|
|||
|
||||
static int __init parse_tag_cmdline(struct tag *tag)
|
||||
{
|
||||
strlcpy(saved_command_line, tag->u.cmdline.cmdline, COMMAND_LINE_SIZE);
|
||||
strlcpy(boot_command_line, tag->u.cmdline.cmdline, COMMAND_LINE_SIZE);
|
||||
return 0;
|
||||
}
|
||||
__tagtable(ATAG_CMDLINE, parse_tag_cmdline);
|
||||
|
@ -294,7 +294,7 @@ void __init setup_arch (char **cmdline_p)
|
|||
init_mm.end_data = (unsigned long) &_edata;
|
||||
init_mm.brk = (unsigned long) &_end;
|
||||
|
||||
strlcpy(command_line, saved_command_line, COMMAND_LINE_SIZE);
|
||||
strlcpy(command_line, boot_command_line, COMMAND_LINE_SIZE);
|
||||
*cmdline_p = command_line;
|
||||
parse_early_param();
|
||||
|
||||
|
|
|
@ -109,15 +109,6 @@ static void avr32_hpt_init(unsigned int count)
|
|||
sysreg_write(COUNT, count);
|
||||
}
|
||||
|
||||
/*
|
||||
* Scheduler clock - returns current time in nanosec units.
|
||||
*/
|
||||
unsigned long long sched_clock(void)
|
||||
{
|
||||
/* There must be better ways...? */
|
||||
return (unsigned long long)jiffies * (1000000000 / HZ);
|
||||
}
|
||||
|
||||
/*
|
||||
* local_timer_interrupt() does profiling and process accounting on a
|
||||
* per-CPU basis.
|
||||
|
|
|
@ -46,10 +46,12 @@ SECTIONS
|
|||
__security_initcall_start = .;
|
||||
*(.security_initcall.init)
|
||||
__security_initcall_end = .;
|
||||
#ifdef CONFIG_BLK_DEV_INITRD
|
||||
. = ALIGN(32);
|
||||
__initramfs_start = .;
|
||||
*(.init.ramfs)
|
||||
__initramfs_end = .;
|
||||
#endif
|
||||
. = ALIGN(4096);
|
||||
__init_end = .;
|
||||
}
|
||||
|
|
|
@ -360,7 +360,7 @@ static int tlb_open(struct inode *inode, struct file *file)
|
|||
return seq_open(file, &tlb_ops);
|
||||
}
|
||||
|
||||
static struct file_operations proc_tlb_operations = {
|
||||
static const struct file_operations proc_tlb_operations = {
|
||||
.open = tlb_open,
|
||||
.read = seq_read,
|
||||
.llseek = seq_lseek,
|
||||
|
|
|
@ -9,6 +9,10 @@ config MMU
|
|||
bool
|
||||
default y
|
||||
|
||||
config ZONE_DMA
|
||||
bool
|
||||
default y
|
||||
|
||||
config RWSEM_GENERIC_SPINLOCK
|
||||
bool
|
||||
default y
|
||||
|
@ -40,6 +44,9 @@ config IRQ_PER_CPU
|
|||
bool
|
||||
default y
|
||||
|
||||
config NO_IOPORT
|
||||
def_bool y
|
||||
|
||||
config CRIS
|
||||
bool
|
||||
default y
|
||||
|
|
|
@ -359,8 +359,7 @@ static struct mtd_info *flash_probe(void)
|
|||
* So we use the MTD concatenation layer instead of further
|
||||
* complicating the probing procedure.
|
||||
*/
|
||||
mtd_cse = mtd_concat_create(mtds,
|
||||
sizeof(mtds) / sizeof(mtds[0]),
|
||||
mtd_cse = mtd_concat_create(mtds, ARRAY_SIZE(mtds),
|
||||
"cse0+cse1");
|
||||
#else
|
||||
printk(KERN_ERR "%s and %s: Cannot concatenate due to kernel "
|
||||
|
|
|
@ -499,7 +499,7 @@ print_rtc_status(void)
|
|||
|
||||
/* The various file operations we support. */
|
||||
|
||||
static struct file_operations rtc_fops = {
|
||||
static const struct file_operations rtc_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.ioctl = rtc_ioctl,
|
||||
};
|
||||
|
|
|
@ -172,7 +172,7 @@ static const char eeprom_name[] = "eeprom";
|
|||
static struct eeprom_type eeprom;
|
||||
|
||||
/* This is the exported file-operations structure for this device. */
|
||||
struct file_operations eeprom_fops =
|
||||
const struct file_operations eeprom_fops =
|
||||
{
|
||||
.llseek = eeprom_lseek,
|
||||
.read = eeprom_read,
|
||||
|
|
|
@ -838,7 +838,7 @@ gpio_leds_ioctl(unsigned int cmd, unsigned long arg)
|
|||
return 0;
|
||||
}
|
||||
|
||||
struct file_operations gpio_fops = {
|
||||
const struct file_operations gpio_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.poll = gpio_poll,
|
||||
.ioctl = gpio_ioctl,
|
||||
|
|
|
@ -692,7 +692,7 @@ i2c_ioctl(struct inode *inode, struct file *file,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static struct file_operations i2c_fops = {
|
||||
static const struct file_operations i2c_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.ioctl = i2c_ioctl,
|
||||
.open = i2c_open,
|
||||
|
|
|
@ -56,7 +56,7 @@ static const unsigned char days_in_month[] =
|
|||
|
||||
int pcf8563_ioctl(struct inode *, struct file *, unsigned int, unsigned long);
|
||||
|
||||
static struct file_operations pcf8563_fops = {
|
||||
static const struct file_operations pcf8563_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.ioctl = pcf8563_ioctl,
|
||||
};
|
||||
|
|
|
@ -38,7 +38,6 @@ unsigned long get_ns_in_jiffie(void)
|
|||
unsigned long flags;
|
||||
|
||||
local_irq_save(flags);
|
||||
local_irq_disable();
|
||||
timer_count = *R_TIMER0_DATA;
|
||||
presc_count = *R_TIM_PRESC_STATUS;
|
||||
/* presc_count might be wrapped */
|
||||
|
|
|
@ -42,8 +42,7 @@ flush_tlb_all(void)
|
|||
* in the same 4-way entry group. details..
|
||||
*/
|
||||
|
||||
local_save_flags(flags);
|
||||
local_irq_disable();
|
||||
local_irq_save(flags);
|
||||
for(i = 0; i < NUM_TLB_ENTRIES; i++) {
|
||||
*R_TLB_SELECT = ( IO_FIELD(R_TLB_SELECT, index, i) );
|
||||
*R_TLB_HI = ( IO_FIELD(R_TLB_HI, page_id, INVALID_PAGEID ) |
|
||||
|
@ -78,8 +77,7 @@ flush_tlb_mm(struct mm_struct *mm)
|
|||
* global pages. is it worth the extra I/O ?
|
||||
*/
|
||||
|
||||
local_save_flags(flags);
|
||||
local_irq_disable();
|
||||
local_irq_save(flags);
|
||||
for(i = 0; i < NUM_TLB_ENTRIES; i++) {
|
||||
*R_TLB_SELECT = IO_FIELD(R_TLB_SELECT, index, i);
|
||||
if (IO_EXTRACT(R_TLB_HI, page_id, *R_TLB_HI) == page_id) {
|
||||
|
@ -118,8 +116,7 @@ flush_tlb_page(struct vm_area_struct *vma,
|
|||
* and the virtual address requested
|
||||
*/
|
||||
|
||||
local_save_flags(flags);
|
||||
local_irq_disable();
|
||||
local_irq_save(flags);
|
||||
for(i = 0; i < NUM_TLB_ENTRIES; i++) {
|
||||
unsigned long tlb_hi;
|
||||
*R_TLB_SELECT = IO_FIELD(R_TLB_SELECT, index, i);
|
||||
|
|
|
@ -82,7 +82,8 @@ SECTIONS
|
|||
__con_initcall_end = .;
|
||||
}
|
||||
SECURITY_INIT
|
||||
|
||||
|
||||
#ifdef CONFIG_BLK_DEV_INITRD
|
||||
.init.ramfs : {
|
||||
__initramfs_start = .;
|
||||
*(.init.ramfs)
|
||||
|
@ -93,6 +94,7 @@ SECTIONS
|
|||
FILL (0);
|
||||
. = ALIGN (8192);
|
||||
}
|
||||
#endif
|
||||
|
||||
__vmlinux_end = .; /* last address of the physical file */
|
||||
__init_end = .;
|
||||
|
|
|
@ -266,7 +266,7 @@ static void print_user_dma_lists(struct cryptocop_dma_list_operation *dma_op);
|
|||
|
||||
|
||||
|
||||
struct file_operations cryptocop_fops = {
|
||||
const struct file_operations cryptocop_fops = {
|
||||
owner: THIS_MODULE,
|
||||
open: cryptocop_open,
|
||||
release: cryptocop_release,
|
||||
|
|
|
@ -705,7 +705,7 @@ gpio_leds_ioctl(unsigned int cmd, unsigned long arg)
|
|||
return 0;
|
||||
}
|
||||
|
||||
struct file_operations gpio_fops = {
|
||||
const struct file_operations gpio_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.poll = gpio_poll,
|
||||
.ioctl = gpio_ioctl,
|
||||
|
|
|
@ -573,7 +573,7 @@ i2c_ioctl(struct inode *inode, struct file *file,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static struct file_operations i2c_fops = {
|
||||
static const struct file_operations i2c_fops = {
|
||||
owner: THIS_MODULE,
|
||||
ioctl: i2c_ioctl,
|
||||
open: i2c_open,
|
||||
|
|
|
@ -50,7 +50,7 @@ int pcf8563_ioctl(struct inode *, struct file *, unsigned int, unsigned long);
|
|||
int pcf8563_open(struct inode *, struct file *);
|
||||
int pcf8563_release(struct inode *, struct file *);
|
||||
|
||||
static struct file_operations pcf8563_fops = {
|
||||
static const struct file_operations pcf8563_fops = {
|
||||
owner: THIS_MODULE,
|
||||
ioctl: pcf8563_ioctl,
|
||||
open: pcf8563_open,
|
||||
|
|
|
@ -187,7 +187,7 @@ static struct sync_port ports[]=
|
|||
|
||||
#define NUMBER_OF_PORTS (sizeof(ports)/sizeof(sync_port))
|
||||
|
||||
static struct file_operations sync_serial_fops = {
|
||||
static const struct file_operations sync_serial_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.write = sync_serial_write,
|
||||
.read = sync_serial_read,
|
||||
|
|
|
@ -54,8 +54,7 @@ __flush_tlb_all(void)
|
|||
* Mask with 0xf so similar TLB entries aren't written in the same 4-way
|
||||
* entry group.
|
||||
*/
|
||||
local_save_flags(flags);
|
||||
local_irq_disable();
|
||||
local_irq_save(flags);
|
||||
|
||||
for (mmu = 1; mmu <= 2; mmu++) {
|
||||
SUPP_BANK_SEL(mmu); /* Select the MMU */
|
||||
|
@ -92,8 +91,7 @@ __flush_tlb_mm(struct mm_struct *mm)
|
|||
return;
|
||||
|
||||
/* Mark the TLB entries that match the page_id as invalid. */
|
||||
local_save_flags(flags);
|
||||
local_irq_disable();
|
||||
local_irq_save(flags);
|
||||
|
||||
for (mmu = 1; mmu <= 2; mmu++) {
|
||||
SUPP_BANK_SEL(mmu);
|
||||
|
@ -140,8 +138,7 @@ __flush_tlb_page(struct vm_area_struct *vma, unsigned long addr)
|
|||
* Invalidate those TLB entries that match both the mm context and the
|
||||
* requested virtual address.
|
||||
*/
|
||||
local_save_flags(flags);
|
||||
local_irq_disable();
|
||||
local_irq_save(flags);
|
||||
|
||||
for (mmu = 1; mmu <= 2; mmu++) {
|
||||
SUPP_BANK_SEL(mmu);
|
||||
|
|
|
@ -95,6 +95,7 @@ SECTIONS
|
|||
.data.percpu : { *(.data.percpu) }
|
||||
__per_cpu_end = .;
|
||||
|
||||
#ifdef CONFIG_BLK_DEV_INITRD
|
||||
.init.ramfs : {
|
||||
__initramfs_start = .;
|
||||
*(.init.ramfs)
|
||||
|
@ -107,6 +108,7 @@ SECTIONS
|
|||
FILL (0);
|
||||
. = ALIGN (8192);
|
||||
}
|
||||
#endif
|
||||
|
||||
__vmlinux_end = .; /* Last address of the physical file. */
|
||||
__init_end = .;
|
||||
|
|
|
@ -50,7 +50,7 @@ write_cris_profile(struct file *file, const char __user *buf,
|
|||
memset(sample_buffer, 0, SAMPLE_BUFFER_SIZE);
|
||||
}
|
||||
|
||||
static struct file_operations cris_proc_profile_operations = {
|
||||
static const struct file_operations cris_proc_profile_operations = {
|
||||
.read = read_cris_profile,
|
||||
.write = write_cris_profile,
|
||||
};
|
||||
|
|
|
@ -29,7 +29,7 @@ struct screen_info screen_info;
|
|||
extern int root_mountflags;
|
||||
extern char _etext, _edata, _end;
|
||||
|
||||
char cris_command_line[COMMAND_LINE_SIZE] = { 0, };
|
||||
char __initdata cris_command_line[COMMAND_LINE_SIZE] = { 0, };
|
||||
|
||||
extern const unsigned long text_start, edata; /* set by the linker script */
|
||||
extern unsigned long dram_start, dram_end;
|
||||
|
@ -153,8 +153,8 @@ setup_arch(char **cmdline_p)
|
|||
#endif
|
||||
|
||||
/* Save command line for future references. */
|
||||
memcpy(saved_command_line, cris_command_line, COMMAND_LINE_SIZE);
|
||||
saved_command_line[COMMAND_LINE_SIZE - 1] = '\0';
|
||||
memcpy(boot_command_line, cris_command_line, COMMAND_LINE_SIZE);
|
||||
boot_command_line[COMMAND_LINE_SIZE - 1] = '\0';
|
||||
|
||||
/* give credit for the CRIS port */
|
||||
show_etrax_copyright();
|
||||
|
|
|
@ -55,7 +55,6 @@ void do_gettimeofday(struct timeval *tv)
|
|||
unsigned long flags;
|
||||
signed long usec, sec;
|
||||
local_irq_save(flags);
|
||||
local_irq_disable();
|
||||
usec = do_gettimeoffset();
|
||||
|
||||
/*
|
||||
|
@ -217,14 +216,6 @@ cris_do_profile(struct pt_regs* regs)
|
|||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* Scheduler clock - returns current time in nanosec units.
|
||||
*/
|
||||
unsigned long long sched_clock(void)
|
||||
{
|
||||
return (unsigned long long)jiffies * (1000000000 / HZ);
|
||||
}
|
||||
|
||||
static int
|
||||
__init init_udelay(void)
|
||||
{
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
*/
|
||||
|
||||
#include <linux/init.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <asm/tlb.h>
|
||||
|
||||
#define D(x)
|
||||
|
@ -100,7 +101,7 @@ tlb_init(void)
|
|||
|
||||
/* clear the page_id map */
|
||||
|
||||
for (i = 1; i < sizeof (page_id_map) / sizeof (page_id_map[0]); i++)
|
||||
for (i = 1; i < ARRAY_SIZE(page_id_map); i++)
|
||||
page_id_map[i] = NULL;
|
||||
|
||||
/* invalidate the entire TLB */
|
||||
|
|
|
@ -6,6 +6,10 @@ config FRV
|
|||
bool
|
||||
default y
|
||||
|
||||
config ZONE_DMA
|
||||
bool
|
||||
default y
|
||||
|
||||
config RWSEM_GENERIC_SPINLOCK
|
||||
bool
|
||||
default y
|
||||
|
|
|
@ -110,7 +110,7 @@ unsigned long __initdata num_mappedpages;
|
|||
|
||||
struct cpuinfo_frv __nongprelbss boot_cpu_data;
|
||||
|
||||
char command_line[COMMAND_LINE_SIZE];
|
||||
char __initdata command_line[COMMAND_LINE_SIZE];
|
||||
char __initdata redboot_command_line[COMMAND_LINE_SIZE];
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
|
@ -762,7 +762,7 @@ void __init setup_arch(char **cmdline_p)
|
|||
printk("uClinux FR-V port done by Red Hat Inc <dhowells@redhat.com>\n");
|
||||
#endif
|
||||
|
||||
memcpy(saved_command_line, redboot_command_line, COMMAND_LINE_SIZE);
|
||||
memcpy(boot_command_line, redboot_command_line, COMMAND_LINE_SIZE);
|
||||
|
||||
determine_cpu();
|
||||
determine_clocks(1);
|
||||
|
@ -803,7 +803,7 @@ void __init setup_arch(char **cmdline_p)
|
|||
#endif
|
||||
|
||||
/* deal with the command line - RedBoot may have passed one to the kernel */
|
||||
memcpy(command_line, saved_command_line, sizeof(command_line));
|
||||
memcpy(command_line, boot_command_line, sizeof(command_line));
|
||||
*cmdline_p = &command_line[0];
|
||||
parse_cmdline_early(command_line);
|
||||
|
||||
|
|
|
@ -61,10 +61,12 @@ SECTIONS
|
|||
.data.percpu : { *(.data.percpu) }
|
||||
__per_cpu_end = .;
|
||||
|
||||
#ifdef CONFIG_BLK_DEV_INITRD
|
||||
. = ALIGN(4096);
|
||||
__initramfs_start = .;
|
||||
.init.ramfs : { *(.init.ramfs) }
|
||||
__initramfs_end = .;
|
||||
#endif
|
||||
|
||||
. = ALIGN(THREAD_SIZE);
|
||||
__init_end = .;
|
||||
|
|
|
@ -17,6 +17,10 @@ config SWAP
|
|||
bool
|
||||
default n
|
||||
|
||||
config ZONE_DMA
|
||||
bool
|
||||
default y
|
||||
|
||||
config FPU
|
||||
bool
|
||||
default n
|
||||
|
@ -53,6 +57,9 @@ config TIME_LOW_RES
|
|||
bool
|
||||
default y
|
||||
|
||||
config NO_IOPORT
|
||||
def_bool y
|
||||
|
||||
config ISA
|
||||
bool
|
||||
default y
|
||||
|
|
|
@ -6,6 +6,8 @@ extra-y := vmlinux.lds
|
|||
|
||||
obj-y := process.o traps.o ptrace.o ints.o \
|
||||
sys_h8300.o time.o semaphore.o signal.o \
|
||||
setup.o gpio.o init_task.o syscalls.o
|
||||
setup.o gpio.o init_task.o syscalls.o devres.o
|
||||
|
||||
devres-y = ../../../kernel/irq/devres.o
|
||||
|
||||
obj-$(CONFIG_MODULES) += module.o h8300_ksyms.o
|
||||
|
|
|
@ -54,7 +54,7 @@ unsigned long rom_length;
|
|||
unsigned long memory_start;
|
||||
unsigned long memory_end;
|
||||
|
||||
char command_line[COMMAND_LINE_SIZE];
|
||||
char __initdata command_line[COMMAND_LINE_SIZE];
|
||||
|
||||
extern int _stext, _etext, _sdata, _edata, _sbss, _ebss, _end;
|
||||
extern int _ramstart, _ramend;
|
||||
|
@ -154,8 +154,8 @@ void __init setup_arch(char **cmdline_p)
|
|||
#endif
|
||||
/* Keep a copy of command line */
|
||||
*cmdline_p = &command_line[0];
|
||||
memcpy(saved_command_line, command_line, COMMAND_LINE_SIZE);
|
||||
saved_command_line[COMMAND_LINE_SIZE-1] = 0;
|
||||
memcpy(boot_command_line, command_line, COMMAND_LINE_SIZE);
|
||||
boot_command_line[COMMAND_LINE_SIZE-1] = 0;
|
||||
|
||||
#ifdef DEBUG
|
||||
if (strlen(*cmdline_p))
|
||||
|
|
|
@ -118,9 +118,3 @@ int do_settimeofday(struct timespec *tv)
|
|||
}
|
||||
|
||||
EXPORT_SYMBOL(do_settimeofday);
|
||||
|
||||
unsigned long long sched_clock(void)
|
||||
{
|
||||
return (unsigned long long)jiffies * (1000000000 / HZ);
|
||||
|
||||
}
|
||||
|
|
|
@ -126,10 +126,12 @@ SECTIONS
|
|||
___con_initcall_end = .;
|
||||
*(.exit.text)
|
||||
*(.exit.data)
|
||||
#if defined(CONFIG_BLK_DEV_INITRD)
|
||||
. = ALIGN(4);
|
||||
___initramfs_start = .;
|
||||
*(.init.ramfs)
|
||||
___initramfs_end = .;
|
||||
#endif
|
||||
. = ALIGN(0x4) ;
|
||||
___init_end = .;
|
||||
__edata = . ;
|
||||
|
|
|
@ -38,6 +38,10 @@ config MMU
|
|||
bool
|
||||
default y
|
||||
|
||||
config ZONE_DMA
|
||||
bool
|
||||
default y
|
||||
|
||||
config SBUS
|
||||
bool
|
||||
|
||||
|
|
|
@ -1894,7 +1894,7 @@ static int __init apm_setup(char *str)
|
|||
__setup("apm=", apm_setup);
|
||||
#endif
|
||||
|
||||
static struct file_operations apm_bios_fops = {
|
||||
static const struct file_operations apm_bios_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.read = do_read,
|
||||
.poll = do_poll,
|
||||
|
|
|
@ -339,7 +339,7 @@ static int mtrr_open(struct inode *inode, struct file *file)
|
|||
return single_open(file, mtrr_seq_show, NULL);
|
||||
}
|
||||
|
||||
static struct file_operations mtrr_fops = {
|
||||
static const struct file_operations mtrr_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.open = mtrr_open,
|
||||
.read = seq_read,
|
||||
|
|
|
@ -148,7 +148,7 @@ static int cpuid_open(struct inode *inode, struct file *file)
|
|||
/*
|
||||
* File operations we support
|
||||
*/
|
||||
static struct file_operations cpuid_fops = {
|
||||
static const struct file_operations cpuid_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.llseek = cpuid_seek,
|
||||
.read = cpuid_read,
|
||||
|
|
|
@ -103,7 +103,7 @@ ENTRY(startup_32)
|
|||
movzwl OLD_CL_OFFSET,%esi
|
||||
addl $(OLD_CL_BASE_ADDR),%esi
|
||||
2:
|
||||
movl $(saved_command_line - __PAGE_OFFSET),%edi
|
||||
movl $(boot_command_line - __PAGE_OFFSET),%edi
|
||||
movl $(COMMAND_LINE_SIZE/4),%ecx
|
||||
rep
|
||||
movsl
|
||||
|
|
|
@ -451,7 +451,7 @@ static ssize_t microcode_write (struct file *file, const char __user *buf, size_
|
|||
return ret;
|
||||
}
|
||||
|
||||
static struct file_operations microcode_fops = {
|
||||
static const struct file_operations microcode_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.write = microcode_write,
|
||||
.open = microcode_open,
|
||||
|
|
|
@ -230,7 +230,7 @@ static int msr_open(struct inode *inode, struct file *file)
|
|||
/*
|
||||
* File operations we support
|
||||
*/
|
||||
static struct file_operations msr_fops = {
|
||||
static const struct file_operations msr_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.llseek = msr_seek,
|
||||
.read = msr_read,
|
||||
|
|
|
@ -132,7 +132,7 @@ unsigned long saved_videomode;
|
|||
#define RAMDISK_PROMPT_FLAG 0x8000
|
||||
#define RAMDISK_LOAD_FLAG 0x4000
|
||||
|
||||
static char command_line[COMMAND_LINE_SIZE];
|
||||
static char __initdata command_line[COMMAND_LINE_SIZE];
|
||||
|
||||
unsigned char __initdata boot_params[PARAM_SIZE];
|
||||
|
||||
|
@ -576,7 +576,7 @@ void __init setup_arch(char **cmdline_p)
|
|||
print_memory_map("user");
|
||||
}
|
||||
|
||||
strlcpy(command_line, saved_command_line, COMMAND_LINE_SIZE);
|
||||
strlcpy(command_line, boot_command_line, COMMAND_LINE_SIZE);
|
||||
*cmdline_p = command_line;
|
||||
|
||||
max_low_pfn = setup_memory();
|
||||
|
|
|
@ -181,12 +181,14 @@ SECTIONS
|
|||
from .altinstructions and .eh_frame */
|
||||
.exit.text : AT(ADDR(.exit.text) - LOAD_OFFSET) { *(.exit.text) }
|
||||
.exit.data : AT(ADDR(.exit.data) - LOAD_OFFSET) { *(.exit.data) }
|
||||
#if defined(CONFIG_BLK_DEV_INITRD)
|
||||
. = ALIGN(4096);
|
||||
.init.ramfs : AT(ADDR(.init.ramfs) - LOAD_OFFSET) {
|
||||
__initramfs_start = .;
|
||||
*(.init.ramfs)
|
||||
__initramfs_end = .;
|
||||
}
|
||||
#endif
|
||||
. = ALIGN(L1_CACHE_BYTES);
|
||||
.data.percpu : AT(ADDR(.data.percpu) - LOAD_OFFSET) {
|
||||
__per_cpu_start = .;
|
||||
|
|
|
@ -59,32 +59,6 @@ static inline int notify_page_fault(enum die_val val, const char *str,
|
|||
return atomic_notifier_call_chain(¬ify_page_fault_chain, val, &args);
|
||||
}
|
||||
|
||||
/*
|
||||
* Unlock any spinlocks which will prevent us from getting the
|
||||
* message out
|
||||
*/
|
||||
void bust_spinlocks(int yes)
|
||||
{
|
||||
int loglevel_save = console_loglevel;
|
||||
|
||||
if (yes) {
|
||||
oops_in_progress = 1;
|
||||
return;
|
||||
}
|
||||
#ifdef CONFIG_VT
|
||||
unblank_screen();
|
||||
#endif
|
||||
oops_in_progress = 0;
|
||||
/*
|
||||
* OK, the message is on the console. Now we call printk()
|
||||
* without oops_in_progress set so that printk will give klogd
|
||||
* a poke. Hold onto your hats...
|
||||
*/
|
||||
console_loglevel = 15; /* NMI oopser may have shut the console up */
|
||||
printk(" ");
|
||||
console_loglevel = loglevel_save;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return EIP plus the CS segment base. The segment limit is also
|
||||
* adjusted, clamped to the kernel/user address space (whichever is
|
||||
|
|
|
@ -33,13 +33,14 @@ void *kmap_atomic(struct page *page, enum km_type type)
|
|||
|
||||
/* even !CONFIG_PREEMPT needs this, for in_atomic in do_page_fault */
|
||||
pagefault_disable();
|
||||
|
||||
idx = type + KM_TYPE_NR*smp_processor_id();
|
||||
BUG_ON(!pte_none(*(kmap_pte-idx)));
|
||||
|
||||
if (!PageHighMem(page))
|
||||
return page_address(page);
|
||||
|
||||
idx = type + KM_TYPE_NR*smp_processor_id();
|
||||
vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx);
|
||||
if (!pte_none(*(kmap_pte-idx)))
|
||||
BUG();
|
||||
set_pte(kmap_pte-idx, mk_pte(page, kmap_prot));
|
||||
|
||||
return (void*) vaddr;
|
||||
|
|
|
@ -24,6 +24,10 @@ config 64BIT
|
|||
bool
|
||||
default y
|
||||
|
||||
config ZONE_DMA
|
||||
def_bool y
|
||||
depends on !IA64_SGI_SN2
|
||||
|
||||
config MMU
|
||||
bool
|
||||
default y
|
||||
|
|
|
@ -1881,7 +1881,7 @@ ioc_open(struct inode *inode, struct file *file)
|
|||
return seq_open(file, &ioc_seq_ops);
|
||||
}
|
||||
|
||||
static struct file_operations ioc_fops = {
|
||||
static const struct file_operations ioc_fops = {
|
||||
.open = ioc_open,
|
||||
.read = seq_read,
|
||||
.llseek = seq_lseek,
|
||||
|
|
|
@ -91,9 +91,8 @@ ia64_elf32_init (struct pt_regs *regs)
|
|||
* it with privilege level 3 because the IVE uses non-privileged accesses to these
|
||||
* tables. IA-32 segmentation is used to protect against IA-32 accesses to them.
|
||||
*/
|
||||
vma = kmem_cache_alloc(vm_area_cachep, GFP_KERNEL);
|
||||
vma = kmem_cache_zalloc(vm_area_cachep, GFP_KERNEL);
|
||||
if (vma) {
|
||||
memset(vma, 0, sizeof(*vma));
|
||||
vma->vm_mm = current->mm;
|
||||
vma->vm_start = IA32_GDT_OFFSET;
|
||||
vma->vm_end = vma->vm_start + PAGE_SIZE;
|
||||
|
@ -117,9 +116,8 @@ ia64_elf32_init (struct pt_regs *regs)
|
|||
* code is locked in specific gate page, which is pointed by pretcode
|
||||
* when setup_frame_ia32
|
||||
*/
|
||||
vma = kmem_cache_alloc(vm_area_cachep, GFP_KERNEL);
|
||||
vma = kmem_cache_zalloc(vm_area_cachep, GFP_KERNEL);
|
||||
if (vma) {
|
||||
memset(vma, 0, sizeof(*vma));
|
||||
vma->vm_mm = current->mm;
|
||||
vma->vm_start = IA32_GATE_OFFSET;
|
||||
vma->vm_end = vma->vm_start + PAGE_SIZE;
|
||||
|
@ -142,9 +140,8 @@ ia64_elf32_init (struct pt_regs *regs)
|
|||
* Install LDT as anonymous memory. This gives us all-zero segment descriptors
|
||||
* until a task modifies them via modify_ldt().
|
||||
*/
|
||||
vma = kmem_cache_alloc(vm_area_cachep, GFP_KERNEL);
|
||||
vma = kmem_cache_zalloc(vm_area_cachep, GFP_KERNEL);
|
||||
if (vma) {
|
||||
memset(vma, 0, sizeof(*vma));
|
||||
vma->vm_mm = current->mm;
|
||||
vma->vm_start = IA32_LDT_OFFSET;
|
||||
vma->vm_end = vma->vm_start + PAGE_ALIGN(IA32_LDT_ENTRIES*IA32_LDT_ENTRY_SIZE);
|
||||
|
@ -214,12 +211,10 @@ ia32_setup_arg_pages (struct linux_binprm *bprm, int executable_stack)
|
|||
bprm->loader += stack_base;
|
||||
bprm->exec += stack_base;
|
||||
|
||||
mpnt = kmem_cache_alloc(vm_area_cachep, GFP_KERNEL);
|
||||
mpnt = kmem_cache_zalloc(vm_area_cachep, GFP_KERNEL);
|
||||
if (!mpnt)
|
||||
return -ENOMEM;
|
||||
|
||||
memset(mpnt, 0, sizeof(*mpnt));
|
||||
|
||||
down_write(¤t->mm->mmap_sem);
|
||||
{
|
||||
mpnt->vm_mm = current->mm;
|
||||
|
|
|
@ -326,7 +326,7 @@ ia32_syscall_table:
|
|||
data8 sys_ni_syscall
|
||||
data8 compat_sys_wait4
|
||||
data8 sys_swapoff /* 115 */
|
||||
data8 sys32_sysinfo
|
||||
data8 compat_sys_sysinfo
|
||||
data8 sys32_ipc
|
||||
data8 sys_fsync
|
||||
data8 sys32_sigreturn
|
||||
|
|
|
@ -2209,74 +2209,6 @@ sys32_fstat64 (unsigned int fd, struct stat64 __user *statbuf)
|
|||
return ret;
|
||||
}
|
||||
|
||||
struct sysinfo32 {
|
||||
s32 uptime;
|
||||
u32 loads[3];
|
||||
u32 totalram;
|
||||
u32 freeram;
|
||||
u32 sharedram;
|
||||
u32 bufferram;
|
||||
u32 totalswap;
|
||||
u32 freeswap;
|
||||
u16 procs;
|
||||
u16 pad;
|
||||
u32 totalhigh;
|
||||
u32 freehigh;
|
||||
u32 mem_unit;
|
||||
char _f[8];
|
||||
};
|
||||
|
||||
asmlinkage long
|
||||
sys32_sysinfo (struct sysinfo32 __user *info)
|
||||
{
|
||||
struct sysinfo s;
|
||||
long ret, err;
|
||||
int bitcount = 0;
|
||||
mm_segment_t old_fs = get_fs();
|
||||
|
||||
set_fs(KERNEL_DS);
|
||||
ret = sys_sysinfo((struct sysinfo __user *) &s);
|
||||
set_fs(old_fs);
|
||||
/* Check to see if any memory value is too large for 32-bit and
|
||||
* scale down if needed.
|
||||
*/
|
||||
if ((s.totalram >> 32) || (s.totalswap >> 32)) {
|
||||
while (s.mem_unit < PAGE_SIZE) {
|
||||
s.mem_unit <<= 1;
|
||||
bitcount++;
|
||||
}
|
||||
s.totalram >>= bitcount;
|
||||
s.freeram >>= bitcount;
|
||||
s.sharedram >>= bitcount;
|
||||
s.bufferram >>= bitcount;
|
||||
s.totalswap >>= bitcount;
|
||||
s.freeswap >>= bitcount;
|
||||
s.totalhigh >>= bitcount;
|
||||
s.freehigh >>= bitcount;
|
||||
}
|
||||
|
||||
if (!access_ok(VERIFY_WRITE, info, sizeof(*info)))
|
||||
return -EFAULT;
|
||||
|
||||
err = __put_user(s.uptime, &info->uptime);
|
||||
err |= __put_user(s.loads[0], &info->loads[0]);
|
||||
err |= __put_user(s.loads[1], &info->loads[1]);
|
||||
err |= __put_user(s.loads[2], &info->loads[2]);
|
||||
err |= __put_user(s.totalram, &info->totalram);
|
||||
err |= __put_user(s.freeram, &info->freeram);
|
||||
err |= __put_user(s.sharedram, &info->sharedram);
|
||||
err |= __put_user(s.bufferram, &info->bufferram);
|
||||
err |= __put_user(s.totalswap, &info->totalswap);
|
||||
err |= __put_user(s.freeswap, &info->freeswap);
|
||||
err |= __put_user(s.procs, &info->procs);
|
||||
err |= __put_user (s.totalhigh, &info->totalhigh);
|
||||
err |= __put_user (s.freehigh, &info->freehigh);
|
||||
err |= __put_user (s.mem_unit, &info->mem_unit);
|
||||
if (err)
|
||||
return -EFAULT;
|
||||
return ret;
|
||||
}
|
||||
|
||||
asmlinkage long
|
||||
sys32_sched_rr_get_interval (pid_t pid, struct compat_timespec __user *interval)
|
||||
{
|
||||
|
|
|
@ -413,11 +413,10 @@ efi_init (void)
|
|||
efi_char16_t *c16;
|
||||
u64 efi_desc_size;
|
||||
char *cp, vendor[100] = "unknown";
|
||||
extern char saved_command_line[];
|
||||
int i;
|
||||
|
||||
/* it's too early to be able to use the standard kernel command line support... */
|
||||
for (cp = saved_command_line; *cp; ) {
|
||||
for (cp = boot_command_line; *cp; ) {
|
||||
if (memcmp(cp, "mem=", 4) == 0) {
|
||||
mem_limit = memparse(cp + 4, &cp);
|
||||
} else if (memcmp(cp, "max_addr=", 9) == 0) {
|
||||
|
|
|
@ -621,7 +621,7 @@ EXPORT_PER_CPU_SYMBOL_GPL(pfm_syst_info);
|
|||
|
||||
|
||||
/* forward declaration */
|
||||
static struct file_operations pfm_file_ops;
|
||||
static const struct file_operations pfm_file_ops;
|
||||
|
||||
/*
|
||||
* forward declarations
|
||||
|
@ -2126,7 +2126,7 @@ pfm_no_open(struct inode *irrelevant, struct file *dontcare)
|
|||
|
||||
|
||||
|
||||
static struct file_operations pfm_file_ops = {
|
||||
static const struct file_operations pfm_file_ops = {
|
||||
.llseek = no_llseek,
|
||||
.read = pfm_read,
|
||||
.write = pfm_write,
|
||||
|
@ -2301,12 +2301,11 @@ pfm_smpl_buffer_alloc(struct task_struct *task, pfm_context_t *ctx, unsigned lon
|
|||
DPRINT(("smpl_buf @%p\n", smpl_buf));
|
||||
|
||||
/* allocate vma */
|
||||
vma = kmem_cache_alloc(vm_area_cachep, GFP_KERNEL);
|
||||
vma = kmem_cache_zalloc(vm_area_cachep, GFP_KERNEL);
|
||||
if (!vma) {
|
||||
DPRINT(("Cannot allocate vma\n"));
|
||||
goto error_kmem;
|
||||
}
|
||||
memset(vma, 0, sizeof(*vma));
|
||||
|
||||
/*
|
||||
* partially initialize the vma for the sampling buffer
|
||||
|
@ -6597,7 +6596,7 @@ pfm_probe_pmu(void)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static struct file_operations pfm_proc_fops = {
|
||||
static const struct file_operations pfm_proc_fops = {
|
||||
.open = pfm_proc_open,
|
||||
.read = seq_read,
|
||||
.llseek = seq_lseek,
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue