forked from luck/tmp_suning_uos_patched
Merge commit 'origin/master' into next
This commit is contained in:
commit
492b057c42
4
CREDITS
4
CREDITS
@ -1253,6 +1253,10 @@ S: 8124 Constitution Apt. 7
|
||||
S: Sterling Heights, Michigan 48313
|
||||
S: USA
|
||||
|
||||
N: Wolfgang Grandegger
|
||||
E: wg@grandegger.com
|
||||
D: Controller Area Network (device drivers)
|
||||
|
||||
N: William Greathouse
|
||||
E: wgreathouse@smva.com
|
||||
E: wgreathouse@myfavoritei.com
|
||||
|
@ -145,7 +145,6 @@ usage should require reading the full document.
|
||||
interface in STA mode at first!
|
||||
</para>
|
||||
!Finclude/net/mac80211.h ieee80211_if_init_conf
|
||||
!Finclude/net/mac80211.h ieee80211_if_conf
|
||||
</chapter>
|
||||
|
||||
<chapter id="rx-tx">
|
||||
|
@ -438,6 +438,13 @@ Why: Superseded by tdfxfb. I2C/DDC support used to live in a separate
|
||||
Who: Jean Delvare <khali@linux-fr.org>
|
||||
Krzysztof Helt <krzysztof.h1@wp.pl>
|
||||
|
||||
---------------------------
|
||||
|
||||
What: CONFIG_RFKILL_INPUT
|
||||
When: 2.6.33
|
||||
Why: Should be implemented in userspace, policy daemon.
|
||||
Who: Johannes Berg <johannes@sipsolutions.net>
|
||||
|
||||
----------------------------
|
||||
|
||||
What: CONFIG_X86_OLD_MCE
|
||||
|
@ -39,9 +39,8 @@ Features which NILFS2 does not support yet:
|
||||
- extended attributes
|
||||
- POSIX ACLs
|
||||
- quotas
|
||||
- writable snapshots
|
||||
- remote backup (CDP)
|
||||
- data integrity
|
||||
- fsck
|
||||
- resize
|
||||
- defragmentation
|
||||
|
||||
Mount options
|
||||
|
@ -132,6 +132,11 @@ rodir -- FAT has the ATTR_RO (read-only) attribute. On Windows,
|
||||
If you want to use ATTR_RO as read-only flag even for
|
||||
the directory, set this option.
|
||||
|
||||
errors=panic|continue|remount-ro
|
||||
-- specify FAT behavior on critical errors: panic, continue
|
||||
without doing anything or remount the partition in
|
||||
read-only mode (default behavior).
|
||||
|
||||
<bool>: 0,1,yes,no,true,false
|
||||
|
||||
TODO
|
||||
|
@ -2,14 +2,18 @@ Kernel driver f71882fg
|
||||
======================
|
||||
|
||||
Supported chips:
|
||||
* Fintek F71882FG and F71883FG
|
||||
Prefix: 'f71882fg'
|
||||
* Fintek F71858FG
|
||||
Prefix: 'f71858fg'
|
||||
Addresses scanned: none, address read from Super I/O config space
|
||||
Datasheet: Available from the Fintek website
|
||||
* Fintek F71862FG and F71863FG
|
||||
Prefix: 'f71862fg'
|
||||
Addresses scanned: none, address read from Super I/O config space
|
||||
Datasheet: Available from the Fintek website
|
||||
* Fintek F71882FG and F71883FG
|
||||
Prefix: 'f71882fg'
|
||||
Addresses scanned: none, address read from Super I/O config space
|
||||
Datasheet: Available from the Fintek website
|
||||
* Fintek F8000
|
||||
Prefix: 'f8000'
|
||||
Addresses scanned: none, address read from Super I/O config space
|
||||
@ -66,13 +70,13 @@ printed when loading the driver.
|
||||
|
||||
Three different fan control modes are supported; the mode number is written
|
||||
to the pwm#_enable file. Note that not all modes are supported on all
|
||||
chips, and some modes may only be available in RPM / PWM mode on the F8000.
|
||||
chips, and some modes may only be available in RPM / PWM mode.
|
||||
Writing an unsupported mode will result in an invalid parameter error.
|
||||
|
||||
* 1: Manual mode
|
||||
You ask for a specific PWM duty cycle / DC voltage or a specific % of
|
||||
fan#_full_speed by writing to the pwm# file. This mode is only
|
||||
available on the F8000 if the fan channel is in RPM mode.
|
||||
available on the F71858FG / F8000 if the fan channel is in RPM mode.
|
||||
|
||||
* 2: Normal auto mode
|
||||
You can define a number of temperature/fan speed trip points, which % the
|
||||
|
@ -7,7 +7,7 @@ henceforth as AEM.
|
||||
Supported systems:
|
||||
* Any recent IBM System X server with AEM support.
|
||||
This includes the x3350, x3550, x3650, x3655, x3755, x3850 M2,
|
||||
x3950 M2, and certain HS2x/LS2x/QS2x blades. The IPMI host interface
|
||||
x3950 M2, and certain HC10/HS2x/LS2x/QS2x blades. The IPMI host interface
|
||||
driver ("ipmi-si") needs to be loaded for this driver to do anything.
|
||||
Prefix: 'ibmaem'
|
||||
Datasheet: Not available
|
||||
|
@ -70,6 +70,7 @@ are interpreted as 0! For more on how written strings are interpreted see the
|
||||
[0-*] denotes any positive number starting from 0
|
||||
[1-*] denotes any positive number starting from 1
|
||||
RO read only value
|
||||
WO write only value
|
||||
RW read/write value
|
||||
|
||||
Read/write values may be read-only for some chips, depending on the
|
||||
@ -295,6 +296,24 @@ temp[1-*]_label Suggested temperature channel label.
|
||||
user-space.
|
||||
RO
|
||||
|
||||
temp[1-*]_lowest
|
||||
Historical minimum temperature
|
||||
Unit: millidegree Celsius
|
||||
RO
|
||||
|
||||
temp[1-*]_highest
|
||||
Historical maximum temperature
|
||||
Unit: millidegree Celsius
|
||||
RO
|
||||
|
||||
temp[1-*]_reset_history
|
||||
Reset temp_lowest and temp_highest
|
||||
WO
|
||||
|
||||
temp_reset_history
|
||||
Reset temp_lowest and temp_highest for all sensors
|
||||
WO
|
||||
|
||||
Some chips measure temperature using external thermistors and an ADC, and
|
||||
report the temperature measurement as a voltage. Converting this voltage
|
||||
back to a temperature (or the other way around for limits) requires
|
||||
|
42
Documentation/hwmon/tmp401
Normal file
42
Documentation/hwmon/tmp401
Normal file
@ -0,0 +1,42 @@
|
||||
Kernel driver tmp401
|
||||
====================
|
||||
|
||||
Supported chips:
|
||||
* Texas Instruments TMP401
|
||||
Prefix: 'tmp401'
|
||||
Addresses scanned: I2C 0x4c
|
||||
Datasheet: http://focus.ti.com/docs/prod/folders/print/tmp401.html
|
||||
* Texas Instruments TMP411
|
||||
Prefix: 'tmp411'
|
||||
Addresses scanned: I2C 0x4c
|
||||
Datasheet: http://focus.ti.com/docs/prod/folders/print/tmp411.html
|
||||
|
||||
Authors:
|
||||
Hans de Goede <hdegoede@redhat.com>
|
||||
Andre Prendel <andre.prendel@gmx.de>
|
||||
|
||||
Description
|
||||
-----------
|
||||
|
||||
This driver implements support for Texas Instruments TMP401 and
|
||||
TMP411 chips. These chips implements one remote and one local
|
||||
temperature sensor. Temperature is measured in degrees
|
||||
Celsius. Resolution of the remote sensor is 0.0625 degree. Local
|
||||
sensor resolution can be set to 0.5, 0.25, 0.125 or 0.0625 degree (not
|
||||
supported by the driver so far, so using the default resolution of 0.5
|
||||
degree).
|
||||
|
||||
The driver provides the common sysfs-interface for temperatures (see
|
||||
/Documentation/hwmon/sysfs-interface under Temperatures).
|
||||
|
||||
The TMP411 chip is compatible with TMP401. It provides some additional
|
||||
features.
|
||||
|
||||
* Minimum and Maximum temperature measured since power-on, chip-reset
|
||||
|
||||
Exported via sysfs attributes tempX_lowest and tempX_highest.
|
||||
|
||||
* Reset of historical minimum/maximum temperature measurements
|
||||
|
||||
Exported via sysfs attribute temp_reset_history. Writing 1 to this
|
||||
file triggers a reset.
|
@ -12,6 +12,10 @@ Supported chips:
|
||||
Addresses scanned: ISA address retrieved from Super I/O registers
|
||||
Datasheet:
|
||||
http://www.nuvoton.com.tw/NR/rdonlyres/7885623D-A487-4CF9-A47F-30C5F73D6FE6/0/W83627DHG.pdf
|
||||
* Winbond W83627DHG-P
|
||||
Prefix: 'w83627dhg'
|
||||
Addresses scanned: ISA address retrieved from Super I/O registers
|
||||
Datasheet: not available
|
||||
* Winbond W83667HG
|
||||
Prefix: 'w83667hg'
|
||||
Addresses scanned: ISA address retrieved from Super I/O registers
|
||||
@ -28,8 +32,8 @@ Description
|
||||
-----------
|
||||
|
||||
This driver implements support for the Winbond W83627EHF, W83627EHG,
|
||||
W83627DHG and W83667HG super I/O chips. We will refer to them collectively
|
||||
as Winbond chips.
|
||||
W83627DHG, W83627DHG-P and W83667HG super I/O chips. We will refer to them
|
||||
collectively as Winbond chips.
|
||||
|
||||
The chips implement three temperature sensors, five fan rotation
|
||||
speed sensors, ten analog voltage sensors (only nine for the 627DHG), one
|
||||
@ -135,3 +139,6 @@ done in the driver for all register addresses.
|
||||
The DHG also supports PECI, where the DHG queries Intel CPU temperatures, and
|
||||
the ICH8 southbridge gets that data via PECI from the DHG, so that the
|
||||
southbridge drives the fans. And the DHG supports SST, a one-wire serial bus.
|
||||
|
||||
The DHG-P has an additional automatic fan speed control mode named Smart Fan
|
||||
(TM) III+. This mode is not yet supported by the driver.
|
||||
|
@ -19,6 +19,9 @@ Supported adapters:
|
||||
* VIA Technologies, Inc. VX800/VX820
|
||||
Datasheet: available on http://linux.via.com.tw
|
||||
|
||||
* VIA Technologies, Inc. VX855/VX875
|
||||
Datasheet: Availability unknown
|
||||
|
||||
Authors:
|
||||
Kyösti Mälkki <kmalkki@cc.hut.fi>,
|
||||
Mark D. Studebaker <mdsxyz123@yahoo.com>,
|
||||
@ -53,6 +56,7 @@ Your lspci -n listing must show one of these :
|
||||
device 1106:3287 (VT8251)
|
||||
device 1106:8324 (CX700)
|
||||
device 1106:8353 (VX800/VX820)
|
||||
device 1106:8409 (VX855/VX875)
|
||||
|
||||
If none of these show up, you should look in the BIOS for settings like
|
||||
enable ACPI / SMBus or even USB.
|
||||
|
@ -22,16 +22,11 @@ README.gigaset
|
||||
- info on the drivers for Siemens Gigaset ISDN adapters.
|
||||
README.icn
|
||||
- info on the ICN-ISDN-card and its driver.
|
||||
>>>>>>> 93af7aca44f0e82e67bda10a0fb73d383edcc8bd:Documentation/isdn/00-INDEX
|
||||
README.HiSax
|
||||
- info on the HiSax driver which replaces the old teles.
|
||||
README.hfc-pci
|
||||
- info on hfc-pci based cards.
|
||||
README.pcbit
|
||||
- info on the PCBIT-D ISDN adapter and driver.
|
||||
README.syncppp
|
||||
- info on running Sync PPP over ISDN.
|
||||
syncPPP.FAQ
|
||||
- frequently asked questions about running PPP over ISDN.
|
||||
README.audio
|
||||
- info for running audio over ISDN.
|
||||
README.avmb1
|
||||
- info on driver for AVM-B1 ISDN card.
|
||||
README.act2000
|
||||
@ -42,10 +37,28 @@ README.concap
|
||||
- info on "CONCAP" encapsulation protocol interface used for X.25.
|
||||
README.diversion
|
||||
- info on module for isdn diversion services.
|
||||
README.fax
|
||||
- info for using Fax over ISDN.
|
||||
README.gigaset
|
||||
- info on the drivers for Siemens Gigaset ISDN adapters
|
||||
README.hfc-pci
|
||||
- info on hfc-pci based cards.
|
||||
README.hysdn
|
||||
- info on driver for Hypercope active HYSDN cards
|
||||
README.icn
|
||||
- info on the ICN-ISDN-card and its driver.
|
||||
README.mISDN
|
||||
- info on the Modular ISDN subsystem (mISDN)
|
||||
README.pcbit
|
||||
- info on the PCBIT-D ISDN adapter and driver.
|
||||
README.sc
|
||||
- info on driver for Spellcaster cards.
|
||||
README.syncppp
|
||||
- info on running Sync PPP over ISDN.
|
||||
README.x25
|
||||
- info for running X.25 over ISDN.
|
||||
syncPPP.FAQ
|
||||
- frequently asked questions about running PPP over ISDN.
|
||||
README.hysdn
|
||||
- info on driver for Hypercope active HYSDN cards
|
||||
README.mISDN
|
||||
|
@ -45,7 +45,7 @@ From then on, Kernel CAPI may call the registered callback functions for the
|
||||
device.
|
||||
|
||||
If the device becomes unusable for any reason (shutdown, disconnect ...), the
|
||||
driver has to call capi_ctr_reseted(). This will prevent further calls to the
|
||||
driver has to call capi_ctr_down(). This will prevent further calls to the
|
||||
callback functions by Kernel CAPI.
|
||||
|
||||
|
||||
@ -114,20 +114,36 @@ char *driver_name
|
||||
int (*load_firmware)(struct capi_ctr *ctrlr, capiloaddata *ldata)
|
||||
(optional) pointer to a callback function for sending firmware and
|
||||
configuration data to the device
|
||||
Return value: 0 on success, error code on error
|
||||
Called in process context.
|
||||
|
||||
void (*reset_ctr)(struct capi_ctr *ctrlr)
|
||||
pointer to a callback function for performing a reset on the device,
|
||||
releasing all registered applications
|
||||
(optional) pointer to a callback function for performing a reset on
|
||||
the device, releasing all registered applications
|
||||
Called in process context.
|
||||
|
||||
void (*register_appl)(struct capi_ctr *ctrlr, u16 applid,
|
||||
capi_register_params *rparam)
|
||||
void (*release_appl)(struct capi_ctr *ctrlr, u16 applid)
|
||||
pointers to callback functions for registration and deregistration of
|
||||
applications with the device
|
||||
Calls to these functions are serialized by Kernel CAPI so that only
|
||||
one call to any of them is active at any time.
|
||||
|
||||
u16 (*send_message)(struct capi_ctr *ctrlr, struct sk_buff *skb)
|
||||
pointer to a callback function for sending a CAPI message to the
|
||||
device
|
||||
Return value: CAPI error code
|
||||
If the method returns 0 (CAPI_NOERROR) the driver has taken ownership
|
||||
of the skb and the caller may no longer access it. If it returns a
|
||||
non-zero (error) value then ownership of the skb returns to the caller
|
||||
who may reuse or free it.
|
||||
The return value should only be used to signal problems with respect
|
||||
to accepting or queueing the message. Errors occurring during the
|
||||
actual processing of the message should be signaled with an
|
||||
appropriate reply message.
|
||||
Calls to this function are not serialized by Kernel CAPI, ie. it must
|
||||
be prepared to be re-entered.
|
||||
|
||||
char *(*procinfo)(struct capi_ctr *ctrlr)
|
||||
pointer to a callback function returning the entry for the device in
|
||||
@ -138,6 +154,8 @@ read_proc_t *ctr_read_proc
|
||||
system entry, /proc/capi/controllers/<n>; will be called with a
|
||||
pointer to the device's capi_ctr structure as the last (data) argument
|
||||
|
||||
Note: Callback functions are never called in interrupt context.
|
||||
|
||||
- to be filled in before calling capi_ctr_ready():
|
||||
|
||||
u8 manu[CAPI_MANUFACTURER_LEN]
|
||||
@ -153,6 +171,45 @@ u8 serial[CAPI_SERIAL_LEN]
|
||||
value to return for CAPI_GET_SERIAL
|
||||
|
||||
|
||||
4.3 The _cmsg Structure
|
||||
|
||||
(declared in <linux/isdn/capiutil.h>)
|
||||
|
||||
The _cmsg structure stores the contents of a CAPI 2.0 message in an easily
|
||||
accessible form. It contains members for all possible CAPI 2.0 parameters, of
|
||||
which only those appearing in the message type currently being processed are
|
||||
actually used. Unused members should be set to zero.
|
||||
|
||||
Members are named after the CAPI 2.0 standard names of the parameters they
|
||||
represent. See <linux/isdn/capiutil.h> for the exact spelling. Member data
|
||||
types are:
|
||||
|
||||
u8 for CAPI parameters of type 'byte'
|
||||
|
||||
u16 for CAPI parameters of type 'word'
|
||||
|
||||
u32 for CAPI parameters of type 'dword'
|
||||
|
||||
_cstruct for CAPI parameters of type 'struct' not containing any
|
||||
variably-sized (struct) subparameters (eg. 'Called Party Number')
|
||||
The member is a pointer to a buffer containing the parameter in
|
||||
CAPI encoding (length + content). It may also be NULL, which will
|
||||
be taken to represent an empty (zero length) parameter.
|
||||
|
||||
_cmstruct for CAPI parameters of type 'struct' containing 'struct'
|
||||
subparameters ('Additional Info' and 'B Protocol')
|
||||
The representation is a single byte containing one of the values:
|
||||
CAPI_DEFAULT: the parameter is empty
|
||||
CAPI_COMPOSE: the values of the subparameters are stored
|
||||
individually in the corresponding _cmsg structure members
|
||||
|
||||
Functions capi_cmsg2message() and capi_message2cmsg() are provided to convert
|
||||
messages between their transport encoding described in the CAPI 2.0 standard
|
||||
and their _cmsg structure representation. Note that capi_cmsg2message() does
|
||||
not know or check the size of its destination buffer. The caller must make
|
||||
sure it is big enough to accomodate the resulting CAPI message.
|
||||
|
||||
|
||||
5. Lower Layer Interface Functions
|
||||
|
||||
(declared in <linux/isdn/capilli.h>)
|
||||
@ -166,7 +223,7 @@ int detach_capi_ctr(struct capi_ctr *ctrlr)
|
||||
register/unregister a device (controller) with Kernel CAPI
|
||||
|
||||
void capi_ctr_ready(struct capi_ctr *ctrlr)
|
||||
void capi_ctr_reseted(struct capi_ctr *ctrlr)
|
||||
void capi_ctr_down(struct capi_ctr *ctrlr)
|
||||
signal controller ready/not ready
|
||||
|
||||
void capi_ctr_suspend_output(struct capi_ctr *ctrlr)
|
||||
@ -211,3 +268,32 @@ CAPIMSG_CONTROL(m) CAPIMSG_SETCONTROL(m, contr) Controller/PLCI/NCCI
|
||||
(u32)
|
||||
CAPIMSG_DATALEN(m) CAPIMSG_SETDATALEN(m, len) Data Length (u16)
|
||||
|
||||
|
||||
Library functions for working with _cmsg structures
|
||||
(from <linux/isdn/capiutil.h>):
|
||||
|
||||
unsigned capi_cmsg2message(_cmsg *cmsg, u8 *msg)
|
||||
Assembles a CAPI 2.0 message from the parameters in *cmsg, storing the
|
||||
result in *msg.
|
||||
|
||||
unsigned capi_message2cmsg(_cmsg *cmsg, u8 *msg)
|
||||
Disassembles the CAPI 2.0 message in *msg, storing the parameters in
|
||||
*cmsg.
|
||||
|
||||
unsigned capi_cmsg_header(_cmsg *cmsg, u16 ApplId, u8 Command, u8 Subcommand,
|
||||
u16 Messagenumber, u32 Controller)
|
||||
Fills the header part and address field of the _cmsg structure *cmsg
|
||||
with the given values, zeroing the remainder of the structure so only
|
||||
parameters with non-default values need to be changed before sending
|
||||
the message.
|
||||
|
||||
void capi_cmsg_answer(_cmsg *cmsg)
|
||||
Sets the low bit of the Subcommand field in *cmsg, thereby converting
|
||||
_REQ to _CONF and _IND to _RESP.
|
||||
|
||||
char *capi_cmd2str(u8 Command, u8 Subcommand)
|
||||
Returns the CAPI 2.0 message name corresponding to the given command
|
||||
and subcommand values, as a static ASCII string. The return value may
|
||||
be NULL if the command/subcommand is not one of those defined in the
|
||||
CAPI 2.0 standard.
|
||||
|
||||
|
@ -149,10 +149,8 @@ GigaSet 307x Device Driver
|
||||
configuration files and chat scripts in the gigaset-VERSION/ppp directory
|
||||
in the driver packages from http://sourceforge.net/projects/gigaset307x/.
|
||||
Please note that the USB drivers are not able to change the state of the
|
||||
control lines (the M105 driver can be configured to use some undocumented
|
||||
control requests, if you really need the control lines, though). This means
|
||||
you must use "Stupid Mode" if you are using wvdial or you should use the
|
||||
nocrtscts option of pppd.
|
||||
control lines. This means you must use "Stupid Mode" if you are using
|
||||
wvdial or you should use the nocrtscts option of pppd.
|
||||
You must also assure that the ppp_async module is loaded with the parameter
|
||||
flag_time=0. You can do this e.g. by adding a line like
|
||||
|
||||
@ -190,20 +188,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 controlled by the kernel configuration option
|
||||
"Support for undocumented USB requests" (CONFIG_GIGASET_UNDOCREQ). If you
|
||||
encounter error code -ENOTTY when trying to use some features of the
|
||||
M105, try setting that option to "y" via 'make {x,menu}config' and
|
||||
recompiling the driver.
|
||||
2.6. Unregistered Wireless Devices (M101/M105)
|
||||
-----------------------------------------
|
||||
The main purpose of the ser_gigaset and usb_gigaset drivers is to allow
|
||||
the M101 and M105 wireless devices to be used as ISDN devices for ISDN
|
||||
connections through a Gigaset base. Therefore they assume that the device
|
||||
is registered to a DECT base.
|
||||
|
||||
If the M101/M105 device is not registered to a base, initialization of
|
||||
the device fails, and a corresponding error message is logged by the
|
||||
driver. In that situation, a restricted set of functions is available
|
||||
which includes, in particular, those necessary for registering the device
|
||||
to a base or for switching it between Fixed Part and Portable Part
|
||||
modes.
|
||||
|
||||
3. Troubleshooting
|
||||
---------------
|
||||
@ -234,11 +231,12 @@ GigaSet 307x Device Driver
|
||||
Select Unimodem mode for all DECT data adapters. (see section 2.4.)
|
||||
|
||||
Problem:
|
||||
You want to configure your USB DECT data adapter (M105) but gigacontr
|
||||
reports an error: "/dev/ttyGU0: Inappropriate ioctl for device".
|
||||
Messages like this:
|
||||
usb_gigaset 3-2:1.0: Could not initialize the device.
|
||||
appear in your syslog.
|
||||
Solution:
|
||||
Recompile the usb_gigaset driver with the kernel configuration option
|
||||
CONFIG_GIGASET_UNDOCREQ set to 'y'. (see section 2.6.)
|
||||
Check whether your M10x wireless device is correctly registered to the
|
||||
Gigaset base. (see section 2.6.)
|
||||
|
||||
3.2. Telling the driver to provide more information
|
||||
----------------------------------------------
|
||||
|
@ -36,10 +36,15 @@ This file contains
|
||||
6.2 local loopback of sent frames
|
||||
6.3 CAN controller hardware filters
|
||||
6.4 The virtual CAN driver (vcan)
|
||||
6.5 currently supported CAN hardware
|
||||
6.6 todo
|
||||
6.5 The CAN network device driver interface
|
||||
6.5.1 Netlink interface to set/get devices properties
|
||||
6.5.2 Setting the CAN bit-timing
|
||||
6.5.3 Starting and stopping the CAN network device
|
||||
6.6 supported CAN hardware
|
||||
|
||||
7 Credits
|
||||
7 Socket CAN resources
|
||||
|
||||
8 Credits
|
||||
|
||||
============================================================================
|
||||
|
||||
@ -234,6 +239,8 @@ solution for a couple of reasons:
|
||||
the user application using the common CAN filter mechanisms. Inside
|
||||
this filter definition the (interested) type of errors may be
|
||||
selected. The reception of error frames is disabled by default.
|
||||
The format of the CAN error frame is briefly decribed in the Linux
|
||||
header file "include/linux/can/error.h".
|
||||
|
||||
4. How to use Socket CAN
|
||||
------------------------
|
||||
@ -605,61 +612,213 @@ solution for a couple of reasons:
|
||||
removal of vcan network devices can be managed with the ip(8) tool:
|
||||
|
||||
- Create a virtual CAN network interface:
|
||||
ip link add type vcan
|
||||
$ ip link add type vcan
|
||||
|
||||
- Create a virtual CAN network interface with a specific name 'vcan42':
|
||||
ip link add dev vcan42 type vcan
|
||||
$ ip link add dev vcan42 type vcan
|
||||
|
||||
- Remove a (virtual CAN) network interface 'vcan42':
|
||||
ip link del vcan42
|
||||
$ ip link del vcan42
|
||||
|
||||
The tool 'vcan' from the SocketCAN SVN repository on BerliOS is obsolete.
|
||||
6.5 The CAN network device driver interface
|
||||
|
||||
Virtual CAN network device creation in older Kernels:
|
||||
In Linux Kernel versions < 2.6.24 the vcan driver creates 4 vcan
|
||||
netdevices at module load time by default. This value can be changed
|
||||
with the module parameter 'numdev'. E.g. 'modprobe vcan numdev=8'
|
||||
The CAN network device driver interface provides a generic interface
|
||||
to setup, configure and monitor CAN network devices. The user can then
|
||||
configure the CAN device, like setting the bit-timing parameters, via
|
||||
the netlink interface using the program "ip" from the "IPROUTE2"
|
||||
utility suite. The following chapter describes briefly how to use it.
|
||||
Furthermore, the interface uses a common data structure and exports a
|
||||
set of common functions, which all real CAN network device drivers
|
||||
should use. Please have a look to the SJA1000 or MSCAN driver to
|
||||
understand how to use them. The name of the module is can-dev.ko.
|
||||
|
||||
6.5 currently supported CAN hardware
|
||||
6.5.1 Netlink interface to set/get devices properties
|
||||
|
||||
On the project website http://developer.berlios.de/projects/socketcan
|
||||
there are different drivers available:
|
||||
The CAN device must be configured via netlink interface. The supported
|
||||
netlink message types are defined and briefly described in
|
||||
"include/linux/can/netlink.h". CAN link support for the program "ip"
|
||||
of the IPROUTE2 utility suite is avaiable and it can be used as shown
|
||||
below:
|
||||
|
||||
vcan: Virtual CAN interface driver (if no real hardware is available)
|
||||
sja1000: Philips SJA1000 CAN controller (recommended)
|
||||
i82527: Intel i82527 CAN controller
|
||||
mscan: Motorola/Freescale CAN controller (e.g. inside SOC MPC5200)
|
||||
ccan: CCAN controller core (e.g. inside SOC h7202)
|
||||
slcan: For a bunch of CAN adaptors that are attached via a
|
||||
serial line ASCII protocol (for serial / USB adaptors)
|
||||
- Setting CAN device properties:
|
||||
|
||||
Additionally the different CAN adaptors (ISA/PCI/PCMCIA/USB/Parport)
|
||||
from PEAK Systemtechnik support the CAN netdevice driver model
|
||||
since Linux driver v6.0: http://www.peak-system.com/linux/index.htm
|
||||
$ ip link set can0 type can help
|
||||
Usage: ip link set DEVICE type can
|
||||
[ bitrate BITRATE [ sample-point SAMPLE-POINT] ] |
|
||||
[ tq TQ prop-seg PROP_SEG phase-seg1 PHASE-SEG1
|
||||
phase-seg2 PHASE-SEG2 [ sjw SJW ] ]
|
||||
|
||||
Please check the Mailing Lists on the berlios OSS project website.
|
||||
[ loopback { on | off } ]
|
||||
[ listen-only { on | off } ]
|
||||
[ triple-sampling { on | off } ]
|
||||
|
||||
6.6 todo
|
||||
[ restart-ms TIME-MS ]
|
||||
[ restart ]
|
||||
|
||||
The configuration interface for CAN network drivers is still an open
|
||||
issue that has not been finalized in the socketcan project. Also the
|
||||
idea of having a library module (candev.ko) that holds functions
|
||||
that are needed by all CAN netdevices is not ready to ship.
|
||||
Your contribution is welcome.
|
||||
Where: BITRATE := { 1..1000000 }
|
||||
SAMPLE-POINT := { 0.000..0.999 }
|
||||
TQ := { NUMBER }
|
||||
PROP-SEG := { 1..8 }
|
||||
PHASE-SEG1 := { 1..8 }
|
||||
PHASE-SEG2 := { 1..8 }
|
||||
SJW := { 1..4 }
|
||||
RESTART-MS := { 0 | NUMBER }
|
||||
|
||||
7. Credits
|
||||
- Display CAN device details and statistics:
|
||||
|
||||
$ ip -details -statistics link show can0
|
||||
2: can0: <NOARP,UP,LOWER_UP,ECHO> mtu 16 qdisc pfifo_fast state UP qlen 10
|
||||
link/can
|
||||
can <TRIPLE-SAMPLING> state ERROR-ACTIVE restart-ms 100
|
||||
bitrate 125000 sample_point 0.875
|
||||
tq 125 prop-seg 6 phase-seg1 7 phase-seg2 2 sjw 1
|
||||
sja1000: tseg1 1..16 tseg2 1..8 sjw 1..4 brp 1..64 brp-inc 1
|
||||
clock 8000000
|
||||
re-started bus-errors arbit-lost error-warn error-pass bus-off
|
||||
41 17457 0 41 42 41
|
||||
RX: bytes packets errors dropped overrun mcast
|
||||
140859 17608 17457 0 0 0
|
||||
TX: bytes packets errors dropped carrier collsns
|
||||
861 112 0 41 0 0
|
||||
|
||||
More info to the above output:
|
||||
|
||||
"<TRIPLE-SAMPLING>"
|
||||
Shows the list of selected CAN controller modes: LOOPBACK,
|
||||
LISTEN-ONLY, or TRIPLE-SAMPLING.
|
||||
|
||||
"state ERROR-ACTIVE"
|
||||
The current state of the CAN controller: "ERROR-ACTIVE",
|
||||
"ERROR-WARNING", "ERROR-PASSIVE", "BUS-OFF" or "STOPPED"
|
||||
|
||||
"restart-ms 100"
|
||||
Automatic restart delay time. If set to a non-zero value, a
|
||||
restart of the CAN controller will be triggered automatically
|
||||
in case of a bus-off condition after the specified delay time
|
||||
in milliseconds. By default it's off.
|
||||
|
||||
"bitrate 125000 sample_point 0.875"
|
||||
Shows the real bit-rate in bits/sec and the sample-point in the
|
||||
range 0.000..0.999. If the calculation of bit-timing parameters
|
||||
is enabled in the kernel (CONFIG_CAN_CALC_BITTIMING=y), the
|
||||
bit-timing can be defined by setting the "bitrate" argument.
|
||||
Optionally the "sample-point" can be specified. By default it's
|
||||
0.000 assuming CIA-recommended sample-points.
|
||||
|
||||
"tq 125 prop-seg 6 phase-seg1 7 phase-seg2 2 sjw 1"
|
||||
Shows the time quanta in ns, propagation segment, phase buffer
|
||||
segment 1 and 2 and the synchronisation jump width in units of
|
||||
tq. They allow to define the CAN bit-timing in a hardware
|
||||
independent format as proposed by the Bosch CAN 2.0 spec (see
|
||||
chapter 8 of http://www.semiconductors.bosch.de/pdf/can2spec.pdf).
|
||||
|
||||
"sja1000: tseg1 1..16 tseg2 1..8 sjw 1..4 brp 1..64 brp-inc 1
|
||||
clock 8000000"
|
||||
Shows the bit-timing constants of the CAN controller, here the
|
||||
"sja1000". The minimum and maximum values of the time segment 1
|
||||
and 2, the synchronisation jump width in units of tq, the
|
||||
bitrate pre-scaler and the CAN system clock frequency in Hz.
|
||||
These constants could be used for user-defined (non-standard)
|
||||
bit-timing calculation algorithms in user-space.
|
||||
|
||||
"re-started bus-errors arbit-lost error-warn error-pass bus-off"
|
||||
Shows the number of restarts, bus and arbitration lost errors,
|
||||
and the state changes to the error-warning, error-passive and
|
||||
bus-off state. RX overrun errors are listed in the "overrun"
|
||||
field of the standard network statistics.
|
||||
|
||||
6.5.2 Setting the CAN bit-timing
|
||||
|
||||
The CAN bit-timing parameters can always be defined in a hardware
|
||||
independent format as proposed in the Bosch CAN 2.0 specification
|
||||
specifying the arguments "tq", "prop_seg", "phase_seg1", "phase_seg2"
|
||||
and "sjw":
|
||||
|
||||
$ ip link set canX type can tq 125 prop-seg 6 \
|
||||
phase-seg1 7 phase-seg2 2 sjw 1
|
||||
|
||||
If the kernel option CONFIG_CAN_CALC_BITTIMING is enabled, CIA
|
||||
recommended CAN bit-timing parameters will be calculated if the bit-
|
||||
rate is specified with the argument "bitrate":
|
||||
|
||||
$ ip link set canX type can bitrate 125000
|
||||
|
||||
Note that this works fine for the most common CAN controllers with
|
||||
standard bit-rates but may *fail* for exotic bit-rates or CAN system
|
||||
clock frequencies. Disabling CONFIG_CAN_CALC_BITTIMING saves some
|
||||
space and allows user-space tools to solely determine and set the
|
||||
bit-timing parameters. The CAN controller specific bit-timing
|
||||
constants can be used for that purpose. They are listed by the
|
||||
following command:
|
||||
|
||||
$ ip -details link show can0
|
||||
...
|
||||
sja1000: clock 8000000 tseg1 1..16 tseg2 1..8 sjw 1..4 brp 1..64 brp-inc 1
|
||||
|
||||
6.5.3 Starting and stopping the CAN network device
|
||||
|
||||
A CAN network device is started or stopped as usual with the command
|
||||
"ifconfig canX up/down" or "ip link set canX up/down". Be aware that
|
||||
you *must* define proper bit-timing parameters for real CAN devices
|
||||
before you can start it to avoid error-prone default settings:
|
||||
|
||||
$ ip link set canX up type can bitrate 125000
|
||||
|
||||
A device may enter the "bus-off" state if too much errors occurred on
|
||||
the CAN bus. Then no more messages are received or sent. An automatic
|
||||
bus-off recovery can be enabled by setting the "restart-ms" to a
|
||||
non-zero value, e.g.:
|
||||
|
||||
$ ip link set canX type can restart-ms 100
|
||||
|
||||
Alternatively, the application may realize the "bus-off" condition
|
||||
by monitoring CAN error frames and do a restart when appropriate with
|
||||
the command:
|
||||
|
||||
$ ip link set canX type can restart
|
||||
|
||||
Note that a restart will also create a CAN error frame (see also
|
||||
chapter 3.4).
|
||||
|
||||
6.6 Supported CAN hardware
|
||||
|
||||
Please check the "Kconfig" file in "drivers/net/can" to get an actual
|
||||
list of the support CAN hardware. On the Socket CAN project website
|
||||
(see chapter 7) there might be further drivers available, also for
|
||||
older kernel versions.
|
||||
|
||||
7. Socket CAN resources
|
||||
-----------------------
|
||||
|
||||
You can find further resources for Socket CAN like user space tools,
|
||||
support for old kernel versions, more drivers, mailing lists, etc.
|
||||
at the BerliOS OSS project website for Socket CAN:
|
||||
|
||||
http://developer.berlios.de/projects/socketcan
|
||||
|
||||
If you have questions, bug fixes, etc., don't hesitate to post them to
|
||||
the Socketcan-Users mailing list. But please search the archives first.
|
||||
|
||||
8. Credits
|
||||
----------
|
||||
|
||||
Oliver Hartkopp (PF_CAN core, filters, drivers, bcm)
|
||||
Oliver Hartkopp (PF_CAN core, filters, drivers, bcm, SJA1000 driver)
|
||||
Urs Thuermann (PF_CAN core, kernel integration, socket interfaces, raw, vcan)
|
||||
Jan Kizka (RT-SocketCAN core, Socket-API reconciliation)
|
||||
Wolfgang Grandegger (RT-SocketCAN core & drivers, Raw Socket-API reviews)
|
||||
Wolfgang Grandegger (RT-SocketCAN core & drivers, Raw Socket-API reviews,
|
||||
CAN device driver interface, MSCAN driver)
|
||||
Robert Schwebel (design reviews, PTXdist integration)
|
||||
Marc Kleine-Budde (design reviews, Kernel 2.6 cleanups, drivers)
|
||||
Benedikt Spranger (reviews)
|
||||
Thomas Gleixner (LKML reviews, coding style, posting hints)
|
||||
Andrey Volkov (kernel subtree structure, ioctls, mscan driver)
|
||||
Andrey Volkov (kernel subtree structure, ioctls, MSCAN driver)
|
||||
Matthias Brukner (first SJA1000 CAN netdevice implementation Q2/2003)
|
||||
Klaus Hitschler (PEAK driver integration)
|
||||
Uwe Koppe (CAN netdevices with PF_PACKET approach)
|
||||
Michael Schulze (driver layer loopback requirement, RT CAN drivers review)
|
||||
Pavel Pisa (Bit-timing calculation)
|
||||
Sascha Hauer (SJA1000 platform driver)
|
||||
Sebastian Haas (SJA1000 EMS PCI driver)
|
||||
Markus Plessing (SJA1000 EMS PCI driver)
|
||||
Per Dalen (SJA1000 Kvaser PCI driver)
|
||||
Sam Ravnborg (reviews, coding style, kbuild help)
|
||||
|
76
Documentation/networking/ieee802154.txt
Normal file
76
Documentation/networking/ieee802154.txt
Normal file
@ -0,0 +1,76 @@
|
||||
|
||||
Linux IEEE 802.15.4 implementation
|
||||
|
||||
|
||||
Introduction
|
||||
============
|
||||
|
||||
The Linux-ZigBee project goal is to provide complete implementation
|
||||
of IEEE 802.15.4 / ZigBee / 6LoWPAN protocols. IEEE 802.15.4 is a stack
|
||||
of protocols for organizing Low-Rate Wireless Personal Area Networks.
|
||||
|
||||
Currently only IEEE 802.15.4 layer is implemented. We have choosen
|
||||
to use plain Berkeley socket API, the generic Linux networking stack
|
||||
to transfer IEEE 802.15.4 messages and a special protocol over genetlink
|
||||
for configuration/management
|
||||
|
||||
|
||||
Socket API
|
||||
==========
|
||||
|
||||
int sd = socket(PF_IEEE802154, SOCK_DGRAM, 0);
|
||||
.....
|
||||
|
||||
The address family, socket addresses etc. are defined in the
|
||||
include/net/ieee802154/af_ieee802154.h header or in the special header
|
||||
in our userspace package (see either linux-zigbee sourceforge download page
|
||||
or git tree at git://linux-zigbee.git.sourceforge.net/gitroot/linux-zigbee).
|
||||
|
||||
One can use SOCK_RAW for passing raw data towards device xmit function. YMMV.
|
||||
|
||||
|
||||
MLME - MAC Level Management
|
||||
============================
|
||||
|
||||
Most of IEEE 802.15.4 MLME interfaces are directly mapped on netlink commands.
|
||||
See the include/net/ieee802154/nl802154.h header. Our userspace tools package
|
||||
(see above) provides CLI configuration utility for radio interfaces and simple
|
||||
coordinator for IEEE 802.15.4 networks as an example users of MLME protocol.
|
||||
|
||||
|
||||
Kernel side
|
||||
=============
|
||||
|
||||
Like with WiFi, there are several types of devices implementing IEEE 802.15.4.
|
||||
1) 'HardMAC'. The MAC layer is implemented in the device itself, the device
|
||||
exports MLME and data API.
|
||||
2) 'SoftMAC' or just radio. These types of devices are just radio transceivers
|
||||
possibly with some kinds of acceleration like automatic CRC computation and
|
||||
comparation, automagic ACK handling, address matching, etc.
|
||||
|
||||
Those types of devices require different approach to be hooked into Linux kernel.
|
||||
|
||||
|
||||
HardMAC
|
||||
=======
|
||||
|
||||
See the header include/net/ieee802154/netdevice.h. You have to implement Linux
|
||||
net_device, with .type = ARPHRD_IEEE802154. Data is exchanged with socket family
|
||||
code via plain sk_buffs. The control block of sk_buffs will contain additional
|
||||
info as described in the struct ieee802154_mac_cb.
|
||||
|
||||
To hook the MLME interface you have to populate the ml_priv field of your
|
||||
net_device with a pointer to struct ieee802154_mlme_ops instance. All fields are
|
||||
required.
|
||||
|
||||
We provide an example of simple HardMAC driver at drivers/ieee802154/fakehard.c
|
||||
|
||||
|
||||
SoftMAC
|
||||
=======
|
||||
|
||||
We are going to provide intermediate layer impelementing IEEE 802.15.4 MAC
|
||||
in software. This is currently WIP.
|
||||
|
||||
See header include/net/ieee802154/mac802154.h and several drivers in
|
||||
drivers/ieee802154/
|
@ -168,7 +168,16 @@ tcp_dsack - BOOLEAN
|
||||
Allows TCP to send "duplicate" SACKs.
|
||||
|
||||
tcp_ecn - BOOLEAN
|
||||
Enable Explicit Congestion Notification in TCP.
|
||||
Enable Explicit Congestion Notification (ECN) in TCP. ECN is only
|
||||
used when both ends of the TCP flow support it. It is useful to
|
||||
avoid losses due to congestion (when the bottleneck router supports
|
||||
ECN).
|
||||
Possible values are:
|
||||
0 disable ECN
|
||||
1 ECN enabled
|
||||
2 Only server-side ECN enabled. If the other end does
|
||||
not support ECN, behavior is like with ECN disabled.
|
||||
Default: 2
|
||||
|
||||
tcp_fack - BOOLEAN
|
||||
Enable FACK congestion avoidance and fast retransmission.
|
||||
@ -1048,6 +1057,13 @@ disable_ipv6 - BOOLEAN
|
||||
address.
|
||||
Default: FALSE (enable IPv6 operation)
|
||||
|
||||
When this value is changed from 1 to 0 (IPv6 is being enabled),
|
||||
it will dynamically create a link-local address on the given
|
||||
interface and start Duplicate Address Detection, if necessary.
|
||||
|
||||
When this value is changed from 0 to 1 (IPv6 is being disabled),
|
||||
it will dynamically delete all address on the given interface.
|
||||
|
||||
accept_dad - INTEGER
|
||||
Whether to accept DAD (Duplicate Address Detection).
|
||||
0: Disable DAD
|
||||
|
@ -33,3 +33,40 @@ disable
|
||||
|
||||
A reboot is required to enable IPv6.
|
||||
|
||||
autoconf
|
||||
|
||||
Specifies whether to enable IPv6 address autoconfiguration
|
||||
on all interfaces. This might be used when one does not wish
|
||||
for addresses to be automatically generated from prefixes
|
||||
received in Router Advertisements.
|
||||
|
||||
The possible values and their effects are:
|
||||
|
||||
0
|
||||
IPv6 address autoconfiguration is disabled on all interfaces.
|
||||
|
||||
Only the IPv6 loopback address (::1) and link-local addresses
|
||||
will be added to interfaces.
|
||||
|
||||
1
|
||||
IPv6 address autoconfiguration is enabled on all interfaces.
|
||||
|
||||
This is the default value.
|
||||
|
||||
disable_ipv6
|
||||
|
||||
Specifies whether to disable IPv6 on all interfaces.
|
||||
This might be used when no IPv6 addresses are desired.
|
||||
|
||||
The possible values and their effects are:
|
||||
|
||||
0
|
||||
IPv6 is enabled on all interfaces.
|
||||
|
||||
This is the default value.
|
||||
|
||||
1
|
||||
IPv6 is disabled on all interfaces.
|
||||
|
||||
No IPv6 addresses will be added to interfaces.
|
||||
|
||||
|
@ -12,38 +12,22 @@ following format:
|
||||
The radiotap format is discussed in
|
||||
./Documentation/networking/radiotap-headers.txt.
|
||||
|
||||
Despite 13 radiotap argument types are currently defined, most only make sense
|
||||
Despite many radiotap parameters being currently defined, most only make sense
|
||||
to appear on received packets. The following information is parsed from the
|
||||
radiotap headers and used to control injection:
|
||||
|
||||
* IEEE80211_RADIOTAP_RATE
|
||||
|
||||
rate in 500kbps units, automatic if invalid or not present
|
||||
|
||||
|
||||
* IEEE80211_RADIOTAP_ANTENNA
|
||||
|
||||
antenna to use, automatic if not present
|
||||
|
||||
|
||||
* IEEE80211_RADIOTAP_DBM_TX_POWER
|
||||
|
||||
transmit power in dBm, automatic if not present
|
||||
|
||||
|
||||
* IEEE80211_RADIOTAP_FLAGS
|
||||
|
||||
IEEE80211_RADIOTAP_F_FCS: FCS will be removed and recalculated
|
||||
IEEE80211_RADIOTAP_F_WEP: frame will be encrypted if key available
|
||||
IEEE80211_RADIOTAP_F_FRAG: frame will be fragmented if longer than the
|
||||
current fragmentation threshold. Note that
|
||||
this flag is only reliable when software
|
||||
fragmentation is enabled)
|
||||
current fragmentation threshold.
|
||||
|
||||
|
||||
The injection code can also skip all other currently defined radiotap fields
|
||||
facilitating replay of captured radiotap headers directly.
|
||||
|
||||
Here is an example valid radiotap header defining these three parameters
|
||||
Here is an example valid radiotap header defining some parameters
|
||||
|
||||
0x00, 0x00, // <-- radiotap version
|
||||
0x0b, 0x00, // <- radiotap header length
|
||||
@ -72,8 +56,8 @@ interface), along the following lines:
|
||||
...
|
||||
r = pcap_inject(ppcap, u8aSendBuffer, nLength);
|
||||
|
||||
You can also find sources for a complete inject test applet here:
|
||||
You can also find a link to a complete inject application here:
|
||||
|
||||
http://penumbra.warmcat.com/_twk/tiki-index.php?page=packetspammer
|
||||
http://wireless.kernel.org/en/users/Documentation/packetspammer
|
||||
|
||||
Andy Green <andy@warmcat.com>
|
||||
|
@ -38,9 +38,6 @@ ifinfomsg::if_flags & IFF_LOWER_UP:
|
||||
ifinfomsg::if_flags & IFF_DORMANT:
|
||||
Driver has signaled netif_dormant_on()
|
||||
|
||||
These interface flags can also be queried without netlink using the
|
||||
SIOCGIFFLAGS ioctl.
|
||||
|
||||
TLV IFLA_OPERSTATE
|
||||
|
||||
contains RFC2863 state of the interface in numeric representation:
|
||||
|
@ -4,16 +4,18 @@
|
||||
|
||||
This file documents the CONFIG_PACKET_MMAP option available with the PACKET
|
||||
socket interface on 2.4 and 2.6 kernels. This type of sockets is used for
|
||||
capture network traffic with utilities like tcpdump or any other that uses
|
||||
the libpcap library.
|
||||
|
||||
You can find the latest version of this document at
|
||||
capture network traffic with utilities like tcpdump or any other that needs
|
||||
raw access to network interface.
|
||||
|
||||
You can find the latest version of this document at:
|
||||
http://pusa.uv.es/~ulisses/packet_mmap/
|
||||
|
||||
Please send me your comments to
|
||||
Howto can be found at:
|
||||
http://wiki.gnu-log.net (packet_mmap)
|
||||
|
||||
Please send your comments to
|
||||
Ulisses Alonso Camaró <uaca@i.hate.spam.alumni.uv.es>
|
||||
Johann Baudy <johann.baudy@gnu-log.net>
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
+ Why use PACKET_MMAP
|
||||
@ -25,19 +27,24 @@ to capture each packet, it requires two if you want to get packet's
|
||||
timestamp (like libpcap always does).
|
||||
|
||||
In the other hand PACKET_MMAP is very efficient. PACKET_MMAP provides a size
|
||||
configurable circular buffer mapped in user space. This way reading packets just
|
||||
needs to wait for them, most of the time there is no need to issue a single
|
||||
system call. By using a shared buffer between the kernel and the user
|
||||
also has the benefit of minimizing packet copies.
|
||||
configurable circular buffer mapped in user space that can be used to either
|
||||
send or receive packets. This way reading packets just needs to wait for them,
|
||||
most of the time there is no need to issue a single system call. Concerning
|
||||
transmission, multiple packets can be sent through one system call to get the
|
||||
highest bandwidth.
|
||||
By using a shared buffer between the kernel and the user also has the benefit
|
||||
of minimizing packet copies.
|
||||
|
||||
It's fine to use PACKET_MMAP to improve the performance of the capture process,
|
||||
but it isn't everything. At least, if you are capturing at high speeds (this
|
||||
is relative to the cpu speed), you should check if the device driver of your
|
||||
network interface card supports some sort of interrupt load mitigation or
|
||||
(even better) if it supports NAPI, also make sure it is enabled.
|
||||
It's fine to use PACKET_MMAP to improve the performance of the capture and
|
||||
transmission process, but it isn't everything. At least, if you are capturing
|
||||
at high speeds (this is relative to the cpu speed), you should check if the
|
||||
device driver of your network interface card supports some sort of interrupt
|
||||
load mitigation or (even better) if it supports NAPI, also make sure it is
|
||||
enabled. For transmission, check the MTU (Maximum Transmission Unit) used and
|
||||
supported by devices of your network.
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
+ How to use CONFIG_PACKET_MMAP
|
||||
+ How to use CONFIG_PACKET_MMAP to improve capture process
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
From the user standpoint, you should use the higher level libpcap library, which
|
||||
@ -57,7 +64,7 @@ the low level details or want to improve libpcap by including PACKET_MMAP
|
||||
support.
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
+ How to use CONFIG_PACKET_MMAP directly
|
||||
+ How to use CONFIG_PACKET_MMAP directly to improve capture process
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
From the system calls stand point, the use of PACKET_MMAP involves
|
||||
@ -66,6 +73,7 @@ the following process:
|
||||
|
||||
[setup] socket() -------> creation of the capture socket
|
||||
setsockopt() ---> allocation of the circular buffer (ring)
|
||||
option: PACKET_RX_RING
|
||||
mmap() ---------> mapping of the allocated buffer to the
|
||||
user process
|
||||
|
||||
@ -96,6 +104,65 @@ Next I will describe PACKET_MMAP settings and it's constraints,
|
||||
also the mapping of the circular buffer in the user process and
|
||||
the use of this buffer.
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
+ How to use CONFIG_PACKET_MMAP directly to improve transmission process
|
||||
--------------------------------------------------------------------------------
|
||||
Transmission process is similar to capture as shown below.
|
||||
|
||||
[setup] socket() -------> creation of the transmission socket
|
||||
setsockopt() ---> allocation of the circular buffer (ring)
|
||||
option: PACKET_TX_RING
|
||||
bind() ---------> bind transmission socket with a network interface
|
||||
mmap() ---------> mapping of the allocated buffer to the
|
||||
user process
|
||||
|
||||
[transmission] poll() ---------> wait for free packets (optional)
|
||||
send() ---------> send all packets that are set as ready in
|
||||
the ring
|
||||
The flag MSG_DONTWAIT can be used to return
|
||||
before end of transfer.
|
||||
|
||||
[shutdown] close() --------> destruction of the transmission socket and
|
||||
deallocation of all associated resources.
|
||||
|
||||
Binding the socket to your network interface is mandatory (with zero copy) to
|
||||
know the header size of frames used in the circular buffer.
|
||||
|
||||
As capture, each frame contains two parts:
|
||||
|
||||
--------------------
|
||||
| struct tpacket_hdr | Header. It contains the status of
|
||||
| | of this frame
|
||||
|--------------------|
|
||||
| data buffer |
|
||||
. . Data that will be sent over the network interface.
|
||||
. .
|
||||
--------------------
|
||||
|
||||
bind() associates the socket to your network interface thanks to
|
||||
sll_ifindex parameter of struct sockaddr_ll.
|
||||
|
||||
Initialization example:
|
||||
|
||||
struct sockaddr_ll my_addr;
|
||||
struct ifreq s_ifr;
|
||||
...
|
||||
|
||||
strncpy (s_ifr.ifr_name, "eth0", sizeof(s_ifr.ifr_name));
|
||||
|
||||
/* get interface index of eth0 */
|
||||
ioctl(this->socket, SIOCGIFINDEX, &s_ifr);
|
||||
|
||||
/* fill sockaddr_ll struct to prepare binding */
|
||||
my_addr.sll_family = AF_PACKET;
|
||||
my_addr.sll_protocol = ETH_P_ALL;
|
||||
my_addr.sll_ifindex = s_ifr.ifr_ifindex;
|
||||
|
||||
/* bind socket to eth0 */
|
||||
bind(this->socket, (struct sockaddr *)&my_addr, sizeof(struct sockaddr_ll));
|
||||
|
||||
A complete tutorial is available at: http://wiki.gnu-log.net/
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
+ PACKET_MMAP settings
|
||||
--------------------------------------------------------------------------------
|
||||
@ -103,7 +170,10 @@ the use of this buffer.
|
||||
|
||||
To setup PACKET_MMAP from user level code is done with a call like
|
||||
|
||||
- Capture process
|
||||
setsockopt(fd, SOL_PACKET, PACKET_RX_RING, (void *) &req, sizeof(req))
|
||||
- Transmission process
|
||||
setsockopt(fd, SOL_PACKET, PACKET_TX_RING, (void *) &req, sizeof(req))
|
||||
|
||||
The most significant argument in the previous call is the req parameter,
|
||||
this parameter must to have the following structure:
|
||||
@ -117,11 +187,11 @@ this parameter must to have the following structure:
|
||||
};
|
||||
|
||||
This structure is defined in /usr/include/linux/if_packet.h and establishes a
|
||||
circular buffer (ring) of unswappable memory mapped in the capture process.
|
||||
circular buffer (ring) of unswappable memory.
|
||||
Being mapped in the capture process allows reading the captured frames and
|
||||
related meta-information like timestamps without requiring a system call.
|
||||
|
||||
Captured frames are grouped in blocks. Each block is a physically contiguous
|
||||
Frames are grouped in blocks. Each block is a physically contiguous
|
||||
region of memory and holds tp_block_size/tp_frame_size frames. The total number
|
||||
of blocks is tp_block_nr. Note that tp_frame_nr is a redundant parameter because
|
||||
|
||||
@ -336,6 +406,7 @@ struct tpacket_hdr). If this field is 0 means that the frame is ready
|
||||
to be used for the kernel, If not, there is a frame the user can read
|
||||
and the following flags apply:
|
||||
|
||||
+++ Capture process:
|
||||
from include/linux/if_packet.h
|
||||
|
||||
#define TP_STATUS_COPY 2
|
||||
@ -391,6 +462,37 @@ packets are in the ring:
|
||||
It doesn't incur in a race condition to first check the status value and
|
||||
then poll for frames.
|
||||
|
||||
|
||||
++ Transmission process
|
||||
Those defines are also used for transmission:
|
||||
|
||||
#define TP_STATUS_AVAILABLE 0 // Frame is available
|
||||
#define TP_STATUS_SEND_REQUEST 1 // Frame will be sent on next send()
|
||||
#define TP_STATUS_SENDING 2 // Frame is currently in transmission
|
||||
#define TP_STATUS_WRONG_FORMAT 4 // Frame format is not correct
|
||||
|
||||
First, the kernel initializes all frames to TP_STATUS_AVAILABLE. To send a
|
||||
packet, the user fills a data buffer of an available frame, sets tp_len to
|
||||
current data buffer size and sets its status field to TP_STATUS_SEND_REQUEST.
|
||||
This can be done on multiple frames. Once the user is ready to transmit, it
|
||||
calls send(). Then all buffers with status equal to TP_STATUS_SEND_REQUEST are
|
||||
forwarded to the network device. The kernel updates each status of sent
|
||||
frames with TP_STATUS_SENDING until the end of transfer.
|
||||
At the end of each transfer, buffer status returns to TP_STATUS_AVAILABLE.
|
||||
|
||||
header->tp_len = in_i_size;
|
||||
header->tp_status = TP_STATUS_SEND_REQUEST;
|
||||
retval = send(this->socket, NULL, 0, 0);
|
||||
|
||||
The user can also use poll() to check if a buffer is available:
|
||||
(status == TP_STATUS_SENDING)
|
||||
|
||||
struct pollfd pfd;
|
||||
pfd.fd = fd;
|
||||
pfd.revents = 0;
|
||||
pfd.events = POLLOUT;
|
||||
retval = poll(&pfd, 1, timeout);
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
+ THANKS
|
||||
--------------------------------------------------------------------------------
|
||||
|
53
Documentation/powerpc/dts-bindings/can/sja1000.txt
Normal file
53
Documentation/powerpc/dts-bindings/can/sja1000.txt
Normal file
@ -0,0 +1,53 @@
|
||||
Memory mapped SJA1000 CAN controller from NXP (formerly Philips)
|
||||
|
||||
Required properties:
|
||||
|
||||
- compatible : should be "nxp,sja1000".
|
||||
|
||||
- reg : should specify the chip select, address offset and size required
|
||||
to map the registers of the SJA1000. The size is usually 0x80.
|
||||
|
||||
- interrupts: property with a value describing the interrupt source
|
||||
(number and sensitivity) required for the SJA1000.
|
||||
|
||||
Optional properties:
|
||||
|
||||
- nxp,external-clock-frequency : Frequency of the external oscillator
|
||||
clock in Hz. Note that the internal clock frequency used by the
|
||||
SJA1000 is half of that value. If not specified, a default value
|
||||
of 16000000 (16 MHz) is used.
|
||||
|
||||
- nxp,tx-output-mode : operation mode of the TX output control logic:
|
||||
<0x0> : bi-phase output mode
|
||||
<0x1> : normal output mode (default)
|
||||
<0x2> : test output mode
|
||||
<0x3> : clock output mode
|
||||
|
||||
- nxp,tx-output-config : TX output pin configuration:
|
||||
<0x01> : TX0 invert
|
||||
<0x02> : TX0 pull-down (default)
|
||||
<0x04> : TX0 pull-up
|
||||
<0x06> : TX0 push-pull
|
||||
<0x08> : TX1 invert
|
||||
<0x10> : TX1 pull-down
|
||||
<0x20> : TX1 pull-up
|
||||
<0x30> : TX1 push-pull
|
||||
|
||||
- nxp,clock-out-frequency : clock frequency in Hz on the CLKOUT pin.
|
||||
If not specified or if the specified value is 0, the CLKOUT pin
|
||||
will be disabled.
|
||||
|
||||
- nxp,no-comparator-bypass : Allows to disable the CAN input comperator.
|
||||
|
||||
For futher information, please have a look to the SJA1000 data sheet.
|
||||
|
||||
Examples:
|
||||
|
||||
can@3,100 {
|
||||
compatible = "nxp,sja1000";
|
||||
reg = <3 0x100 0x80>;
|
||||
interrupts = <2 0>;
|
||||
interrupt-parent = <&mpic>;
|
||||
nxp,external-clock-frequency = <16000000>;
|
||||
};
|
||||
|
@ -1,575 +1,136 @@
|
||||
rfkill - RF switch subsystem support
|
||||
====================================
|
||||
rfkill - RF kill switch support
|
||||
===============================
|
||||
|
||||
1 Introduction
|
||||
2 Implementation details
|
||||
3 Kernel driver guidelines
|
||||
3.1 wireless device drivers
|
||||
3.2 platform/switch drivers
|
||||
3.3 input device drivers
|
||||
4 Kernel API
|
||||
5 Userspace support
|
||||
1. Introduction
|
||||
2. Implementation details
|
||||
3. Kernel driver guidelines
|
||||
4. Kernel API
|
||||
5. Userspace support
|
||||
|
||||
|
||||
1. Introduction:
|
||||
1. Introduction
|
||||
|
||||
The rfkill switch subsystem exists to add a generic interface to circuitry that
|
||||
can enable or disable the signal output of a wireless *transmitter* of any
|
||||
type. By far, the most common use is to disable radio-frequency transmitters.
|
||||
The rfkill subsystem provides a generic interface to disabling any radio
|
||||
transmitter in the system. When a transmitter is blocked, it shall not
|
||||
radiate any power.
|
||||
|
||||
Note that disabling the signal output means that the the transmitter is to be
|
||||
made to not emit any energy when "blocked". rfkill is not about blocking data
|
||||
transmissions, it is about blocking energy emission.
|
||||
The subsystem also provides the ability to react on button presses and
|
||||
disable all transmitters of a certain type (or all). This is intended for
|
||||
situations where transmitters need to be turned off, for example on
|
||||
aircraft.
|
||||
|
||||
The rfkill subsystem offers support for keys and switches often found on
|
||||
laptops to enable wireless devices like WiFi and Bluetooth, so that these keys
|
||||
and switches actually perform an action in all wireless devices of a given type
|
||||
attached to the system.
|
||||
|
||||
The buttons to enable and disable the wireless transmitters are important in
|
||||
situations where the user is for example using his laptop on a location where
|
||||
radio-frequency transmitters _must_ be disabled (e.g. airplanes).
|
||||
|
||||
Because of this requirement, userspace support for the keys should not be made
|
||||
mandatory. Because userspace might want to perform some additional smarter
|
||||
tasks when the key is pressed, rfkill provides userspace the possibility to
|
||||
take over the task to handle the key events.
|
||||
|
||||
===============================================================================
|
||||
2: Implementation details
|
||||
2. Implementation details
|
||||
|
||||
The rfkill subsystem is composed of various components: the rfkill class, the
|
||||
rfkill-input module (an input layer handler), and some specific input layer
|
||||
events.
|
||||
|
||||
The rfkill class provides kernel drivers with an interface that allows them to
|
||||
know when they should enable or disable a wireless network device transmitter.
|
||||
This is enabled by the CONFIG_RFKILL Kconfig option.
|
||||
The rfkill class is provided for kernel drivers to register their radio
|
||||
transmitter with the kernel, provide methods for turning it on and off and,
|
||||
optionally, letting the system know about hardware-disabled states that may
|
||||
be implemented on the device. This code is enabled with the CONFIG_RFKILL
|
||||
Kconfig option, which drivers can "select".
|
||||
|
||||
The rfkill class support makes sure userspace will be notified of all state
|
||||
changes on rfkill devices through uevents. It provides a notification chain
|
||||
for interested parties in the kernel to also get notified of rfkill state
|
||||
changes in other drivers. It creates several sysfs entries which can be used
|
||||
by userspace. See section "Userspace support".
|
||||
The rfkill class code also notifies userspace of state changes, this is
|
||||
achieved via uevents. It also provides some sysfs files for userspace to
|
||||
check the status of radio transmitters. See the "Userspace support" section
|
||||
below.
|
||||
|
||||
The rfkill-input module provides the kernel with the ability to implement a
|
||||
basic response when the user presses a key or button (or toggles a switch)
|
||||
related to rfkill functionality. It is an in-kernel implementation of default
|
||||
policy of reacting to rfkill-related input events and neither mandatory nor
|
||||
required for wireless drivers to operate. It is enabled by the
|
||||
CONFIG_RFKILL_INPUT Kconfig option.
|
||||
|
||||
rfkill-input is a rfkill-related events input layer handler. This handler will
|
||||
listen to all rfkill key events and will change the rfkill state of the
|
||||
wireless devices accordingly. With this option enabled userspace could either
|
||||
do nothing or simply perform monitoring tasks.
|
||||
The rfkill-input code implements a basic response to rfkill buttons -- it
|
||||
implements turning on/off all devices of a certain class (or all).
|
||||
|
||||
The rfkill-input module also provides EPO (emergency power-off) functionality
|
||||
for all wireless transmitters. This function cannot be overridden, and it is
|
||||
always active. rfkill EPO is related to *_RFKILL_ALL input layer events.
|
||||
When the device is hard-blocked (either by a call to rfkill_set_hw_state()
|
||||
or from query_hw_block) set_block() will be invoked but drivers can well
|
||||
ignore the method call since they can use the return value of the function
|
||||
rfkill_set_hw_state() to sync the software state instead of keeping track
|
||||
of calls to set_block().
|
||||
|
||||
|
||||
Important terms for the rfkill subsystem:
|
||||
The entire functionality is spread over more than one subsystem:
|
||||
|
||||
In order to avoid confusion, we avoid the term "switch" in rfkill when it is
|
||||
referring to an electronic control circuit that enables or disables a
|
||||
transmitter. We reserve it for the physical device a human manipulates
|
||||
(which is an input device, by the way):
|
||||
* The kernel input layer generates KEY_WWAN, KEY_WLAN etc. and
|
||||
SW_RFKILL_ALL -- when the user presses a button. Drivers for radio
|
||||
transmitters generally do not register to the input layer, unless the
|
||||
device really provides an input device (i.e. a button that has no
|
||||
effect other than generating a button press event)
|
||||
|
||||
rfkill switch:
|
||||
* The rfkill-input code hooks up to these events and switches the soft-block
|
||||
of the various radio transmitters, depending on the button type.
|
||||
|
||||
A physical device a human manipulates. Its state can be perceived by
|
||||
the kernel either directly (through a GPIO pin, ACPI GPE) or by its
|
||||
effect on a rfkill line of a wireless device.
|
||||
* The rfkill drivers turn off/on their transmitters as requested.
|
||||
|
||||
rfkill controller:
|
||||
* The rfkill class will generate userspace notifications (uevents) to tell
|
||||
userspace what the current state is.
|
||||
|
||||
A hardware circuit that controls the state of a rfkill line, which a
|
||||
kernel driver can interact with *to modify* that state (i.e. it has
|
||||
either write-only or read/write access).
|
||||
|
||||
rfkill line:
|
||||
|
||||
An input channel (hardware or software) of a wireless device, which
|
||||
causes a wireless transmitter to stop emitting energy (BLOCK) when it
|
||||
is active. Point of view is extremely important here: rfkill lines are
|
||||
always seen from the PoV of a wireless device (and its driver).
|
||||
3. Kernel driver guidelines
|
||||
|
||||
soft rfkill line/software rfkill line:
|
||||
|
||||
A rfkill line the wireless device driver can directly change the state
|
||||
of. Related to rfkill_state RFKILL_STATE_SOFT_BLOCKED.
|
||||
Drivers for radio transmitters normally implement only the rfkill class.
|
||||
These drivers may not unblock the transmitter based on own decisions, they
|
||||
should act on information provided by the rfkill class only.
|
||||
|
||||
hard rfkill line/hardware rfkill line:
|
||||
Platform drivers might implement input devices if the rfkill button is just
|
||||
that, a button. If that button influences the hardware then you need to
|
||||
implement an rfkill class instead. This also applies if the platform provides
|
||||
a way to turn on/off the transmitter(s).
|
||||
|
||||
A rfkill line that works fully in hardware or firmware, and that cannot
|
||||
be overridden by the kernel driver. The hardware device or the
|
||||
firmware just exports its status to the driver, but it is read-only.
|
||||
Related to rfkill_state RFKILL_STATE_HARD_BLOCKED.
|
||||
During suspend/hibernation, transmitters should only be left enabled when
|
||||
wake-on wlan or similar functionality requires it and the device wasn't
|
||||
blocked before suspend/hibernate. Note that it may be necessary to update
|
||||
the rfkill subsystem's idea of what the current state is at resume time if
|
||||
the state may have changed over suspend.
|
||||
|
||||
The enum rfkill_state describes the rfkill state of a transmitter:
|
||||
|
||||
When a rfkill line or rfkill controller is in the RFKILL_STATE_UNBLOCKED state,
|
||||
the wireless transmitter (radio TX circuit for example) is *enabled*. When the
|
||||
it is in the RFKILL_STATE_SOFT_BLOCKED or RFKILL_STATE_HARD_BLOCKED, the
|
||||
wireless transmitter is to be *blocked* from operating.
|
||||
|
||||
RFKILL_STATE_SOFT_BLOCKED indicates that a call to toggle_radio() can change
|
||||
that state. RFKILL_STATE_HARD_BLOCKED indicates that a call to toggle_radio()
|
||||
will not be able to change the state and will return with a suitable error if
|
||||
attempts are made to set the state to RFKILL_STATE_UNBLOCKED.
|
||||
|
||||
RFKILL_STATE_HARD_BLOCKED is used by drivers to signal that the device is
|
||||
locked in the BLOCKED state by a hardwire rfkill line (typically an input pin
|
||||
that, when active, forces the transmitter to be disabled) which the driver
|
||||
CANNOT override.
|
||||
|
||||
Full rfkill functionality requires two different subsystems to cooperate: the
|
||||
input layer and the rfkill class. The input layer issues *commands* to the
|
||||
entire system requesting that devices registered to the rfkill class change
|
||||
state. The way this interaction happens is not complex, but it is not obvious
|
||||
either:
|
||||
|
||||
Kernel Input layer:
|
||||
|
||||
* Generates KEY_WWAN, KEY_WLAN, KEY_BLUETOOTH, SW_RFKILL_ALL, and
|
||||
other such events when the user presses certain keys, buttons, or
|
||||
toggles certain physical switches.
|
||||
|
||||
THE INPUT LAYER IS NEVER USED TO PROPAGATE STATUS, NOTIFICATIONS OR THE
|
||||
KIND OF STUFF AN ON-SCREEN-DISPLAY APPLICATION WOULD REPORT. It is
|
||||
used to issue *commands* for the system to change behaviour, and these
|
||||
commands may or may not be carried out by some kernel driver or
|
||||
userspace application. It follows that doing user feedback based only
|
||||
on input events is broken, as there is no guarantee that an input event
|
||||
will be acted upon.
|
||||
|
||||
Most wireless communication device drivers implementing rfkill
|
||||
functionality MUST NOT generate these events, and have no reason to
|
||||
register themselves with the input layer. Doing otherwise is a common
|
||||
misconception. There is an API to propagate rfkill status change
|
||||
information, and it is NOT the input layer.
|
||||
|
||||
rfkill class:
|
||||
|
||||
* Calls a hook in a driver to effectively change the wireless
|
||||
transmitter state;
|
||||
* Keeps track of the wireless transmitter state (with help from
|
||||
the driver);
|
||||
* Generates userspace notifications (uevents) and a call to a
|
||||
notification chain (kernel) when there is a wireless transmitter
|
||||
state change;
|
||||
* Connects a wireless communications driver with the common rfkill
|
||||
control system, which, for example, allows actions such as
|
||||
"switch all bluetooth devices offline" to be carried out by
|
||||
userspace or by rfkill-input.
|
||||
|
||||
THE RFKILL CLASS NEVER ISSUES INPUT EVENTS. THE RFKILL CLASS DOES
|
||||
NOT LISTEN TO INPUT EVENTS. NO DRIVER USING THE RFKILL CLASS SHALL
|
||||
EVER LISTEN TO, OR ACT ON RFKILL INPUT EVENTS. Doing otherwise is
|
||||
a layering violation.
|
||||
|
||||
Most wireless data communication drivers in the kernel have just to
|
||||
implement the rfkill class API to work properly. Interfacing to the
|
||||
input layer is not often required (and is very often a *bug*) on
|
||||
wireless drivers.
|
||||
|
||||
Platform drivers often have to attach to the input layer to *issue*
|
||||
(but never to listen to) rfkill events for rfkill switches, and also to
|
||||
the rfkill class to export a control interface for the platform rfkill
|
||||
controllers to the rfkill subsystem. This does NOT mean the rfkill
|
||||
switch is attached to a rfkill class (doing so is almost always wrong).
|
||||
It just means the same kernel module is the driver for different
|
||||
devices (rfkill switches and rfkill controllers).
|
||||
|
||||
|
||||
Userspace input handlers (uevents) or kernel input handlers (rfkill-input):
|
||||
|
||||
* Implements the policy of what should happen when one of the input
|
||||
layer events related to rfkill operation is received.
|
||||
* Uses the sysfs interface (userspace) or private rfkill API calls
|
||||
to tell the devices registered with the rfkill class to change
|
||||
their state (i.e. translates the input layer event into real
|
||||
action).
|
||||
|
||||
* rfkill-input implements EPO by handling EV_SW SW_RFKILL_ALL 0
|
||||
(power off all transmitters) in a special way: it ignores any
|
||||
overrides and local state cache and forces all transmitters to the
|
||||
RFKILL_STATE_SOFT_BLOCKED state (including those which are already
|
||||
supposed to be BLOCKED).
|
||||
* rfkill EPO will remain active until rfkill-input receives an
|
||||
EV_SW SW_RFKILL_ALL 1 event. While the EPO is active, transmitters
|
||||
are locked in the blocked state (rfkill will refuse to unblock them).
|
||||
* rfkill-input implements different policies that the user can
|
||||
select for handling EV_SW SW_RFKILL_ALL 1. It will unlock rfkill,
|
||||
and either do nothing (leave transmitters blocked, but now unlocked),
|
||||
restore the transmitters to their state before the EPO, or unblock
|
||||
them all.
|
||||
|
||||
Userspace uevent handler or kernel platform-specific drivers hooked to the
|
||||
rfkill notifier chain:
|
||||
|
||||
* Taps into the rfkill notifier chain or to KOBJ_CHANGE uevents,
|
||||
in order to know when a device that is registered with the rfkill
|
||||
class changes state;
|
||||
* Issues feedback notifications to the user;
|
||||
* In the rare platforms where this is required, synthesizes an input
|
||||
event to command all *OTHER* rfkill devices to also change their
|
||||
statues when a specific rfkill device changes state.
|
||||
|
||||
|
||||
===============================================================================
|
||||
3: Kernel driver guidelines
|
||||
|
||||
Remember: point-of-view is everything for a driver that connects to the rfkill
|
||||
subsystem. All the details below must be measured/perceived from the point of
|
||||
view of the specific driver being modified.
|
||||
|
||||
The first thing one needs to know is whether his driver should be talking to
|
||||
the rfkill class or to the input layer. In rare cases (platform drivers), it
|
||||
could happen that you need to do both, as platform drivers often handle a
|
||||
variety of devices in the same driver.
|
||||
|
||||
Do not mistake input devices for rfkill controllers. The only type of "rfkill
|
||||
switch" device that is to be registered with the rfkill class are those
|
||||
directly controlling the circuits that cause a wireless transmitter to stop
|
||||
working (or the software equivalent of them), i.e. what we call a rfkill
|
||||
controller. Every other kind of "rfkill switch" is just an input device and
|
||||
MUST NOT be registered with the rfkill class.
|
||||
|
||||
A driver should register a device with the rfkill class when ALL of the
|
||||
following conditions are met (they define a rfkill controller):
|
||||
|
||||
1. The device is/controls a data communications wireless transmitter;
|
||||
|
||||
2. The kernel can interact with the hardware/firmware to CHANGE the wireless
|
||||
transmitter state (block/unblock TX operation);
|
||||
|
||||
3. The transmitter can be made to not emit any energy when "blocked":
|
||||
rfkill is not about blocking data transmissions, it is about blocking
|
||||
energy emission;
|
||||
|
||||
A driver should register a device with the input subsystem to issue
|
||||
rfkill-related events (KEY_WLAN, KEY_BLUETOOTH, KEY_WWAN, KEY_WIMAX,
|
||||
SW_RFKILL_ALL, etc) when ALL of the folowing conditions are met:
|
||||
|
||||
1. It is directly related to some physical device the user interacts with, to
|
||||
command the O.S./firmware/hardware to enable/disable a data communications
|
||||
wireless transmitter.
|
||||
|
||||
Examples of the physical device are: buttons, keys and switches the user
|
||||
will press/touch/slide/switch to enable or disable the wireless
|
||||
communication device.
|
||||
|
||||
2. It is NOT slaved to another device, i.e. there is no other device that
|
||||
issues rfkill-related input events in preference to this one.
|
||||
|
||||
Please refer to the corner cases and examples section for more details.
|
||||
|
||||
When in doubt, do not issue input events. For drivers that should generate
|
||||
input events in some platforms, but not in others (e.g. b43), the best solution
|
||||
is to NEVER generate input events in the first place. That work should be
|
||||
deferred to a platform-specific kernel module (which will know when to generate
|
||||
events through the rfkill notifier chain) or to userspace. This avoids the
|
||||
usual maintenance problems with DMI whitelisting.
|
||||
|
||||
|
||||
Corner cases and examples:
|
||||
====================================
|
||||
|
||||
1. If the device is an input device that, because of hardware or firmware,
|
||||
causes wireless transmitters to be blocked regardless of the kernel's will, it
|
||||
is still just an input device, and NOT to be registered with the rfkill class.
|
||||
|
||||
2. If the wireless transmitter switch control is read-only, it is an input
|
||||
device and not to be registered with the rfkill class (and maybe not to be made
|
||||
an input layer event source either, see below).
|
||||
|
||||
3. If there is some other device driver *closer* to the actual hardware the
|
||||
user interacted with (the button/switch/key) to issue an input event, THAT is
|
||||
the device driver that should be issuing input events.
|
||||
|
||||
E.g:
|
||||
[RFKILL slider switch] -- [GPIO hardware] -- [WLAN card rf-kill input]
|
||||
(platform driver) (wireless card driver)
|
||||
|
||||
The user is closer to the RFKILL slide switch plaform driver, so the driver
|
||||
which must issue input events is the platform driver looking at the GPIO
|
||||
hardware, and NEVER the wireless card driver (which is just a slave). It is
|
||||
very likely that there are other leaves than just the WLAN card rf-kill input
|
||||
(e.g. a bluetooth card, etc)...
|
||||
|
||||
On the other hand, some embedded devices do this:
|
||||
|
||||
[RFKILL slider switch] -- [WLAN card rf-kill input]
|
||||
(wireless card driver)
|
||||
|
||||
In this situation, the wireless card driver *could* register itself as an input
|
||||
device and issue rf-kill related input events... but in order to AVOID the need
|
||||
for DMI whitelisting, the wireless card driver does NOT do it. Userspace (HAL)
|
||||
or a platform driver (that exists only on these embedded devices) will do the
|
||||
dirty job of issuing the input events.
|
||||
|
||||
|
||||
COMMON MISTAKES in kernel drivers, related to rfkill:
|
||||
====================================
|
||||
|
||||
1. NEVER confuse input device keys and buttons with input device switches.
|
||||
|
||||
1a. Switches are always set or reset. They report the current state
|
||||
(on position or off position).
|
||||
|
||||
1b. Keys and buttons are either in the pressed or not-pressed state, and
|
||||
that's it. A "button" that latches down when you press it, and
|
||||
unlatches when you press it again is in fact a switch as far as input
|
||||
devices go.
|
||||
|
||||
Add the SW_* events you need for switches, do NOT try to emulate a button using
|
||||
KEY_* events just because there is no such SW_* event yet. Do NOT try to use,
|
||||
for example, KEY_BLUETOOTH when you should be using SW_BLUETOOTH instead.
|
||||
|
||||
2. Input device switches (sources of EV_SW events) DO store their current state
|
||||
(so you *must* initialize it by issuing a gratuitous input layer event on
|
||||
driver start-up and also when resuming from sleep), and that state CAN be
|
||||
queried from userspace through IOCTLs. There is no sysfs interface for this,
|
||||
but that doesn't mean you should break things trying to hook it to the rfkill
|
||||
class to get a sysfs interface :-)
|
||||
|
||||
3. Do not issue *_RFKILL_ALL events by default, unless you are sure it is the
|
||||
correct event for your switch/button. These events are emergency power-off
|
||||
events when they are trying to turn the transmitters off. An example of an
|
||||
input device which SHOULD generate *_RFKILL_ALL events is the wireless-kill
|
||||
switch in a laptop which is NOT a hotkey, but a real sliding/rocker switch.
|
||||
An example of an input device which SHOULD NOT generate *_RFKILL_ALL events by
|
||||
default, is any sort of hot key that is type-specific (e.g. the one for WLAN).
|
||||
|
||||
|
||||
3.1 Guidelines for wireless device drivers
|
||||
------------------------------------------
|
||||
|
||||
(in this text, rfkill->foo means the foo field of struct rfkill).
|
||||
|
||||
1. Each independent transmitter in a wireless device (usually there is only one
|
||||
transmitter per device) should have a SINGLE rfkill class attached to it.
|
||||
|
||||
2. If the device does not have any sort of hardware assistance to allow the
|
||||
driver to rfkill the device, the driver should emulate it by taking all actions
|
||||
required to silence the transmitter.
|
||||
|
||||
3. If it is impossible to silence the transmitter (i.e. it still emits energy,
|
||||
even if it is just in brief pulses, when there is no data to transmit and there
|
||||
is no hardware support to turn it off) do NOT lie to the users. Do not attach
|
||||
it to a rfkill class. The rfkill subsystem does not deal with data
|
||||
transmission, it deals with energy emission. If the transmitter is emitting
|
||||
energy, it is not blocked in rfkill terms.
|
||||
|
||||
4. It doesn't matter if the device has multiple rfkill input lines affecting
|
||||
the same transmitter, their combined state is to be exported as a single state
|
||||
per transmitter (see rule 1).
|
||||
|
||||
This rule exists because users of the rfkill subsystem expect to get (and set,
|
||||
when possible) the overall transmitter rfkill state, not of a particular rfkill
|
||||
line.
|
||||
|
||||
5. The wireless device driver MUST NOT leave the transmitter enabled during
|
||||
suspend and hibernation unless:
|
||||
|
||||
5.1. The transmitter has to be enabled for some sort of functionality
|
||||
like wake-on-wireless-packet or autonomous packed forwarding in a mesh
|
||||
network, and that functionality is enabled for this suspend/hibernation
|
||||
cycle.
|
||||
|
||||
AND
|
||||
|
||||
5.2. The device was not on a user-requested BLOCKED state before
|
||||
the suspend (i.e. the driver must NOT unblock a device, not even
|
||||
to support wake-on-wireless-packet or remain in the mesh).
|
||||
|
||||
In other words, there is absolutely no allowed scenario where a driver can
|
||||
automatically take action to unblock a rfkill controller (obviously, this deals
|
||||
with scenarios where soft-blocking or both soft and hard blocking is happening.
|
||||
Scenarios where hardware rfkill lines are the only ones blocking the
|
||||
transmitter are outside of this rule, since the wireless device driver does not
|
||||
control its input hardware rfkill lines in the first place).
|
||||
|
||||
6. During resume, rfkill will try to restore its previous state.
|
||||
|
||||
7. After a rfkill class is suspended, it will *not* call rfkill->toggle_radio
|
||||
until it is resumed.
|
||||
|
||||
|
||||
Example of a WLAN wireless driver connected to the rfkill subsystem:
|
||||
--------------------------------------------------------------------
|
||||
|
||||
A certain WLAN card has one input pin that causes it to block the transmitter
|
||||
and makes the status of that input pin available (only for reading!) to the
|
||||
kernel driver. This is a hard rfkill input line (it cannot be overridden by
|
||||
the kernel driver).
|
||||
|
||||
The card also has one PCI register that, if manipulated by the driver, causes
|
||||
it to block the transmitter. This is a soft rfkill input line.
|
||||
|
||||
It has also a thermal protection circuitry that shuts down its transmitter if
|
||||
the card overheats, and makes the status of that protection available (only for
|
||||
reading!) to the kernel driver. This is also a hard rfkill input line.
|
||||
|
||||
If either one of these rfkill lines are active, the transmitter is blocked by
|
||||
the hardware and forced offline.
|
||||
|
||||
The driver should allocate and attach to its struct device *ONE* instance of
|
||||
the rfkill class (there is only one transmitter).
|
||||
|
||||
It can implement the get_state() hook, and return RFKILL_STATE_HARD_BLOCKED if
|
||||
either one of its two hard rfkill input lines are active. If the two hard
|
||||
rfkill lines are inactive, it must return RFKILL_STATE_SOFT_BLOCKED if its soft
|
||||
rfkill input line is active. Only if none of the rfkill input lines are
|
||||
active, will it return RFKILL_STATE_UNBLOCKED.
|
||||
|
||||
Since the device has a hardware rfkill line, it IS subject to state changes
|
||||
external to rfkill. Therefore, the driver must make sure that it calls
|
||||
rfkill_force_state() to keep the status always up-to-date, and it must do a
|
||||
rfkill_force_state() on resume from sleep.
|
||||
|
||||
Every time the driver gets a notification from the card that one of its rfkill
|
||||
lines changed state (polling might be needed on badly designed cards that don't
|
||||
generate interrupts for such events), it recomputes the rfkill state as per
|
||||
above, and calls rfkill_force_state() to update it.
|
||||
|
||||
The driver should implement the toggle_radio() hook, that:
|
||||
|
||||
1. Returns an error if one of the hardware rfkill lines are active, and the
|
||||
caller asked for RFKILL_STATE_UNBLOCKED.
|
||||
|
||||
2. Activates the soft rfkill line if the caller asked for state
|
||||
RFKILL_STATE_SOFT_BLOCKED. It should do this even if one of the hard rfkill
|
||||
lines are active, effectively double-blocking the transmitter.
|
||||
|
||||
3. Deactivates the soft rfkill line if none of the hardware rfkill lines are
|
||||
active and the caller asked for RFKILL_STATE_UNBLOCKED.
|
||||
|
||||
===============================================================================
|
||||
4: Kernel API
|
||||
4. Kernel API
|
||||
|
||||
To build a driver with rfkill subsystem support, the driver should depend on
|
||||
(or select) the Kconfig symbol RFKILL; it should _not_ depend on RKFILL_INPUT.
|
||||
(or select) the Kconfig symbol RFKILL.
|
||||
|
||||
The hardware the driver talks to may be write-only (where the current state
|
||||
of the hardware is unknown), or read-write (where the hardware can be queried
|
||||
about its current state).
|
||||
|
||||
The rfkill class will call the get_state hook of a device every time it needs
|
||||
to know the *real* current state of the hardware. This can happen often, but
|
||||
it does not do any polling, so it is not enough on hardware that is subject
|
||||
to state changes outside of the rfkill subsystem.
|
||||
Calling rfkill_set_hw_state() when a state change happens is required from
|
||||
rfkill drivers that control devices that can be hard-blocked unless they also
|
||||
assign the poll_hw_block() callback (then the rfkill core will poll the
|
||||
device). Don't do this unless you cannot get the event in any other way.
|
||||
|
||||
Therefore, calling rfkill_force_state() when a state change happens is
|
||||
mandatory when the device has a hardware rfkill line, or when something else
|
||||
like the firmware could cause its state to be changed without going through the
|
||||
rfkill class.
|
||||
|
||||
Some hardware provides events when its status changes. In these cases, it is
|
||||
best for the driver to not provide a get_state hook, and instead register the
|
||||
rfkill class *already* with the correct status, and keep it updated using
|
||||
rfkill_force_state() when it gets an event from the hardware.
|
||||
|
||||
rfkill_force_state() must be used on the device resume handlers to update the
|
||||
rfkill status, should there be any chance of the device status changing during
|
||||
the sleep.
|
||||
5. Userspace support
|
||||
|
||||
There is no provision for a statically-allocated rfkill struct. You must
|
||||
use rfkill_allocate() to allocate one.
|
||||
|
||||
You should:
|
||||
- rfkill_allocate()
|
||||
- modify rfkill fields (flags, name)
|
||||
- modify state to the current hardware state (THIS IS THE ONLY TIME
|
||||
YOU CAN ACCESS state DIRECTLY)
|
||||
- rfkill_register()
|
||||
|
||||
The only way to set a device to the RFKILL_STATE_HARD_BLOCKED state is through
|
||||
a suitable return of get_state() or through rfkill_force_state().
|
||||
|
||||
When a device is in the RFKILL_STATE_HARD_BLOCKED state, the only way to switch
|
||||
it to a different state is through a suitable return of get_state() or through
|
||||
rfkill_force_state().
|
||||
|
||||
If toggle_radio() is called to set a device to state RFKILL_STATE_SOFT_BLOCKED
|
||||
when that device is already at the RFKILL_STATE_HARD_BLOCKED state, it should
|
||||
not return an error. Instead, it should try to double-block the transmitter,
|
||||
so that its state will change from RFKILL_STATE_HARD_BLOCKED to
|
||||
RFKILL_STATE_SOFT_BLOCKED should the hardware blocking cease.
|
||||
|
||||
Please refer to the source for more documentation.
|
||||
|
||||
===============================================================================
|
||||
5: Userspace support
|
||||
|
||||
rfkill devices issue uevents (with an action of "change"), with the following
|
||||
environment variables set:
|
||||
|
||||
RFKILL_NAME
|
||||
RFKILL_STATE
|
||||
RFKILL_TYPE
|
||||
|
||||
The ABI for these variables is defined by the sysfs attributes. It is best
|
||||
to take a quick look at the source to make sure of the possible values.
|
||||
|
||||
It is expected that HAL will trap those, and bridge them to DBUS, etc. These
|
||||
events CAN and SHOULD be used to give feedback to the user about the rfkill
|
||||
status of the system.
|
||||
|
||||
Input devices may issue events that are related to rfkill. These are the
|
||||
various KEY_* events and SW_* events supported by rfkill-input.c.
|
||||
|
||||
******IMPORTANT******
|
||||
When rfkill-input is ACTIVE, userspace is NOT TO CHANGE THE STATE OF AN RFKILL
|
||||
SWITCH IN RESPONSE TO AN INPUT EVENT also handled by rfkill-input, unless it
|
||||
has set to true the user_claim attribute for that particular switch. This rule
|
||||
is *absolute*; do NOT violate it.
|
||||
******IMPORTANT******
|
||||
|
||||
Userspace must not assume it is the only source of control for rfkill switches.
|
||||
Their state CAN and WILL change due to firmware actions, direct user actions,
|
||||
and the rfkill-input EPO override for *_RFKILL_ALL.
|
||||
|
||||
When rfkill-input is not active, userspace must initiate a rfkill status
|
||||
change by writing to the "state" attribute in order for anything to happen.
|
||||
|
||||
Take particular care to implement EV_SW SW_RFKILL_ALL properly. When that
|
||||
switch is set to OFF, *every* rfkill device *MUST* be immediately put into the
|
||||
RFKILL_STATE_SOFT_BLOCKED state, no questions asked.
|
||||
|
||||
The following sysfs entries will be created:
|
||||
The following sysfs entries exist for every rfkill device:
|
||||
|
||||
name: Name assigned by driver to this key (interface or driver name).
|
||||
type: Name of the key type ("wlan", "bluetooth", etc).
|
||||
state: Current state of the transmitter
|
||||
0: RFKILL_STATE_SOFT_BLOCKED
|
||||
transmitter is forced off, but one can override it
|
||||
by a write to the state attribute;
|
||||
transmitter is turned off by software
|
||||
1: RFKILL_STATE_UNBLOCKED
|
||||
transmiter is NOT forced off, and may operate if
|
||||
all other conditions for such operation are met
|
||||
(such as interface is up and configured, etc);
|
||||
transmitter is (potentially) active
|
||||
2: RFKILL_STATE_HARD_BLOCKED
|
||||
transmitter is forced off by something outside of
|
||||
the driver's control. One cannot set a device to
|
||||
this state through writes to the state attribute;
|
||||
claim: 1: Userspace handles events, 0: Kernel handles events
|
||||
the driver's control.
|
||||
claim: 0: Kernel handles events (currently always reads that value)
|
||||
|
||||
Both the "state" and "claim" entries are also writable. For the "state" entry
|
||||
this means that when 1 or 0 is written, the device rfkill state (if not yet in
|
||||
the requested state), will be will be toggled accordingly.
|
||||
rfkill devices also issue uevents (with an action of "change"), with the
|
||||
following environment variables set:
|
||||
|
||||
For the "claim" entry writing 1 to it means that the kernel no longer handles
|
||||
key events even though RFKILL_INPUT input was enabled. When "claim" has been
|
||||
set to 0, userspace should make sure that it listens for the input events or
|
||||
check the sysfs "state" entry regularly to correctly perform the required tasks
|
||||
when the rkfill key is pressed.
|
||||
RFKILL_NAME
|
||||
RFKILL_STATE
|
||||
RFKILL_TYPE
|
||||
|
||||
A note about input devices and EV_SW events:
|
||||
The contents of these variables corresponds to the "name", "state" and
|
||||
"type" sysfs files explained above.
|
||||
|
||||
In order to know the current state of an input device switch (like
|
||||
SW_RFKILL_ALL), you will need to use an IOCTL. That information is not
|
||||
available through sysfs in a generic way at this time, and it is not available
|
||||
through the rfkill class AT ALL.
|
||||
An alternative userspace interface exists as a misc device /dev/rfkill,
|
||||
which allows userspace to obtain and set the state of rfkill devices and
|
||||
sets of devices. It also notifies userspace about device addition and
|
||||
removal. The API is a simple read/write API that is defined in
|
||||
linux/rfkill.h.
|
||||
|
41
MAINTAINERS
41
MAINTAINERS
@ -157,9 +157,10 @@ S: Maintained
|
||||
F: drivers/net/r8169.c
|
||||
|
||||
8250/16?50 (AND CLONE UARTS) SERIAL DRIVER
|
||||
P: Alan Cox
|
||||
M: alan@lxorguk.ukuu.org.uk
|
||||
L: linux-serial@vger.kernel.org
|
||||
W: http://serial.sourceforge.net
|
||||
M: alan@lxorguk.ukuu.org.uk
|
||||
S: Odd Fixes
|
||||
F: drivers/serial/8250*
|
||||
F: include/linux/serial_8250.h
|
||||
@ -947,6 +948,12 @@ P: Luis R. Rodriguez
|
||||
M: lrodriguez@atheros.com
|
||||
P: Jouni Malinen
|
||||
M: jmalinen@atheros.com
|
||||
P: Sujith Manoharan
|
||||
M: Sujith.Manoharan@atheros.com
|
||||
P: Vasanthakumar Thiagarajan
|
||||
M: vasanth@atheros.com
|
||||
P: Senthil Balasubramanian
|
||||
M: senthilkumar@atheros.com
|
||||
L: linux-wireless@vger.kernel.org
|
||||
L: ath9k-devel@lists.ath9k.org
|
||||
S: Supported
|
||||
@ -1339,6 +1346,13 @@ F: drivers/net/can/
|
||||
F: include/linux/can/
|
||||
F: include/linux/can.h
|
||||
|
||||
CAN NETWORK DRIVERS
|
||||
P: Wolfgang Grandegger
|
||||
M: wg@grandegger.com
|
||||
L: socketcan-core@lists.berlios.de (subscribers-only)
|
||||
W: http://developer.berlios.de/projects/socketcan/
|
||||
S: Maintained
|
||||
|
||||
CELL BROADBAND ENGINE ARCHITECTURE
|
||||
P: Arnd Bergmann
|
||||
M: arnd@arndb.de
|
||||
@ -2843,6 +2857,18 @@ L: linux1394-devel@lists.sourceforge.net
|
||||
S: Maintained
|
||||
F: drivers/ieee1394/raw1394*
|
||||
|
||||
IEEE 802.15.4 SUBSYSTEM
|
||||
P: Dmitry Eremin-Solenikov
|
||||
M: dbaryshkov@gmail.com
|
||||
P: Sergey Lapin
|
||||
M: slapin@ossfans.org
|
||||
L: linux-zigbee-devel@lists.sourceforge.net
|
||||
W: http://apps.sourceforge.net/trac/linux-zigbee
|
||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/lumag/lowpan.git
|
||||
S: Maintained
|
||||
F: net/ieee802154/
|
||||
F: drivers/ieee801254/
|
||||
|
||||
INTEGRITY MEASUREMENT ARCHITECTURE (IMA)
|
||||
P: Mimi Zohar
|
||||
M: zohar@us.ibm.com
|
||||
@ -3136,6 +3162,7 @@ M: samuel@sortiz.org
|
||||
L: irda-users@lists.sourceforge.net (subscribers-only)
|
||||
W: http://irda.sourceforge.net/
|
||||
S: Maintained
|
||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/sameo/irda-2.6.git
|
||||
F: Documentation/networking/irda.txt
|
||||
F: drivers/net/irda/
|
||||
F: include/net/irda/
|
||||
@ -4621,8 +4648,8 @@ S: Maintained
|
||||
F: drivers/ata/sata_promise.*
|
||||
|
||||
PS3 NETWORK SUPPORT
|
||||
P: Masakazu Mokuno
|
||||
M: mokuno@sm.sony.co.jp
|
||||
P: Geoff Levand
|
||||
M: geoffrey.levand@am.sony.com
|
||||
L: netdev@vger.kernel.org
|
||||
L: cbe-oss-dev@ozlabs.org
|
||||
S: Supported
|
||||
@ -4823,7 +4850,7 @@ F: drivers/net/r6040.c
|
||||
RDS - RELIABLE DATAGRAM SOCKETS
|
||||
P: Andy Grover
|
||||
M: andy.grover@oracle.com
|
||||
L: rds-devel@oss.oracle.com
|
||||
L: rds-devel@oss.oracle.com (moderated for non-subscribers)
|
||||
S: Supported
|
||||
F: net/rds/
|
||||
|
||||
@ -4863,9 +4890,9 @@ S: Supported
|
||||
F: fs/reiserfs/
|
||||
|
||||
RFKILL
|
||||
P: Ivo van Doorn
|
||||
M: IvDoorn@gmail.com
|
||||
L: netdev@vger.kernel.org
|
||||
P: Johannes Berg
|
||||
M: johannes@sipsolutions.net
|
||||
L: linux-wireless@vger.kernel.org
|
||||
S: Maintained
|
||||
F Documentation/rfkill.txt
|
||||
F: net/rfkill/
|
||||
|
@ -120,4 +120,6 @@
|
||||
#define EOWNERDEAD 136 /* Owner died */
|
||||
#define ENOTRECOVERABLE 137 /* State not recoverable */
|
||||
|
||||
#define ERFKILL 138 /* Operation not possible due to RF-kill */
|
||||
|
||||
#endif
|
||||
|
@ -536,7 +536,7 @@ setup_rt_frame(int usig, struct k_sigaction *ka, siginfo_t *info,
|
||||
return err;
|
||||
}
|
||||
|
||||
static inline void restart_syscall(struct pt_regs *regs)
|
||||
static inline void setup_syscall_restart(struct pt_regs *regs)
|
||||
{
|
||||
regs->ARM_r0 = regs->ARM_ORIG_r0;
|
||||
regs->ARM_pc -= thumb_mode(regs) ? 2 : 4;
|
||||
@ -571,7 +571,7 @@ handle_signal(unsigned long sig, struct k_sigaction *ka,
|
||||
}
|
||||
/* fallthrough */
|
||||
case -ERESTARTNOINTR:
|
||||
restart_syscall(regs);
|
||||
setup_syscall_restart(regs);
|
||||
}
|
||||
}
|
||||
|
||||
@ -695,7 +695,7 @@ static int do_signal(sigset_t *oldset, struct pt_regs *regs, int syscall)
|
||||
if (regs->ARM_r0 == -ERESTARTNOHAND ||
|
||||
regs->ARM_r0 == -ERESTARTSYS ||
|
||||
regs->ARM_r0 == -ERESTARTNOINTR) {
|
||||
restart_syscall(regs);
|
||||
setup_syscall_restart(regs);
|
||||
}
|
||||
}
|
||||
single_step_set(current);
|
||||
|
@ -35,21 +35,25 @@ static void tosa_bt_off(struct tosa_bt_data *data)
|
||||
gpio_set_value(data->gpio_reset, 0);
|
||||
}
|
||||
|
||||
static int tosa_bt_toggle_radio(void *data, enum rfkill_state state)
|
||||
static int tosa_bt_set_block(void *data, bool blocked)
|
||||
{
|
||||
pr_info("BT_RADIO going: %s\n",
|
||||
state == RFKILL_STATE_ON ? "on" : "off");
|
||||
pr_info("BT_RADIO going: %s\n", blocked ? "off" : "on");
|
||||
|
||||
if (state == RFKILL_STATE_ON) {
|
||||
if (!blocked) {
|
||||
pr_info("TOSA_BT: going ON\n");
|
||||
tosa_bt_on(data);
|
||||
} else {
|
||||
pr_info("TOSA_BT: going OFF\n");
|
||||
tosa_bt_off(data);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct rfkill_ops tosa_bt_rfkill_ops = {
|
||||
.set_block = tosa_bt_set_block,
|
||||
};
|
||||
|
||||
static int tosa_bt_probe(struct platform_device *dev)
|
||||
{
|
||||
int rc;
|
||||
@ -70,18 +74,14 @@ static int tosa_bt_probe(struct platform_device *dev)
|
||||
if (rc)
|
||||
goto err_pwr_dir;
|
||||
|
||||
rfk = rfkill_allocate(&dev->dev, RFKILL_TYPE_BLUETOOTH);
|
||||
rfk = rfkill_alloc("tosa-bt", &dev->dev, RFKILL_TYPE_BLUETOOTH,
|
||||
&tosa_bt_rfkill_ops, data);
|
||||
if (!rfk) {
|
||||
rc = -ENOMEM;
|
||||
goto err_rfk_alloc;
|
||||
}
|
||||
|
||||
rfk->name = "tosa-bt";
|
||||
rfk->toggle_radio = tosa_bt_toggle_radio;
|
||||
rfk->data = data;
|
||||
#ifdef CONFIG_RFKILL_LEDS
|
||||
rfk->led_trigger.name = "tosa-bt";
|
||||
#endif
|
||||
rfkill_set_led_trigger_name(rfk, "tosa-bt");
|
||||
|
||||
rc = rfkill_register(rfk);
|
||||
if (rc)
|
||||
@ -92,9 +92,7 @@ static int tosa_bt_probe(struct platform_device *dev)
|
||||
return 0;
|
||||
|
||||
err_rfkill:
|
||||
if (rfk)
|
||||
rfkill_free(rfk);
|
||||
rfk = NULL;
|
||||
rfkill_destroy(rfk);
|
||||
err_rfk_alloc:
|
||||
tosa_bt_off(data);
|
||||
err_pwr_dir:
|
||||
@ -113,8 +111,10 @@ static int __devexit tosa_bt_remove(struct platform_device *dev)
|
||||
|
||||
platform_set_drvdata(dev, NULL);
|
||||
|
||||
if (rfk)
|
||||
if (rfk) {
|
||||
rfkill_unregister(rfk);
|
||||
rfkill_destroy(rfk);
|
||||
}
|
||||
rfk = NULL;
|
||||
|
||||
tosa_bt_off(data);
|
||||
|
@ -31,7 +31,6 @@
|
||||
#include <linux/input.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/pda_power.h>
|
||||
#include <linux/rfkill.h>
|
||||
#include <linux/spi/spi.h>
|
||||
|
||||
#include <asm/setup.h>
|
||||
|
@ -212,7 +212,7 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
|
||||
return err;
|
||||
}
|
||||
|
||||
static inline void restart_syscall(struct pt_regs *regs)
|
||||
static inline void setup_syscall_restart(struct pt_regs *regs)
|
||||
{
|
||||
if (regs->r12 == -ERESTART_RESTARTBLOCK)
|
||||
regs->r8 = __NR_restart_syscall;
|
||||
@ -296,7 +296,7 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset, int syscall)
|
||||
}
|
||||
/* fall through */
|
||||
case -ERESTARTNOINTR:
|
||||
restart_syscall(regs);
|
||||
setup_syscall_restart(regs);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -6,59 +6,65 @@
|
||||
mainmenu "Blackfin Kernel Configuration"
|
||||
|
||||
config MMU
|
||||
bool
|
||||
default n
|
||||
def_bool n
|
||||
|
||||
config FPU
|
||||
bool
|
||||
default n
|
||||
def_bool n
|
||||
|
||||
config RWSEM_GENERIC_SPINLOCK
|
||||
bool
|
||||
default y
|
||||
def_bool y
|
||||
|
||||
config RWSEM_XCHGADD_ALGORITHM
|
||||
bool
|
||||
default n
|
||||
def_bool n
|
||||
|
||||
config BLACKFIN
|
||||
bool
|
||||
default y
|
||||
def_bool y
|
||||
select HAVE_FUNCTION_GRAPH_TRACER
|
||||
select HAVE_FUNCTION_TRACER
|
||||
select HAVE_IDE
|
||||
select HAVE_KERNEL_GZIP
|
||||
select HAVE_KERNEL_BZIP2
|
||||
select HAVE_KERNEL_LZMA
|
||||
select HAVE_OPROFILE
|
||||
select ARCH_WANT_OPTIONAL_GPIOLIB
|
||||
|
||||
config GENERIC_BUG
|
||||
def_bool y
|
||||
depends on BUG
|
||||
|
||||
config ZONE_DMA
|
||||
bool
|
||||
default y
|
||||
def_bool y
|
||||
|
||||
config GENERIC_FIND_NEXT_BIT
|
||||
bool
|
||||
default y
|
||||
def_bool y
|
||||
|
||||
config GENERIC_HWEIGHT
|
||||
bool
|
||||
default y
|
||||
def_bool y
|
||||
|
||||
config GENERIC_HARDIRQS
|
||||
bool
|
||||
default y
|
||||
def_bool y
|
||||
|
||||
config GENERIC_IRQ_PROBE
|
||||
bool
|
||||
default y
|
||||
def_bool y
|
||||
|
||||
config GENERIC_GPIO
|
||||
bool
|
||||
default y
|
||||
def_bool y
|
||||
|
||||
config FORCE_MAX_ZONEORDER
|
||||
int
|
||||
default "14"
|
||||
|
||||
config GENERIC_CALIBRATE_DELAY
|
||||
bool
|
||||
default y
|
||||
def_bool y
|
||||
|
||||
config LOCKDEP_SUPPORT
|
||||
def_bool y
|
||||
|
||||
config STACKTRACE_SUPPORT
|
||||
def_bool y
|
||||
|
||||
config TRACE_IRQFLAGS_SUPPORT
|
||||
def_bool y
|
||||
|
||||
source "init/Kconfig"
|
||||
|
||||
@ -408,12 +414,12 @@ comment "Clock/PLL Setup"
|
||||
|
||||
config CLKIN_HZ
|
||||
int "Frequency of the crystal on the board in Hz"
|
||||
default "11059200" if BFIN533_STAMP
|
||||
default "27000000" if BFIN533_EZKIT
|
||||
default "25000000" if (BFIN537_STAMP || BFIN527_EZKIT || H8606_HVSISTEMAS || BLACKSTAMP || BFIN526_EZBRD || BFIN538_EZKIT || BFIN518F-EZBRD)
|
||||
default "30000000" if BFIN561_EZKIT
|
||||
default "24576000" if PNAV10
|
||||
default "10000000" if BFIN532_IP0X
|
||||
default "11059200" if BFIN533_STAMP
|
||||
default "24576000" if PNAV10
|
||||
default "25000000" # most people use this
|
||||
default "27000000" if BFIN533_EZKIT
|
||||
default "30000000" if BFIN561_EZKIT
|
||||
help
|
||||
The frequency of CLKIN crystal oscillator on the board in Hz.
|
||||
Warning: This value should match the crystal on the board. Otherwise,
|
||||
|
@ -137,7 +137,7 @@ archclean:
|
||||
|
||||
INSTALL_PATH ?= /tftpboot
|
||||
boot := arch/$(ARCH)/boot
|
||||
BOOT_TARGETS = vmImage
|
||||
BOOT_TARGETS = vmImage vmImage.bz2 vmImage.gz vmImage.lzma
|
||||
PHONY += $(BOOT_TARGETS) install
|
||||
KBUILD_IMAGE := $(boot)/vmImage
|
||||
|
||||
@ -150,7 +150,10 @@ install:
|
||||
$(Q)$(MAKE) $(build)=$(boot) BOOTIMAGE=$(KBUILD_IMAGE) install
|
||||
|
||||
define archhelp
|
||||
echo '* vmImage - Kernel-only image for U-Boot (arch/$(ARCH)/boot/vmImage)'
|
||||
echo '* vmImage - Alias to selected kernel format (vmImage.gz by default)'
|
||||
echo ' vmImage.bz2 - Kernel-only image for U-Boot (arch/$(ARCH)/boot/vmImage.bz2)'
|
||||
echo '* vmImage.gz - Kernel-only image for U-Boot (arch/$(ARCH)/boot/vmImage.gz)'
|
||||
echo ' vmImage.lzma - Kernel-only image for U-Boot (arch/$(ARCH)/boot/vmImage.lzma)'
|
||||
echo ' install - Install kernel using'
|
||||
echo ' (your) ~/bin/$(CROSS_COMPILE)installkernel or'
|
||||
echo ' (distribution) PATH: $(CROSS_COMPILE)installkernel or'
|
||||
|
3
arch/blackfin/boot/.gitignore
vendored
3
arch/blackfin/boot/.gitignore
vendored
@ -1 +1,2 @@
|
||||
+vmImage
|
||||
vmImage*
|
||||
vmlinux*
|
||||
|
@ -8,24 +8,41 @@
|
||||
|
||||
MKIMAGE := $(srctree)/scripts/mkuboot.sh
|
||||
|
||||
targets := vmImage
|
||||
extra-y += vmlinux.bin vmlinux.gz
|
||||
targets := vmImage vmImage.bz2 vmImage.gz vmImage.lzma
|
||||
extra-y += vmlinux.bin vmlinux.bin.gz vmlinux.bin.bz2 vmlinux.bin.lzma
|
||||
|
||||
quiet_cmd_uimage = UIMAGE $@
|
||||
cmd_uimage = $(CONFIG_SHELL) $(MKIMAGE) -A $(ARCH) -O linux -T kernel \
|
||||
-C gzip -n 'Linux-$(KERNELRELEASE)' -a $(CONFIG_BOOT_LOAD) \
|
||||
-C $(2) -n 'Linux-$(KERNELRELEASE)' -a $(CONFIG_BOOT_LOAD) \
|
||||
-e $(shell $(NM) vmlinux | awk '$$NF == "__start" {print $$1}') \
|
||||
-d $< $@
|
||||
|
||||
$(obj)/vmlinux.bin: vmlinux FORCE
|
||||
$(call if_changed,objcopy)
|
||||
|
||||
$(obj)/vmlinux.gz: $(obj)/vmlinux.bin FORCE
|
||||
$(obj)/vmlinux.bin.gz: $(obj)/vmlinux.bin FORCE
|
||||
$(call if_changed,gzip)
|
||||
|
||||
$(obj)/vmImage: $(obj)/vmlinux.gz
|
||||
$(call if_changed,uimage)
|
||||
@$(kecho) 'Kernel: $@ is ready'
|
||||
$(obj)/vmlinux.bin.bz2: $(obj)/vmlinux.bin FORCE
|
||||
$(call if_changed,bzip2)
|
||||
|
||||
$(obj)/vmlinux.bin.lzma: $(obj)/vmlinux.bin FORCE
|
||||
$(call if_changed,lzma)
|
||||
|
||||
$(obj)/vmImage.bz2: $(obj)/vmlinux.bin.bz2
|
||||
$(call if_changed,uimage,bzip2)
|
||||
|
||||
$(obj)/vmImage.gz: $(obj)/vmlinux.bin.gz
|
||||
$(call if_changed,uimage,gzip)
|
||||
|
||||
$(obj)/vmImage.lzma: $(obj)/vmlinux.bin.lzma
|
||||
$(call if_changed,uimage,lzma)
|
||||
|
||||
suffix-$(CONFIG_KERNEL_GZIP) := gz
|
||||
suffix-$(CONFIG_KERNEL_BZIP2) := bz2
|
||||
suffix-$(CONFIG_KERNEL_LZMA) := lzma
|
||||
$(obj)/vmImage: $(obj)/vmImage.$(suffix-y)
|
||||
@ln -sf $(notdir $<) $@
|
||||
|
||||
install:
|
||||
sh $(srctree)/$(src)/install.sh $(KERNELRELEASE) $(BOOTIMAGE) System.map "$(INSTALL_PATH)"
|
||||
|
@ -90,7 +90,7 @@ static inline int atomic_test_mask(int mask, atomic_t *v)
|
||||
|
||||
static inline void atomic_add(int i, atomic_t *v)
|
||||
{
|
||||
long flags;
|
||||
unsigned long flags;
|
||||
|
||||
local_irq_save_hw(flags);
|
||||
v->counter += i;
|
||||
@ -99,7 +99,7 @@ static inline void atomic_add(int i, atomic_t *v)
|
||||
|
||||
static inline void atomic_sub(int i, atomic_t *v)
|
||||
{
|
||||
long flags;
|
||||
unsigned long flags;
|
||||
|
||||
local_irq_save_hw(flags);
|
||||
v->counter -= i;
|
||||
@ -110,7 +110,7 @@ static inline void atomic_sub(int i, atomic_t *v)
|
||||
static inline int atomic_add_return(int i, atomic_t *v)
|
||||
{
|
||||
int __temp = 0;
|
||||
long flags;
|
||||
unsigned long flags;
|
||||
|
||||
local_irq_save_hw(flags);
|
||||
v->counter += i;
|
||||
@ -124,7 +124,7 @@ static inline int atomic_add_return(int i, atomic_t *v)
|
||||
static inline int atomic_sub_return(int i, atomic_t *v)
|
||||
{
|
||||
int __temp = 0;
|
||||
long flags;
|
||||
unsigned long flags;
|
||||
|
||||
local_irq_save_hw(flags);
|
||||
v->counter -= i;
|
||||
@ -136,7 +136,7 @@ static inline int atomic_sub_return(int i, atomic_t *v)
|
||||
|
||||
static inline void atomic_inc(volatile atomic_t *v)
|
||||
{
|
||||
long flags;
|
||||
unsigned long flags;
|
||||
|
||||
local_irq_save_hw(flags);
|
||||
v->counter++;
|
||||
@ -145,7 +145,7 @@ static inline void atomic_inc(volatile atomic_t *v)
|
||||
|
||||
static inline void atomic_dec(volatile atomic_t *v)
|
||||
{
|
||||
long flags;
|
||||
unsigned long flags;
|
||||
|
||||
local_irq_save_hw(flags);
|
||||
v->counter--;
|
||||
@ -154,7 +154,7 @@ static inline void atomic_dec(volatile atomic_t *v)
|
||||
|
||||
static inline void atomic_clear_mask(unsigned int mask, atomic_t *v)
|
||||
{
|
||||
long flags;
|
||||
unsigned long flags;
|
||||
|
||||
local_irq_save_hw(flags);
|
||||
v->counter &= ~mask;
|
||||
@ -163,7 +163,7 @@ static inline void atomic_clear_mask(unsigned int mask, atomic_t *v)
|
||||
|
||||
static inline void atomic_set_mask(unsigned int mask, atomic_t *v)
|
||||
{
|
||||
long flags;
|
||||
unsigned long flags;
|
||||
|
||||
local_irq_save_hw(flags);
|
||||
v->counter |= mask;
|
||||
|
@ -31,7 +31,7 @@
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
|
||||
#include <asm-generic/sections.h>
|
||||
#include <asm/sections.h>
|
||||
#include <asm/ptrace.h>
|
||||
#include <asm/user.h>
|
||||
#include <linux/linkage.h>
|
||||
@ -99,15 +99,6 @@ extern const char bfin_board_name[];
|
||||
extern unsigned long bfin_sic_iwr[];
|
||||
extern unsigned vr_wakeup;
|
||||
extern u16 _bfin_swrst; /* shadow for Software Reset Register (SWRST) */
|
||||
extern unsigned long _ramstart, _ramend, _rambase;
|
||||
extern unsigned long memory_start, memory_end, physical_mem_end;
|
||||
extern char _stext_l1[], _etext_l1[], _sdata_l1[], _edata_l1[], _sbss_l1[],
|
||||
_ebss_l1[], _l1_lma_start[], _sdata_b_l1[], _sbss_b_l1[], _ebss_b_l1[],
|
||||
_stext_l2[], _etext_l2[], _sdata_l2[], _edata_l2[], _sbss_l2[],
|
||||
_ebss_l2[], _l2_lma_start[];
|
||||
|
||||
/* only used when MTD_UCLINUX */
|
||||
extern unsigned long memory_mtd_start, memory_mtd_end, mtd_size;
|
||||
|
||||
#ifdef CONFIG_BFIN_ICACHE_LOCK
|
||||
extern void cache_grab_lock(int way);
|
||||
|
@ -109,7 +109,8 @@ static inline void clear_bit(int nr, volatile unsigned long *addr)
|
||||
|
||||
static inline void change_bit(int nr, volatile unsigned long *addr)
|
||||
{
|
||||
int mask, flags;
|
||||
int mask;
|
||||
unsigned long flags;
|
||||
unsigned long *ADDR = (unsigned long *)addr;
|
||||
|
||||
ADDR += nr >> 5;
|
||||
|
@ -2,13 +2,58 @@
|
||||
#define _BLACKFIN_BUG_H
|
||||
|
||||
#ifdef CONFIG_BUG
|
||||
#define HAVE_ARCH_BUG
|
||||
|
||||
#define BUG() do { \
|
||||
dump_bfin_trace_buffer(); \
|
||||
printk(KERN_EMERG "BUG: failure at %s:%d/%s()!\n", __FILE__, __LINE__, __func__); \
|
||||
panic("BUG!"); \
|
||||
} while (0)
|
||||
#define BFIN_BUG_OPCODE 0xefcd
|
||||
|
||||
#ifdef CONFIG_DEBUG_BUGVERBOSE
|
||||
|
||||
#define _BUG_OR_WARN(flags) \
|
||||
asm volatile( \
|
||||
"1: .hword %0\n" \
|
||||
" .section __bug_table,\"a\",@progbits\n" \
|
||||
"2: .long 1b\n" \
|
||||
" .long %1\n" \
|
||||
" .short %2\n" \
|
||||
" .short %3\n" \
|
||||
" .org 2b + %4\n" \
|
||||
" .previous" \
|
||||
: \
|
||||
: "i"(BFIN_BUG_OPCODE), "i"(__FILE__), \
|
||||
"i"(__LINE__), "i"(flags), \
|
||||
"i"(sizeof(struct bug_entry)))
|
||||
|
||||
#else
|
||||
|
||||
#define _BUG_OR_WARN(flags) \
|
||||
asm volatile( \
|
||||
"1: .hword %0\n" \
|
||||
" .section __bug_table,\"a\",@progbits\n" \
|
||||
"2: .long 1b\n" \
|
||||
" .short %1\n" \
|
||||
" .org 2b + %2\n" \
|
||||
" .previous" \
|
||||
: \
|
||||
: "i"(BFIN_BUG_OPCODE), "i"(flags), \
|
||||
"i"(sizeof(struct bug_entry)))
|
||||
|
||||
#endif /* CONFIG_DEBUG_BUGVERBOSE */
|
||||
|
||||
#define BUG() \
|
||||
do { \
|
||||
_BUG_OR_WARN(0); \
|
||||
for (;;); \
|
||||
} while (0)
|
||||
|
||||
#define WARN_ON(condition) \
|
||||
({ \
|
||||
int __ret_warn_on = !!(condition); \
|
||||
if (unlikely(__ret_warn_on)) \
|
||||
_BUG_OR_WARN(BUGFLAG_WARNING); \
|
||||
unlikely(__ret_warn_on); \
|
||||
})
|
||||
|
||||
#define HAVE_ARCH_BUG
|
||||
#define HAVE_ARCH_WARN_ON
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -34,9 +34,13 @@
|
||||
#define L1_CACHE_SHIFT_MAX 5
|
||||
|
||||
#if defined(CONFIG_SMP) && \
|
||||
!defined(CONFIG_BFIN_CACHE_COHERENT) && \
|
||||
defined(CONFIG_BFIN_DCACHE)
|
||||
#define __ARCH_SYNC_CORE_DCACHE
|
||||
!defined(CONFIG_BFIN_CACHE_COHERENT)
|
||||
# if defined(CONFIG_BFIN_ICACHE)
|
||||
# define __ARCH_SYNC_CORE_ICACHE
|
||||
# endif
|
||||
# if defined(CONFIG_BFIN_DCACHE)
|
||||
# define __ARCH_SYNC_CORE_DCACHE
|
||||
# endif
|
||||
#ifndef __ASSEMBLY__
|
||||
asmlinkage void __raw_smp_mark_barrier_asm(void);
|
||||
asmlinkage void __raw_smp_check_barrier_asm(void);
|
||||
@ -51,6 +55,7 @@ static inline void smp_check_barrier(void)
|
||||
}
|
||||
|
||||
void resync_core_dcache(void);
|
||||
void resync_core_icache(void);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
@ -37,6 +37,7 @@ extern void blackfin_dcache_flush_range(unsigned long start_address, unsigned lo
|
||||
extern void blackfin_dcache_invalidate_range(unsigned long start_address, unsigned long end_address);
|
||||
extern void blackfin_dflush_page(void *page);
|
||||
extern void blackfin_invalidate_entire_dcache(void);
|
||||
extern void blackfin_invalidate_entire_icache(void);
|
||||
|
||||
#define flush_dcache_mmap_lock(mapping) do { } while (0)
|
||||
#define flush_dcache_mmap_unlock(mapping) do { } while (0)
|
||||
@ -97,7 +98,7 @@ do { memcpy(dst, src, len); \
|
||||
extern unsigned long reserved_mem_dcache_on;
|
||||
extern unsigned long reserved_mem_icache_on;
|
||||
|
||||
static inline int bfin_addr_dcachable(unsigned long addr)
|
||||
static inline int bfin_addr_dcacheable(unsigned long addr)
|
||||
{
|
||||
#ifdef CONFIG_BFIN_DCACHE
|
||||
if (addr < (_ramend - DMA_UNCACHED_REGION))
|
||||
|
@ -34,6 +34,7 @@ struct blackfin_cpudata {
|
||||
unsigned int dmemctl;
|
||||
unsigned long loops_per_jiffy;
|
||||
unsigned long dcache_invld_count;
|
||||
unsigned long icache_invld_count;
|
||||
};
|
||||
|
||||
DECLARE_PER_CPU(struct blackfin_cpudata, cpu_data);
|
||||
|
@ -1 +1,13 @@
|
||||
/* empty */
|
||||
/*
|
||||
* Blackfin ftrace code
|
||||
*
|
||||
* Copyright 2009 Analog Devices Inc.
|
||||
* Licensed under the GPL-2 or later.
|
||||
*/
|
||||
|
||||
#ifndef __ASM_BFIN_FTRACE_H__
|
||||
#define __ASM_BFIN_FTRACE_H__
|
||||
|
||||
#define MCOUNT_INSN_SIZE 8 /* sizeof mcount call: LINK + CALL */
|
||||
|
||||
#endif
|
||||
|
@ -35,10 +35,10 @@
|
||||
#include <asm/atomic.h>
|
||||
#include <asm/traps.h>
|
||||
|
||||
#define IPIPE_ARCH_STRING "1.9-01"
|
||||
#define IPIPE_ARCH_STRING "1.10-00"
|
||||
#define IPIPE_MAJOR_NUMBER 1
|
||||
#define IPIPE_MINOR_NUMBER 9
|
||||
#define IPIPE_PATCH_NUMBER 1
|
||||
#define IPIPE_MINOR_NUMBER 10
|
||||
#define IPIPE_PATCH_NUMBER 0
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
#error "I-pipe/blackfin: SMP not implemented"
|
||||
@ -54,10 +54,11 @@ do { \
|
||||
|
||||
#define task_hijacked(p) \
|
||||
({ \
|
||||
int __x__ = ipipe_current_domain != ipipe_root_domain; \
|
||||
/* We would need to clear the SYNC flag for the root domain */ \
|
||||
/* over the current processor in SMP mode. */ \
|
||||
local_irq_enable_hw(); __x__; \
|
||||
int __x__ = __ipipe_root_domain_p; \
|
||||
__clear_bit(IPIPE_SYNC_FLAG, &ipipe_root_cpudom_var(status)); \
|
||||
if (__x__) \
|
||||
local_irq_enable_hw(); \
|
||||
!__x__; \
|
||||
})
|
||||
|
||||
struct ipipe_domain;
|
||||
@ -179,23 +180,24 @@ static inline unsigned long __ipipe_ffnz(unsigned long ul)
|
||||
|
||||
#define __ipipe_run_isr(ipd, irq) \
|
||||
do { \
|
||||
if (ipd == ipipe_root_domain) { \
|
||||
if (!__ipipe_pipeline_head_p(ipd)) \
|
||||
local_irq_enable_hw(); \
|
||||
if (ipipe_virtual_irq_p(irq)) \
|
||||
if (ipd == ipipe_root_domain) { \
|
||||
if (unlikely(ipipe_virtual_irq_p(irq))) { \
|
||||
irq_enter(); \
|
||||
ipd->irqs[irq].handler(irq, ipd->irqs[irq].cookie); \
|
||||
else \
|
||||
irq_exit(); \
|
||||
} else \
|
||||
ipd->irqs[irq].handler(irq, &__raw_get_cpu_var(__ipipe_tick_regs)); \
|
||||
local_irq_disable_hw(); \
|
||||
} else { \
|
||||
__clear_bit(IPIPE_SYNC_FLAG, &ipipe_cpudom_var(ipd, status)); \
|
||||
local_irq_enable_nohead(ipd); \
|
||||
ipd->irqs[irq].handler(irq, ipd->irqs[irq].cookie); \
|
||||
/* Attempt to exit the outer interrupt level before \
|
||||
* starting the deferred IRQ processing. */ \
|
||||
local_irq_disable_nohead(ipd); \
|
||||
__ipipe_run_irqtail(); \
|
||||
__set_bit(IPIPE_SYNC_FLAG, &ipipe_cpudom_var(ipd, status)); \
|
||||
} \
|
||||
local_irq_disable_hw(); \
|
||||
} while (0)
|
||||
|
||||
#define __ipipe_syscall_watched_p(p, sc) \
|
||||
|
@ -17,270 +17,17 @@
|
||||
#ifndef _BFIN_IRQ_H_
|
||||
#define _BFIN_IRQ_H_
|
||||
|
||||
/* SYS_IRQS and NR_IRQS are defined in <mach-bf5xx/irq.h>*/
|
||||
#include <linux/irqflags.h>
|
||||
|
||||
/* SYS_IRQS and NR_IRQS are defined in <mach-bf5xx/irq.h> */
|
||||
#include <mach/irq.h>
|
||||
#include <asm/pda.h>
|
||||
#include <asm/processor.h>
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
/* Forward decl needed due to cdef inter dependencies */
|
||||
static inline uint32_t __pure bfin_dspid(void);
|
||||
# define blackfin_core_id() (bfin_dspid() & 0xff)
|
||||
# define bfin_irq_flags cpu_pda[blackfin_core_id()].imask
|
||||
#else
|
||||
extern unsigned long bfin_irq_flags;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_IPIPE
|
||||
|
||||
#include <linux/ipipe_trace.h>
|
||||
|
||||
void __ipipe_unstall_root(void);
|
||||
|
||||
void __ipipe_restore_root(unsigned long flags);
|
||||
|
||||
#ifdef CONFIG_DEBUG_HWERR
|
||||
# define __all_masked_irq_flags 0x3f
|
||||
# define __save_and_cli_hw(x) \
|
||||
__asm__ __volatile__( \
|
||||
"cli %0;" \
|
||||
"sti %1;" \
|
||||
: "=&d"(x) \
|
||||
: "d" (0x3F) \
|
||||
)
|
||||
#else
|
||||
# define __all_masked_irq_flags 0x1f
|
||||
# define __save_and_cli_hw(x) \
|
||||
__asm__ __volatile__( \
|
||||
"cli %0;" \
|
||||
: "=&d"(x) \
|
||||
)
|
||||
#endif
|
||||
|
||||
#define irqs_enabled_from_flags_hw(x) ((x) != __all_masked_irq_flags)
|
||||
#define raw_irqs_disabled_flags(flags) (!irqs_enabled_from_flags_hw(flags))
|
||||
#define local_test_iflag_hw(x) irqs_enabled_from_flags_hw(x)
|
||||
|
||||
#define local_save_flags(x) \
|
||||
do { \
|
||||
(x) = __ipipe_test_root() ? \
|
||||
__all_masked_irq_flags : bfin_irq_flags; \
|
||||
barrier(); \
|
||||
} while (0)
|
||||
|
||||
#define local_irq_save(x) \
|
||||
do { \
|
||||
(x) = __ipipe_test_and_stall_root() ? \
|
||||
__all_masked_irq_flags : bfin_irq_flags; \
|
||||
barrier(); \
|
||||
} while (0)
|
||||
|
||||
static inline void local_irq_restore(unsigned long x)
|
||||
{
|
||||
barrier();
|
||||
__ipipe_restore_root(x == __all_masked_irq_flags);
|
||||
}
|
||||
|
||||
#define local_irq_disable() \
|
||||
do { \
|
||||
__ipipe_stall_root(); \
|
||||
barrier(); \
|
||||
} while (0)
|
||||
|
||||
static inline void local_irq_enable(void)
|
||||
{
|
||||
barrier();
|
||||
__ipipe_unstall_root();
|
||||
}
|
||||
|
||||
#define irqs_disabled() __ipipe_test_root()
|
||||
|
||||
#define local_save_flags_hw(x) \
|
||||
__asm__ __volatile__( \
|
||||
"cli %0;" \
|
||||
"sti %0;" \
|
||||
: "=d"(x) \
|
||||
)
|
||||
|
||||
#define irqs_disabled_hw() \
|
||||
({ \
|
||||
unsigned long flags; \
|
||||
local_save_flags_hw(flags); \
|
||||
!irqs_enabled_from_flags_hw(flags); \
|
||||
})
|
||||
|
||||
static inline unsigned long raw_mangle_irq_bits(int virt, unsigned long real)
|
||||
{
|
||||
/* Merge virtual and real interrupt mask bits into a single
|
||||
32bit word. */
|
||||
return (real & ~(1 << 31)) | ((virt != 0) << 31);
|
||||
}
|
||||
|
||||
static inline int raw_demangle_irq_bits(unsigned long *x)
|
||||
{
|
||||
int virt = (*x & (1 << 31)) != 0;
|
||||
*x &= ~(1L << 31);
|
||||
return virt;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_IPIPE_TRACE_IRQSOFF
|
||||
|
||||
#define local_irq_disable_hw() \
|
||||
do { \
|
||||
int _tmp_dummy; \
|
||||
if (!irqs_disabled_hw()) \
|
||||
ipipe_trace_begin(0x80000000); \
|
||||
__asm__ __volatile__ ("cli %0;" : "=d" (_tmp_dummy) : ); \
|
||||
} while (0)
|
||||
|
||||
#define local_irq_enable_hw() \
|
||||
do { \
|
||||
if (irqs_disabled_hw()) \
|
||||
ipipe_trace_end(0x80000000); \
|
||||
__asm__ __volatile__ ("sti %0;" : : "d"(bfin_irq_flags)); \
|
||||
} while (0)
|
||||
|
||||
#define local_irq_save_hw(x) \
|
||||
do { \
|
||||
__save_and_cli_hw(x); \
|
||||
if (local_test_iflag_hw(x)) \
|
||||
ipipe_trace_begin(0x80000001); \
|
||||
} while (0)
|
||||
|
||||
#define local_irq_restore_hw(x) \
|
||||
do { \
|
||||
if (local_test_iflag_hw(x)) { \
|
||||
ipipe_trace_end(0x80000001); \
|
||||
local_irq_enable_hw_notrace(); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define local_irq_disable_hw_notrace() \
|
||||
do { \
|
||||
int _tmp_dummy; \
|
||||
__asm__ __volatile__ ("cli %0;" : "=d" (_tmp_dummy) : ); \
|
||||
} while (0)
|
||||
|
||||
#define local_irq_enable_hw_notrace() \
|
||||
__asm__ __volatile__( \
|
||||
"sti %0;" \
|
||||
: \
|
||||
: "d"(bfin_irq_flags) \
|
||||
)
|
||||
|
||||
#define local_irq_save_hw_notrace(x) __save_and_cli_hw(x)
|
||||
|
||||
#define local_irq_restore_hw_notrace(x) \
|
||||
do { \
|
||||
if (local_test_iflag_hw(x)) \
|
||||
local_irq_enable_hw_notrace(); \
|
||||
} while (0)
|
||||
|
||||
#else /* CONFIG_IPIPE_TRACE_IRQSOFF */
|
||||
|
||||
#define local_irq_enable_hw() \
|
||||
__asm__ __volatile__( \
|
||||
"sti %0;" \
|
||||
: \
|
||||
: "d"(bfin_irq_flags) \
|
||||
)
|
||||
|
||||
#define local_irq_disable_hw() \
|
||||
do { \
|
||||
int _tmp_dummy; \
|
||||
__asm__ __volatile__ ( \
|
||||
"cli %0;" \
|
||||
: "=d" (_tmp_dummy)); \
|
||||
} while (0)
|
||||
|
||||
#define local_irq_restore_hw(x) \
|
||||
do { \
|
||||
if (irqs_enabled_from_flags_hw(x)) \
|
||||
local_irq_enable_hw(); \
|
||||
} while (0)
|
||||
|
||||
#define local_irq_save_hw(x) __save_and_cli_hw(x)
|
||||
|
||||
#define local_irq_disable_hw_notrace() local_irq_disable_hw()
|
||||
#define local_irq_enable_hw_notrace() local_irq_enable_hw()
|
||||
#define local_irq_save_hw_notrace(x) local_irq_save_hw(x)
|
||||
#define local_irq_restore_hw_notrace(x) local_irq_restore_hw(x)
|
||||
|
||||
#endif /* CONFIG_IPIPE_TRACE_IRQSOFF */
|
||||
|
||||
#else /* !CONFIG_IPIPE */
|
||||
|
||||
/*
|
||||
* Interrupt configuring macros.
|
||||
*/
|
||||
#define local_irq_disable() \
|
||||
do { \
|
||||
int __tmp_dummy; \
|
||||
__asm__ __volatile__( \
|
||||
"cli %0;" \
|
||||
: "=d" (__tmp_dummy) \
|
||||
); \
|
||||
} while (0)
|
||||
|
||||
#define local_irq_enable() \
|
||||
__asm__ __volatile__( \
|
||||
"sti %0;" \
|
||||
: \
|
||||
: "d" (bfin_irq_flags) \
|
||||
)
|
||||
|
||||
#ifdef CONFIG_DEBUG_HWERR
|
||||
# define __save_and_cli(x) \
|
||||
__asm__ __volatile__( \
|
||||
"cli %0;" \
|
||||
"sti %1;" \
|
||||
: "=&d" (x) \
|
||||
: "d" (0x3F) \
|
||||
)
|
||||
#else
|
||||
# define __save_and_cli(x) \
|
||||
__asm__ __volatile__( \
|
||||
"cli %0;" \
|
||||
: "=&d" (x) \
|
||||
)
|
||||
#endif
|
||||
|
||||
#define local_save_flags(x) \
|
||||
__asm__ __volatile__( \
|
||||
"cli %0;" \
|
||||
"sti %0;" \
|
||||
: "=d" (x) \
|
||||
)
|
||||
|
||||
#ifdef CONFIG_DEBUG_HWERR
|
||||
#define irqs_enabled_from_flags(x) (((x) & ~0x3f) != 0)
|
||||
#else
|
||||
#define irqs_enabled_from_flags(x) ((x) != 0x1f)
|
||||
#endif
|
||||
|
||||
#define local_irq_restore(x) \
|
||||
do { \
|
||||
if (irqs_enabled_from_flags(x)) \
|
||||
local_irq_enable(); \
|
||||
} while (0)
|
||||
|
||||
/* For spinlocks etc */
|
||||
#define local_irq_save(x) __save_and_cli(x)
|
||||
|
||||
#define irqs_disabled() \
|
||||
({ \
|
||||
unsigned long flags; \
|
||||
local_save_flags(flags); \
|
||||
!irqs_enabled_from_flags(flags); \
|
||||
})
|
||||
|
||||
#define local_irq_save_hw(x) local_irq_save(x)
|
||||
#define local_irq_restore_hw(x) local_irq_restore(x)
|
||||
#define local_irq_enable_hw() local_irq_enable()
|
||||
#define local_irq_disable_hw() local_irq_disable()
|
||||
#define irqs_disabled_hw() irqs_disabled()
|
||||
|
||||
#endif /* !CONFIG_IPIPE */
|
||||
/* Xenomai IPIPE helpers */
|
||||
#define local_irq_restore_hw(x) local_irq_restore(x)
|
||||
#define local_irq_save_hw(x) local_irq_save(x)
|
||||
#define local_irq_enable_hw(x) local_irq_enable(x)
|
||||
#define local_irq_disable_hw(x) local_irq_disable(x)
|
||||
#define irqs_disabled_hw(x) irqs_disabled(x)
|
||||
|
||||
#if ANOMALY_05000244 && defined(CONFIG_BFIN_ICACHE)
|
||||
# define NOP_PAD_ANOMALY_05000244 "nop; nop;"
|
||||
|
63
arch/blackfin/include/asm/irqflags.h
Normal file
63
arch/blackfin/include/asm/irqflags.h
Normal file
@ -0,0 +1,63 @@
|
||||
/*
|
||||
* interface to Blackfin CEC
|
||||
*
|
||||
* Copyright 2009 Analog Devices Inc.
|
||||
* Licensed under the GPL-2 or later.
|
||||
*/
|
||||
|
||||
#ifndef __ASM_BFIN_IRQFLAGS_H__
|
||||
#define __ASM_BFIN_IRQFLAGS_H__
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
# include <asm/pda.h>
|
||||
# include <asm/processor.h>
|
||||
/* Forward decl needed due to cdef inter dependencies */
|
||||
static inline uint32_t __pure bfin_dspid(void);
|
||||
# define blackfin_core_id() (bfin_dspid() & 0xff)
|
||||
# define bfin_irq_flags cpu_pda[blackfin_core_id()].imask
|
||||
#else
|
||||
extern unsigned long bfin_irq_flags;
|
||||
#endif
|
||||
|
||||
static inline void bfin_sti(unsigned long flags)
|
||||
{
|
||||
asm volatile("sti %0;" : : "d" (flags));
|
||||
}
|
||||
|
||||
static inline unsigned long bfin_cli(void)
|
||||
{
|
||||
unsigned long flags;
|
||||
asm volatile("cli %0;" : "=d" (flags));
|
||||
return flags;
|
||||
}
|
||||
|
||||
static inline void raw_local_irq_disable(void)
|
||||
{
|
||||
bfin_cli();
|
||||
}
|
||||
static inline void raw_local_irq_enable(void)
|
||||
{
|
||||
bfin_sti(bfin_irq_flags);
|
||||
}
|
||||
|
||||
#define raw_local_save_flags(flags) do { (flags) = bfin_read_IMASK(); } while (0)
|
||||
|
||||
#define raw_irqs_disabled_flags(flags) (((flags) & ~0x3f) == 0)
|
||||
|
||||
static inline void raw_local_irq_restore(unsigned long flags)
|
||||
{
|
||||
if (!raw_irqs_disabled_flags(flags))
|
||||
raw_local_irq_enable();
|
||||
}
|
||||
|
||||
static inline unsigned long __raw_local_irq_save(void)
|
||||
{
|
||||
unsigned long flags = bfin_cli();
|
||||
#ifdef CONFIG_DEBUG_HWERR
|
||||
bfin_sti(0x3f);
|
||||
#endif
|
||||
return flags;
|
||||
}
|
||||
#define raw_local_irq_save(flags) do { (flags) = __raw_local_irq_save(); } while (0)
|
||||
|
||||
#endif
|
@ -1,112 +0,0 @@
|
||||
/*
|
||||
* include/asm-generic/mutex-dec.h
|
||||
*
|
||||
* Generic implementation of the mutex fastpath, based on atomic
|
||||
* decrement/increment.
|
||||
*/
|
||||
#ifndef _ASM_GENERIC_MUTEX_DEC_H
|
||||
#define _ASM_GENERIC_MUTEX_DEC_H
|
||||
|
||||
/**
|
||||
* __mutex_fastpath_lock - try to take the lock by moving the count
|
||||
* from 1 to a 0 value
|
||||
* @count: pointer of type atomic_t
|
||||
* @fail_fn: function to call if the original value was not 1
|
||||
*
|
||||
* Change the count from 1 to a value lower than 1, and call <fail_fn> if
|
||||
* it wasn't 1 originally. This function MUST leave the value lower than
|
||||
* 1 even when the "1" assertion wasn't true.
|
||||
*/
|
||||
static inline void
|
||||
__mutex_fastpath_lock(atomic_t *count, fastcall void (*fail_fn)(atomic_t *))
|
||||
{
|
||||
if (unlikely(atomic_dec_return(count) < 0))
|
||||
fail_fn(count);
|
||||
else
|
||||
smp_mb();
|
||||
}
|
||||
|
||||
/**
|
||||
* __mutex_fastpath_lock_retval - try to take the lock by moving the count
|
||||
* from 1 to a 0 value
|
||||
* @count: pointer of type atomic_t
|
||||
* @fail_fn: function to call if the original value was not 1
|
||||
*
|
||||
* Change the count from 1 to a value lower than 1, and call <fail_fn> if
|
||||
* it wasn't 1 originally. This function returns 0 if the fastpath succeeds,
|
||||
* or anything the slow path function returns.
|
||||
*/
|
||||
static inline int
|
||||
__mutex_fastpath_lock_retval(atomic_t *count, fastcall int (*fail_fn)(atomic_t *))
|
||||
{
|
||||
if (unlikely(atomic_dec_return(count) < 0))
|
||||
return fail_fn(count);
|
||||
else {
|
||||
smp_mb();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* __mutex_fastpath_unlock - try to promote the count from 0 to 1
|
||||
* @count: pointer of type atomic_t
|
||||
* @fail_fn: function to call if the original value was not 0
|
||||
*
|
||||
* Try to promote the count from 0 to 1. If it wasn't 0, call <fail_fn>.
|
||||
* In the failure case, this function is allowed to either set the value to
|
||||
* 1, or to set it to a value lower than 1.
|
||||
*
|
||||
* If the implementation sets it to a value of lower than 1, then the
|
||||
* __mutex_slowpath_needs_to_unlock() macro needs to return 1, it needs
|
||||
* to return 0 otherwise.
|
||||
*/
|
||||
static inline void
|
||||
__mutex_fastpath_unlock(atomic_t *count, fastcall void (*fail_fn)(atomic_t *))
|
||||
{
|
||||
smp_mb();
|
||||
if (unlikely(atomic_inc_return(count) <= 0))
|
||||
fail_fn(count);
|
||||
}
|
||||
|
||||
#define __mutex_slowpath_needs_to_unlock() 1
|
||||
|
||||
/**
|
||||
* __mutex_fastpath_trylock - try to acquire the mutex, without waiting
|
||||
*
|
||||
* @count: pointer of type atomic_t
|
||||
* @fail_fn: fallback function
|
||||
*
|
||||
* Change the count from 1 to a value lower than 1, and return 0 (failure)
|
||||
* if it wasn't 1 originally, or return 1 (success) otherwise. This function
|
||||
* MUST leave the value lower than 1 even when the "1" assertion wasn't true.
|
||||
* Additionally, if the value was < 0 originally, this function must not leave
|
||||
* it to 0 on failure.
|
||||
*
|
||||
* If the architecture has no effective trylock variant, it should call the
|
||||
* <fail_fn> spinlock-based trylock variant unconditionally.
|
||||
*/
|
||||
static inline int
|
||||
__mutex_fastpath_trylock(atomic_t *count, int (*fail_fn)(atomic_t *))
|
||||
{
|
||||
/*
|
||||
* We have two variants here. The cmpxchg based one is the best one
|
||||
* because it never induce a false contention state. It is included
|
||||
* here because architectures using the inc/dec algorithms over the
|
||||
* xchg ones are much more likely to support cmpxchg natively.
|
||||
*
|
||||
* If not we fall back to the spinlock based variant - that is
|
||||
* just as efficient (and simpler) as a 'destructive' probing of
|
||||
* the mutex state would be.
|
||||
*/
|
||||
#ifdef __HAVE_ARCH_CMPXCHG
|
||||
if (likely(atomic_cmpxchg(count, 1, 0) == 1)) {
|
||||
smp_mb();
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
#else
|
||||
return fail_fn(count);
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
@ -4,4 +4,15 @@
|
||||
/* nothing to see, move along */
|
||||
#include <asm-generic/sections.h>
|
||||
|
||||
/* only used when MTD_UCLINUX */
|
||||
extern unsigned long memory_mtd_start, memory_mtd_end, mtd_size;
|
||||
|
||||
extern unsigned long _ramstart, _ramend, _rambase;
|
||||
extern unsigned long memory_start, memory_end, physical_mem_end;
|
||||
|
||||
extern char _stext_l1[], _etext_l1[], _sdata_l1[], _edata_l1[], _sbss_l1[],
|
||||
_ebss_l1[], _l1_lma_start[], _sdata_b_l1[], _sbss_b_l1[], _ebss_b_l1[],
|
||||
_stext_l2[], _etext_l2[], _sdata_l2[], _edata_l2[], _sbss_l2[],
|
||||
_ebss_l2[], _l2_lma_start[];
|
||||
|
||||
#endif
|
||||
|
@ -35,10 +35,10 @@
|
||||
#define _BLACKFIN_SYSTEM_H
|
||||
|
||||
#include <linux/linkage.h>
|
||||
#include <linux/compiler.h>
|
||||
#include <linux/irqflags.h>
|
||||
#include <mach/anomaly.h>
|
||||
#include <asm/cache.h>
|
||||
#include <asm/pda.h>
|
||||
#include <asm/processor.h>
|
||||
#include <asm/irq.h>
|
||||
|
||||
/*
|
||||
|
@ -380,8 +380,9 @@
|
||||
#define __NR_inotify_init1 365
|
||||
#define __NR_preadv 366
|
||||
#define __NR_pwritev 367
|
||||
#define __NR_rt_tgsigqueueinfo 368
|
||||
|
||||
#define __NR_syscall 368
|
||||
#define __NR_syscall 369
|
||||
#define NR_syscalls __NR_syscall
|
||||
|
||||
/* Old optional stuff no one actually uses */
|
||||
|
@ -15,6 +15,10 @@ else
|
||||
obj-y += time.o
|
||||
endif
|
||||
|
||||
obj-$(CONFIG_FUNCTION_TRACER) += ftrace-entry.o
|
||||
obj-$(CONFIG_FUNCTION_GRAPH_TRACER) += ftrace.o
|
||||
CFLAGS_REMOVE_ftrace.o = -pg
|
||||
|
||||
obj-$(CONFIG_IPIPE) += ipipe.o
|
||||
obj-$(CONFIG_IPIPE_TRACE_MCOUNT) += mcount.o
|
||||
obj-$(CONFIG_BFIN_GPTIMERS) += gptimers.o
|
||||
@ -23,6 +27,7 @@ obj-$(CONFIG_MODULES) += module.o
|
||||
obj-$(CONFIG_KGDB) += kgdb.o
|
||||
obj-$(CONFIG_KGDB_TESTS) += kgdb_test.o
|
||||
obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
|
||||
obj-$(CONFIG_STACKTRACE) += stacktrace.o
|
||||
|
||||
# the kgdb test puts code into L2 and without linker
|
||||
# relaxation, we need to force long calls to/from it
|
||||
|
@ -453,10 +453,10 @@ void *dma_memcpy(void *pdst, const void *psrc, size_t size)
|
||||
unsigned long src = (unsigned long)psrc;
|
||||
size_t bulk, rest;
|
||||
|
||||
if (bfin_addr_dcachable(src))
|
||||
if (bfin_addr_dcacheable(src))
|
||||
blackfin_dcache_flush_range(src, src + size);
|
||||
|
||||
if (bfin_addr_dcachable(dst))
|
||||
if (bfin_addr_dcacheable(dst))
|
||||
blackfin_dcache_invalidate_range(dst, dst + size);
|
||||
|
||||
bulk = size & ~0xffff;
|
||||
|
@ -103,3 +103,8 @@ EXPORT_SYMBOL(__raw_smp_mark_barrier_asm);
|
||||
EXPORT_SYMBOL(__raw_smp_check_barrier_asm);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_FUNCTION_TRACER
|
||||
extern void _mcount(void);
|
||||
EXPORT_SYMBOL(_mcount);
|
||||
#endif
|
||||
|
@ -151,7 +151,7 @@ static noinline int dcplb_miss(unsigned int cpu)
|
||||
|
||||
d_data = CPLB_SUPV_WR | CPLB_VALID | CPLB_DIRTY | PAGE_SIZE_4KB;
|
||||
#ifdef CONFIG_BFIN_DCACHE
|
||||
if (bfin_addr_dcachable(addr)) {
|
||||
if (bfin_addr_dcacheable(addr)) {
|
||||
d_data |= CPLB_L1_CHBL | ANOMALY_05000158_WORKAROUND;
|
||||
#ifdef CONFIG_BFIN_WT
|
||||
d_data |= CPLB_L1_AOW | CPLB_WT;
|
||||
|
@ -28,6 +28,7 @@
|
||||
#include <asm/cplbinit.h>
|
||||
#include <asm/cplb.h>
|
||||
#include <asm/mmu_context.h>
|
||||
#include <asm/traps.h>
|
||||
|
||||
/*
|
||||
* WARNING
|
||||
@ -100,28 +101,6 @@ static inline void write_icplb_data(int cpu, int idx, unsigned long data,
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* Given the contents of the status register, return the index of the
|
||||
* CPLB that caused the fault.
|
||||
*/
|
||||
static inline int faulting_cplb_index(int status)
|
||||
{
|
||||
int signbits = __builtin_bfin_norm_fr1x32(status & 0xFFFF);
|
||||
return 30 - signbits;
|
||||
}
|
||||
|
||||
/*
|
||||
* Given the contents of the status register and the DCPLB_DATA contents,
|
||||
* return true if a write access should be permitted.
|
||||
*/
|
||||
static inline int write_permitted(int status, unsigned long data)
|
||||
{
|
||||
if (status & FAULT_USERSUPV)
|
||||
return !!(data & CPLB_SUPV_WR);
|
||||
else
|
||||
return !!(data & CPLB_USER_WR);
|
||||
}
|
||||
|
||||
/* Counters to implement round-robin replacement. */
|
||||
static int icplb_rr_index[NR_CPUS] PDT_ATTR;
|
||||
static int dcplb_rr_index[NR_CPUS] PDT_ATTR;
|
||||
@ -245,43 +224,16 @@ MGR_ATTR static int dcplb_miss(int cpu)
|
||||
return CPLB_RELOADED;
|
||||
}
|
||||
|
||||
MGR_ATTR static noinline int dcplb_protection_fault(int cpu)
|
||||
{
|
||||
int status = bfin_read_DCPLB_STATUS();
|
||||
|
||||
nr_dcplb_prot[cpu]++;
|
||||
|
||||
if (likely(status & FAULT_RW)) {
|
||||
int idx = faulting_cplb_index(status);
|
||||
unsigned long regaddr = DCPLB_DATA0 + idx * 4;
|
||||
unsigned long data = bfin_read32(regaddr);
|
||||
|
||||
/* Check if fault is to dirty a clean page */
|
||||
if (!(data & CPLB_WT) && !(data & CPLB_DIRTY) &&
|
||||
write_permitted(status, data)) {
|
||||
|
||||
dcplb_tbl[cpu][idx].data = data;
|
||||
bfin_write32(regaddr, data);
|
||||
return CPLB_RELOADED;
|
||||
}
|
||||
}
|
||||
|
||||
return CPLB_PROT_VIOL;
|
||||
}
|
||||
|
||||
MGR_ATTR int cplb_hdr(int seqstat, struct pt_regs *regs)
|
||||
{
|
||||
int cause = seqstat & 0x3f;
|
||||
unsigned int cpu = smp_processor_id();
|
||||
switch (cause) {
|
||||
case 0x2C:
|
||||
case VEC_CPLB_I_M:
|
||||
return icplb_miss(cpu);
|
||||
case 0x26:
|
||||
case VEC_CPLB_M:
|
||||
return dcplb_miss(cpu);
|
||||
default:
|
||||
if (unlikely(cause == 0x23))
|
||||
return dcplb_protection_fault(cpu);
|
||||
|
||||
return CPLB_UNKNOWN_ERR;
|
||||
}
|
||||
}
|
||||
|
@ -202,11 +202,15 @@ asmlinkage void __init init_early_exception_vectors(void)
|
||||
asmlinkage void __init early_trap_c(struct pt_regs *fp, void *retaddr)
|
||||
{
|
||||
/* This can happen before the uart is initialized, so initialize
|
||||
* the UART now
|
||||
* the UART now (but only if we are running on the processor we think
|
||||
* we are compiled for - otherwise we write to MMRs that don't exist,
|
||||
* and cause other problems. Nothing comes out the UART, but it does
|
||||
* end up in the __buf_log.
|
||||
*/
|
||||
if (likely(early_console == NULL))
|
||||
if (likely(early_console == NULL) && CPUID == bfin_cpuid())
|
||||
setup_early_printk(DEFAULT_EARLY_PORT);
|
||||
|
||||
printk(KERN_EMERG "Early panic\n");
|
||||
dump_bfin_mem(fp);
|
||||
show_regs(fp);
|
||||
dump_bfin_trace_buffer();
|
||||
|
140
arch/blackfin/kernel/ftrace-entry.S
Normal file
140
arch/blackfin/kernel/ftrace-entry.S
Normal file
@ -0,0 +1,140 @@
|
||||
/*
|
||||
* mcount and friends -- ftrace stuff
|
||||
*
|
||||
* Copyright (C) 2009 Analog Devices Inc.
|
||||
* Licensed under the GPL-2 or later.
|
||||
*/
|
||||
|
||||
#include <linux/linkage.h>
|
||||
#include <asm/ftrace.h>
|
||||
|
||||
.text
|
||||
|
||||
/* GCC will have called us before setting up the function prologue, so we
|
||||
* can clobber the normal scratch registers, but we need to make sure to
|
||||
* save/restore the registers used for argument passing (R0-R2) in case
|
||||
* the profiled function is using them. With data registers, R3 is the
|
||||
* only one we can blow away. With pointer registers, we have P0-P2.
|
||||
*
|
||||
* Upon entry, the RETS will point to the top of the current profiled
|
||||
* function. And since GCC setup the frame for us, the previous function
|
||||
* will be waiting there. mmmm pie.
|
||||
*/
|
||||
ENTRY(__mcount)
|
||||
/* save third function arg early so we can do testing below */
|
||||
[--sp] = r2;
|
||||
|
||||
/* load the function pointer to the tracer */
|
||||
p0.l = _ftrace_trace_function;
|
||||
p0.h = _ftrace_trace_function;
|
||||
r3 = [p0];
|
||||
|
||||
/* optional micro optimization: don't call the stub tracer */
|
||||
r2.l = _ftrace_stub;
|
||||
r2.h = _ftrace_stub;
|
||||
cc = r2 == r3;
|
||||
if ! cc jump .Ldo_trace;
|
||||
|
||||
#ifdef CONFIG_FUNCTION_GRAPH_TRACER
|
||||
/* if the ftrace_graph_return function pointer is not set to
|
||||
* the ftrace_stub entry, call prepare_ftrace_return().
|
||||
*/
|
||||
p0.l = _ftrace_graph_return;
|
||||
p0.h = _ftrace_graph_return;
|
||||
r3 = [p0];
|
||||
cc = r2 == r3;
|
||||
if ! cc jump _ftrace_graph_caller;
|
||||
|
||||
/* similarly, if the ftrace_graph_entry function pointer is not
|
||||
* set to the ftrace_graph_entry_stub entry, ...
|
||||
*/
|
||||
p0.l = _ftrace_graph_entry;
|
||||
p0.h = _ftrace_graph_entry;
|
||||
r2.l = _ftrace_graph_entry_stub;
|
||||
r2.h = _ftrace_graph_entry_stub;
|
||||
r3 = [p0];
|
||||
cc = r2 == r3;
|
||||
if ! cc jump _ftrace_graph_caller;
|
||||
#endif
|
||||
|
||||
r2 = [sp++];
|
||||
rts;
|
||||
|
||||
.Ldo_trace:
|
||||
|
||||
/* save first/second function arg and the return register */
|
||||
[--sp] = r0;
|
||||
[--sp] = r1;
|
||||
[--sp] = rets;
|
||||
|
||||
/* setup the tracer function */
|
||||
p0 = r3;
|
||||
|
||||
/* tracer(ulong frompc, ulong selfpc):
|
||||
* frompc: the pc that did the call to ...
|
||||
* selfpc: ... this location
|
||||
* the selfpc itself will need adjusting for the mcount call
|
||||
*/
|
||||
r1 = rets;
|
||||
r0 = [fp + 4];
|
||||
r1 += -MCOUNT_INSN_SIZE;
|
||||
|
||||
/* call the tracer */
|
||||
call (p0);
|
||||
|
||||
/* restore state and get out of dodge */
|
||||
.Lfinish_trace:
|
||||
rets = [sp++];
|
||||
r1 = [sp++];
|
||||
r0 = [sp++];
|
||||
r2 = [sp++];
|
||||
|
||||
.globl _ftrace_stub
|
||||
_ftrace_stub:
|
||||
rts;
|
||||
ENDPROC(__mcount)
|
||||
|
||||
#ifdef CONFIG_FUNCTION_GRAPH_TRACER
|
||||
/* The prepare_ftrace_return() function is similar to the trace function
|
||||
* except it takes a pointer to the location of the frompc. This is so
|
||||
* the prepare_ftrace_return() can hijack it temporarily for probing
|
||||
* purposes.
|
||||
*/
|
||||
ENTRY(_ftrace_graph_caller)
|
||||
/* save first/second function arg and the return register */
|
||||
[--sp] = r0;
|
||||
[--sp] = r1;
|
||||
[--sp] = rets;
|
||||
|
||||
r0 = fp;
|
||||
r1 = rets;
|
||||
r0 += 4;
|
||||
r1 += -MCOUNT_INSN_SIZE;
|
||||
call _prepare_ftrace_return;
|
||||
|
||||
jump .Lfinish_trace;
|
||||
ENDPROC(_ftrace_graph_caller)
|
||||
|
||||
/* Undo the rewrite caused by ftrace_graph_caller(). The common function
|
||||
* ftrace_return_to_handler() will return the original rets so we can
|
||||
* restore it and be on our way.
|
||||
*/
|
||||
ENTRY(_return_to_handler)
|
||||
/* make sure original return values are saved */
|
||||
[--sp] = p0;
|
||||
[--sp] = r0;
|
||||
[--sp] = r1;
|
||||
|
||||
/* get original return address */
|
||||
call _ftrace_return_to_handler;
|
||||
rets = r0;
|
||||
|
||||
/* anomaly 05000371 - make sure we have at least three instructions
|
||||
* between rets setting and the return
|
||||
*/
|
||||
r1 = [sp++];
|
||||
r0 = [sp++];
|
||||
p0 = [sp++];
|
||||
rts;
|
||||
ENDPROC(_return_to_handler)
|
||||
#endif
|
42
arch/blackfin/kernel/ftrace.c
Normal file
42
arch/blackfin/kernel/ftrace.c
Normal file
@ -0,0 +1,42 @@
|
||||
/*
|
||||
* ftrace graph code
|
||||
*
|
||||
* Copyright (C) 2009 Analog Devices Inc.
|
||||
* Licensed under the GPL-2 or later.
|
||||
*/
|
||||
|
||||
#include <linux/ftrace.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/sched.h>
|
||||
#include <asm/atomic.h>
|
||||
|
||||
#ifdef CONFIG_FUNCTION_GRAPH_TRACER
|
||||
|
||||
/*
|
||||
* Hook the return address and push it in the stack of return addrs
|
||||
* in current thread info.
|
||||
*/
|
||||
void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr)
|
||||
{
|
||||
struct ftrace_graph_ent trace;
|
||||
unsigned long return_hooker = (unsigned long)&return_to_handler;
|
||||
|
||||
if (unlikely(atomic_read(¤t->tracing_graph_pause)))
|
||||
return;
|
||||
|
||||
if (ftrace_push_return_trace(*parent, self_addr, &trace.depth) == -EBUSY)
|
||||
return;
|
||||
|
||||
trace.func = self_addr;
|
||||
|
||||
/* Only trace if the calling function expects to */
|
||||
if (!ftrace_graph_entry(&trace)) {
|
||||
current->curr_ret_stack--;
|
||||
return;
|
||||
}
|
||||
|
||||
/* all is well in the world ! hijack RETS ... */
|
||||
*parent = return_hooker;
|
||||
}
|
||||
|
||||
#endif
|
@ -99,7 +99,7 @@ void __ipipe_handle_irq(unsigned irq, struct pt_regs *regs)
|
||||
* interrupt.
|
||||
*/
|
||||
m_ack = (regs == NULL || irq == IRQ_SYSTMR || irq == IRQ_CORETMR);
|
||||
this_domain = ipipe_current_domain;
|
||||
this_domain = __ipipe_current_domain;
|
||||
|
||||
if (unlikely(test_bit(IPIPE_STICKY_FLAG, &this_domain->irqs[irq].control)))
|
||||
head = &this_domain->p_link;
|
||||
@ -212,7 +212,9 @@ void __ipipe_unstall_root_raw(void)
|
||||
|
||||
int __ipipe_syscall_root(struct pt_regs *regs)
|
||||
{
|
||||
struct ipipe_percpu_domain_data *p;
|
||||
unsigned long flags;
|
||||
int ret;
|
||||
|
||||
/*
|
||||
* We need to run the IRQ tail hook whenever we don't
|
||||
@ -231,29 +233,31 @@ int __ipipe_syscall_root(struct pt_regs *regs)
|
||||
/*
|
||||
* This routine either returns:
|
||||
* 0 -- if the syscall is to be passed to Linux;
|
||||
* 1 -- if the syscall should not be passed to Linux, and no
|
||||
* >0 -- if the syscall should not be passed to Linux, and no
|
||||
* tail work should be performed;
|
||||
* -1 -- if the syscall should not be passed to Linux but the
|
||||
* <0 -- if the syscall should not be passed to Linux but the
|
||||
* tail work has to be performed (for handling signals etc).
|
||||
*/
|
||||
|
||||
if (__ipipe_event_monitored_p(IPIPE_EVENT_SYSCALL) &&
|
||||
__ipipe_dispatch_event(IPIPE_EVENT_SYSCALL, regs) > 0) {
|
||||
if (ipipe_root_domain_p && !in_atomic()) {
|
||||
/*
|
||||
* Sync pending VIRQs before _TIF_NEED_RESCHED
|
||||
* is tested.
|
||||
*/
|
||||
local_irq_save_hw(flags);
|
||||
if ((ipipe_root_cpudom_var(irqpend_himask) & IPIPE_IRQMASK_VIRT) != 0)
|
||||
__ipipe_sync_pipeline(IPIPE_IRQMASK_VIRT);
|
||||
local_irq_restore_hw(flags);
|
||||
return -1;
|
||||
}
|
||||
if (!__ipipe_event_monitored_p(IPIPE_EVENT_SYSCALL))
|
||||
return 0;
|
||||
|
||||
ret = __ipipe_dispatch_event(IPIPE_EVENT_SYSCALL, regs);
|
||||
|
||||
local_irq_save_hw(flags);
|
||||
|
||||
if (!__ipipe_root_domain_p) {
|
||||
local_irq_restore_hw(flags);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
p = ipipe_root_cpudom_ptr();
|
||||
if ((p->irqpend_himask & IPIPE_IRQMASK_VIRT) != 0)
|
||||
__ipipe_sync_pipeline(IPIPE_IRQMASK_VIRT);
|
||||
|
||||
local_irq_restore_hw(flags);
|
||||
|
||||
return -ret;
|
||||
}
|
||||
|
||||
unsigned long ipipe_critical_enter(void (*syncfn) (void))
|
||||
@ -329,9 +333,7 @@ asmlinkage void __ipipe_sync_root(void)
|
||||
|
||||
void ___ipipe_sync_pipeline(unsigned long syncmask)
|
||||
{
|
||||
struct ipipe_domain *ipd = ipipe_current_domain;
|
||||
|
||||
if (ipd == ipipe_root_domain) {
|
||||
if (__ipipe_root_domain_p) {
|
||||
if (test_bit(IPIPE_SYNCDEFER_FLAG, &ipipe_root_cpudom_var(status)))
|
||||
return;
|
||||
}
|
||||
|
@ -1098,7 +1098,7 @@ static int show_cpuinfo(struct seq_file *m, void *v)
|
||||
CPUID, bfin_cpuid());
|
||||
|
||||
seq_printf(m, "model name\t: ADSP-%s %lu(MHz CCLK) %lu(MHz SCLK) (%s)\n"
|
||||
"stepping\t: %d\n",
|
||||
"stepping\t: %d ",
|
||||
cpu, cclk/1000000, sclk/1000000,
|
||||
#ifdef CONFIG_MPU
|
||||
"mpu on",
|
||||
@ -1107,7 +1107,16 @@ static int show_cpuinfo(struct seq_file *m, void *v)
|
||||
#endif
|
||||
revid);
|
||||
|
||||
seq_printf(m, "cpu MHz\t\t: %lu.%03lu/%lu.%03lu\n",
|
||||
if (bfin_revid() != bfin_compiled_revid()) {
|
||||
if (bfin_compiled_revid() == -1)
|
||||
seq_printf(m, "(Compiled for Rev none)");
|
||||
else if (bfin_compiled_revid() == 0xffff)
|
||||
seq_printf(m, "(Compiled for Rev any)");
|
||||
else
|
||||
seq_printf(m, "(Compiled for Rev %d)", bfin_compiled_revid());
|
||||
}
|
||||
|
||||
seq_printf(m, "\ncpu MHz\t\t: %lu.%03lu/%lu.%03lu\n",
|
||||
cclk/1000000, cclk%1000000,
|
||||
sclk/1000000, sclk%1000000);
|
||||
seq_printf(m, "bogomips\t: %lu.%02lu\n"
|
||||
@ -1172,6 +1181,9 @@ static int show_cpuinfo(struct seq_file *m, void *v)
|
||||
#ifdef __ARCH_SYNC_CORE_DCACHE
|
||||
seq_printf(m, "SMP Dcache Flushes\t: %lu\n\n", cpudata->dcache_invld_count);
|
||||
#endif
|
||||
#ifdef __ARCH_SYNC_CORE_ICACHE
|
||||
seq_printf(m, "SMP Icache Flushes\t: %lu\n\n", cpudata->icache_invld_count);
|
||||
#endif
|
||||
#ifdef CONFIG_BFIN_ICACHE_LOCK
|
||||
switch ((cpudata->imemctl >> 3) & WAYALL_L) {
|
||||
case WAY0_L:
|
||||
|
53
arch/blackfin/kernel/stacktrace.c
Normal file
53
arch/blackfin/kernel/stacktrace.c
Normal file
@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Blackfin stacktrace code (mostly copied from avr32)
|
||||
*
|
||||
* Copyright 2009 Analog Devices Inc.
|
||||
* Licensed under the GPL-2 or later.
|
||||
*/
|
||||
|
||||
#include <linux/sched.h>
|
||||
#include <linux/stacktrace.h>
|
||||
#include <linux/thread_info.h>
|
||||
#include <linux/module.h>
|
||||
|
||||
register unsigned long current_frame_pointer asm("FP");
|
||||
|
||||
struct stackframe {
|
||||
unsigned long fp;
|
||||
unsigned long rets;
|
||||
};
|
||||
|
||||
/*
|
||||
* Save stack-backtrace addresses into a stack_trace buffer.
|
||||
*/
|
||||
void save_stack_trace(struct stack_trace *trace)
|
||||
{
|
||||
unsigned long low, high;
|
||||
unsigned long fp;
|
||||
struct stackframe *frame;
|
||||
int skip = trace->skip;
|
||||
|
||||
low = (unsigned long)task_stack_page(current);
|
||||
high = low + THREAD_SIZE;
|
||||
fp = current_frame_pointer;
|
||||
|
||||
while (fp >= low && fp <= (high - sizeof(*frame))) {
|
||||
frame = (struct stackframe *)fp;
|
||||
|
||||
if (skip) {
|
||||
skip--;
|
||||
} else {
|
||||
trace->entries[trace->nr_entries++] = frame->rets;
|
||||
if (trace->nr_entries >= trace->max_entries)
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* The next frame must be at a higher address than the
|
||||
* current frame.
|
||||
*/
|
||||
low = fp + sizeof(*frame);
|
||||
fp = frame->fp;
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(save_stack_trace);
|
@ -27,6 +27,7 @@
|
||||
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include <linux/bug.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/module.h>
|
||||
@ -238,6 +239,11 @@ asmlinkage void double_fault_c(struct pt_regs *fp)
|
||||
|
||||
}
|
||||
|
||||
static int kernel_mode_regs(struct pt_regs *regs)
|
||||
{
|
||||
return regs->ipend & 0xffc0;
|
||||
}
|
||||
|
||||
asmlinkage void trap_c(struct pt_regs *fp)
|
||||
{
|
||||
#ifdef CONFIG_DEBUG_BFIN_HWTRACE_ON
|
||||
@ -246,6 +252,7 @@ asmlinkage void trap_c(struct pt_regs *fp)
|
||||
#ifdef CONFIG_DEBUG_HUNT_FOR_ZERO
|
||||
unsigned int cpu = smp_processor_id();
|
||||
#endif
|
||||
const char *strerror = NULL;
|
||||
int sig = 0;
|
||||
siginfo_t info;
|
||||
unsigned long trapnr = fp->seqstat & SEQSTAT_EXCAUSE;
|
||||
@ -259,27 +266,10 @@ asmlinkage void trap_c(struct pt_regs *fp)
|
||||
* double faults if the stack has become corrupt
|
||||
*/
|
||||
|
||||
/* If the fault was caused by a kernel thread, or interrupt handler
|
||||
* we will kernel panic, so the system reboots.
|
||||
* If KGDB is enabled, don't set this for kernel breakpoints
|
||||
*/
|
||||
|
||||
/* TODO: check to see if we are in some sort of deferred HWERR
|
||||
* that we should be able to recover from, not kernel panic
|
||||
*/
|
||||
if ((bfin_read_IPEND() & 0xFFC0) && (trapnr != VEC_STEP)
|
||||
#ifdef CONFIG_KGDB
|
||||
&& (trapnr != VEC_EXCPT02)
|
||||
#ifndef CONFIG_KGDB
|
||||
/* IPEND is skipped if KGDB isn't enabled (see entry code) */
|
||||
fp->ipend = bfin_read_IPEND();
|
||||
#endif
|
||||
){
|
||||
console_verbose();
|
||||
oops_in_progress = 1;
|
||||
} else if (current) {
|
||||
if (current->mm == NULL) {
|
||||
console_verbose();
|
||||
oops_in_progress = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* trap_c() will be called for exceptions. During exceptions
|
||||
* processing, the pc value should be set with retx value.
|
||||
@ -307,15 +297,15 @@ asmlinkage void trap_c(struct pt_regs *fp)
|
||||
sig = SIGTRAP;
|
||||
CHK_DEBUGGER_TRAP_MAYBE();
|
||||
/* Check if this is a breakpoint in kernel space */
|
||||
if (fp->ipend & 0xffc0)
|
||||
return;
|
||||
if (kernel_mode_regs(fp))
|
||||
goto traps_done;
|
||||
else
|
||||
break;
|
||||
/* 0x03 - User Defined, userspace stack overflow */
|
||||
case VEC_EXCPT03:
|
||||
info.si_code = SEGV_STACKFLOW;
|
||||
sig = SIGSEGV;
|
||||
verbose_printk(KERN_NOTICE EXC_0x03(KERN_NOTICE));
|
||||
strerror = KERN_NOTICE EXC_0x03(KERN_NOTICE);
|
||||
CHK_DEBUGGER_TRAP_MAYBE();
|
||||
break;
|
||||
/* 0x02 - KGDB initial connection and break signal trap */
|
||||
@ -324,7 +314,7 @@ asmlinkage void trap_c(struct pt_regs *fp)
|
||||
info.si_code = TRAP_ILLTRAP;
|
||||
sig = SIGTRAP;
|
||||
CHK_DEBUGGER_TRAP();
|
||||
return;
|
||||
goto traps_done;
|
||||
#endif
|
||||
/* 0x04 - User Defined */
|
||||
/* 0x05 - User Defined */
|
||||
@ -344,7 +334,7 @@ asmlinkage void trap_c(struct pt_regs *fp)
|
||||
case VEC_EXCPT04 ... VEC_EXCPT15:
|
||||
info.si_code = ILL_ILLPARAOP;
|
||||
sig = SIGILL;
|
||||
verbose_printk(KERN_NOTICE EXC_0x04(KERN_NOTICE));
|
||||
strerror = KERN_NOTICE EXC_0x04(KERN_NOTICE);
|
||||
CHK_DEBUGGER_TRAP_MAYBE();
|
||||
break;
|
||||
/* 0x10 HW Single step, handled here */
|
||||
@ -353,15 +343,15 @@ asmlinkage void trap_c(struct pt_regs *fp)
|
||||
sig = SIGTRAP;
|
||||
CHK_DEBUGGER_TRAP_MAYBE();
|
||||
/* Check if this is a single step in kernel space */
|
||||
if (fp->ipend & 0xffc0)
|
||||
return;
|
||||
if (kernel_mode_regs(fp))
|
||||
goto traps_done;
|
||||
else
|
||||
break;
|
||||
/* 0x11 - Trace Buffer Full, handled here */
|
||||
case VEC_OVFLOW:
|
||||
info.si_code = TRAP_TRACEFLOW;
|
||||
sig = SIGTRAP;
|
||||
verbose_printk(KERN_NOTICE EXC_0x11(KERN_NOTICE));
|
||||
strerror = KERN_NOTICE EXC_0x11(KERN_NOTICE);
|
||||
CHK_DEBUGGER_TRAP_MAYBE();
|
||||
break;
|
||||
/* 0x12 - Reserved, Caught by default */
|
||||
@ -381,37 +371,54 @@ asmlinkage void trap_c(struct pt_regs *fp)
|
||||
/* 0x20 - Reserved, Caught by default */
|
||||
/* 0x21 - Undefined Instruction, handled here */
|
||||
case VEC_UNDEF_I:
|
||||
#ifdef CONFIG_BUG
|
||||
if (kernel_mode_regs(fp)) {
|
||||
switch (report_bug(fp->pc, fp)) {
|
||||
case BUG_TRAP_TYPE_NONE:
|
||||
break;
|
||||
case BUG_TRAP_TYPE_WARN:
|
||||
dump_bfin_trace_buffer();
|
||||
fp->pc += 2;
|
||||
goto traps_done;
|
||||
case BUG_TRAP_TYPE_BUG:
|
||||
/* call to panic() will dump trace, and it is
|
||||
* off at this point, so it won't be clobbered
|
||||
*/
|
||||
panic("BUG()");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
info.si_code = ILL_ILLOPC;
|
||||
sig = SIGILL;
|
||||
verbose_printk(KERN_NOTICE EXC_0x21(KERN_NOTICE));
|
||||
strerror = KERN_NOTICE EXC_0x21(KERN_NOTICE);
|
||||
CHK_DEBUGGER_TRAP_MAYBE();
|
||||
break;
|
||||
/* 0x22 - Illegal Instruction Combination, handled here */
|
||||
case VEC_ILGAL_I:
|
||||
info.si_code = ILL_ILLPARAOP;
|
||||
sig = SIGILL;
|
||||
verbose_printk(KERN_NOTICE EXC_0x22(KERN_NOTICE));
|
||||
strerror = KERN_NOTICE EXC_0x22(KERN_NOTICE);
|
||||
CHK_DEBUGGER_TRAP_MAYBE();
|
||||
break;
|
||||
/* 0x23 - Data CPLB protection violation, handled here */
|
||||
case VEC_CPLB_VL:
|
||||
info.si_code = ILL_CPLB_VI;
|
||||
sig = SIGBUS;
|
||||
verbose_printk(KERN_NOTICE EXC_0x23(KERN_NOTICE));
|
||||
strerror = KERN_NOTICE EXC_0x23(KERN_NOTICE);
|
||||
CHK_DEBUGGER_TRAP_MAYBE();
|
||||
break;
|
||||
/* 0x24 - Data access misaligned, handled here */
|
||||
case VEC_MISALI_D:
|
||||
info.si_code = BUS_ADRALN;
|
||||
sig = SIGBUS;
|
||||
verbose_printk(KERN_NOTICE EXC_0x24(KERN_NOTICE));
|
||||
strerror = KERN_NOTICE EXC_0x24(KERN_NOTICE);
|
||||
CHK_DEBUGGER_TRAP_MAYBE();
|
||||
break;
|
||||
/* 0x25 - Unrecoverable Event, handled here */
|
||||
case VEC_UNCOV:
|
||||
info.si_code = ILL_ILLEXCPT;
|
||||
sig = SIGILL;
|
||||
verbose_printk(KERN_NOTICE EXC_0x25(KERN_NOTICE));
|
||||
strerror = KERN_NOTICE EXC_0x25(KERN_NOTICE);
|
||||
CHK_DEBUGGER_TRAP_MAYBE();
|
||||
break;
|
||||
/* 0x26 - Data CPLB Miss, normal case is handled in _cplb_hdr,
|
||||
@ -419,7 +426,7 @@ asmlinkage void trap_c(struct pt_regs *fp)
|
||||
case VEC_CPLB_M:
|
||||
info.si_code = BUS_ADRALN;
|
||||
sig = SIGBUS;
|
||||
verbose_printk(KERN_NOTICE EXC_0x26(KERN_NOTICE));
|
||||
strerror = KERN_NOTICE EXC_0x26(KERN_NOTICE);
|
||||
break;
|
||||
/* 0x27 - Data CPLB Multiple Hits - Linux Trap Zero, handled here */
|
||||
case VEC_CPLB_MHIT:
|
||||
@ -427,10 +434,10 @@ asmlinkage void trap_c(struct pt_regs *fp)
|
||||
sig = SIGSEGV;
|
||||
#ifdef CONFIG_DEBUG_HUNT_FOR_ZERO
|
||||
if (cpu_pda[cpu].dcplb_fault_addr < FIXED_CODE_START)
|
||||
verbose_printk(KERN_NOTICE "NULL pointer access\n");
|
||||
strerror = KERN_NOTICE "NULL pointer access\n";
|
||||
else
|
||||
#endif
|
||||
verbose_printk(KERN_NOTICE EXC_0x27(KERN_NOTICE));
|
||||
strerror = KERN_NOTICE EXC_0x27(KERN_NOTICE);
|
||||
CHK_DEBUGGER_TRAP_MAYBE();
|
||||
break;
|
||||
/* 0x28 - Emulation Watchpoint, handled here */
|
||||
@ -440,8 +447,8 @@ asmlinkage void trap_c(struct pt_regs *fp)
|
||||
pr_debug(EXC_0x28(KERN_DEBUG));
|
||||
CHK_DEBUGGER_TRAP_MAYBE();
|
||||
/* Check if this is a watchpoint in kernel space */
|
||||
if (fp->ipend & 0xffc0)
|
||||
return;
|
||||
if (kernel_mode_regs(fp))
|
||||
goto traps_done;
|
||||
else
|
||||
break;
|
||||
#ifdef CONFIG_BF535
|
||||
@ -449,7 +456,7 @@ asmlinkage void trap_c(struct pt_regs *fp)
|
||||
case VEC_ISTRU_VL: /* ADSP-BF535 only (MH) */
|
||||
info.si_code = BUS_OPFETCH;
|
||||
sig = SIGBUS;
|
||||
verbose_printk(KERN_NOTICE "BF535: VEC_ISTRU_VL\n");
|
||||
strerror = KERN_NOTICE "BF535: VEC_ISTRU_VL\n";
|
||||
CHK_DEBUGGER_TRAP_MAYBE();
|
||||
break;
|
||||
#else
|
||||
@ -459,21 +466,21 @@ asmlinkage void trap_c(struct pt_regs *fp)
|
||||
case VEC_MISALI_I:
|
||||
info.si_code = BUS_ADRALN;
|
||||
sig = SIGBUS;
|
||||
verbose_printk(KERN_NOTICE EXC_0x2A(KERN_NOTICE));
|
||||
strerror = KERN_NOTICE EXC_0x2A(KERN_NOTICE);
|
||||
CHK_DEBUGGER_TRAP_MAYBE();
|
||||
break;
|
||||
/* 0x2B - Instruction CPLB protection violation, handled here */
|
||||
case VEC_CPLB_I_VL:
|
||||
info.si_code = ILL_CPLB_VI;
|
||||
sig = SIGBUS;
|
||||
verbose_printk(KERN_NOTICE EXC_0x2B(KERN_NOTICE));
|
||||
strerror = KERN_NOTICE EXC_0x2B(KERN_NOTICE);
|
||||
CHK_DEBUGGER_TRAP_MAYBE();
|
||||
break;
|
||||
/* 0x2C - Instruction CPLB miss, handled in _cplb_hdr */
|
||||
case VEC_CPLB_I_M:
|
||||
info.si_code = ILL_CPLB_MISS;
|
||||
sig = SIGBUS;
|
||||
verbose_printk(KERN_NOTICE EXC_0x2C(KERN_NOTICE));
|
||||
strerror = KERN_NOTICE EXC_0x2C(KERN_NOTICE);
|
||||
break;
|
||||
/* 0x2D - Instruction CPLB Multiple Hits, handled here */
|
||||
case VEC_CPLB_I_MHIT:
|
||||
@ -481,17 +488,17 @@ asmlinkage void trap_c(struct pt_regs *fp)
|
||||
sig = SIGSEGV;
|
||||
#ifdef CONFIG_DEBUG_HUNT_FOR_ZERO
|
||||
if (cpu_pda[cpu].icplb_fault_addr < FIXED_CODE_START)
|
||||
verbose_printk(KERN_NOTICE "Jump to NULL address\n");
|
||||
strerror = KERN_NOTICE "Jump to NULL address\n";
|
||||
else
|
||||
#endif
|
||||
verbose_printk(KERN_NOTICE EXC_0x2D(KERN_NOTICE));
|
||||
strerror = KERN_NOTICE EXC_0x2D(KERN_NOTICE);
|
||||
CHK_DEBUGGER_TRAP_MAYBE();
|
||||
break;
|
||||
/* 0x2E - Illegal use of Supervisor Resource, handled here */
|
||||
case VEC_ILL_RES:
|
||||
info.si_code = ILL_PRVOPC;
|
||||
sig = SIGILL;
|
||||
verbose_printk(KERN_NOTICE EXC_0x2E(KERN_NOTICE));
|
||||
strerror = KERN_NOTICE EXC_0x2E(KERN_NOTICE);
|
||||
CHK_DEBUGGER_TRAP_MAYBE();
|
||||
break;
|
||||
/* 0x2F - Reserved, Caught by default */
|
||||
@ -519,17 +526,17 @@ asmlinkage void trap_c(struct pt_regs *fp)
|
||||
case (SEQSTAT_HWERRCAUSE_SYSTEM_MMR):
|
||||
info.si_code = BUS_ADRALN;
|
||||
sig = SIGBUS;
|
||||
verbose_printk(KERN_NOTICE HWC_x2(KERN_NOTICE));
|
||||
strerror = KERN_NOTICE HWC_x2(KERN_NOTICE);
|
||||
break;
|
||||
/* External Memory Addressing Error */
|
||||
case (SEQSTAT_HWERRCAUSE_EXTERN_ADDR):
|
||||
info.si_code = BUS_ADRERR;
|
||||
sig = SIGBUS;
|
||||
verbose_printk(KERN_NOTICE HWC_x3(KERN_NOTICE));
|
||||
strerror = KERN_NOTICE HWC_x3(KERN_NOTICE);
|
||||
break;
|
||||
/* Performance Monitor Overflow */
|
||||
case (SEQSTAT_HWERRCAUSE_PERF_FLOW):
|
||||
verbose_printk(KERN_NOTICE HWC_x12(KERN_NOTICE));
|
||||
strerror = KERN_NOTICE HWC_x12(KERN_NOTICE);
|
||||
break;
|
||||
/* RAISE 5 instruction */
|
||||
case (SEQSTAT_HWERRCAUSE_RAISE_5):
|
||||
@ -546,7 +553,6 @@ asmlinkage void trap_c(struct pt_regs *fp)
|
||||
* if we get here we hit a reserved one, so panic
|
||||
*/
|
||||
default:
|
||||
oops_in_progress = 1;
|
||||
info.si_code = ILL_ILLPARAOP;
|
||||
sig = SIGILL;
|
||||
verbose_printk(KERN_EMERG "Caught Unhandled Exception, code = %08lx\n",
|
||||
@ -557,6 +563,16 @@ asmlinkage void trap_c(struct pt_regs *fp)
|
||||
|
||||
BUG_ON(sig == 0);
|
||||
|
||||
/* If the fault was caused by a kernel thread, or interrupt handler
|
||||
* we will kernel panic, so the system reboots.
|
||||
*/
|
||||
if (kernel_mode_regs(fp) || (current && !current->mm)) {
|
||||
console_verbose();
|
||||
oops_in_progress = 1;
|
||||
if (strerror)
|
||||
verbose_printk(strerror);
|
||||
}
|
||||
|
||||
if (sig != SIGTRAP) {
|
||||
dump_bfin_process(fp);
|
||||
dump_bfin_mem(fp);
|
||||
@ -606,8 +622,8 @@ asmlinkage void trap_c(struct pt_regs *fp)
|
||||
if (ANOMALY_05000461 && trapnr == VEC_HWERR && !access_ok(VERIFY_READ, fp->pc, 8))
|
||||
fp->pc = SAFE_USER_INSTRUCTION;
|
||||
|
||||
traps_done:
|
||||
trace_buffer_restore(j);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Typical exception handling routines */
|
||||
@ -792,6 +808,18 @@ void dump_bfin_trace_buffer(void)
|
||||
}
|
||||
EXPORT_SYMBOL(dump_bfin_trace_buffer);
|
||||
|
||||
#ifdef CONFIG_BUG
|
||||
int is_valid_bugaddr(unsigned long addr)
|
||||
{
|
||||
unsigned short opcode;
|
||||
|
||||
if (!get_instruction(&opcode, (unsigned short *)addr))
|
||||
return 0;
|
||||
|
||||
return opcode == BFIN_BUG_OPCODE;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Checks to see if the address pointed to is either a
|
||||
* 16-bit CALL instruction, or a 32-bit CALL instruction
|
||||
|
@ -54,6 +54,7 @@ SECTIONS
|
||||
SCHED_TEXT
|
||||
#endif
|
||||
LOCK_TEXT
|
||||
IRQENTRY_TEXT
|
||||
KPROBES_TEXT
|
||||
*(.text.*)
|
||||
*(.fixup)
|
||||
@ -166,6 +167,20 @@ SECTIONS
|
||||
}
|
||||
PERCPU(4)
|
||||
SECURITY_INIT
|
||||
|
||||
/* we have to discard exit text and such at runtime, not link time, to
|
||||
* handle embedded cross-section references (alt instructions, bug
|
||||
* table, eh_frame, etc...)
|
||||
*/
|
||||
.exit.text :
|
||||
{
|
||||
EXIT_TEXT
|
||||
}
|
||||
.exit.data :
|
||||
{
|
||||
EXIT_DATA
|
||||
}
|
||||
|
||||
.init.ramfs :
|
||||
{
|
||||
. = ALIGN(4);
|
||||
@ -264,8 +279,6 @@ SECTIONS
|
||||
|
||||
/DISCARD/ :
|
||||
{
|
||||
EXIT_TEXT
|
||||
EXIT_DATA
|
||||
*(.exitcall.exit)
|
||||
}
|
||||
}
|
||||
|
@ -116,6 +116,7 @@ __sum16 ip_compute_csum(const void *buff, int len)
|
||||
{
|
||||
return (__force __sum16)~do_csum(buff, len);
|
||||
}
|
||||
EXPORT_SYMBOL(ip_compute_csum);
|
||||
|
||||
/*
|
||||
* copy from fs while checksumming, otherwise like csum_partial
|
||||
@ -130,6 +131,7 @@ csum_partial_copy_from_user(const void __user *src, void *dst,
|
||||
memcpy(dst, (__force void *)src, len);
|
||||
return csum_partial(dst, len, sum);
|
||||
}
|
||||
EXPORT_SYMBOL(csum_partial_copy_from_user);
|
||||
|
||||
/*
|
||||
* copy from ds while checksumming, otherwise like csum_partial
|
||||
|
@ -246,7 +246,7 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
|
||||
.modalias = "m25p80", /* Name of spi_driver for this device */
|
||||
.max_speed_hz = 25000000, /* max spi clock (SCK) speed in HZ */
|
||||
.bus_num = 0, /* Framework bus number */
|
||||
.chip_select = 1, /* Framework chip select. On STAMP537 it is SPISSEL1*/
|
||||
.chip_select = 2, /* On BF518F-EZBRD it's SPI0_SSEL2 */
|
||||
.platform_data = &bfin_spi_flash_data,
|
||||
.controller_data = &spi_flash_chip_info,
|
||||
.mode = SPI_MODE_3,
|
||||
@ -369,6 +369,11 @@ static struct resource bfin_spi0_resource[] = {
|
||||
[1] = {
|
||||
.start = CH_SPI0,
|
||||
.end = CH_SPI0,
|
||||
.flags = IORESOURCE_DMA,
|
||||
},
|
||||
[2] = {
|
||||
.start = IRQ_SPI0,
|
||||
.end = IRQ_SPI0,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
};
|
||||
@ -399,6 +404,11 @@ static struct resource bfin_spi1_resource[] = {
|
||||
[1] = {
|
||||
.start = CH_SPI1,
|
||||
.end = CH_SPI1,
|
||||
.flags = IORESOURCE_DMA,
|
||||
},
|
||||
[2] = {
|
||||
.start = IRQ_SPI1,
|
||||
.end = IRQ_SPI1,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
};
|
||||
|
@ -664,6 +664,11 @@ static struct resource bfin_spi0_resource[] = {
|
||||
[1] = {
|
||||
.start = CH_SPI,
|
||||
.end = CH_SPI,
|
||||
.flags = IORESOURCE_DMA,
|
||||
},
|
||||
[2] = {
|
||||
.start = IRQ_SPI,
|
||||
.end = IRQ_SPI,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
};
|
||||
|
@ -467,6 +467,11 @@ static struct resource bfin_spi0_resource[] = {
|
||||
[1] = {
|
||||
.start = CH_SPI,
|
||||
.end = CH_SPI,
|
||||
.flags = IORESOURCE_DMA,
|
||||
},
|
||||
[2] = {
|
||||
.start = IRQ_SPI,
|
||||
.end = IRQ_SPI,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
};
|
||||
|
@ -723,6 +723,11 @@ static struct resource bfin_spi0_resource[] = {
|
||||
[1] = {
|
||||
.start = CH_SPI,
|
||||
.end = CH_SPI,
|
||||
.flags = IORESOURCE_DMA,
|
||||
},
|
||||
[2] = {
|
||||
.start = IRQ_SPI,
|
||||
.end = IRQ_SPI,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
};
|
||||
|
@ -266,6 +266,11 @@ static struct resource bfin_spi0_resource[] = {
|
||||
[1] = {
|
||||
.start = CH_SPI,
|
||||
.end = CH_SPI,
|
||||
.flags = IORESOURCE_DMA,
|
||||
},
|
||||
[2] = {
|
||||
.start = IRQ_SPI,
|
||||
.end = IRQ_SPI,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
}
|
||||
};
|
||||
|
@ -162,6 +162,11 @@ static struct resource bfin_spi0_resource[] = {
|
||||
[1] = {
|
||||
.start = CH_SPI,
|
||||
.end = CH_SPI,
|
||||
.flags = IORESOURCE_DMA,
|
||||
},
|
||||
[2] = {
|
||||
.start = IRQ_SPI,
|
||||
.end = IRQ_SPI,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
}
|
||||
};
|
||||
|
@ -160,6 +160,11 @@ static struct resource bfin_spi0_resource[] = {
|
||||
[1] = {
|
||||
.start = CH_SPI,
|
||||
.end = CH_SPI,
|
||||
.flags = IORESOURCE_DMA,
|
||||
},
|
||||
[2] = {
|
||||
.start = IRQ_SPI,
|
||||
.end = IRQ_SPI,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
}
|
||||
};
|
||||
|
@ -196,6 +196,11 @@ static struct resource bfin_spi0_resource[] = {
|
||||
[1] = {
|
||||
.start = CH_SPI,
|
||||
.end = CH_SPI,
|
||||
.flags = IORESOURCE_DMA,
|
||||
},
|
||||
[2] = {
|
||||
.start = IRQ_SPI,
|
||||
.end = IRQ_SPI,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
}
|
||||
};
|
||||
|
@ -299,6 +299,11 @@ static struct resource bfin_spi0_resource[] = {
|
||||
[1] = {
|
||||
.start = CH_SPI,
|
||||
.end = CH_SPI,
|
||||
.flags = IORESOURCE_DMA,
|
||||
},
|
||||
[2] = {
|
||||
.start = IRQ_SPI,
|
||||
.end = IRQ_SPI,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
}
|
||||
};
|
||||
|
@ -182,8 +182,13 @@ static struct resource bfin_spi0_resource[] = {
|
||||
[1] = {
|
||||
.start = CH_SPI,
|
||||
.end = CH_SPI,
|
||||
.flags = IORESOURCE_DMA,
|
||||
},
|
||||
[2] = {
|
||||
.start = IRQ_SPI,
|
||||
.end = IRQ_SPI,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
/* SPI controller data */
|
||||
|
@ -184,6 +184,11 @@ static struct resource bfin_spi0_resource[] = {
|
||||
[1] = {
|
||||
.start = CH_SPI,
|
||||
.end = CH_SPI,
|
||||
.flags = IORESOURCE_DMA,
|
||||
},
|
||||
[2] = {
|
||||
.start = IRQ_SPI,
|
||||
.end = IRQ_SPI,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
};
|
||||
|
@ -398,8 +398,13 @@ static struct resource bfin_spi0_resource[] = {
|
||||
[1] = {
|
||||
.start = CH_SPI,
|
||||
.end = CH_SPI,
|
||||
.flags = IORESOURCE_DMA,
|
||||
},
|
||||
[2] = {
|
||||
.start = IRQ_SPI,
|
||||
.end = IRQ_SPI,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
/* SPI controller data */
|
||||
|
@ -1345,7 +1345,7 @@ static struct i2c_board_info __initdata bfin_i2c_board_info[] = {
|
||||
#if defined(CONFIG_PMIC_ADP5520) || defined(CONFIG_PMIC_ADP5520_MODULE)
|
||||
{
|
||||
I2C_BOARD_INFO("pmic-adp5520", 0x32),
|
||||
.irq = IRQ_PF7,
|
||||
.irq = IRQ_PG0,
|
||||
.platform_data = (void *)&adp5520_pdev_data,
|
||||
},
|
||||
#endif
|
||||
|
@ -182,6 +182,11 @@ static struct resource bfin_spi0_resource[] = {
|
||||
[1] = {
|
||||
.start = CH_SPI,
|
||||
.end = CH_SPI,
|
||||
.flags = IORESOURCE_DMA,
|
||||
},
|
||||
[2] = {
|
||||
.start = IRQ_SPI,
|
||||
.end = IRQ_SPI,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
}
|
||||
};
|
||||
|
@ -352,6 +352,11 @@ static struct resource bfin_spi0_resource[] = {
|
||||
[1] = {
|
||||
.start = CH_SPI0,
|
||||
.end = CH_SPI0,
|
||||
.flags = IORESOURCE_DMA,
|
||||
},
|
||||
[2] = {
|
||||
.start = IRQ_SPI0,
|
||||
.end = IRQ_SPI0,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
}
|
||||
};
|
||||
@ -366,6 +371,11 @@ static struct resource bfin_spi1_resource[] = {
|
||||
[1] = {
|
||||
.start = CH_SPI1,
|
||||
.end = CH_SPI1,
|
||||
.flags = IORESOURCE_DMA,
|
||||
},
|
||||
[2] = {
|
||||
.start = IRQ_SPI1,
|
||||
.end = IRQ_SPI1,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
}
|
||||
};
|
||||
|
@ -612,6 +612,11 @@ static struct resource bfin_spi0_resource[] = {
|
||||
[1] = {
|
||||
.start = CH_SPI0,
|
||||
.end = CH_SPI0,
|
||||
.flags = IORESOURCE_DMA,
|
||||
},
|
||||
[2] = {
|
||||
.start = IRQ_SPI0,
|
||||
.end = IRQ_SPI0,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
}
|
||||
};
|
||||
@ -626,6 +631,11 @@ static struct resource bfin_spi1_resource[] = {
|
||||
[1] = {
|
||||
.start = CH_SPI1,
|
||||
.end = CH_SPI1,
|
||||
.flags = IORESOURCE_DMA,
|
||||
},
|
||||
[2] = {
|
||||
.start = IRQ_SPI1,
|
||||
.end = IRQ_SPI1,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
}
|
||||
};
|
||||
|
@ -396,6 +396,8 @@ static struct platform_device bfin_sir3_device = {
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_SMSC911X) || defined(CONFIG_SMSC911X_MODULE)
|
||||
#include <linux/smsc911x.h>
|
||||
|
||||
static struct resource smsc911x_resources[] = {
|
||||
{
|
||||
.name = "smsc911x-memory",
|
||||
@ -409,11 +411,22 @@ static struct resource smsc911x_resources[] = {
|
||||
.flags = IORESOURCE_IRQ | IORESOURCE_IRQ_LOWLEVEL,
|
||||
},
|
||||
};
|
||||
|
||||
static struct smsc911x_platform_config smsc911x_config = {
|
||||
.flags = SMSC911X_USE_32BIT,
|
||||
.irq_polarity = SMSC911X_IRQ_POLARITY_ACTIVE_LOW,
|
||||
.irq_type = SMSC911X_IRQ_TYPE_OPEN_DRAIN,
|
||||
.phy_interface = PHY_INTERFACE_MODE_MII,
|
||||
};
|
||||
|
||||
static struct platform_device smsc911x_device = {
|
||||
.name = "smsc911x",
|
||||
.id = 0,
|
||||
.num_resources = ARRAY_SIZE(smsc911x_resources),
|
||||
.resource = smsc911x_resources,
|
||||
.dev = {
|
||||
.platform_data = &smsc911x_config,
|
||||
},
|
||||
};
|
||||
#endif
|
||||
|
||||
@ -741,6 +754,11 @@ static struct resource bfin_spi0_resource[] = {
|
||||
[1] = {
|
||||
.start = CH_SPI0,
|
||||
.end = CH_SPI0,
|
||||
.flags = IORESOURCE_DMA,
|
||||
},
|
||||
[2] = {
|
||||
.start = IRQ_SPI0,
|
||||
.end = IRQ_SPI0,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
}
|
||||
};
|
||||
@ -755,6 +773,11 @@ static struct resource bfin_spi1_resource[] = {
|
||||
[1] = {
|
||||
.start = CH_SPI1,
|
||||
.end = CH_SPI1,
|
||||
.flags = IORESOURCE_DMA,
|
||||
},
|
||||
[2] = {
|
||||
.start = IRQ_SPI1,
|
||||
.end = IRQ_SPI1,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
}
|
||||
};
|
||||
|
@ -177,8 +177,13 @@ static struct resource bfin_spi0_resource[] = {
|
||||
[1] = {
|
||||
.start = CH_SPI,
|
||||
.end = CH_SPI,
|
||||
.flags = IORESOURCE_DMA,
|
||||
},
|
||||
[2] = {
|
||||
.start = IRQ_SPI,
|
||||
.end = IRQ_SPI,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
/* SPI controller data */
|
||||
|
@ -304,6 +304,11 @@ static struct resource bfin_spi0_resource[] = {
|
||||
[1] = {
|
||||
.start = CH_SPI,
|
||||
.end = CH_SPI,
|
||||
.flags = IORESOURCE_DMA,
|
||||
},
|
||||
[2] = {
|
||||
.start = IRQ_SPI,
|
||||
.end = IRQ_SPI,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
}
|
||||
};
|
||||
|
@ -16,9 +16,21 @@
|
||||
void blackfin_invalidate_entire_dcache(void)
|
||||
{
|
||||
u32 dmem = bfin_read_DMEM_CONTROL();
|
||||
SSYNC();
|
||||
bfin_write_DMEM_CONTROL(dmem & ~0xc);
|
||||
SSYNC();
|
||||
bfin_write_DMEM_CONTROL(dmem);
|
||||
SSYNC();
|
||||
}
|
||||
|
||||
/* Invalidate the Entire Instruction cache by
|
||||
* clearing IMC bit
|
||||
*/
|
||||
void blackfin_invalidate_entire_icache(void)
|
||||
{
|
||||
u32 imem = bfin_read_IMEM_CONTROL();
|
||||
bfin_write_IMEM_CONTROL(imem & ~0x4);
|
||||
SSYNC();
|
||||
bfin_write_IMEM_CONTROL(imem);
|
||||
SSYNC();
|
||||
}
|
||||
|
||||
|
@ -42,6 +42,7 @@
|
||||
#include <asm/thread_info.h> /* TIF_NEED_RESCHED */
|
||||
#include <asm/asm-offsets.h>
|
||||
#include <asm/trace.h>
|
||||
#include <asm/traps.h>
|
||||
|
||||
#include <asm/context.S>
|
||||
|
||||
@ -84,13 +85,15 @@ ENTRY(_ex_workaround_261)
|
||||
if !cc jump _bfin_return_from_exception;
|
||||
/* fall through */
|
||||
R7 = P4;
|
||||
R6 = 0x26; /* Data CPLB Miss */
|
||||
R6 = VEC_CPLB_M; /* Data CPLB Miss */
|
||||
cc = R6 == R7;
|
||||
if cc jump _ex_dcplb_miss (BP);
|
||||
R6 = 0x23; /* Data CPLB Miss */
|
||||
#ifdef CONFIG_MPU
|
||||
R6 = VEC_CPLB_VL; /* Data CPLB Violation */
|
||||
cc = R6 == R7;
|
||||
if cc jump _ex_dcplb_viol (BP);
|
||||
/* Handle 0x23 Data CPLB Protection Violation
|
||||
#endif
|
||||
/* Handle Data CPLB Protection Violation
|
||||
* and Data CPLB Multiple Hits - Linux Trap Zero
|
||||
*/
|
||||
jump _ex_trap_c;
|
||||
@ -270,7 +273,7 @@ ENTRY(_bfin_return_from_exception)
|
||||
r6.l = lo(SEQSTAT_EXCAUSE);
|
||||
r6.h = hi(SEQSTAT_EXCAUSE);
|
||||
r7 = r7 & r6;
|
||||
r6 = 0x25;
|
||||
r6 = VEC_UNCOV;
|
||||
CC = R7 == R6;
|
||||
if CC JUMP _double_fault;
|
||||
#endif
|
||||
@ -1605,6 +1608,7 @@ ENTRY(_sys_call_table)
|
||||
.long _sys_inotify_init1 /* 365 */
|
||||
.long _sys_preadv
|
||||
.long _sys_pwritev
|
||||
.long _sys_rt_tgsigqueueinfo
|
||||
|
||||
.rept NR_syscalls-(.-_sys_call_table)/4
|
||||
.long _sys_ni_syscall
|
||||
|
@ -144,7 +144,7 @@ static void ipi_call_function(unsigned int cpu, struct ipi_message *msg)
|
||||
|
||||
static irqreturn_t ipi_handler(int irq, void *dev_instance)
|
||||
{
|
||||
struct ipi_message *msg, *mg;
|
||||
struct ipi_message *msg;
|
||||
struct ipi_message_queue *msg_queue;
|
||||
unsigned int cpu = smp_processor_id();
|
||||
|
||||
@ -154,7 +154,8 @@ static irqreturn_t ipi_handler(int irq, void *dev_instance)
|
||||
msg_queue->count++;
|
||||
|
||||
spin_lock(&msg_queue->lock);
|
||||
list_for_each_entry_safe(msg, mg, &msg_queue->head, list) {
|
||||
while (!list_empty(&msg_queue->head)) {
|
||||
msg = list_entry(msg_queue->head.next, typeof(*msg), list);
|
||||
list_del(&msg->list);
|
||||
switch (msg->type) {
|
||||
case BFIN_IPI_RESCHEDULE:
|
||||
@ -221,7 +222,7 @@ int smp_call_function(void (*func)(void *info), void *info, int wait)
|
||||
for_each_cpu_mask(cpu, callmap) {
|
||||
msg_queue = &per_cpu(ipi_msg_queue, cpu);
|
||||
spin_lock_irqsave(&msg_queue->lock, flags);
|
||||
list_add(&msg->list, &msg_queue->head);
|
||||
list_add_tail(&msg->list, &msg_queue->head);
|
||||
spin_unlock_irqrestore(&msg_queue->lock, flags);
|
||||
platform_send_ipi_cpu(cpu);
|
||||
}
|
||||
@ -261,7 +262,7 @@ int smp_call_function_single(int cpuid, void (*func) (void *info), void *info,
|
||||
|
||||
msg_queue = &per_cpu(ipi_msg_queue, cpu);
|
||||
spin_lock_irqsave(&msg_queue->lock, flags);
|
||||
list_add(&msg->list, &msg_queue->head);
|
||||
list_add_tail(&msg->list, &msg_queue->head);
|
||||
spin_unlock_irqrestore(&msg_queue->lock, flags);
|
||||
platform_send_ipi_cpu(cpu);
|
||||
|
||||
@ -292,7 +293,7 @@ void smp_send_reschedule(int cpu)
|
||||
|
||||
msg_queue = &per_cpu(ipi_msg_queue, cpu);
|
||||
spin_lock_irqsave(&msg_queue->lock, flags);
|
||||
list_add(&msg->list, &msg_queue->head);
|
||||
list_add_tail(&msg->list, &msg_queue->head);
|
||||
spin_unlock_irqrestore(&msg_queue->lock, flags);
|
||||
platform_send_ipi_cpu(cpu);
|
||||
|
||||
@ -320,7 +321,7 @@ void smp_send_stop(void)
|
||||
for_each_cpu_mask(cpu, callmap) {
|
||||
msg_queue = &per_cpu(ipi_msg_queue, cpu);
|
||||
spin_lock_irqsave(&msg_queue->lock, flags);
|
||||
list_add(&msg->list, &msg_queue->head);
|
||||
list_add_tail(&msg->list, &msg_queue->head);
|
||||
spin_unlock_irqrestore(&msg_queue->lock, flags);
|
||||
platform_send_ipi_cpu(cpu);
|
||||
}
|
||||
@ -468,6 +469,17 @@ void smp_icache_flush_range_others(unsigned long start, unsigned long end)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(smp_icache_flush_range_others);
|
||||
|
||||
#ifdef __ARCH_SYNC_CORE_ICACHE
|
||||
void resync_core_icache(void)
|
||||
{
|
||||
unsigned int cpu = get_cpu();
|
||||
blackfin_invalidate_entire_icache();
|
||||
++per_cpu(cpu_data, cpu).icache_invld_count;
|
||||
put_cpu();
|
||||
}
|
||||
EXPORT_SYMBOL(resync_core_icache);
|
||||
#endif
|
||||
|
||||
#ifdef __ARCH_SYNC_CORE_DCACHE
|
||||
unsigned long barrier_mask __attribute__ ((__section__(".l2.bss")));
|
||||
|
||||
|
@ -8,7 +8,7 @@
|
||||
#include <linux/sort.h>
|
||||
|
||||
#include <asm/uaccess.h>
|
||||
#include <asm/module.h>
|
||||
#include <linux/module.h>
|
||||
|
||||
static int cmp_ex(const void *a, const void *b)
|
||||
{
|
||||
@ -55,7 +55,7 @@ void sort_extable (struct exception_table_entry *start,
|
||||
|
||||
static inline unsigned long ex_to_addr(const struct exception_table_entry *x)
|
||||
{
|
||||
return (unsigned long)&x->insn + x->insn;
|
||||
return (unsigned long)&x->addr + x->addr;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_MODULES
|
||||
|
@ -963,7 +963,7 @@ CONFIG_EEPROM_LEGACY=y
|
||||
CONFIG_SENSORS_PCF8574=y
|
||||
# CONFIG_PCF8575 is not set
|
||||
CONFIG_SENSORS_PCF8591=y
|
||||
CONFIG_SENSORS_MAX6875=y
|
||||
CONFIG_EEPROM_MAX6875=y
|
||||
# CONFIG_SENSORS_TSL2550 is not set
|
||||
CONFIG_I2C_DEBUG_CORE=y
|
||||
CONFIG_I2C_DEBUG_ALGO=y
|
||||
|
@ -1849,7 +1849,7 @@ CONFIG_EEPROM_LEGACY=m
|
||||
CONFIG_SENSORS_PCF8574=m
|
||||
CONFIG_SENSORS_PCA9539=m
|
||||
CONFIG_SENSORS_PCF8591=m
|
||||
CONFIG_SENSORS_MAX6875=m
|
||||
CONFIG_EEPROM_MAX6875=m
|
||||
# CONFIG_SENSORS_TSL2550 is not set
|
||||
# CONFIG_I2C_DEBUG_CORE is not set
|
||||
# CONFIG_I2C_DEBUG_ALGO is not set
|
||||
|
@ -119,6 +119,8 @@
|
||||
#define EOWNERDEAD 165 /* Owner died */
|
||||
#define ENOTRECOVERABLE 166 /* State not recoverable */
|
||||
|
||||
#define ERFKILL 167 /* Operation not possible due to RF-kill */
|
||||
|
||||
#define EDQUOT 1133 /* Quota exceeded */
|
||||
|
||||
#ifdef __KERNEL__
|
||||
|
@ -120,5 +120,6 @@
|
||||
#define EOWNERDEAD 254 /* Owner died */
|
||||
#define ENOTRECOVERABLE 255 /* State not recoverable */
|
||||
|
||||
#define ERFKILL 256 /* Operation not possible due to RF-kill */
|
||||
|
||||
#endif
|
||||
|
@ -1808,7 +1808,7 @@ CONFIG_PCF8575=m
|
||||
CONFIG_SENSORS_PCA9539=m
|
||||
CONFIG_SENSORS_PCF8591=m
|
||||
# CONFIG_TPS65010 is not set
|
||||
CONFIG_SENSORS_MAX6875=m
|
||||
CONFIG_EEPROM_MAX6875=m
|
||||
CONFIG_SENSORS_TSL2550=m
|
||||
CONFIG_MCU_MPC8349EMITX=m
|
||||
# CONFIG_I2C_DEBUG_CORE is not set
|
||||
|
@ -675,6 +675,8 @@ struct ucc_slow_pram {
|
||||
#define UCC_GETH_UPSMR_RMM 0x00001000
|
||||
#define UCC_GETH_UPSMR_CAM 0x00000400
|
||||
#define UCC_GETH_UPSMR_BRO 0x00000200
|
||||
#define UCC_GETH_UPSMR_SMM 0x00000080
|
||||
#define UCC_GETH_UPSMR_SGMM 0x00000020
|
||||
|
||||
/* UCC Transmit On Demand Register (UTODR) */
|
||||
#define UCC_SLOW_TOD 0x8000
|
||||
|
@ -14,6 +14,7 @@
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/fsl_devices.h>
|
||||
#include <linux/mdio-bitbang.h>
|
||||
#include <linux/of_mdio.h>
|
||||
#include <linux/of_platform.h>
|
||||
|
||||
#include <asm/io.h>
|
||||
@ -115,7 +116,7 @@ static int __devinit ep8248e_mdio_probe(struct of_device *ofdev,
|
||||
struct mii_bus *bus;
|
||||
struct resource res;
|
||||
struct device_node *node;
|
||||
int ret, i;
|
||||
int ret;
|
||||
|
||||
node = of_get_parent(ofdev->node);
|
||||
of_node_put(node);
|
||||
@ -130,17 +131,13 @@ static int __devinit ep8248e_mdio_probe(struct of_device *ofdev,
|
||||
if (!bus)
|
||||
return -ENOMEM;
|
||||
|
||||
bus->phy_mask = 0;
|
||||
bus->irq = kmalloc(sizeof(int) * PHY_MAX_ADDR, GFP_KERNEL);
|
||||
|
||||
for (i = 0; i < PHY_MAX_ADDR; i++)
|
||||
bus->irq[i] = -1;
|
||||
|
||||
bus->name = "ep8248e-mdio-bitbang";
|
||||
bus->parent = &ofdev->dev;
|
||||
snprintf(bus->id, MII_BUS_ID_SIZE, "%x", res.start);
|
||||
|
||||
return mdiobus_register(bus);
|
||||
return of_mdiobus_register(bus, ofdev->node);
|
||||
}
|
||||
|
||||
static int ep8248e_mdio_remove(struct of_device *ofdev)
|
||||
|
@ -29,7 +29,7 @@
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/phy.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/of_mdio.h>
|
||||
#include <linux/of_platform.h>
|
||||
|
||||
#define DELAY 1
|
||||
@ -39,6 +39,7 @@ static void __iomem *gpio_regs;
|
||||
struct gpio_priv {
|
||||
int mdc_pin;
|
||||
int mdio_pin;
|
||||
int mdio_irqs[PHY_MAX_ADDR];
|
||||
};
|
||||
|
||||
#define MDC_PIN(bus) (((struct gpio_priv *)bus->priv)->mdc_pin)
|
||||
@ -218,12 +219,11 @@ static int __devinit gpio_mdio_probe(struct of_device *ofdev,
|
||||
const struct of_device_id *match)
|
||||
{
|
||||
struct device *dev = &ofdev->dev;
|
||||
struct device_node *phy_dn, *np = ofdev->node;
|
||||
struct device_node *np = ofdev->node;
|
||||
struct mii_bus *new_bus;
|
||||
struct gpio_priv *priv;
|
||||
const unsigned int *prop;
|
||||
int err;
|
||||
int i;
|
||||
|
||||
err = -ENOMEM;
|
||||
priv = kzalloc(sizeof(struct gpio_priv), GFP_KERNEL);
|
||||
@ -244,27 +244,7 @@ static int __devinit gpio_mdio_probe(struct of_device *ofdev,
|
||||
snprintf(new_bus->id, MII_BUS_ID_SIZE, "%x", *prop);
|
||||
new_bus->priv = priv;
|
||||
|
||||
new_bus->phy_mask = 0;
|
||||
|
||||
new_bus->irq = kmalloc(sizeof(int)*PHY_MAX_ADDR, GFP_KERNEL);
|
||||
|
||||
if (!new_bus->irq)
|
||||
goto out_free_bus;
|
||||
|
||||
for (i = 0; i < PHY_MAX_ADDR; i++)
|
||||
new_bus->irq[i] = NO_IRQ;
|
||||
|
||||
for (phy_dn = of_get_next_child(np, NULL);
|
||||
phy_dn != NULL;
|
||||
phy_dn = of_get_next_child(np, phy_dn)) {
|
||||
const unsigned int *ip, *regp;
|
||||
|
||||
ip = of_get_property(phy_dn, "interrupts", NULL);
|
||||
regp = of_get_property(phy_dn, "reg", NULL);
|
||||
if (!ip || !regp || *regp >= PHY_MAX_ADDR)
|
||||
continue;
|
||||
new_bus->irq[*regp] = irq_create_mapping(NULL, *ip);
|
||||
}
|
||||
new_bus->irq = priv->mdio_irqs;
|
||||
|
||||
prop = of_get_property(np, "mdc-pin", NULL);
|
||||
priv->mdc_pin = *prop;
|
||||
@ -275,7 +255,7 @@ static int __devinit gpio_mdio_probe(struct of_device *ofdev,
|
||||
new_bus->parent = dev;
|
||||
dev_set_drvdata(dev, new_bus);
|
||||
|
||||
err = mdiobus_register(new_bus);
|
||||
err = of_mdiobus_register(new_bus, np);
|
||||
|
||||
if (err != 0) {
|
||||
printk(KERN_ERR "%s: Cannot register as MDIO bus, err %d\n",
|
||||
@ -286,8 +266,6 @@ static int __devinit gpio_mdio_probe(struct of_device *ofdev,
|
||||
return 0;
|
||||
|
||||
out_free_irq:
|
||||
kfree(new_bus->irq);
|
||||
out_free_bus:
|
||||
kfree(new_bus);
|
||||
out_free_priv:
|
||||
kfree(priv);
|
||||
|
@ -348,6 +348,9 @@ config ARCH_ENABLE_MEMORY_HOTPLUG
|
||||
config ARCH_ENABLE_MEMORY_HOTREMOVE
|
||||
def_bool y
|
||||
|
||||
config ARCH_HIBERNATION_POSSIBLE
|
||||
def_bool y if 64BIT
|
||||
|
||||
source "mm/Kconfig"
|
||||
|
||||
comment "I/O subsystem configuration"
|
||||
@ -592,6 +595,12 @@ config SECCOMP
|
||||
|
||||
endmenu
|
||||
|
||||
menu "Power Management"
|
||||
|
||||
source "kernel/power/Kconfig"
|
||||
|
||||
endmenu
|
||||
|
||||
source "net/Kconfig"
|
||||
|
||||
config PCMCIA
|
||||
|
@ -88,7 +88,9 @@ LDFLAGS_vmlinux := -e start
|
||||
head-y := arch/s390/kernel/head.o arch/s390/kernel/init_task.o
|
||||
|
||||
core-y += arch/s390/mm/ arch/s390/kernel/ arch/s390/crypto/ \
|
||||
arch/s390/appldata/ arch/s390/hypfs/ arch/s390/kvm/
|
||||
arch/s390/appldata/ arch/s390/hypfs/ arch/s390/kvm/ \
|
||||
arch/s390/power/
|
||||
|
||||
libs-y += arch/s390/lib/
|
||||
drivers-y += drivers/s390/
|
||||
drivers-$(CONFIG_MATHEMU) += arch/s390/math-emu/
|
||||
|
@ -5,7 +5,7 @@
|
||||
* Exports appldata_register_ops() and appldata_unregister_ops() for the
|
||||
* data gathering modules.
|
||||
*
|
||||
* Copyright IBM Corp. 2003, 2008
|
||||
* Copyright IBM Corp. 2003, 2009
|
||||
*
|
||||
* Author: Gerald Schaefer <gerald.schaefer@de.ibm.com>
|
||||
*/
|
||||
@ -26,6 +26,8 @@
|
||||
#include <linux/notifier.h>
|
||||
#include <linux/cpu.h>
|
||||
#include <linux/workqueue.h>
|
||||
#include <linux/suspend.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <asm/appldata.h>
|
||||
#include <asm/timer.h>
|
||||
#include <asm/uaccess.h>
|
||||
@ -41,6 +43,9 @@
|
||||
|
||||
#define TOD_MICRO 0x01000 /* nr. of TOD clock units
|
||||
for 1 microsecond */
|
||||
|
||||
static struct platform_device *appldata_pdev;
|
||||
|
||||
/*
|
||||
* /proc entries (sysctl)
|
||||
*/
|
||||
@ -86,6 +91,7 @@ static atomic_t appldata_expire_count = ATOMIC_INIT(0);
|
||||
static DEFINE_SPINLOCK(appldata_timer_lock);
|
||||
static int appldata_interval = APPLDATA_CPU_INTERVAL;
|
||||
static int appldata_timer_active;
|
||||
static int appldata_timer_suspended = 0;
|
||||
|
||||
/*
|
||||
* Work queue
|
||||
@ -475,6 +481,93 @@ void appldata_unregister_ops(struct appldata_ops *ops)
|
||||
/********************** module-ops management <END> **************************/
|
||||
|
||||
|
||||
/**************************** suspend / resume *******************************/
|
||||
static int appldata_freeze(struct device *dev)
|
||||
{
|
||||
struct appldata_ops *ops;
|
||||
int rc;
|
||||
struct list_head *lh;
|
||||
|
||||
get_online_cpus();
|
||||
spin_lock(&appldata_timer_lock);
|
||||
if (appldata_timer_active) {
|
||||
__appldata_vtimer_setup(APPLDATA_DEL_TIMER);
|
||||
appldata_timer_suspended = 1;
|
||||
}
|
||||
spin_unlock(&appldata_timer_lock);
|
||||
put_online_cpus();
|
||||
|
||||
mutex_lock(&appldata_ops_mutex);
|
||||
list_for_each(lh, &appldata_ops_list) {
|
||||
ops = list_entry(lh, struct appldata_ops, list);
|
||||
if (ops->active == 1) {
|
||||
rc = appldata_diag(ops->record_nr, APPLDATA_STOP_REC,
|
||||
(unsigned long) ops->data, ops->size,
|
||||
ops->mod_lvl);
|
||||
if (rc != 0)
|
||||
pr_err("Stopping the data collection for %s "
|
||||
"failed with rc=%d\n", ops->name, rc);
|
||||
}
|
||||
}
|
||||
mutex_unlock(&appldata_ops_mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int appldata_restore(struct device *dev)
|
||||
{
|
||||
struct appldata_ops *ops;
|
||||
int rc;
|
||||
struct list_head *lh;
|
||||
|
||||
get_online_cpus();
|
||||
spin_lock(&appldata_timer_lock);
|
||||
if (appldata_timer_suspended) {
|
||||
__appldata_vtimer_setup(APPLDATA_ADD_TIMER);
|
||||
appldata_timer_suspended = 0;
|
||||
}
|
||||
spin_unlock(&appldata_timer_lock);
|
||||
put_online_cpus();
|
||||
|
||||
mutex_lock(&appldata_ops_mutex);
|
||||
list_for_each(lh, &appldata_ops_list) {
|
||||
ops = list_entry(lh, struct appldata_ops, list);
|
||||
if (ops->active == 1) {
|
||||
ops->callback(ops->data); // init record
|
||||
rc = appldata_diag(ops->record_nr,
|
||||
APPLDATA_START_INTERVAL_REC,
|
||||
(unsigned long) ops->data, ops->size,
|
||||
ops->mod_lvl);
|
||||
if (rc != 0) {
|
||||
pr_err("Starting the data collection for %s "
|
||||
"failed with rc=%d\n", ops->name, rc);
|
||||
}
|
||||
}
|
||||
}
|
||||
mutex_unlock(&appldata_ops_mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int appldata_thaw(struct device *dev)
|
||||
{
|
||||
return appldata_restore(dev);
|
||||
}
|
||||
|
||||
static struct dev_pm_ops appldata_pm_ops = {
|
||||
.freeze = appldata_freeze,
|
||||
.thaw = appldata_thaw,
|
||||
.restore = appldata_restore,
|
||||
};
|
||||
|
||||
static struct platform_driver appldata_pdrv = {
|
||||
.driver = {
|
||||
.name = "appldata",
|
||||
.owner = THIS_MODULE,
|
||||
.pm = &appldata_pm_ops,
|
||||
},
|
||||
};
|
||||
/************************* suspend / resume <END> ****************************/
|
||||
|
||||
|
||||
/******************************* init / exit *********************************/
|
||||
|
||||
static void __cpuinit appldata_online_cpu(int cpu)
|
||||
@ -531,11 +624,23 @@ static struct notifier_block __cpuinitdata appldata_nb = {
|
||||
*/
|
||||
static int __init appldata_init(void)
|
||||
{
|
||||
int i;
|
||||
int i, rc;
|
||||
|
||||
rc = platform_driver_register(&appldata_pdrv);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
appldata_pdev = platform_device_register_simple("appldata", -1, NULL,
|
||||
0);
|
||||
if (IS_ERR(appldata_pdev)) {
|
||||
rc = PTR_ERR(appldata_pdev);
|
||||
goto out_driver;
|
||||
}
|
||||
appldata_wq = create_singlethread_workqueue("appldata");
|
||||
if (!appldata_wq)
|
||||
return -ENOMEM;
|
||||
if (!appldata_wq) {
|
||||
rc = -ENOMEM;
|
||||
goto out_device;
|
||||
}
|
||||
|
||||
get_online_cpus();
|
||||
for_each_online_cpu(i)
|
||||
@ -547,6 +652,12 @@ static int __init appldata_init(void)
|
||||
|
||||
appldata_sysctl_header = register_sysctl_table(appldata_dir_table);
|
||||
return 0;
|
||||
|
||||
out_device:
|
||||
platform_device_unregister(appldata_pdev);
|
||||
out_driver:
|
||||
platform_driver_unregister(&appldata_pdrv);
|
||||
return rc;
|
||||
}
|
||||
|
||||
__initcall(appldata_init);
|
||||
|
@ -1,11 +1,9 @@
|
||||
/*
|
||||
* include/asm-s390/ccwdev.h
|
||||
* include/asm-s390x/ccwdev.h
|
||||
* Copyright IBM Corp. 2002, 2009
|
||||
*
|
||||
* Copyright (C) 2002 IBM Deutschland Entwicklung GmbH, IBM Corporation
|
||||
* Author(s): Arnd Bergmann <arndb@de.ibm.com>
|
||||
* Author(s): Arnd Bergmann <arndb@de.ibm.com>
|
||||
*
|
||||
* Interface for CCW device drivers
|
||||
* Interface for CCW device drivers
|
||||
*/
|
||||
#ifndef _S390_CCWDEV_H_
|
||||
#define _S390_CCWDEV_H_
|
||||
@ -104,6 +102,11 @@ struct ccw_device {
|
||||
* @set_offline: called when setting device offline
|
||||
* @notify: notify driver of device state changes
|
||||
* @shutdown: called at device shutdown
|
||||
* @prepare: prepare for pm state transition
|
||||
* @complete: undo work done in @prepare
|
||||
* @freeze: callback for freezing during hibernation snapshotting
|
||||
* @thaw: undo work done in @freeze
|
||||
* @restore: callback for restoring after hibernation
|
||||
* @driver: embedded device driver structure
|
||||
* @name: device driver name
|
||||
*/
|
||||
@ -116,6 +119,11 @@ struct ccw_driver {
|
||||
int (*set_offline) (struct ccw_device *);
|
||||
int (*notify) (struct ccw_device *, int);
|
||||
void (*shutdown) (struct ccw_device *);
|
||||
int (*prepare) (struct ccw_device *);
|
||||
void (*complete) (struct ccw_device *);
|
||||
int (*freeze)(struct ccw_device *);
|
||||
int (*thaw) (struct ccw_device *);
|
||||
int (*restore)(struct ccw_device *);
|
||||
struct device_driver driver;
|
||||
char *name;
|
||||
};
|
||||
@ -184,6 +192,7 @@ extern void ccw_device_get_id(struct ccw_device *, struct ccw_dev_id *);
|
||||
#define to_ccwdrv(n) container_of(n, struct ccw_driver, driver)
|
||||
|
||||
extern struct ccw_device *ccw_device_probe_console(void);
|
||||
extern int ccw_device_force_console(void);
|
||||
|
||||
// FIXME: these have to go
|
||||
extern int _ccw_device_get_subchannel_number(struct ccw_device *);
|
||||
|
@ -38,6 +38,11 @@ struct ccwgroup_device {
|
||||
* @set_online: function called when device is set online
|
||||
* @set_offline: function called when device is set offline
|
||||
* @shutdown: function called when device is shut down
|
||||
* @prepare: prepare for pm state transition
|
||||
* @complete: undo work done in @prepare
|
||||
* @freeze: callback for freezing during hibernation snapshotting
|
||||
* @thaw: undo work done in @freeze
|
||||
* @restore: callback for restoring after hibernation
|
||||
* @driver: embedded driver structure
|
||||
*/
|
||||
struct ccwgroup_driver {
|
||||
@ -51,6 +56,11 @@ struct ccwgroup_driver {
|
||||
int (*set_online) (struct ccwgroup_device *);
|
||||
int (*set_offline) (struct ccwgroup_device *);
|
||||
void (*shutdown)(struct ccwgroup_device *);
|
||||
int (*prepare) (struct ccwgroup_device *);
|
||||
void (*complete) (struct ccwgroup_device *);
|
||||
int (*freeze)(struct ccwgroup_device *);
|
||||
int (*thaw) (struct ccwgroup_device *);
|
||||
int (*restore)(struct ccwgroup_device *);
|
||||
|
||||
struct device_driver driver;
|
||||
};
|
||||
|
10
arch/s390/include/asm/suspend.h
Normal file
10
arch/s390/include/asm/suspend.h
Normal file
@ -0,0 +1,10 @@
|
||||
#ifndef __ASM_S390_SUSPEND_H
|
||||
#define __ASM_S390_SUSPEND_H
|
||||
|
||||
static inline int arch_prepare_suspend(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -1,11 +1,7 @@
|
||||
/*
|
||||
* include/asm-s390/system.h
|
||||
* Copyright IBM Corp. 1999, 2009
|
||||
*
|
||||
* S390 version
|
||||
* Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
|
||||
* Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com),
|
||||
*
|
||||
* Derived from "include/asm-i386/system.h"
|
||||
* Author(s): Martin Schwidefsky <schwidefsky@de.ibm.com>
|
||||
*/
|
||||
|
||||
#ifndef __ASM_SYSTEM_H
|
||||
@ -469,6 +465,20 @@ extern psw_t sysc_restore_trace_psw;
|
||||
extern psw_t io_restore_trace_psw;
|
||||
#endif
|
||||
|
||||
static inline int tprot(unsigned long addr)
|
||||
{
|
||||
int rc = -EFAULT;
|
||||
|
||||
asm volatile(
|
||||
" tprot 0(%1),0\n"
|
||||
"0: ipm %0\n"
|
||||
" srl %0,28\n"
|
||||
"1:\n"
|
||||
EX_TABLE(0b,1b)
|
||||
: "+d" (rc) : "a" (addr) : "cc");
|
||||
return rc;
|
||||
}
|
||||
|
||||
#endif /* __KERNEL__ */
|
||||
|
||||
#endif
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user