mirror of
https://github.com/edk2-porting/linux-next.git
synced 2024-12-30 08:04:13 +08:00
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: Sterling Heights, Michigan 48313
|
||||||
S: USA
|
S: USA
|
||||||
|
|
||||||
|
N: Wolfgang Grandegger
|
||||||
|
E: wg@grandegger.com
|
||||||
|
D: Controller Area Network (device drivers)
|
||||||
|
|
||||||
N: William Greathouse
|
N: William Greathouse
|
||||||
E: wgreathouse@smva.com
|
E: wgreathouse@smva.com
|
||||||
E: wgreathouse@myfavoritei.com
|
E: wgreathouse@myfavoritei.com
|
||||||
|
@ -145,7 +145,6 @@ usage should require reading the full document.
|
|||||||
interface in STA mode at first!
|
interface in STA mode at first!
|
||||||
</para>
|
</para>
|
||||||
!Finclude/net/mac80211.h ieee80211_if_init_conf
|
!Finclude/net/mac80211.h ieee80211_if_init_conf
|
||||||
!Finclude/net/mac80211.h ieee80211_if_conf
|
|
||||||
</chapter>
|
</chapter>
|
||||||
|
|
||||||
<chapter id="rx-tx">
|
<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>
|
Who: Jean Delvare <khali@linux-fr.org>
|
||||||
Krzysztof Helt <krzysztof.h1@wp.pl>
|
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
|
What: CONFIG_X86_OLD_MCE
|
||||||
|
@ -39,9 +39,8 @@ Features which NILFS2 does not support yet:
|
|||||||
- extended attributes
|
- extended attributes
|
||||||
- POSIX ACLs
|
- POSIX ACLs
|
||||||
- quotas
|
- quotas
|
||||||
- writable snapshots
|
- fsck
|
||||||
- remote backup (CDP)
|
- resize
|
||||||
- data integrity
|
|
||||||
- defragmentation
|
- defragmentation
|
||||||
|
|
||||||
Mount options
|
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
|
If you want to use ATTR_RO as read-only flag even for
|
||||||
the directory, set this option.
|
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
|
<bool>: 0,1,yes,no,true,false
|
||||||
|
|
||||||
TODO
|
TODO
|
||||||
|
@ -2,14 +2,18 @@ Kernel driver f71882fg
|
|||||||
======================
|
======================
|
||||||
|
|
||||||
Supported chips:
|
Supported chips:
|
||||||
* Fintek F71882FG and F71883FG
|
* Fintek F71858FG
|
||||||
Prefix: 'f71882fg'
|
Prefix: 'f71858fg'
|
||||||
Addresses scanned: none, address read from Super I/O config space
|
Addresses scanned: none, address read from Super I/O config space
|
||||||
Datasheet: Available from the Fintek website
|
Datasheet: Available from the Fintek website
|
||||||
* Fintek F71862FG and F71863FG
|
* Fintek F71862FG and F71863FG
|
||||||
Prefix: 'f71862fg'
|
Prefix: 'f71862fg'
|
||||||
Addresses scanned: none, address read from Super I/O config space
|
Addresses scanned: none, address read from Super I/O config space
|
||||||
Datasheet: Available from the Fintek website
|
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
|
* Fintek F8000
|
||||||
Prefix: 'f8000'
|
Prefix: 'f8000'
|
||||||
Addresses scanned: none, address read from Super I/O config space
|
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
|
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
|
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.
|
Writing an unsupported mode will result in an invalid parameter error.
|
||||||
|
|
||||||
* 1: Manual mode
|
* 1: Manual mode
|
||||||
You ask for a specific PWM duty cycle / DC voltage or a specific % of
|
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
|
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
|
* 2: Normal auto mode
|
||||||
You can define a number of temperature/fan speed trip points, which % the
|
You can define a number of temperature/fan speed trip points, which % the
|
||||||
|
@ -7,7 +7,7 @@ henceforth as AEM.
|
|||||||
Supported systems:
|
Supported systems:
|
||||||
* Any recent IBM System X server with AEM support.
|
* Any recent IBM System X server with AEM support.
|
||||||
This includes the x3350, x3550, x3650, x3655, x3755, x3850 M2,
|
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.
|
driver ("ipmi-si") needs to be loaded for this driver to do anything.
|
||||||
Prefix: 'ibmaem'
|
Prefix: 'ibmaem'
|
||||||
Datasheet: Not available
|
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
|
[0-*] denotes any positive number starting from 0
|
||||||
[1-*] denotes any positive number starting from 1
|
[1-*] denotes any positive number starting from 1
|
||||||
RO read only value
|
RO read only value
|
||||||
|
WO write only value
|
||||||
RW read/write value
|
RW read/write value
|
||||||
|
|
||||||
Read/write values may be read-only for some chips, depending on the
|
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.
|
user-space.
|
||||||
RO
|
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
|
Some chips measure temperature using external thermistors and an ADC, and
|
||||||
report the temperature measurement as a voltage. Converting this voltage
|
report the temperature measurement as a voltage. Converting this voltage
|
||||||
back to a temperature (or the other way around for limits) requires
|
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
|
Addresses scanned: ISA address retrieved from Super I/O registers
|
||||||
Datasheet:
|
Datasheet:
|
||||||
http://www.nuvoton.com.tw/NR/rdonlyres/7885623D-A487-4CF9-A47F-30C5F73D6FE6/0/W83627DHG.pdf
|
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
|
* Winbond W83667HG
|
||||||
Prefix: 'w83667hg'
|
Prefix: 'w83667hg'
|
||||||
Addresses scanned: ISA address retrieved from Super I/O registers
|
Addresses scanned: ISA address retrieved from Super I/O registers
|
||||||
@ -28,8 +32,8 @@ Description
|
|||||||
-----------
|
-----------
|
||||||
|
|
||||||
This driver implements support for the Winbond W83627EHF, W83627EHG,
|
This driver implements support for the Winbond W83627EHF, W83627EHG,
|
||||||
W83627DHG and W83667HG super I/O chips. We will refer to them collectively
|
W83627DHG, W83627DHG-P and W83667HG super I/O chips. We will refer to them
|
||||||
as Winbond chips.
|
collectively as Winbond chips.
|
||||||
|
|
||||||
The chips implement three temperature sensors, five fan rotation
|
The chips implement three temperature sensors, five fan rotation
|
||||||
speed sensors, ten analog voltage sensors (only nine for the 627DHG), one
|
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 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
|
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.
|
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
|
* VIA Technologies, Inc. VX800/VX820
|
||||||
Datasheet: available on http://linux.via.com.tw
|
Datasheet: available on http://linux.via.com.tw
|
||||||
|
|
||||||
|
* VIA Technologies, Inc. VX855/VX875
|
||||||
|
Datasheet: Availability unknown
|
||||||
|
|
||||||
Authors:
|
Authors:
|
||||||
Kyösti Mälkki <kmalkki@cc.hut.fi>,
|
Kyösti Mälkki <kmalkki@cc.hut.fi>,
|
||||||
Mark D. Studebaker <mdsxyz123@yahoo.com>,
|
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:3287 (VT8251)
|
||||||
device 1106:8324 (CX700)
|
device 1106:8324 (CX700)
|
||||||
device 1106:8353 (VX800/VX820)
|
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
|
If none of these show up, you should look in the BIOS for settings like
|
||||||
enable ACPI / SMBus or even USB.
|
enable ACPI / SMBus or even USB.
|
||||||
|
@ -22,16 +22,11 @@ README.gigaset
|
|||||||
- info on the drivers for Siemens Gigaset ISDN adapters.
|
- info on the drivers for Siemens Gigaset ISDN adapters.
|
||||||
README.icn
|
README.icn
|
||||||
- info on the ICN-ISDN-card and its driver.
|
- info on the ICN-ISDN-card and its driver.
|
||||||
|
>>>>>>> 93af7aca44f0e82e67bda10a0fb73d383edcc8bd:Documentation/isdn/00-INDEX
|
||||||
README.HiSax
|
README.HiSax
|
||||||
- info on the HiSax driver which replaces the old teles.
|
- info on the HiSax driver which replaces the old teles.
|
||||||
README.hfc-pci
|
README.audio
|
||||||
- info on hfc-pci based cards.
|
- info for running audio over ISDN.
|
||||||
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.avmb1
|
README.avmb1
|
||||||
- info on driver for AVM-B1 ISDN card.
|
- info on driver for AVM-B1 ISDN card.
|
||||||
README.act2000
|
README.act2000
|
||||||
@ -42,10 +37,28 @@ README.concap
|
|||||||
- info on "CONCAP" encapsulation protocol interface used for X.25.
|
- info on "CONCAP" encapsulation protocol interface used for X.25.
|
||||||
README.diversion
|
README.diversion
|
||||||
- info on module for isdn diversion services.
|
- 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
|
README.sc
|
||||||
- info on driver for Spellcaster cards.
|
- info on driver for Spellcaster cards.
|
||||||
|
README.syncppp
|
||||||
|
- info on running Sync PPP over ISDN.
|
||||||
README.x25
|
README.x25
|
||||||
- info for running X.25 over ISDN.
|
- info for running X.25 over ISDN.
|
||||||
|
syncPPP.FAQ
|
||||||
|
- frequently asked questions about running PPP over ISDN.
|
||||||
README.hysdn
|
README.hysdn
|
||||||
- info on driver for Hypercope active HYSDN cards
|
- info on driver for Hypercope active HYSDN cards
|
||||||
README.mISDN
|
README.mISDN
|
||||||
|
@ -45,7 +45,7 @@ From then on, Kernel CAPI may call the registered callback functions for the
|
|||||||
device.
|
device.
|
||||||
|
|
||||||
If the device becomes unusable for any reason (shutdown, disconnect ...), the
|
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.
|
callback functions by Kernel CAPI.
|
||||||
|
|
||||||
|
|
||||||
@ -114,20 +114,36 @@ char *driver_name
|
|||||||
int (*load_firmware)(struct capi_ctr *ctrlr, capiloaddata *ldata)
|
int (*load_firmware)(struct capi_ctr *ctrlr, capiloaddata *ldata)
|
||||||
(optional) pointer to a callback function for sending firmware and
|
(optional) pointer to a callback function for sending firmware and
|
||||||
configuration data to the device
|
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)
|
void (*reset_ctr)(struct capi_ctr *ctrlr)
|
||||||
pointer to a callback function for performing a reset on the device,
|
(optional) pointer to a callback function for performing a reset on
|
||||||
releasing all registered applications
|
the device, releasing all registered applications
|
||||||
|
Called in process context.
|
||||||
|
|
||||||
void (*register_appl)(struct capi_ctr *ctrlr, u16 applid,
|
void (*register_appl)(struct capi_ctr *ctrlr, u16 applid,
|
||||||
capi_register_params *rparam)
|
capi_register_params *rparam)
|
||||||
void (*release_appl)(struct capi_ctr *ctrlr, u16 applid)
|
void (*release_appl)(struct capi_ctr *ctrlr, u16 applid)
|
||||||
pointers to callback functions for registration and deregistration of
|
pointers to callback functions for registration and deregistration of
|
||||||
applications with the device
|
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)
|
u16 (*send_message)(struct capi_ctr *ctrlr, struct sk_buff *skb)
|
||||||
pointer to a callback function for sending a CAPI message to the
|
pointer to a callback function for sending a CAPI message to the
|
||||||
device
|
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)
|
char *(*procinfo)(struct capi_ctr *ctrlr)
|
||||||
pointer to a callback function returning the entry for the device in
|
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
|
system entry, /proc/capi/controllers/<n>; will be called with a
|
||||||
pointer to the device's capi_ctr structure as the last (data) argument
|
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():
|
- to be filled in before calling capi_ctr_ready():
|
||||||
|
|
||||||
u8 manu[CAPI_MANUFACTURER_LEN]
|
u8 manu[CAPI_MANUFACTURER_LEN]
|
||||||
@ -153,6 +171,45 @@ u8 serial[CAPI_SERIAL_LEN]
|
|||||||
value to return for CAPI_GET_SERIAL
|
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
|
5. Lower Layer Interface Functions
|
||||||
|
|
||||||
(declared in <linux/isdn/capilli.h>)
|
(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
|
register/unregister a device (controller) with Kernel CAPI
|
||||||
|
|
||||||
void capi_ctr_ready(struct capi_ctr *ctrlr)
|
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
|
signal controller ready/not ready
|
||||||
|
|
||||||
void capi_ctr_suspend_output(struct capi_ctr *ctrlr)
|
void capi_ctr_suspend_output(struct capi_ctr *ctrlr)
|
||||||
@ -211,3 +268,32 @@ CAPIMSG_CONTROL(m) CAPIMSG_SETCONTROL(m, contr) Controller/PLCI/NCCI
|
|||||||
(u32)
|
(u32)
|
||||||
CAPIMSG_DATALEN(m) CAPIMSG_SETDATALEN(m, len) Data Length (u16)
|
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
|
configuration files and chat scripts in the gigaset-VERSION/ppp directory
|
||||||
in the driver packages from http://sourceforge.net/projects/gigaset307x/.
|
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
|
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 lines. This means you must use "Stupid Mode" if you are using
|
||||||
control requests, if you really need the control lines, though). This means
|
wvdial or you should use the nocrtscts option of pppd.
|
||||||
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
|
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
|
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
|
You can also use /sys/class/tty/ttyGxy/cidmode for changing the CID mode
|
||||||
setting (ttyGxy is ttyGU0 or ttyGB0).
|
setting (ttyGxy is ttyGU0 or ttyGB0).
|
||||||
|
|
||||||
2.6. M105 Undocumented USB Requests
|
2.6. Unregistered Wireless Devices (M101/M105)
|
||||||
------------------------------
|
-----------------------------------------
|
||||||
|
The main purpose of the ser_gigaset and usb_gigaset drivers is to allow
|
||||||
The Gigaset M105 USB data box understands a couple of useful, but
|
the M101 and M105 wireless devices to be used as ISDN devices for ISDN
|
||||||
undocumented USB commands. These requests are not used in normal
|
connections through a Gigaset base. Therefore they assume that the device
|
||||||
operation (for wireless access to the base), but are needed for access
|
is registered to a DECT base.
|
||||||
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.
|
|
||||||
|
|
||||||
|
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
|
3. Troubleshooting
|
||||||
---------------
|
---------------
|
||||||
@ -234,11 +231,12 @@ GigaSet 307x Device Driver
|
|||||||
Select Unimodem mode for all DECT data adapters. (see section 2.4.)
|
Select Unimodem mode for all DECT data adapters. (see section 2.4.)
|
||||||
|
|
||||||
Problem:
|
Problem:
|
||||||
You want to configure your USB DECT data adapter (M105) but gigacontr
|
Messages like this:
|
||||||
reports an error: "/dev/ttyGU0: Inappropriate ioctl for device".
|
usb_gigaset 3-2:1.0: Could not initialize the device.
|
||||||
|
appear in your syslog.
|
||||||
Solution:
|
Solution:
|
||||||
Recompile the usb_gigaset driver with the kernel configuration option
|
Check whether your M10x wireless device is correctly registered to the
|
||||||
CONFIG_GIGASET_UNDOCREQ set to 'y'. (see section 2.6.)
|
Gigaset base. (see section 2.6.)
|
||||||
|
|
||||||
3.2. Telling the driver to provide more information
|
3.2. Telling the driver to provide more information
|
||||||
----------------------------------------------
|
----------------------------------------------
|
||||||
|
@ -36,10 +36,15 @@ This file contains
|
|||||||
6.2 local loopback of sent frames
|
6.2 local loopback of sent frames
|
||||||
6.3 CAN controller hardware filters
|
6.3 CAN controller hardware filters
|
||||||
6.4 The virtual CAN driver (vcan)
|
6.4 The virtual CAN driver (vcan)
|
||||||
6.5 currently supported CAN hardware
|
6.5 The CAN network device driver interface
|
||||||
6.6 todo
|
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
|
the user application using the common CAN filter mechanisms. Inside
|
||||||
this filter definition the (interested) type of errors may be
|
this filter definition the (interested) type of errors may be
|
||||||
selected. The reception of error frames is disabled by default.
|
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
|
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:
|
removal of vcan network devices can be managed with the ip(8) tool:
|
||||||
|
|
||||||
- Create a virtual CAN network interface:
|
- 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':
|
- 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':
|
- 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:
|
The CAN network device driver interface provides a generic interface
|
||||||
In Linux Kernel versions < 2.6.24 the vcan driver creates 4 vcan
|
to setup, configure and monitor CAN network devices. The user can then
|
||||||
netdevices at module load time by default. This value can be changed
|
configure the CAN device, like setting the bit-timing parameters, via
|
||||||
with the module parameter 'numdev'. E.g. 'modprobe vcan numdev=8'
|
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
|
The CAN device must be configured via netlink interface. The supported
|
||||||
there are different drivers available:
|
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)
|
- Setting CAN device properties:
|
||||||
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)
|
|
||||||
|
|
||||||
Additionally the different CAN adaptors (ISA/PCI/PCMCIA/USB/Parport)
|
$ ip link set can0 type can help
|
||||||
from PEAK Systemtechnik support the CAN netdevice driver model
|
Usage: ip link set DEVICE type can
|
||||||
since Linux driver v6.0: http://www.peak-system.com/linux/index.htm
|
[ 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
|
Where: BITRATE := { 1..1000000 }
|
||||||
issue that has not been finalized in the socketcan project. Also the
|
SAMPLE-POINT := { 0.000..0.999 }
|
||||||
idea of having a library module (candev.ko) that holds functions
|
TQ := { NUMBER }
|
||||||
that are needed by all CAN netdevices is not ready to ship.
|
PROP-SEG := { 1..8 }
|
||||||
Your contribution is welcome.
|
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)
|
Urs Thuermann (PF_CAN core, kernel integration, socket interfaces, raw, vcan)
|
||||||
Jan Kizka (RT-SocketCAN core, Socket-API reconciliation)
|
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)
|
Robert Schwebel (design reviews, PTXdist integration)
|
||||||
Marc Kleine-Budde (design reviews, Kernel 2.6 cleanups, drivers)
|
Marc Kleine-Budde (design reviews, Kernel 2.6 cleanups, drivers)
|
||||||
Benedikt Spranger (reviews)
|
Benedikt Spranger (reviews)
|
||||||
Thomas Gleixner (LKML reviews, coding style, posting hints)
|
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)
|
Matthias Brukner (first SJA1000 CAN netdevice implementation Q2/2003)
|
||||||
Klaus Hitschler (PEAK driver integration)
|
Klaus Hitschler (PEAK driver integration)
|
||||||
Uwe Koppe (CAN netdevices with PF_PACKET approach)
|
Uwe Koppe (CAN netdevices with PF_PACKET approach)
|
||||||
Michael Schulze (driver layer loopback requirement, RT CAN drivers review)
|
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.
|
Allows TCP to send "duplicate" SACKs.
|
||||||
|
|
||||||
tcp_ecn - BOOLEAN
|
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
|
tcp_fack - BOOLEAN
|
||||||
Enable FACK congestion avoidance and fast retransmission.
|
Enable FACK congestion avoidance and fast retransmission.
|
||||||
@ -1048,6 +1057,13 @@ disable_ipv6 - BOOLEAN
|
|||||||
address.
|
address.
|
||||||
Default: FALSE (enable IPv6 operation)
|
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
|
accept_dad - INTEGER
|
||||||
Whether to accept DAD (Duplicate Address Detection).
|
Whether to accept DAD (Duplicate Address Detection).
|
||||||
0: Disable DAD
|
0: Disable DAD
|
||||||
|
@ -33,3 +33,40 @@ disable
|
|||||||
|
|
||||||
A reboot is required to enable IPv6.
|
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
|
The radiotap format is discussed in
|
||||||
./Documentation/networking/radiotap-headers.txt.
|
./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
|
to appear on received packets. The following information is parsed from the
|
||||||
radiotap headers and used to control injection:
|
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_FLAGS
|
||||||
|
|
||||||
IEEE80211_RADIOTAP_F_FCS: FCS will be removed and recalculated
|
IEEE80211_RADIOTAP_F_FCS: FCS will be removed and recalculated
|
||||||
IEEE80211_RADIOTAP_F_WEP: frame will be encrypted if key available
|
IEEE80211_RADIOTAP_F_WEP: frame will be encrypted if key available
|
||||||
IEEE80211_RADIOTAP_F_FRAG: frame will be fragmented if longer than the
|
IEEE80211_RADIOTAP_F_FRAG: frame will be fragmented if longer than the
|
||||||
current fragmentation threshold. Note that
|
current fragmentation threshold.
|
||||||
this flag is only reliable when software
|
|
||||||
fragmentation is enabled)
|
|
||||||
|
|
||||||
The injection code can also skip all other currently defined radiotap fields
|
The injection code can also skip all other currently defined radiotap fields
|
||||||
facilitating replay of captured radiotap headers directly.
|
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
|
0x00, 0x00, // <-- radiotap version
|
||||||
0x0b, 0x00, // <- radiotap header length
|
0x0b, 0x00, // <- radiotap header length
|
||||||
@ -72,8 +56,8 @@ interface), along the following lines:
|
|||||||
...
|
...
|
||||||
r = pcap_inject(ppcap, u8aSendBuffer, nLength);
|
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>
|
Andy Green <andy@warmcat.com>
|
||||||
|
@ -38,9 +38,6 @@ ifinfomsg::if_flags & IFF_LOWER_UP:
|
|||||||
ifinfomsg::if_flags & IFF_DORMANT:
|
ifinfomsg::if_flags & IFF_DORMANT:
|
||||||
Driver has signaled netif_dormant_on()
|
Driver has signaled netif_dormant_on()
|
||||||
|
|
||||||
These interface flags can also be queried without netlink using the
|
|
||||||
SIOCGIFFLAGS ioctl.
|
|
||||||
|
|
||||||
TLV IFLA_OPERSTATE
|
TLV IFLA_OPERSTATE
|
||||||
|
|
||||||
contains RFC2863 state of the interface in numeric representation:
|
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
|
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
|
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
|
capture network traffic with utilities like tcpdump or any other that needs
|
||||||
the libpcap library.
|
raw access to network interface.
|
||||||
|
|
||||||
You can find the latest version of this document at
|
|
||||||
|
|
||||||
|
You can find the latest version of this document at:
|
||||||
http://pusa.uv.es/~ulisses/packet_mmap/
|
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>
|
Ulisses Alonso Camaró <uaca@i.hate.spam.alumni.uv.es>
|
||||||
|
Johann Baudy <johann.baudy@gnu-log.net>
|
||||||
|
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
+ Why use PACKET_MMAP
|
+ 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).
|
timestamp (like libpcap always does).
|
||||||
|
|
||||||
In the other hand PACKET_MMAP is very efficient. PACKET_MMAP provides a size
|
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
|
configurable circular buffer mapped in user space that can be used to either
|
||||||
needs to wait for them, most of the time there is no need to issue a single
|
send or receive packets. This way reading packets just needs to wait for them,
|
||||||
system call. By using a shared buffer between the kernel and the user
|
most of the time there is no need to issue a single system call. Concerning
|
||||||
also has the benefit of minimizing packet copies.
|
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,
|
It's fine to use PACKET_MMAP to improve the performance of the capture and
|
||||||
but it isn't everything. At least, if you are capturing at high speeds (this
|
transmission process, but it isn't everything. At least, if you are capturing
|
||||||
is relative to the cpu speed), you should check if the device driver of your
|
at high speeds (this is relative to the cpu speed), you should check if the
|
||||||
network interface card supports some sort of interrupt load mitigation or
|
device driver of your network interface card supports some sort of interrupt
|
||||||
(even better) if it supports NAPI, also make sure it is enabled.
|
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
|
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.
|
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
|
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
|
[setup] socket() -------> creation of the capture socket
|
||||||
setsockopt() ---> allocation of the circular buffer (ring)
|
setsockopt() ---> allocation of the circular buffer (ring)
|
||||||
|
option: PACKET_RX_RING
|
||||||
mmap() ---------> mapping of the allocated buffer to the
|
mmap() ---------> mapping of the allocated buffer to the
|
||||||
user process
|
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
|
also the mapping of the circular buffer in the user process and
|
||||||
the use of this buffer.
|
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
|
+ 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
|
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))
|
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,
|
The most significant argument in the previous call is the req parameter,
|
||||||
this parameter must to have the following structure:
|
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
|
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
|
Being mapped in the capture process allows reading the captured frames and
|
||||||
related meta-information like timestamps without requiring a system call.
|
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
|
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
|
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
|
to be used for the kernel, If not, there is a frame the user can read
|
||||||
and the following flags apply:
|
and the following flags apply:
|
||||||
|
|
||||||
|
+++ Capture process:
|
||||||
from include/linux/if_packet.h
|
from include/linux/if_packet.h
|
||||||
|
|
||||||
#define TP_STATUS_COPY 2
|
#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
|
It doesn't incur in a race condition to first check the status value and
|
||||||
then poll for frames.
|
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
|
+ 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
|
1. Introduction
|
||||||
2 Implementation details
|
2. Implementation details
|
||||||
3 Kernel driver guidelines
|
3. Kernel driver guidelines
|
||||||
3.1 wireless device drivers
|
4. Kernel API
|
||||||
3.2 platform/switch drivers
|
5. Userspace support
|
||||||
3.3 input device drivers
|
|
||||||
4 Kernel API
|
|
||||||
5 Userspace support
|
|
||||||
|
|
||||||
|
|
||||||
1. Introduction:
|
1. Introduction
|
||||||
|
|
||||||
The rfkill switch subsystem exists to add a generic interface to circuitry that
|
The rfkill subsystem provides a generic interface to disabling any radio
|
||||||
can enable or disable the signal output of a wireless *transmitter* of any
|
transmitter in the system. When a transmitter is blocked, it shall not
|
||||||
type. By far, the most common use is to disable radio-frequency transmitters.
|
radiate any power.
|
||||||
|
|
||||||
Note that disabling the signal output means that the the transmitter is to be
|
The subsystem also provides the ability to react on button presses and
|
||||||
made to not emit any energy when "blocked". rfkill is not about blocking data
|
disable all transmitters of a certain type (or all). This is intended for
|
||||||
transmissions, it is about blocking energy emission.
|
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
|
2. Implementation details
|
||||||
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
|
|
||||||
|
|
||||||
The rfkill subsystem is composed of various components: the rfkill class, the
|
The rfkill subsystem is composed of various components: the rfkill class, the
|
||||||
rfkill-input module (an input layer handler), and some specific input layer
|
rfkill-input module (an input layer handler), and some specific input layer
|
||||||
events.
|
events.
|
||||||
|
|
||||||
The rfkill class provides kernel drivers with an interface that allows them to
|
The rfkill class is provided for kernel drivers to register their radio
|
||||||
know when they should enable or disable a wireless network device transmitter.
|
transmitter with the kernel, provide methods for turning it on and off and,
|
||||||
This is enabled by the CONFIG_RFKILL Kconfig option.
|
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
|
The rfkill class code also notifies userspace of state changes, this is
|
||||||
changes on rfkill devices through uevents. It provides a notification chain
|
achieved via uevents. It also provides some sysfs files for userspace to
|
||||||
for interested parties in the kernel to also get notified of rfkill state
|
check the status of radio transmitters. See the "Userspace support" section
|
||||||
changes in other drivers. It creates several sysfs entries which can be used
|
below.
|
||||||
by userspace. See section "Userspace support".
|
|
||||||
|
|
||||||
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
|
The rfkill-input code implements a basic response to rfkill buttons -- it
|
||||||
listen to all rfkill key events and will change the rfkill state of the
|
implements turning on/off all devices of a certain class (or all).
|
||||||
wireless devices accordingly. With this option enabled userspace could either
|
|
||||||
do nothing or simply perform monitoring tasks.
|
|
||||||
|
|
||||||
The rfkill-input module also provides EPO (emergency power-off) functionality
|
When the device is hard-blocked (either by a call to rfkill_set_hw_state()
|
||||||
for all wireless transmitters. This function cannot be overridden, and it is
|
or from query_hw_block) set_block() will be invoked but drivers can well
|
||||||
always active. rfkill EPO is related to *_RFKILL_ALL input layer events.
|
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
|
* The kernel input layer generates KEY_WWAN, KEY_WLAN etc. and
|
||||||
referring to an electronic control circuit that enables or disables a
|
SW_RFKILL_ALL -- when the user presses a button. Drivers for radio
|
||||||
transmitter. We reserve it for the physical device a human manipulates
|
transmitters generally do not register to the input layer, unless the
|
||||||
(which is an input device, by the way):
|
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 rfkill drivers turn off/on their transmitters as requested.
|
||||||
the kernel either directly (through a GPIO pin, ACPI GPE) or by its
|
|
||||||
effect on a rfkill line of a wireless device.
|
|
||||||
|
|
||||||
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
|
3. Kernel driver guidelines
|
||||||
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).
|
|
||||||
|
|
||||||
soft rfkill line/software rfkill line:
|
|
||||||
|
|
||||||
A rfkill line the wireless device driver can directly change the state
|
Drivers for radio transmitters normally implement only the rfkill class.
|
||||||
of. Related to rfkill_state RFKILL_STATE_SOFT_BLOCKED.
|
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
|
During suspend/hibernation, transmitters should only be left enabled when
|
||||||
be overridden by the kernel driver. The hardware device or the
|
wake-on wlan or similar functionality requires it and the device wasn't
|
||||||
firmware just exports its status to the driver, but it is read-only.
|
blocked before suspend/hibernate. Note that it may be necessary to update
|
||||||
Related to rfkill_state RFKILL_STATE_HARD_BLOCKED.
|
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
|
4. Kernel API
|
||||||
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
|
|
||||||
|
|
||||||
To build a driver with rfkill subsystem support, the driver should depend on
|
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
|
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
|
of the hardware is unknown), or read-write (where the hardware can be queried
|
||||||
about its current state).
|
about its current state).
|
||||||
|
|
||||||
The rfkill class will call the get_state hook of a device every time it needs
|
Calling rfkill_set_hw_state() when a state change happens is required from
|
||||||
to know the *real* current state of the hardware. This can happen often, but
|
rfkill drivers that control devices that can be hard-blocked unless they also
|
||||||
it does not do any polling, so it is not enough on hardware that is subject
|
assign the poll_hw_block() callback (then the rfkill core will poll the
|
||||||
to state changes outside of the rfkill subsystem.
|
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
|
5. Userspace support
|
||||||
rfkill status, should there be any chance of the device status changing during
|
|
||||||
the sleep.
|
|
||||||
|
|
||||||
There is no provision for a statically-allocated rfkill struct. You must
|
The following sysfs entries exist for every rfkill device:
|
||||||
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:
|
|
||||||
|
|
||||||
name: Name assigned by driver to this key (interface or driver name).
|
name: Name assigned by driver to this key (interface or driver name).
|
||||||
type: Name of the key type ("wlan", "bluetooth", etc).
|
type: Name of the key type ("wlan", "bluetooth", etc).
|
||||||
state: Current state of the transmitter
|
state: Current state of the transmitter
|
||||||
0: RFKILL_STATE_SOFT_BLOCKED
|
0: RFKILL_STATE_SOFT_BLOCKED
|
||||||
transmitter is forced off, but one can override it
|
transmitter is turned off by software
|
||||||
by a write to the state attribute;
|
|
||||||
1: RFKILL_STATE_UNBLOCKED
|
1: RFKILL_STATE_UNBLOCKED
|
||||||
transmiter is NOT forced off, and may operate if
|
transmitter is (potentially) active
|
||||||
all other conditions for such operation are met
|
|
||||||
(such as interface is up and configured, etc);
|
|
||||||
2: RFKILL_STATE_HARD_BLOCKED
|
2: RFKILL_STATE_HARD_BLOCKED
|
||||||
transmitter is forced off by something outside of
|
transmitter is forced off by something outside of
|
||||||
the driver's control. One cannot set a device to
|
the driver's control.
|
||||||
this state through writes to the state attribute;
|
claim: 0: Kernel handles events (currently always reads that value)
|
||||||
claim: 1: Userspace handles events, 0: Kernel handles events
|
|
||||||
|
|
||||||
Both the "state" and "claim" entries are also writable. For the "state" entry
|
rfkill devices also issue uevents (with an action of "change"), with the
|
||||||
this means that when 1 or 0 is written, the device rfkill state (if not yet in
|
following environment variables set:
|
||||||
the requested state), will be will be toggled accordingly.
|
|
||||||
|
|
||||||
For the "claim" entry writing 1 to it means that the kernel no longer handles
|
RFKILL_NAME
|
||||||
key events even though RFKILL_INPUT input was enabled. When "claim" has been
|
RFKILL_STATE
|
||||||
set to 0, userspace should make sure that it listens for the input events or
|
RFKILL_TYPE
|
||||||
check the sysfs "state" entry regularly to correctly perform the required tasks
|
|
||||||
when the rkfill key is pressed.
|
|
||||||
|
|
||||||
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
|
An alternative userspace interface exists as a misc device /dev/rfkill,
|
||||||
SW_RFKILL_ALL), you will need to use an IOCTL. That information is not
|
which allows userspace to obtain and set the state of rfkill devices and
|
||||||
available through sysfs in a generic way at this time, and it is not available
|
sets of devices. It also notifies userspace about device addition and
|
||||||
through the rfkill class AT ALL.
|
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
|
F: drivers/net/r8169.c
|
||||||
|
|
||||||
8250/16?50 (AND CLONE UARTS) SERIAL DRIVER
|
8250/16?50 (AND CLONE UARTS) SERIAL DRIVER
|
||||||
|
P: Alan Cox
|
||||||
|
M: alan@lxorguk.ukuu.org.uk
|
||||||
L: linux-serial@vger.kernel.org
|
L: linux-serial@vger.kernel.org
|
||||||
W: http://serial.sourceforge.net
|
W: http://serial.sourceforge.net
|
||||||
M: alan@lxorguk.ukuu.org.uk
|
|
||||||
S: Odd Fixes
|
S: Odd Fixes
|
||||||
F: drivers/serial/8250*
|
F: drivers/serial/8250*
|
||||||
F: include/linux/serial_8250.h
|
F: include/linux/serial_8250.h
|
||||||
@ -947,6 +948,12 @@ P: Luis R. Rodriguez
|
|||||||
M: lrodriguez@atheros.com
|
M: lrodriguez@atheros.com
|
||||||
P: Jouni Malinen
|
P: Jouni Malinen
|
||||||
M: jmalinen@atheros.com
|
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: linux-wireless@vger.kernel.org
|
||||||
L: ath9k-devel@lists.ath9k.org
|
L: ath9k-devel@lists.ath9k.org
|
||||||
S: Supported
|
S: Supported
|
||||||
@ -1339,6 +1346,13 @@ F: drivers/net/can/
|
|||||||
F: include/linux/can/
|
F: include/linux/can/
|
||||||
F: include/linux/can.h
|
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
|
CELL BROADBAND ENGINE ARCHITECTURE
|
||||||
P: Arnd Bergmann
|
P: Arnd Bergmann
|
||||||
M: arnd@arndb.de
|
M: arnd@arndb.de
|
||||||
@ -2843,6 +2857,18 @@ L: linux1394-devel@lists.sourceforge.net
|
|||||||
S: Maintained
|
S: Maintained
|
||||||
F: drivers/ieee1394/raw1394*
|
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)
|
INTEGRITY MEASUREMENT ARCHITECTURE (IMA)
|
||||||
P: Mimi Zohar
|
P: Mimi Zohar
|
||||||
M: zohar@us.ibm.com
|
M: zohar@us.ibm.com
|
||||||
@ -3136,6 +3162,7 @@ M: samuel@sortiz.org
|
|||||||
L: irda-users@lists.sourceforge.net (subscribers-only)
|
L: irda-users@lists.sourceforge.net (subscribers-only)
|
||||||
W: http://irda.sourceforge.net/
|
W: http://irda.sourceforge.net/
|
||||||
S: Maintained
|
S: Maintained
|
||||||
|
T: git git://git.kernel.org/pub/scm/linux/kernel/git/sameo/irda-2.6.git
|
||||||
F: Documentation/networking/irda.txt
|
F: Documentation/networking/irda.txt
|
||||||
F: drivers/net/irda/
|
F: drivers/net/irda/
|
||||||
F: include/net/irda/
|
F: include/net/irda/
|
||||||
@ -4621,8 +4648,8 @@ S: Maintained
|
|||||||
F: drivers/ata/sata_promise.*
|
F: drivers/ata/sata_promise.*
|
||||||
|
|
||||||
PS3 NETWORK SUPPORT
|
PS3 NETWORK SUPPORT
|
||||||
P: Masakazu Mokuno
|
P: Geoff Levand
|
||||||
M: mokuno@sm.sony.co.jp
|
M: geoffrey.levand@am.sony.com
|
||||||
L: netdev@vger.kernel.org
|
L: netdev@vger.kernel.org
|
||||||
L: cbe-oss-dev@ozlabs.org
|
L: cbe-oss-dev@ozlabs.org
|
||||||
S: Supported
|
S: Supported
|
||||||
@ -4823,7 +4850,7 @@ F: drivers/net/r6040.c
|
|||||||
RDS - RELIABLE DATAGRAM SOCKETS
|
RDS - RELIABLE DATAGRAM SOCKETS
|
||||||
P: Andy Grover
|
P: Andy Grover
|
||||||
M: andy.grover@oracle.com
|
M: andy.grover@oracle.com
|
||||||
L: rds-devel@oss.oracle.com
|
L: rds-devel@oss.oracle.com (moderated for non-subscribers)
|
||||||
S: Supported
|
S: Supported
|
||||||
F: net/rds/
|
F: net/rds/
|
||||||
|
|
||||||
@ -4863,9 +4890,9 @@ S: Supported
|
|||||||
F: fs/reiserfs/
|
F: fs/reiserfs/
|
||||||
|
|
||||||
RFKILL
|
RFKILL
|
||||||
P: Ivo van Doorn
|
P: Johannes Berg
|
||||||
M: IvDoorn@gmail.com
|
M: johannes@sipsolutions.net
|
||||||
L: netdev@vger.kernel.org
|
L: linux-wireless@vger.kernel.org
|
||||||
S: Maintained
|
S: Maintained
|
||||||
F Documentation/rfkill.txt
|
F Documentation/rfkill.txt
|
||||||
F: net/rfkill/
|
F: net/rfkill/
|
||||||
|
@ -120,4 +120,6 @@
|
|||||||
#define EOWNERDEAD 136 /* Owner died */
|
#define EOWNERDEAD 136 /* Owner died */
|
||||||
#define ENOTRECOVERABLE 137 /* State not recoverable */
|
#define ENOTRECOVERABLE 137 /* State not recoverable */
|
||||||
|
|
||||||
|
#define ERFKILL 138 /* Operation not possible due to RF-kill */
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -536,7 +536,7 @@ setup_rt_frame(int usig, struct k_sigaction *ka, siginfo_t *info,
|
|||||||
return err;
|
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_r0 = regs->ARM_ORIG_r0;
|
||||||
regs->ARM_pc -= thumb_mode(regs) ? 2 : 4;
|
regs->ARM_pc -= thumb_mode(regs) ? 2 : 4;
|
||||||
@ -571,7 +571,7 @@ handle_signal(unsigned long sig, struct k_sigaction *ka,
|
|||||||
}
|
}
|
||||||
/* fallthrough */
|
/* fallthrough */
|
||||||
case -ERESTARTNOINTR:
|
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 ||
|
if (regs->ARM_r0 == -ERESTARTNOHAND ||
|
||||||
regs->ARM_r0 == -ERESTARTSYS ||
|
regs->ARM_r0 == -ERESTARTSYS ||
|
||||||
regs->ARM_r0 == -ERESTARTNOINTR) {
|
regs->ARM_r0 == -ERESTARTNOINTR) {
|
||||||
restart_syscall(regs);
|
setup_syscall_restart(regs);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
single_step_set(current);
|
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);
|
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",
|
pr_info("BT_RADIO going: %s\n", blocked ? "off" : "on");
|
||||||
state == RFKILL_STATE_ON ? "on" : "off");
|
|
||||||
|
|
||||||
if (state == RFKILL_STATE_ON) {
|
if (!blocked) {
|
||||||
pr_info("TOSA_BT: going ON\n");
|
pr_info("TOSA_BT: going ON\n");
|
||||||
tosa_bt_on(data);
|
tosa_bt_on(data);
|
||||||
} else {
|
} else {
|
||||||
pr_info("TOSA_BT: going OFF\n");
|
pr_info("TOSA_BT: going OFF\n");
|
||||||
tosa_bt_off(data);
|
tosa_bt_off(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
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)
|
static int tosa_bt_probe(struct platform_device *dev)
|
||||||
{
|
{
|
||||||
int rc;
|
int rc;
|
||||||
@ -70,18 +74,14 @@ static int tosa_bt_probe(struct platform_device *dev)
|
|||||||
if (rc)
|
if (rc)
|
||||||
goto err_pwr_dir;
|
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) {
|
if (!rfk) {
|
||||||
rc = -ENOMEM;
|
rc = -ENOMEM;
|
||||||
goto err_rfk_alloc;
|
goto err_rfk_alloc;
|
||||||
}
|
}
|
||||||
|
|
||||||
rfk->name = "tosa-bt";
|
rfkill_set_led_trigger_name(rfk, "tosa-bt");
|
||||||
rfk->toggle_radio = tosa_bt_toggle_radio;
|
|
||||||
rfk->data = data;
|
|
||||||
#ifdef CONFIG_RFKILL_LEDS
|
|
||||||
rfk->led_trigger.name = "tosa-bt";
|
|
||||||
#endif
|
|
||||||
|
|
||||||
rc = rfkill_register(rfk);
|
rc = rfkill_register(rfk);
|
||||||
if (rc)
|
if (rc)
|
||||||
@ -92,9 +92,7 @@ static int tosa_bt_probe(struct platform_device *dev)
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
err_rfkill:
|
err_rfkill:
|
||||||
if (rfk)
|
rfkill_destroy(rfk);
|
||||||
rfkill_free(rfk);
|
|
||||||
rfk = NULL;
|
|
||||||
err_rfk_alloc:
|
err_rfk_alloc:
|
||||||
tosa_bt_off(data);
|
tosa_bt_off(data);
|
||||||
err_pwr_dir:
|
err_pwr_dir:
|
||||||
@ -113,8 +111,10 @@ static int __devexit tosa_bt_remove(struct platform_device *dev)
|
|||||||
|
|
||||||
platform_set_drvdata(dev, NULL);
|
platform_set_drvdata(dev, NULL);
|
||||||
|
|
||||||
if (rfk)
|
if (rfk) {
|
||||||
rfkill_unregister(rfk);
|
rfkill_unregister(rfk);
|
||||||
|
rfkill_destroy(rfk);
|
||||||
|
}
|
||||||
rfk = NULL;
|
rfk = NULL;
|
||||||
|
|
||||||
tosa_bt_off(data);
|
tosa_bt_off(data);
|
||||||
|
@ -31,7 +31,6 @@
|
|||||||
#include <linux/input.h>
|
#include <linux/input.h>
|
||||||
#include <linux/gpio.h>
|
#include <linux/gpio.h>
|
||||||
#include <linux/pda_power.h>
|
#include <linux/pda_power.h>
|
||||||
#include <linux/rfkill.h>
|
|
||||||
#include <linux/spi/spi.h>
|
#include <linux/spi/spi.h>
|
||||||
|
|
||||||
#include <asm/setup.h>
|
#include <asm/setup.h>
|
||||||
|
@ -212,7 +212,7 @@ out:
|
|||||||
return err;
|
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)
|
if (regs->r12 == -ERESTART_RESTARTBLOCK)
|
||||||
regs->r8 = __NR_restart_syscall;
|
regs->r8 = __NR_restart_syscall;
|
||||||
@ -296,7 +296,7 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset, int syscall)
|
|||||||
}
|
}
|
||||||
/* fall through */
|
/* fall through */
|
||||||
case -ERESTARTNOINTR:
|
case -ERESTARTNOINTR:
|
||||||
restart_syscall(regs);
|
setup_syscall_restart(regs);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,59 +6,65 @@
|
|||||||
mainmenu "Blackfin Kernel Configuration"
|
mainmenu "Blackfin Kernel Configuration"
|
||||||
|
|
||||||
config MMU
|
config MMU
|
||||||
bool
|
def_bool n
|
||||||
default n
|
|
||||||
|
|
||||||
config FPU
|
config FPU
|
||||||
bool
|
def_bool n
|
||||||
default n
|
|
||||||
|
|
||||||
config RWSEM_GENERIC_SPINLOCK
|
config RWSEM_GENERIC_SPINLOCK
|
||||||
bool
|
def_bool y
|
||||||
default y
|
|
||||||
|
|
||||||
config RWSEM_XCHGADD_ALGORITHM
|
config RWSEM_XCHGADD_ALGORITHM
|
||||||
bool
|
def_bool n
|
||||||
default n
|
|
||||||
|
|
||||||
config BLACKFIN
|
config BLACKFIN
|
||||||
bool
|
def_bool y
|
||||||
default y
|
select HAVE_FUNCTION_GRAPH_TRACER
|
||||||
|
select HAVE_FUNCTION_TRACER
|
||||||
select HAVE_IDE
|
select HAVE_IDE
|
||||||
|
select HAVE_KERNEL_GZIP
|
||||||
|
select HAVE_KERNEL_BZIP2
|
||||||
|
select HAVE_KERNEL_LZMA
|
||||||
select HAVE_OPROFILE
|
select HAVE_OPROFILE
|
||||||
select ARCH_WANT_OPTIONAL_GPIOLIB
|
select ARCH_WANT_OPTIONAL_GPIOLIB
|
||||||
|
|
||||||
|
config GENERIC_BUG
|
||||||
|
def_bool y
|
||||||
|
depends on BUG
|
||||||
|
|
||||||
config ZONE_DMA
|
config ZONE_DMA
|
||||||
bool
|
def_bool y
|
||||||
default y
|
|
||||||
|
|
||||||
config GENERIC_FIND_NEXT_BIT
|
config GENERIC_FIND_NEXT_BIT
|
||||||
bool
|
def_bool y
|
||||||
default y
|
|
||||||
|
|
||||||
config GENERIC_HWEIGHT
|
config GENERIC_HWEIGHT
|
||||||
bool
|
def_bool y
|
||||||
default y
|
|
||||||
|
|
||||||
config GENERIC_HARDIRQS
|
config GENERIC_HARDIRQS
|
||||||
bool
|
def_bool y
|
||||||
default y
|
|
||||||
|
|
||||||
config GENERIC_IRQ_PROBE
|
config GENERIC_IRQ_PROBE
|
||||||
bool
|
def_bool y
|
||||||
default y
|
|
||||||
|
|
||||||
config GENERIC_GPIO
|
config GENERIC_GPIO
|
||||||
bool
|
def_bool y
|
||||||
default y
|
|
||||||
|
|
||||||
config FORCE_MAX_ZONEORDER
|
config FORCE_MAX_ZONEORDER
|
||||||
int
|
int
|
||||||
default "14"
|
default "14"
|
||||||
|
|
||||||
config GENERIC_CALIBRATE_DELAY
|
config GENERIC_CALIBRATE_DELAY
|
||||||
bool
|
def_bool y
|
||||||
default y
|
|
||||||
|
config LOCKDEP_SUPPORT
|
||||||
|
def_bool y
|
||||||
|
|
||||||
|
config STACKTRACE_SUPPORT
|
||||||
|
def_bool y
|
||||||
|
|
||||||
|
config TRACE_IRQFLAGS_SUPPORT
|
||||||
|
def_bool y
|
||||||
|
|
||||||
source "init/Kconfig"
|
source "init/Kconfig"
|
||||||
|
|
||||||
@ -408,12 +414,12 @@ comment "Clock/PLL Setup"
|
|||||||
|
|
||||||
config CLKIN_HZ
|
config CLKIN_HZ
|
||||||
int "Frequency of the crystal on the board in 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 "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
|
help
|
||||||
The frequency of CLKIN crystal oscillator on the board in Hz.
|
The frequency of CLKIN crystal oscillator on the board in Hz.
|
||||||
Warning: This value should match the crystal on the board. Otherwise,
|
Warning: This value should match the crystal on the board. Otherwise,
|
||||||
|
@ -137,7 +137,7 @@ archclean:
|
|||||||
|
|
||||||
INSTALL_PATH ?= /tftpboot
|
INSTALL_PATH ?= /tftpboot
|
||||||
boot := arch/$(ARCH)/boot
|
boot := arch/$(ARCH)/boot
|
||||||
BOOT_TARGETS = vmImage
|
BOOT_TARGETS = vmImage vmImage.bz2 vmImage.gz vmImage.lzma
|
||||||
PHONY += $(BOOT_TARGETS) install
|
PHONY += $(BOOT_TARGETS) install
|
||||||
KBUILD_IMAGE := $(boot)/vmImage
|
KBUILD_IMAGE := $(boot)/vmImage
|
||||||
|
|
||||||
@ -150,7 +150,10 @@ install:
|
|||||||
$(Q)$(MAKE) $(build)=$(boot) BOOTIMAGE=$(KBUILD_IMAGE) install
|
$(Q)$(MAKE) $(build)=$(boot) BOOTIMAGE=$(KBUILD_IMAGE) install
|
||||||
|
|
||||||
define archhelp
|
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 ' install - Install kernel using'
|
||||||
echo ' (your) ~/bin/$(CROSS_COMPILE)installkernel or'
|
echo ' (your) ~/bin/$(CROSS_COMPILE)installkernel or'
|
||||||
echo ' (distribution) PATH: $(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
|
MKIMAGE := $(srctree)/scripts/mkuboot.sh
|
||||||
|
|
||||||
targets := vmImage
|
targets := vmImage vmImage.bz2 vmImage.gz vmImage.lzma
|
||||||
extra-y += vmlinux.bin vmlinux.gz
|
extra-y += vmlinux.bin vmlinux.bin.gz vmlinux.bin.bz2 vmlinux.bin.lzma
|
||||||
|
|
||||||
quiet_cmd_uimage = UIMAGE $@
|
quiet_cmd_uimage = UIMAGE $@
|
||||||
cmd_uimage = $(CONFIG_SHELL) $(MKIMAGE) -A $(ARCH) -O linux -T kernel \
|
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}') \
|
-e $(shell $(NM) vmlinux | awk '$$NF == "__start" {print $$1}') \
|
||||||
-d $< $@
|
-d $< $@
|
||||||
|
|
||||||
$(obj)/vmlinux.bin: vmlinux FORCE
|
$(obj)/vmlinux.bin: vmlinux FORCE
|
||||||
$(call if_changed,objcopy)
|
$(call if_changed,objcopy)
|
||||||
|
|
||||||
$(obj)/vmlinux.gz: $(obj)/vmlinux.bin FORCE
|
$(obj)/vmlinux.bin.gz: $(obj)/vmlinux.bin FORCE
|
||||||
$(call if_changed,gzip)
|
$(call if_changed,gzip)
|
||||||
|
|
||||||
$(obj)/vmImage: $(obj)/vmlinux.gz
|
$(obj)/vmlinux.bin.bz2: $(obj)/vmlinux.bin FORCE
|
||||||
$(call if_changed,uimage)
|
$(call if_changed,bzip2)
|
||||||
@$(kecho) 'Kernel: $@ is ready'
|
|
||||||
|
$(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:
|
install:
|
||||||
sh $(srctree)/$(src)/install.sh $(KERNELRELEASE) $(BOOTIMAGE) System.map "$(INSTALL_PATH)"
|
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)
|
static inline void atomic_add(int i, atomic_t *v)
|
||||||
{
|
{
|
||||||
long flags;
|
unsigned long flags;
|
||||||
|
|
||||||
local_irq_save_hw(flags);
|
local_irq_save_hw(flags);
|
||||||
v->counter += i;
|
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)
|
static inline void atomic_sub(int i, atomic_t *v)
|
||||||
{
|
{
|
||||||
long flags;
|
unsigned long flags;
|
||||||
|
|
||||||
local_irq_save_hw(flags);
|
local_irq_save_hw(flags);
|
||||||
v->counter -= i;
|
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)
|
static inline int atomic_add_return(int i, atomic_t *v)
|
||||||
{
|
{
|
||||||
int __temp = 0;
|
int __temp = 0;
|
||||||
long flags;
|
unsigned long flags;
|
||||||
|
|
||||||
local_irq_save_hw(flags);
|
local_irq_save_hw(flags);
|
||||||
v->counter += i;
|
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)
|
static inline int atomic_sub_return(int i, atomic_t *v)
|
||||||
{
|
{
|
||||||
int __temp = 0;
|
int __temp = 0;
|
||||||
long flags;
|
unsigned long flags;
|
||||||
|
|
||||||
local_irq_save_hw(flags);
|
local_irq_save_hw(flags);
|
||||||
v->counter -= i;
|
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)
|
static inline void atomic_inc(volatile atomic_t *v)
|
||||||
{
|
{
|
||||||
long flags;
|
unsigned long flags;
|
||||||
|
|
||||||
local_irq_save_hw(flags);
|
local_irq_save_hw(flags);
|
||||||
v->counter++;
|
v->counter++;
|
||||||
@ -145,7 +145,7 @@ static inline void atomic_inc(volatile atomic_t *v)
|
|||||||
|
|
||||||
static inline void atomic_dec(volatile atomic_t *v)
|
static inline void atomic_dec(volatile atomic_t *v)
|
||||||
{
|
{
|
||||||
long flags;
|
unsigned long flags;
|
||||||
|
|
||||||
local_irq_save_hw(flags);
|
local_irq_save_hw(flags);
|
||||||
v->counter--;
|
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)
|
static inline void atomic_clear_mask(unsigned int mask, atomic_t *v)
|
||||||
{
|
{
|
||||||
long flags;
|
unsigned long flags;
|
||||||
|
|
||||||
local_irq_save_hw(flags);
|
local_irq_save_hw(flags);
|
||||||
v->counter &= ~mask;
|
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)
|
static inline void atomic_set_mask(unsigned int mask, atomic_t *v)
|
||||||
{
|
{
|
||||||
long flags;
|
unsigned long flags;
|
||||||
|
|
||||||
local_irq_save_hw(flags);
|
local_irq_save_hw(flags);
|
||||||
v->counter |= mask;
|
v->counter |= mask;
|
||||||
|
@ -31,7 +31,7 @@
|
|||||||
|
|
||||||
#ifndef __ASSEMBLY__
|
#ifndef __ASSEMBLY__
|
||||||
|
|
||||||
#include <asm-generic/sections.h>
|
#include <asm/sections.h>
|
||||||
#include <asm/ptrace.h>
|
#include <asm/ptrace.h>
|
||||||
#include <asm/user.h>
|
#include <asm/user.h>
|
||||||
#include <linux/linkage.h>
|
#include <linux/linkage.h>
|
||||||
@ -99,15 +99,6 @@ extern const char bfin_board_name[];
|
|||||||
extern unsigned long bfin_sic_iwr[];
|
extern unsigned long bfin_sic_iwr[];
|
||||||
extern unsigned vr_wakeup;
|
extern unsigned vr_wakeup;
|
||||||
extern u16 _bfin_swrst; /* shadow for Software Reset Register (SWRST) */
|
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
|
#ifdef CONFIG_BFIN_ICACHE_LOCK
|
||||||
extern void cache_grab_lock(int way);
|
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)
|
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;
|
unsigned long *ADDR = (unsigned long *)addr;
|
||||||
|
|
||||||
ADDR += nr >> 5;
|
ADDR += nr >> 5;
|
||||||
|
@ -2,13 +2,58 @@
|
|||||||
#define _BLACKFIN_BUG_H
|
#define _BLACKFIN_BUG_H
|
||||||
|
|
||||||
#ifdef CONFIG_BUG
|
#ifdef CONFIG_BUG
|
||||||
#define HAVE_ARCH_BUG
|
|
||||||
|
|
||||||
#define BUG() do { \
|
#define BFIN_BUG_OPCODE 0xefcd
|
||||||
dump_bfin_trace_buffer(); \
|
|
||||||
printk(KERN_EMERG "BUG: failure at %s:%d/%s()!\n", __FILE__, __LINE__, __func__); \
|
#ifdef CONFIG_DEBUG_BUGVERBOSE
|
||||||
panic("BUG!"); \
|
|
||||||
} while (0)
|
#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
|
#endif
|
||||||
|
|
||||||
|
@ -34,9 +34,13 @@
|
|||||||
#define L1_CACHE_SHIFT_MAX 5
|
#define L1_CACHE_SHIFT_MAX 5
|
||||||
|
|
||||||
#if defined(CONFIG_SMP) && \
|
#if defined(CONFIG_SMP) && \
|
||||||
!defined(CONFIG_BFIN_CACHE_COHERENT) && \
|
!defined(CONFIG_BFIN_CACHE_COHERENT)
|
||||||
defined(CONFIG_BFIN_DCACHE)
|
# if defined(CONFIG_BFIN_ICACHE)
|
||||||
#define __ARCH_SYNC_CORE_DCACHE
|
# define __ARCH_SYNC_CORE_ICACHE
|
||||||
|
# endif
|
||||||
|
# if defined(CONFIG_BFIN_DCACHE)
|
||||||
|
# define __ARCH_SYNC_CORE_DCACHE
|
||||||
|
# endif
|
||||||
#ifndef __ASSEMBLY__
|
#ifndef __ASSEMBLY__
|
||||||
asmlinkage void __raw_smp_mark_barrier_asm(void);
|
asmlinkage void __raw_smp_mark_barrier_asm(void);
|
||||||
asmlinkage void __raw_smp_check_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_dcache(void);
|
||||||
|
void resync_core_icache(void);
|
||||||
#endif
|
#endif
|
||||||
#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_dcache_invalidate_range(unsigned long start_address, unsigned long end_address);
|
||||||
extern void blackfin_dflush_page(void *page);
|
extern void blackfin_dflush_page(void *page);
|
||||||
extern void blackfin_invalidate_entire_dcache(void);
|
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_lock(mapping) do { } while (0)
|
||||||
#define flush_dcache_mmap_unlock(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_dcache_on;
|
||||||
extern unsigned long reserved_mem_icache_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
|
#ifdef CONFIG_BFIN_DCACHE
|
||||||
if (addr < (_ramend - DMA_UNCACHED_REGION))
|
if (addr < (_ramend - DMA_UNCACHED_REGION))
|
||||||
|
@ -34,6 +34,7 @@ struct blackfin_cpudata {
|
|||||||
unsigned int dmemctl;
|
unsigned int dmemctl;
|
||||||
unsigned long loops_per_jiffy;
|
unsigned long loops_per_jiffy;
|
||||||
unsigned long dcache_invld_count;
|
unsigned long dcache_invld_count;
|
||||||
|
unsigned long icache_invld_count;
|
||||||
};
|
};
|
||||||
|
|
||||||
DECLARE_PER_CPU(struct blackfin_cpudata, cpu_data);
|
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/atomic.h>
|
||||||
#include <asm/traps.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_MAJOR_NUMBER 1
|
||||||
#define IPIPE_MINOR_NUMBER 9
|
#define IPIPE_MINOR_NUMBER 10
|
||||||
#define IPIPE_PATCH_NUMBER 1
|
#define IPIPE_PATCH_NUMBER 0
|
||||||
|
|
||||||
#ifdef CONFIG_SMP
|
#ifdef CONFIG_SMP
|
||||||
#error "I-pipe/blackfin: SMP not implemented"
|
#error "I-pipe/blackfin: SMP not implemented"
|
||||||
@ -54,10 +54,11 @@ do { \
|
|||||||
|
|
||||||
#define task_hijacked(p) \
|
#define task_hijacked(p) \
|
||||||
({ \
|
({ \
|
||||||
int __x__ = ipipe_current_domain != ipipe_root_domain; \
|
int __x__ = __ipipe_root_domain_p; \
|
||||||
/* We would need to clear the SYNC flag for the root domain */ \
|
__clear_bit(IPIPE_SYNC_FLAG, &ipipe_root_cpudom_var(status)); \
|
||||||
/* over the current processor in SMP mode. */ \
|
if (__x__) \
|
||||||
local_irq_enable_hw(); __x__; \
|
local_irq_enable_hw(); \
|
||||||
|
!__x__; \
|
||||||
})
|
})
|
||||||
|
|
||||||
struct ipipe_domain;
|
struct ipipe_domain;
|
||||||
@ -179,23 +180,24 @@ static inline unsigned long __ipipe_ffnz(unsigned long ul)
|
|||||||
|
|
||||||
#define __ipipe_run_isr(ipd, irq) \
|
#define __ipipe_run_isr(ipd, irq) \
|
||||||
do { \
|
do { \
|
||||||
if (ipd == ipipe_root_domain) { \
|
if (!__ipipe_pipeline_head_p(ipd)) \
|
||||||
local_irq_enable_hw(); \
|
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); \
|
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)); \
|
ipd->irqs[irq].handler(irq, &__raw_get_cpu_var(__ipipe_tick_regs)); \
|
||||||
local_irq_disable_hw(); \
|
|
||||||
} else { \
|
} else { \
|
||||||
__clear_bit(IPIPE_SYNC_FLAG, &ipipe_cpudom_var(ipd, status)); \
|
__clear_bit(IPIPE_SYNC_FLAG, &ipipe_cpudom_var(ipd, status)); \
|
||||||
local_irq_enable_nohead(ipd); \
|
|
||||||
ipd->irqs[irq].handler(irq, ipd->irqs[irq].cookie); \
|
ipd->irqs[irq].handler(irq, ipd->irqs[irq].cookie); \
|
||||||
/* Attempt to exit the outer interrupt level before \
|
/* Attempt to exit the outer interrupt level before \
|
||||||
* starting the deferred IRQ processing. */ \
|
* starting the deferred IRQ processing. */ \
|
||||||
local_irq_disable_nohead(ipd); \
|
|
||||||
__ipipe_run_irqtail(); \
|
__ipipe_run_irqtail(); \
|
||||||
__set_bit(IPIPE_SYNC_FLAG, &ipipe_cpudom_var(ipd, status)); \
|
__set_bit(IPIPE_SYNC_FLAG, &ipipe_cpudom_var(ipd, status)); \
|
||||||
} \
|
} \
|
||||||
|
local_irq_disable_hw(); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
#define __ipipe_syscall_watched_p(p, sc) \
|
#define __ipipe_syscall_watched_p(p, sc) \
|
||||||
|
@ -17,270 +17,17 @@
|
|||||||
#ifndef _BFIN_IRQ_H_
|
#ifndef _BFIN_IRQ_H_
|
||||||
#define _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 <mach/irq.h>
|
||||||
#include <asm/pda.h>
|
|
||||||
#include <asm/processor.h>
|
|
||||||
|
|
||||||
#ifdef CONFIG_SMP
|
/* Xenomai IPIPE helpers */
|
||||||
/* Forward decl needed due to cdef inter dependencies */
|
#define local_irq_restore_hw(x) local_irq_restore(x)
|
||||||
static inline uint32_t __pure bfin_dspid(void);
|
#define local_irq_save_hw(x) local_irq_save(x)
|
||||||
# define blackfin_core_id() (bfin_dspid() & 0xff)
|
#define local_irq_enable_hw(x) local_irq_enable(x)
|
||||||
# define bfin_irq_flags cpu_pda[blackfin_core_id()].imask
|
#define local_irq_disable_hw(x) local_irq_disable(x)
|
||||||
#else
|
#define irqs_disabled_hw(x) irqs_disabled(x)
|
||||||
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 */
|
|
||||||
|
|
||||||
#if ANOMALY_05000244 && defined(CONFIG_BFIN_ICACHE)
|
#if ANOMALY_05000244 && defined(CONFIG_BFIN_ICACHE)
|
||||||
# define NOP_PAD_ANOMALY_05000244 "nop; nop;"
|
# 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 */
|
/* nothing to see, move along */
|
||||||
#include <asm-generic/sections.h>
|
#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
|
#endif
|
||||||
|
@ -35,10 +35,10 @@
|
|||||||
#define _BLACKFIN_SYSTEM_H
|
#define _BLACKFIN_SYSTEM_H
|
||||||
|
|
||||||
#include <linux/linkage.h>
|
#include <linux/linkage.h>
|
||||||
#include <linux/compiler.h>
|
#include <linux/irqflags.h>
|
||||||
#include <mach/anomaly.h>
|
#include <mach/anomaly.h>
|
||||||
|
#include <asm/cache.h>
|
||||||
#include <asm/pda.h>
|
#include <asm/pda.h>
|
||||||
#include <asm/processor.h>
|
|
||||||
#include <asm/irq.h>
|
#include <asm/irq.h>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -380,8 +380,9 @@
|
|||||||
#define __NR_inotify_init1 365
|
#define __NR_inotify_init1 365
|
||||||
#define __NR_preadv 366
|
#define __NR_preadv 366
|
||||||
#define __NR_pwritev 367
|
#define __NR_pwritev 367
|
||||||
|
#define __NR_rt_tgsigqueueinfo 368
|
||||||
|
|
||||||
#define __NR_syscall 368
|
#define __NR_syscall 369
|
||||||
#define NR_syscalls __NR_syscall
|
#define NR_syscalls __NR_syscall
|
||||||
|
|
||||||
/* Old optional stuff no one actually uses */
|
/* Old optional stuff no one actually uses */
|
||||||
|
@ -15,6 +15,10 @@ else
|
|||||||
obj-y += time.o
|
obj-y += time.o
|
||||||
endif
|
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) += ipipe.o
|
||||||
obj-$(CONFIG_IPIPE_TRACE_MCOUNT) += mcount.o
|
obj-$(CONFIG_IPIPE_TRACE_MCOUNT) += mcount.o
|
||||||
obj-$(CONFIG_BFIN_GPTIMERS) += gptimers.o
|
obj-$(CONFIG_BFIN_GPTIMERS) += gptimers.o
|
||||||
@ -23,6 +27,7 @@ obj-$(CONFIG_MODULES) += module.o
|
|||||||
obj-$(CONFIG_KGDB) += kgdb.o
|
obj-$(CONFIG_KGDB) += kgdb.o
|
||||||
obj-$(CONFIG_KGDB_TESTS) += kgdb_test.o
|
obj-$(CONFIG_KGDB_TESTS) += kgdb_test.o
|
||||||
obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
|
obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
|
||||||
|
obj-$(CONFIG_STACKTRACE) += stacktrace.o
|
||||||
|
|
||||||
# the kgdb test puts code into L2 and without linker
|
# the kgdb test puts code into L2 and without linker
|
||||||
# relaxation, we need to force long calls to/from it
|
# 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;
|
unsigned long src = (unsigned long)psrc;
|
||||||
size_t bulk, rest;
|
size_t bulk, rest;
|
||||||
|
|
||||||
if (bfin_addr_dcachable(src))
|
if (bfin_addr_dcacheable(src))
|
||||||
blackfin_dcache_flush_range(src, src + size);
|
blackfin_dcache_flush_range(src, src + size);
|
||||||
|
|
||||||
if (bfin_addr_dcachable(dst))
|
if (bfin_addr_dcacheable(dst))
|
||||||
blackfin_dcache_invalidate_range(dst, dst + size);
|
blackfin_dcache_invalidate_range(dst, dst + size);
|
||||||
|
|
||||||
bulk = size & ~0xffff;
|
bulk = size & ~0xffff;
|
||||||
|
@ -103,3 +103,8 @@ EXPORT_SYMBOL(__raw_smp_mark_barrier_asm);
|
|||||||
EXPORT_SYMBOL(__raw_smp_check_barrier_asm);
|
EXPORT_SYMBOL(__raw_smp_check_barrier_asm);
|
||||||
#endif
|
#endif
|
||||||
#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;
|
d_data = CPLB_SUPV_WR | CPLB_VALID | CPLB_DIRTY | PAGE_SIZE_4KB;
|
||||||
#ifdef CONFIG_BFIN_DCACHE
|
#ifdef CONFIG_BFIN_DCACHE
|
||||||
if (bfin_addr_dcachable(addr)) {
|
if (bfin_addr_dcacheable(addr)) {
|
||||||
d_data |= CPLB_L1_CHBL | ANOMALY_05000158_WORKAROUND;
|
d_data |= CPLB_L1_CHBL | ANOMALY_05000158_WORKAROUND;
|
||||||
#ifdef CONFIG_BFIN_WT
|
#ifdef CONFIG_BFIN_WT
|
||||||
d_data |= CPLB_L1_AOW | CPLB_WT;
|
d_data |= CPLB_L1_AOW | CPLB_WT;
|
||||||
|
@ -28,6 +28,7 @@
|
|||||||
#include <asm/cplbinit.h>
|
#include <asm/cplbinit.h>
|
||||||
#include <asm/cplb.h>
|
#include <asm/cplb.h>
|
||||||
#include <asm/mmu_context.h>
|
#include <asm/mmu_context.h>
|
||||||
|
#include <asm/traps.h>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* WARNING
|
* WARNING
|
||||||
@ -100,28 +101,6 @@ static inline void write_icplb_data(int cpu, int idx, unsigned long data,
|
|||||||
#endif
|
#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. */
|
/* Counters to implement round-robin replacement. */
|
||||||
static int icplb_rr_index[NR_CPUS] PDT_ATTR;
|
static int icplb_rr_index[NR_CPUS] PDT_ATTR;
|
||||||
static int dcplb_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;
|
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)
|
MGR_ATTR int cplb_hdr(int seqstat, struct pt_regs *regs)
|
||||||
{
|
{
|
||||||
int cause = seqstat & 0x3f;
|
int cause = seqstat & 0x3f;
|
||||||
unsigned int cpu = smp_processor_id();
|
unsigned int cpu = smp_processor_id();
|
||||||
switch (cause) {
|
switch (cause) {
|
||||||
case 0x2C:
|
case VEC_CPLB_I_M:
|
||||||
return icplb_miss(cpu);
|
return icplb_miss(cpu);
|
||||||
case 0x26:
|
case VEC_CPLB_M:
|
||||||
return dcplb_miss(cpu);
|
return dcplb_miss(cpu);
|
||||||
default:
|
default:
|
||||||
if (unlikely(cause == 0x23))
|
|
||||||
return dcplb_protection_fault(cpu);
|
|
||||||
|
|
||||||
return CPLB_UNKNOWN_ERR;
|
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)
|
asmlinkage void __init early_trap_c(struct pt_regs *fp, void *retaddr)
|
||||||
{
|
{
|
||||||
/* This can happen before the uart is initialized, so initialize
|
/* 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);
|
setup_early_printk(DEFAULT_EARLY_PORT);
|
||||||
|
|
||||||
|
printk(KERN_EMERG "Early panic\n");
|
||||||
dump_bfin_mem(fp);
|
dump_bfin_mem(fp);
|
||||||
show_regs(fp);
|
show_regs(fp);
|
||||||
dump_bfin_trace_buffer();
|
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.
|
* interrupt.
|
||||||
*/
|
*/
|
||||||
m_ack = (regs == NULL || irq == IRQ_SYSTMR || irq == IRQ_CORETMR);
|
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)))
|
if (unlikely(test_bit(IPIPE_STICKY_FLAG, &this_domain->irqs[irq].control)))
|
||||||
head = &this_domain->p_link;
|
head = &this_domain->p_link;
|
||||||
@ -212,7 +212,9 @@ void __ipipe_unstall_root_raw(void)
|
|||||||
|
|
||||||
int __ipipe_syscall_root(struct pt_regs *regs)
|
int __ipipe_syscall_root(struct pt_regs *regs)
|
||||||
{
|
{
|
||||||
|
struct ipipe_percpu_domain_data *p;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
int ret;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We need to run the IRQ tail hook whenever we don't
|
* 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:
|
* This routine either returns:
|
||||||
* 0 -- if the syscall is to be passed to Linux;
|
* 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;
|
* 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).
|
* tail work has to be performed (for handling signals etc).
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (__ipipe_event_monitored_p(IPIPE_EVENT_SYSCALL) &&
|
if (!__ipipe_event_monitored_p(IPIPE_EVENT_SYSCALL))
|
||||||
__ipipe_dispatch_event(IPIPE_EVENT_SYSCALL, regs) > 0) {
|
return 0;
|
||||||
if (ipipe_root_domain_p && !in_atomic()) {
|
|
||||||
/*
|
ret = __ipipe_dispatch_event(IPIPE_EVENT_SYSCALL, regs);
|
||||||
* Sync pending VIRQs before _TIF_NEED_RESCHED
|
|
||||||
* is tested.
|
local_irq_save_hw(flags);
|
||||||
*/
|
|
||||||
local_irq_save_hw(flags);
|
if (!__ipipe_root_domain_p) {
|
||||||
if ((ipipe_root_cpudom_var(irqpend_himask) & IPIPE_IRQMASK_VIRT) != 0)
|
local_irq_restore_hw(flags);
|
||||||
__ipipe_sync_pipeline(IPIPE_IRQMASK_VIRT);
|
|
||||||
local_irq_restore_hw(flags);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return 1;
|
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))
|
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)
|
void ___ipipe_sync_pipeline(unsigned long syncmask)
|
||||||
{
|
{
|
||||||
struct ipipe_domain *ipd = ipipe_current_domain;
|
if (__ipipe_root_domain_p) {
|
||||||
|
|
||||||
if (ipd == ipipe_root_domain) {
|
|
||||||
if (test_bit(IPIPE_SYNCDEFER_FLAG, &ipipe_root_cpudom_var(status)))
|
if (test_bit(IPIPE_SYNCDEFER_FLAG, &ipipe_root_cpudom_var(status)))
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -1098,7 +1098,7 @@ static int show_cpuinfo(struct seq_file *m, void *v)
|
|||||||
CPUID, bfin_cpuid());
|
CPUID, bfin_cpuid());
|
||||||
|
|
||||||
seq_printf(m, "model name\t: ADSP-%s %lu(MHz CCLK) %lu(MHz SCLK) (%s)\n"
|
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,
|
cpu, cclk/1000000, sclk/1000000,
|
||||||
#ifdef CONFIG_MPU
|
#ifdef CONFIG_MPU
|
||||||
"mpu on",
|
"mpu on",
|
||||||
@ -1107,7 +1107,16 @@ static int show_cpuinfo(struct seq_file *m, void *v)
|
|||||||
#endif
|
#endif
|
||||||
revid);
|
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,
|
cclk/1000000, cclk%1000000,
|
||||||
sclk/1000000, sclk%1000000);
|
sclk/1000000, sclk%1000000);
|
||||||
seq_printf(m, "bogomips\t: %lu.%02lu\n"
|
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
|
#ifdef __ARCH_SYNC_CORE_DCACHE
|
||||||
seq_printf(m, "SMP Dcache Flushes\t: %lu\n\n", cpudata->dcache_invld_count);
|
seq_printf(m, "SMP Dcache Flushes\t: %lu\n\n", cpudata->dcache_invld_count);
|
||||||
#endif
|
#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
|
#ifdef CONFIG_BFIN_ICACHE_LOCK
|
||||||
switch ((cpudata->imemctl >> 3) & WAYALL_L) {
|
switch ((cpudata->imemctl >> 3) & WAYALL_L) {
|
||||||
case WAY0_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
|
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <linux/bug.h>
|
||||||
#include <linux/uaccess.h>
|
#include <linux/uaccess.h>
|
||||||
#include <linux/interrupt.h>
|
#include <linux/interrupt.h>
|
||||||
#include <linux/module.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)
|
asmlinkage void trap_c(struct pt_regs *fp)
|
||||||
{
|
{
|
||||||
#ifdef CONFIG_DEBUG_BFIN_HWTRACE_ON
|
#ifdef CONFIG_DEBUG_BFIN_HWTRACE_ON
|
||||||
@ -246,6 +252,7 @@ asmlinkage void trap_c(struct pt_regs *fp)
|
|||||||
#ifdef CONFIG_DEBUG_HUNT_FOR_ZERO
|
#ifdef CONFIG_DEBUG_HUNT_FOR_ZERO
|
||||||
unsigned int cpu = smp_processor_id();
|
unsigned int cpu = smp_processor_id();
|
||||||
#endif
|
#endif
|
||||||
|
const char *strerror = NULL;
|
||||||
int sig = 0;
|
int sig = 0;
|
||||||
siginfo_t info;
|
siginfo_t info;
|
||||||
unsigned long trapnr = fp->seqstat & SEQSTAT_EXCAUSE;
|
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
|
* double faults if the stack has become corrupt
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* If the fault was caused by a kernel thread, or interrupt handler
|
#ifndef CONFIG_KGDB
|
||||||
* we will kernel panic, so the system reboots.
|
/* IPEND is skipped if KGDB isn't enabled (see entry code) */
|
||||||
* If KGDB is enabled, don't set this for kernel breakpoints
|
fp->ipend = bfin_read_IPEND();
|
||||||
*/
|
|
||||||
|
|
||||||
/* 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)
|
|
||||||
#endif
|
#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
|
/* trap_c() will be called for exceptions. During exceptions
|
||||||
* processing, the pc value should be set with retx value.
|
* processing, the pc value should be set with retx value.
|
||||||
@ -307,15 +297,15 @@ asmlinkage void trap_c(struct pt_regs *fp)
|
|||||||
sig = SIGTRAP;
|
sig = SIGTRAP;
|
||||||
CHK_DEBUGGER_TRAP_MAYBE();
|
CHK_DEBUGGER_TRAP_MAYBE();
|
||||||
/* Check if this is a breakpoint in kernel space */
|
/* Check if this is a breakpoint in kernel space */
|
||||||
if (fp->ipend & 0xffc0)
|
if (kernel_mode_regs(fp))
|
||||||
return;
|
goto traps_done;
|
||||||
else
|
else
|
||||||
break;
|
break;
|
||||||
/* 0x03 - User Defined, userspace stack overflow */
|
/* 0x03 - User Defined, userspace stack overflow */
|
||||||
case VEC_EXCPT03:
|
case VEC_EXCPT03:
|
||||||
info.si_code = SEGV_STACKFLOW;
|
info.si_code = SEGV_STACKFLOW;
|
||||||
sig = SIGSEGV;
|
sig = SIGSEGV;
|
||||||
verbose_printk(KERN_NOTICE EXC_0x03(KERN_NOTICE));
|
strerror = KERN_NOTICE EXC_0x03(KERN_NOTICE);
|
||||||
CHK_DEBUGGER_TRAP_MAYBE();
|
CHK_DEBUGGER_TRAP_MAYBE();
|
||||||
break;
|
break;
|
||||||
/* 0x02 - KGDB initial connection and break signal trap */
|
/* 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;
|
info.si_code = TRAP_ILLTRAP;
|
||||||
sig = SIGTRAP;
|
sig = SIGTRAP;
|
||||||
CHK_DEBUGGER_TRAP();
|
CHK_DEBUGGER_TRAP();
|
||||||
return;
|
goto traps_done;
|
||||||
#endif
|
#endif
|
||||||
/* 0x04 - User Defined */
|
/* 0x04 - User Defined */
|
||||||
/* 0x05 - User Defined */
|
/* 0x05 - User Defined */
|
||||||
@ -344,7 +334,7 @@ asmlinkage void trap_c(struct pt_regs *fp)
|
|||||||
case VEC_EXCPT04 ... VEC_EXCPT15:
|
case VEC_EXCPT04 ... VEC_EXCPT15:
|
||||||
info.si_code = ILL_ILLPARAOP;
|
info.si_code = ILL_ILLPARAOP;
|
||||||
sig = SIGILL;
|
sig = SIGILL;
|
||||||
verbose_printk(KERN_NOTICE EXC_0x04(KERN_NOTICE));
|
strerror = KERN_NOTICE EXC_0x04(KERN_NOTICE);
|
||||||
CHK_DEBUGGER_TRAP_MAYBE();
|
CHK_DEBUGGER_TRAP_MAYBE();
|
||||||
break;
|
break;
|
||||||
/* 0x10 HW Single step, handled here */
|
/* 0x10 HW Single step, handled here */
|
||||||
@ -353,15 +343,15 @@ asmlinkage void trap_c(struct pt_regs *fp)
|
|||||||
sig = SIGTRAP;
|
sig = SIGTRAP;
|
||||||
CHK_DEBUGGER_TRAP_MAYBE();
|
CHK_DEBUGGER_TRAP_MAYBE();
|
||||||
/* Check if this is a single step in kernel space */
|
/* Check if this is a single step in kernel space */
|
||||||
if (fp->ipend & 0xffc0)
|
if (kernel_mode_regs(fp))
|
||||||
return;
|
goto traps_done;
|
||||||
else
|
else
|
||||||
break;
|
break;
|
||||||
/* 0x11 - Trace Buffer Full, handled here */
|
/* 0x11 - Trace Buffer Full, handled here */
|
||||||
case VEC_OVFLOW:
|
case VEC_OVFLOW:
|
||||||
info.si_code = TRAP_TRACEFLOW;
|
info.si_code = TRAP_TRACEFLOW;
|
||||||
sig = SIGTRAP;
|
sig = SIGTRAP;
|
||||||
verbose_printk(KERN_NOTICE EXC_0x11(KERN_NOTICE));
|
strerror = KERN_NOTICE EXC_0x11(KERN_NOTICE);
|
||||||
CHK_DEBUGGER_TRAP_MAYBE();
|
CHK_DEBUGGER_TRAP_MAYBE();
|
||||||
break;
|
break;
|
||||||
/* 0x12 - Reserved, Caught by default */
|
/* 0x12 - Reserved, Caught by default */
|
||||||
@ -381,37 +371,54 @@ asmlinkage void trap_c(struct pt_regs *fp)
|
|||||||
/* 0x20 - Reserved, Caught by default */
|
/* 0x20 - Reserved, Caught by default */
|
||||||
/* 0x21 - Undefined Instruction, handled here */
|
/* 0x21 - Undefined Instruction, handled here */
|
||||||
case VEC_UNDEF_I:
|
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;
|
info.si_code = ILL_ILLOPC;
|
||||||
sig = SIGILL;
|
sig = SIGILL;
|
||||||
verbose_printk(KERN_NOTICE EXC_0x21(KERN_NOTICE));
|
strerror = KERN_NOTICE EXC_0x21(KERN_NOTICE);
|
||||||
CHK_DEBUGGER_TRAP_MAYBE();
|
CHK_DEBUGGER_TRAP_MAYBE();
|
||||||
break;
|
break;
|
||||||
/* 0x22 - Illegal Instruction Combination, handled here */
|
/* 0x22 - Illegal Instruction Combination, handled here */
|
||||||
case VEC_ILGAL_I:
|
case VEC_ILGAL_I:
|
||||||
info.si_code = ILL_ILLPARAOP;
|
info.si_code = ILL_ILLPARAOP;
|
||||||
sig = SIGILL;
|
sig = SIGILL;
|
||||||
verbose_printk(KERN_NOTICE EXC_0x22(KERN_NOTICE));
|
strerror = KERN_NOTICE EXC_0x22(KERN_NOTICE);
|
||||||
CHK_DEBUGGER_TRAP_MAYBE();
|
CHK_DEBUGGER_TRAP_MAYBE();
|
||||||
break;
|
break;
|
||||||
/* 0x23 - Data CPLB protection violation, handled here */
|
/* 0x23 - Data CPLB protection violation, handled here */
|
||||||
case VEC_CPLB_VL:
|
case VEC_CPLB_VL:
|
||||||
info.si_code = ILL_CPLB_VI;
|
info.si_code = ILL_CPLB_VI;
|
||||||
sig = SIGBUS;
|
sig = SIGBUS;
|
||||||
verbose_printk(KERN_NOTICE EXC_0x23(KERN_NOTICE));
|
strerror = KERN_NOTICE EXC_0x23(KERN_NOTICE);
|
||||||
CHK_DEBUGGER_TRAP_MAYBE();
|
CHK_DEBUGGER_TRAP_MAYBE();
|
||||||
break;
|
break;
|
||||||
/* 0x24 - Data access misaligned, handled here */
|
/* 0x24 - Data access misaligned, handled here */
|
||||||
case VEC_MISALI_D:
|
case VEC_MISALI_D:
|
||||||
info.si_code = BUS_ADRALN;
|
info.si_code = BUS_ADRALN;
|
||||||
sig = SIGBUS;
|
sig = SIGBUS;
|
||||||
verbose_printk(KERN_NOTICE EXC_0x24(KERN_NOTICE));
|
strerror = KERN_NOTICE EXC_0x24(KERN_NOTICE);
|
||||||
CHK_DEBUGGER_TRAP_MAYBE();
|
CHK_DEBUGGER_TRAP_MAYBE();
|
||||||
break;
|
break;
|
||||||
/* 0x25 - Unrecoverable Event, handled here */
|
/* 0x25 - Unrecoverable Event, handled here */
|
||||||
case VEC_UNCOV:
|
case VEC_UNCOV:
|
||||||
info.si_code = ILL_ILLEXCPT;
|
info.si_code = ILL_ILLEXCPT;
|
||||||
sig = SIGILL;
|
sig = SIGILL;
|
||||||
verbose_printk(KERN_NOTICE EXC_0x25(KERN_NOTICE));
|
strerror = KERN_NOTICE EXC_0x25(KERN_NOTICE);
|
||||||
CHK_DEBUGGER_TRAP_MAYBE();
|
CHK_DEBUGGER_TRAP_MAYBE();
|
||||||
break;
|
break;
|
||||||
/* 0x26 - Data CPLB Miss, normal case is handled in _cplb_hdr,
|
/* 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:
|
case VEC_CPLB_M:
|
||||||
info.si_code = BUS_ADRALN;
|
info.si_code = BUS_ADRALN;
|
||||||
sig = SIGBUS;
|
sig = SIGBUS;
|
||||||
verbose_printk(KERN_NOTICE EXC_0x26(KERN_NOTICE));
|
strerror = KERN_NOTICE EXC_0x26(KERN_NOTICE);
|
||||||
break;
|
break;
|
||||||
/* 0x27 - Data CPLB Multiple Hits - Linux Trap Zero, handled here */
|
/* 0x27 - Data CPLB Multiple Hits - Linux Trap Zero, handled here */
|
||||||
case VEC_CPLB_MHIT:
|
case VEC_CPLB_MHIT:
|
||||||
@ -427,10 +434,10 @@ asmlinkage void trap_c(struct pt_regs *fp)
|
|||||||
sig = SIGSEGV;
|
sig = SIGSEGV;
|
||||||
#ifdef CONFIG_DEBUG_HUNT_FOR_ZERO
|
#ifdef CONFIG_DEBUG_HUNT_FOR_ZERO
|
||||||
if (cpu_pda[cpu].dcplb_fault_addr < FIXED_CODE_START)
|
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
|
else
|
||||||
#endif
|
#endif
|
||||||
verbose_printk(KERN_NOTICE EXC_0x27(KERN_NOTICE));
|
strerror = KERN_NOTICE EXC_0x27(KERN_NOTICE);
|
||||||
CHK_DEBUGGER_TRAP_MAYBE();
|
CHK_DEBUGGER_TRAP_MAYBE();
|
||||||
break;
|
break;
|
||||||
/* 0x28 - Emulation Watchpoint, handled here */
|
/* 0x28 - Emulation Watchpoint, handled here */
|
||||||
@ -440,8 +447,8 @@ asmlinkage void trap_c(struct pt_regs *fp)
|
|||||||
pr_debug(EXC_0x28(KERN_DEBUG));
|
pr_debug(EXC_0x28(KERN_DEBUG));
|
||||||
CHK_DEBUGGER_TRAP_MAYBE();
|
CHK_DEBUGGER_TRAP_MAYBE();
|
||||||
/* Check if this is a watchpoint in kernel space */
|
/* Check if this is a watchpoint in kernel space */
|
||||||
if (fp->ipend & 0xffc0)
|
if (kernel_mode_regs(fp))
|
||||||
return;
|
goto traps_done;
|
||||||
else
|
else
|
||||||
break;
|
break;
|
||||||
#ifdef CONFIG_BF535
|
#ifdef CONFIG_BF535
|
||||||
@ -449,7 +456,7 @@ asmlinkage void trap_c(struct pt_regs *fp)
|
|||||||
case VEC_ISTRU_VL: /* ADSP-BF535 only (MH) */
|
case VEC_ISTRU_VL: /* ADSP-BF535 only (MH) */
|
||||||
info.si_code = BUS_OPFETCH;
|
info.si_code = BUS_OPFETCH;
|
||||||
sig = SIGBUS;
|
sig = SIGBUS;
|
||||||
verbose_printk(KERN_NOTICE "BF535: VEC_ISTRU_VL\n");
|
strerror = KERN_NOTICE "BF535: VEC_ISTRU_VL\n";
|
||||||
CHK_DEBUGGER_TRAP_MAYBE();
|
CHK_DEBUGGER_TRAP_MAYBE();
|
||||||
break;
|
break;
|
||||||
#else
|
#else
|
||||||
@ -459,21 +466,21 @@ asmlinkage void trap_c(struct pt_regs *fp)
|
|||||||
case VEC_MISALI_I:
|
case VEC_MISALI_I:
|
||||||
info.si_code = BUS_ADRALN;
|
info.si_code = BUS_ADRALN;
|
||||||
sig = SIGBUS;
|
sig = SIGBUS;
|
||||||
verbose_printk(KERN_NOTICE EXC_0x2A(KERN_NOTICE));
|
strerror = KERN_NOTICE EXC_0x2A(KERN_NOTICE);
|
||||||
CHK_DEBUGGER_TRAP_MAYBE();
|
CHK_DEBUGGER_TRAP_MAYBE();
|
||||||
break;
|
break;
|
||||||
/* 0x2B - Instruction CPLB protection violation, handled here */
|
/* 0x2B - Instruction CPLB protection violation, handled here */
|
||||||
case VEC_CPLB_I_VL:
|
case VEC_CPLB_I_VL:
|
||||||
info.si_code = ILL_CPLB_VI;
|
info.si_code = ILL_CPLB_VI;
|
||||||
sig = SIGBUS;
|
sig = SIGBUS;
|
||||||
verbose_printk(KERN_NOTICE EXC_0x2B(KERN_NOTICE));
|
strerror = KERN_NOTICE EXC_0x2B(KERN_NOTICE);
|
||||||
CHK_DEBUGGER_TRAP_MAYBE();
|
CHK_DEBUGGER_TRAP_MAYBE();
|
||||||
break;
|
break;
|
||||||
/* 0x2C - Instruction CPLB miss, handled in _cplb_hdr */
|
/* 0x2C - Instruction CPLB miss, handled in _cplb_hdr */
|
||||||
case VEC_CPLB_I_M:
|
case VEC_CPLB_I_M:
|
||||||
info.si_code = ILL_CPLB_MISS;
|
info.si_code = ILL_CPLB_MISS;
|
||||||
sig = SIGBUS;
|
sig = SIGBUS;
|
||||||
verbose_printk(KERN_NOTICE EXC_0x2C(KERN_NOTICE));
|
strerror = KERN_NOTICE EXC_0x2C(KERN_NOTICE);
|
||||||
break;
|
break;
|
||||||
/* 0x2D - Instruction CPLB Multiple Hits, handled here */
|
/* 0x2D - Instruction CPLB Multiple Hits, handled here */
|
||||||
case VEC_CPLB_I_MHIT:
|
case VEC_CPLB_I_MHIT:
|
||||||
@ -481,17 +488,17 @@ asmlinkage void trap_c(struct pt_regs *fp)
|
|||||||
sig = SIGSEGV;
|
sig = SIGSEGV;
|
||||||
#ifdef CONFIG_DEBUG_HUNT_FOR_ZERO
|
#ifdef CONFIG_DEBUG_HUNT_FOR_ZERO
|
||||||
if (cpu_pda[cpu].icplb_fault_addr < FIXED_CODE_START)
|
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
|
else
|
||||||
#endif
|
#endif
|
||||||
verbose_printk(KERN_NOTICE EXC_0x2D(KERN_NOTICE));
|
strerror = KERN_NOTICE EXC_0x2D(KERN_NOTICE);
|
||||||
CHK_DEBUGGER_TRAP_MAYBE();
|
CHK_DEBUGGER_TRAP_MAYBE();
|
||||||
break;
|
break;
|
||||||
/* 0x2E - Illegal use of Supervisor Resource, handled here */
|
/* 0x2E - Illegal use of Supervisor Resource, handled here */
|
||||||
case VEC_ILL_RES:
|
case VEC_ILL_RES:
|
||||||
info.si_code = ILL_PRVOPC;
|
info.si_code = ILL_PRVOPC;
|
||||||
sig = SIGILL;
|
sig = SIGILL;
|
||||||
verbose_printk(KERN_NOTICE EXC_0x2E(KERN_NOTICE));
|
strerror = KERN_NOTICE EXC_0x2E(KERN_NOTICE);
|
||||||
CHK_DEBUGGER_TRAP_MAYBE();
|
CHK_DEBUGGER_TRAP_MAYBE();
|
||||||
break;
|
break;
|
||||||
/* 0x2F - Reserved, Caught by default */
|
/* 0x2F - Reserved, Caught by default */
|
||||||
@ -519,17 +526,17 @@ asmlinkage void trap_c(struct pt_regs *fp)
|
|||||||
case (SEQSTAT_HWERRCAUSE_SYSTEM_MMR):
|
case (SEQSTAT_HWERRCAUSE_SYSTEM_MMR):
|
||||||
info.si_code = BUS_ADRALN;
|
info.si_code = BUS_ADRALN;
|
||||||
sig = SIGBUS;
|
sig = SIGBUS;
|
||||||
verbose_printk(KERN_NOTICE HWC_x2(KERN_NOTICE));
|
strerror = KERN_NOTICE HWC_x2(KERN_NOTICE);
|
||||||
break;
|
break;
|
||||||
/* External Memory Addressing Error */
|
/* External Memory Addressing Error */
|
||||||
case (SEQSTAT_HWERRCAUSE_EXTERN_ADDR):
|
case (SEQSTAT_HWERRCAUSE_EXTERN_ADDR):
|
||||||
info.si_code = BUS_ADRERR;
|
info.si_code = BUS_ADRERR;
|
||||||
sig = SIGBUS;
|
sig = SIGBUS;
|
||||||
verbose_printk(KERN_NOTICE HWC_x3(KERN_NOTICE));
|
strerror = KERN_NOTICE HWC_x3(KERN_NOTICE);
|
||||||
break;
|
break;
|
||||||
/* Performance Monitor Overflow */
|
/* Performance Monitor Overflow */
|
||||||
case (SEQSTAT_HWERRCAUSE_PERF_FLOW):
|
case (SEQSTAT_HWERRCAUSE_PERF_FLOW):
|
||||||
verbose_printk(KERN_NOTICE HWC_x12(KERN_NOTICE));
|
strerror = KERN_NOTICE HWC_x12(KERN_NOTICE);
|
||||||
break;
|
break;
|
||||||
/* RAISE 5 instruction */
|
/* RAISE 5 instruction */
|
||||||
case (SEQSTAT_HWERRCAUSE_RAISE_5):
|
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
|
* if we get here we hit a reserved one, so panic
|
||||||
*/
|
*/
|
||||||
default:
|
default:
|
||||||
oops_in_progress = 1;
|
|
||||||
info.si_code = ILL_ILLPARAOP;
|
info.si_code = ILL_ILLPARAOP;
|
||||||
sig = SIGILL;
|
sig = SIGILL;
|
||||||
verbose_printk(KERN_EMERG "Caught Unhandled Exception, code = %08lx\n",
|
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);
|
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) {
|
if (sig != SIGTRAP) {
|
||||||
dump_bfin_process(fp);
|
dump_bfin_process(fp);
|
||||||
dump_bfin_mem(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))
|
if (ANOMALY_05000461 && trapnr == VEC_HWERR && !access_ok(VERIFY_READ, fp->pc, 8))
|
||||||
fp->pc = SAFE_USER_INSTRUCTION;
|
fp->pc = SAFE_USER_INSTRUCTION;
|
||||||
|
|
||||||
|
traps_done:
|
||||||
trace_buffer_restore(j);
|
trace_buffer_restore(j);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Typical exception handling routines */
|
/* Typical exception handling routines */
|
||||||
@ -792,6 +808,18 @@ void dump_bfin_trace_buffer(void)
|
|||||||
}
|
}
|
||||||
EXPORT_SYMBOL(dump_bfin_trace_buffer);
|
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
|
* Checks to see if the address pointed to is either a
|
||||||
* 16-bit CALL instruction, or a 32-bit CALL instruction
|
* 16-bit CALL instruction, or a 32-bit CALL instruction
|
||||||
|
@ -54,6 +54,7 @@ SECTIONS
|
|||||||
SCHED_TEXT
|
SCHED_TEXT
|
||||||
#endif
|
#endif
|
||||||
LOCK_TEXT
|
LOCK_TEXT
|
||||||
|
IRQENTRY_TEXT
|
||||||
KPROBES_TEXT
|
KPROBES_TEXT
|
||||||
*(.text.*)
|
*(.text.*)
|
||||||
*(.fixup)
|
*(.fixup)
|
||||||
@ -166,6 +167,20 @@ SECTIONS
|
|||||||
}
|
}
|
||||||
PERCPU(4)
|
PERCPU(4)
|
||||||
SECURITY_INIT
|
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 :
|
.init.ramfs :
|
||||||
{
|
{
|
||||||
. = ALIGN(4);
|
. = ALIGN(4);
|
||||||
@ -264,8 +279,6 @@ SECTIONS
|
|||||||
|
|
||||||
/DISCARD/ :
|
/DISCARD/ :
|
||||||
{
|
{
|
||||||
EXIT_TEXT
|
|
||||||
EXIT_DATA
|
|
||||||
*(.exitcall.exit)
|
*(.exitcall.exit)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -116,6 +116,7 @@ __sum16 ip_compute_csum(const void *buff, int len)
|
|||||||
{
|
{
|
||||||
return (__force __sum16)~do_csum(buff, len);
|
return (__force __sum16)~do_csum(buff, len);
|
||||||
}
|
}
|
||||||
|
EXPORT_SYMBOL(ip_compute_csum);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* copy from fs while checksumming, otherwise like csum_partial
|
* 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);
|
memcpy(dst, (__force void *)src, len);
|
||||||
return csum_partial(dst, len, sum);
|
return csum_partial(dst, len, sum);
|
||||||
}
|
}
|
||||||
|
EXPORT_SYMBOL(csum_partial_copy_from_user);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* copy from ds while checksumming, otherwise like csum_partial
|
* 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 */
|
.modalias = "m25p80", /* Name of spi_driver for this device */
|
||||||
.max_speed_hz = 25000000, /* max spi clock (SCK) speed in HZ */
|
.max_speed_hz = 25000000, /* max spi clock (SCK) speed in HZ */
|
||||||
.bus_num = 0, /* Framework bus number */
|
.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,
|
.platform_data = &bfin_spi_flash_data,
|
||||||
.controller_data = &spi_flash_chip_info,
|
.controller_data = &spi_flash_chip_info,
|
||||||
.mode = SPI_MODE_3,
|
.mode = SPI_MODE_3,
|
||||||
@ -369,6 +369,11 @@ static struct resource bfin_spi0_resource[] = {
|
|||||||
[1] = {
|
[1] = {
|
||||||
.start = CH_SPI0,
|
.start = CH_SPI0,
|
||||||
.end = CH_SPI0,
|
.end = CH_SPI0,
|
||||||
|
.flags = IORESOURCE_DMA,
|
||||||
|
},
|
||||||
|
[2] = {
|
||||||
|
.start = IRQ_SPI0,
|
||||||
|
.end = IRQ_SPI0,
|
||||||
.flags = IORESOURCE_IRQ,
|
.flags = IORESOURCE_IRQ,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
@ -399,6 +404,11 @@ static struct resource bfin_spi1_resource[] = {
|
|||||||
[1] = {
|
[1] = {
|
||||||
.start = CH_SPI1,
|
.start = CH_SPI1,
|
||||||
.end = CH_SPI1,
|
.end = CH_SPI1,
|
||||||
|
.flags = IORESOURCE_DMA,
|
||||||
|
},
|
||||||
|
[2] = {
|
||||||
|
.start = IRQ_SPI1,
|
||||||
|
.end = IRQ_SPI1,
|
||||||
.flags = IORESOURCE_IRQ,
|
.flags = IORESOURCE_IRQ,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
@ -664,6 +664,11 @@ static struct resource bfin_spi0_resource[] = {
|
|||||||
[1] = {
|
[1] = {
|
||||||
.start = CH_SPI,
|
.start = CH_SPI,
|
||||||
.end = CH_SPI,
|
.end = CH_SPI,
|
||||||
|
.flags = IORESOURCE_DMA,
|
||||||
|
},
|
||||||
|
[2] = {
|
||||||
|
.start = IRQ_SPI,
|
||||||
|
.end = IRQ_SPI,
|
||||||
.flags = IORESOURCE_IRQ,
|
.flags = IORESOURCE_IRQ,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
@ -467,6 +467,11 @@ static struct resource bfin_spi0_resource[] = {
|
|||||||
[1] = {
|
[1] = {
|
||||||
.start = CH_SPI,
|
.start = CH_SPI,
|
||||||
.end = CH_SPI,
|
.end = CH_SPI,
|
||||||
|
.flags = IORESOURCE_DMA,
|
||||||
|
},
|
||||||
|
[2] = {
|
||||||
|
.start = IRQ_SPI,
|
||||||
|
.end = IRQ_SPI,
|
||||||
.flags = IORESOURCE_IRQ,
|
.flags = IORESOURCE_IRQ,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
@ -723,6 +723,11 @@ static struct resource bfin_spi0_resource[] = {
|
|||||||
[1] = {
|
[1] = {
|
||||||
.start = CH_SPI,
|
.start = CH_SPI,
|
||||||
.end = CH_SPI,
|
.end = CH_SPI,
|
||||||
|
.flags = IORESOURCE_DMA,
|
||||||
|
},
|
||||||
|
[2] = {
|
||||||
|
.start = IRQ_SPI,
|
||||||
|
.end = IRQ_SPI,
|
||||||
.flags = IORESOURCE_IRQ,
|
.flags = IORESOURCE_IRQ,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
@ -266,6 +266,11 @@ static struct resource bfin_spi0_resource[] = {
|
|||||||
[1] = {
|
[1] = {
|
||||||
.start = CH_SPI,
|
.start = CH_SPI,
|
||||||
.end = CH_SPI,
|
.end = CH_SPI,
|
||||||
|
.flags = IORESOURCE_DMA,
|
||||||
|
},
|
||||||
|
[2] = {
|
||||||
|
.start = IRQ_SPI,
|
||||||
|
.end = IRQ_SPI,
|
||||||
.flags = IORESOURCE_IRQ,
|
.flags = IORESOURCE_IRQ,
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -162,6 +162,11 @@ static struct resource bfin_spi0_resource[] = {
|
|||||||
[1] = {
|
[1] = {
|
||||||
.start = CH_SPI,
|
.start = CH_SPI,
|
||||||
.end = CH_SPI,
|
.end = CH_SPI,
|
||||||
|
.flags = IORESOURCE_DMA,
|
||||||
|
},
|
||||||
|
[2] = {
|
||||||
|
.start = IRQ_SPI,
|
||||||
|
.end = IRQ_SPI,
|
||||||
.flags = IORESOURCE_IRQ,
|
.flags = IORESOURCE_IRQ,
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -160,6 +160,11 @@ static struct resource bfin_spi0_resource[] = {
|
|||||||
[1] = {
|
[1] = {
|
||||||
.start = CH_SPI,
|
.start = CH_SPI,
|
||||||
.end = CH_SPI,
|
.end = CH_SPI,
|
||||||
|
.flags = IORESOURCE_DMA,
|
||||||
|
},
|
||||||
|
[2] = {
|
||||||
|
.start = IRQ_SPI,
|
||||||
|
.end = IRQ_SPI,
|
||||||
.flags = IORESOURCE_IRQ,
|
.flags = IORESOURCE_IRQ,
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -196,6 +196,11 @@ static struct resource bfin_spi0_resource[] = {
|
|||||||
[1] = {
|
[1] = {
|
||||||
.start = CH_SPI,
|
.start = CH_SPI,
|
||||||
.end = CH_SPI,
|
.end = CH_SPI,
|
||||||
|
.flags = IORESOURCE_DMA,
|
||||||
|
},
|
||||||
|
[2] = {
|
||||||
|
.start = IRQ_SPI,
|
||||||
|
.end = IRQ_SPI,
|
||||||
.flags = IORESOURCE_IRQ,
|
.flags = IORESOURCE_IRQ,
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -299,6 +299,11 @@ static struct resource bfin_spi0_resource[] = {
|
|||||||
[1] = {
|
[1] = {
|
||||||
.start = CH_SPI,
|
.start = CH_SPI,
|
||||||
.end = CH_SPI,
|
.end = CH_SPI,
|
||||||
|
.flags = IORESOURCE_DMA,
|
||||||
|
},
|
||||||
|
[2] = {
|
||||||
|
.start = IRQ_SPI,
|
||||||
|
.end = IRQ_SPI,
|
||||||
.flags = IORESOURCE_IRQ,
|
.flags = IORESOURCE_IRQ,
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -182,8 +182,13 @@ static struct resource bfin_spi0_resource[] = {
|
|||||||
[1] = {
|
[1] = {
|
||||||
.start = CH_SPI,
|
.start = CH_SPI,
|
||||||
.end = CH_SPI,
|
.end = CH_SPI,
|
||||||
|
.flags = IORESOURCE_DMA,
|
||||||
|
},
|
||||||
|
[2] = {
|
||||||
|
.start = IRQ_SPI,
|
||||||
|
.end = IRQ_SPI,
|
||||||
.flags = IORESOURCE_IRQ,
|
.flags = IORESOURCE_IRQ,
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
/* SPI controller data */
|
/* SPI controller data */
|
||||||
|
@ -184,6 +184,11 @@ static struct resource bfin_spi0_resource[] = {
|
|||||||
[1] = {
|
[1] = {
|
||||||
.start = CH_SPI,
|
.start = CH_SPI,
|
||||||
.end = CH_SPI,
|
.end = CH_SPI,
|
||||||
|
.flags = IORESOURCE_DMA,
|
||||||
|
},
|
||||||
|
[2] = {
|
||||||
|
.start = IRQ_SPI,
|
||||||
|
.end = IRQ_SPI,
|
||||||
.flags = IORESOURCE_IRQ,
|
.flags = IORESOURCE_IRQ,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
@ -398,8 +398,13 @@ static struct resource bfin_spi0_resource[] = {
|
|||||||
[1] = {
|
[1] = {
|
||||||
.start = CH_SPI,
|
.start = CH_SPI,
|
||||||
.end = CH_SPI,
|
.end = CH_SPI,
|
||||||
|
.flags = IORESOURCE_DMA,
|
||||||
|
},
|
||||||
|
[2] = {
|
||||||
|
.start = IRQ_SPI,
|
||||||
|
.end = IRQ_SPI,
|
||||||
.flags = IORESOURCE_IRQ,
|
.flags = IORESOURCE_IRQ,
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
/* SPI controller data */
|
/* 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)
|
#if defined(CONFIG_PMIC_ADP5520) || defined(CONFIG_PMIC_ADP5520_MODULE)
|
||||||
{
|
{
|
||||||
I2C_BOARD_INFO("pmic-adp5520", 0x32),
|
I2C_BOARD_INFO("pmic-adp5520", 0x32),
|
||||||
.irq = IRQ_PF7,
|
.irq = IRQ_PG0,
|
||||||
.platform_data = (void *)&adp5520_pdev_data,
|
.platform_data = (void *)&adp5520_pdev_data,
|
||||||
},
|
},
|
||||||
#endif
|
#endif
|
||||||
|
@ -182,6 +182,11 @@ static struct resource bfin_spi0_resource[] = {
|
|||||||
[1] = {
|
[1] = {
|
||||||
.start = CH_SPI,
|
.start = CH_SPI,
|
||||||
.end = CH_SPI,
|
.end = CH_SPI,
|
||||||
|
.flags = IORESOURCE_DMA,
|
||||||
|
},
|
||||||
|
[2] = {
|
||||||
|
.start = IRQ_SPI,
|
||||||
|
.end = IRQ_SPI,
|
||||||
.flags = IORESOURCE_IRQ,
|
.flags = IORESOURCE_IRQ,
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -352,6 +352,11 @@ static struct resource bfin_spi0_resource[] = {
|
|||||||
[1] = {
|
[1] = {
|
||||||
.start = CH_SPI0,
|
.start = CH_SPI0,
|
||||||
.end = CH_SPI0,
|
.end = CH_SPI0,
|
||||||
|
.flags = IORESOURCE_DMA,
|
||||||
|
},
|
||||||
|
[2] = {
|
||||||
|
.start = IRQ_SPI0,
|
||||||
|
.end = IRQ_SPI0,
|
||||||
.flags = IORESOURCE_IRQ,
|
.flags = IORESOURCE_IRQ,
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -366,6 +371,11 @@ static struct resource bfin_spi1_resource[] = {
|
|||||||
[1] = {
|
[1] = {
|
||||||
.start = CH_SPI1,
|
.start = CH_SPI1,
|
||||||
.end = CH_SPI1,
|
.end = CH_SPI1,
|
||||||
|
.flags = IORESOURCE_DMA,
|
||||||
|
},
|
||||||
|
[2] = {
|
||||||
|
.start = IRQ_SPI1,
|
||||||
|
.end = IRQ_SPI1,
|
||||||
.flags = IORESOURCE_IRQ,
|
.flags = IORESOURCE_IRQ,
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -612,6 +612,11 @@ static struct resource bfin_spi0_resource[] = {
|
|||||||
[1] = {
|
[1] = {
|
||||||
.start = CH_SPI0,
|
.start = CH_SPI0,
|
||||||
.end = CH_SPI0,
|
.end = CH_SPI0,
|
||||||
|
.flags = IORESOURCE_DMA,
|
||||||
|
},
|
||||||
|
[2] = {
|
||||||
|
.start = IRQ_SPI0,
|
||||||
|
.end = IRQ_SPI0,
|
||||||
.flags = IORESOURCE_IRQ,
|
.flags = IORESOURCE_IRQ,
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -626,6 +631,11 @@ static struct resource bfin_spi1_resource[] = {
|
|||||||
[1] = {
|
[1] = {
|
||||||
.start = CH_SPI1,
|
.start = CH_SPI1,
|
||||||
.end = CH_SPI1,
|
.end = CH_SPI1,
|
||||||
|
.flags = IORESOURCE_DMA,
|
||||||
|
},
|
||||||
|
[2] = {
|
||||||
|
.start = IRQ_SPI1,
|
||||||
|
.end = IRQ_SPI1,
|
||||||
.flags = IORESOURCE_IRQ,
|
.flags = IORESOURCE_IRQ,
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -396,6 +396,8 @@ static struct platform_device bfin_sir3_device = {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(CONFIG_SMSC911X) || defined(CONFIG_SMSC911X_MODULE)
|
#if defined(CONFIG_SMSC911X) || defined(CONFIG_SMSC911X_MODULE)
|
||||||
|
#include <linux/smsc911x.h>
|
||||||
|
|
||||||
static struct resource smsc911x_resources[] = {
|
static struct resource smsc911x_resources[] = {
|
||||||
{
|
{
|
||||||
.name = "smsc911x-memory",
|
.name = "smsc911x-memory",
|
||||||
@ -409,11 +411,22 @@ static struct resource smsc911x_resources[] = {
|
|||||||
.flags = IORESOURCE_IRQ | IORESOURCE_IRQ_LOWLEVEL,
|
.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 = {
|
static struct platform_device smsc911x_device = {
|
||||||
.name = "smsc911x",
|
.name = "smsc911x",
|
||||||
.id = 0,
|
.id = 0,
|
||||||
.num_resources = ARRAY_SIZE(smsc911x_resources),
|
.num_resources = ARRAY_SIZE(smsc911x_resources),
|
||||||
.resource = smsc911x_resources,
|
.resource = smsc911x_resources,
|
||||||
|
.dev = {
|
||||||
|
.platform_data = &smsc911x_config,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -741,6 +754,11 @@ static struct resource bfin_spi0_resource[] = {
|
|||||||
[1] = {
|
[1] = {
|
||||||
.start = CH_SPI0,
|
.start = CH_SPI0,
|
||||||
.end = CH_SPI0,
|
.end = CH_SPI0,
|
||||||
|
.flags = IORESOURCE_DMA,
|
||||||
|
},
|
||||||
|
[2] = {
|
||||||
|
.start = IRQ_SPI0,
|
||||||
|
.end = IRQ_SPI0,
|
||||||
.flags = IORESOURCE_IRQ,
|
.flags = IORESOURCE_IRQ,
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -755,6 +773,11 @@ static struct resource bfin_spi1_resource[] = {
|
|||||||
[1] = {
|
[1] = {
|
||||||
.start = CH_SPI1,
|
.start = CH_SPI1,
|
||||||
.end = CH_SPI1,
|
.end = CH_SPI1,
|
||||||
|
.flags = IORESOURCE_DMA,
|
||||||
|
},
|
||||||
|
[2] = {
|
||||||
|
.start = IRQ_SPI1,
|
||||||
|
.end = IRQ_SPI1,
|
||||||
.flags = IORESOURCE_IRQ,
|
.flags = IORESOURCE_IRQ,
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -177,8 +177,13 @@ static struct resource bfin_spi0_resource[] = {
|
|||||||
[1] = {
|
[1] = {
|
||||||
.start = CH_SPI,
|
.start = CH_SPI,
|
||||||
.end = CH_SPI,
|
.end = CH_SPI,
|
||||||
|
.flags = IORESOURCE_DMA,
|
||||||
|
},
|
||||||
|
[2] = {
|
||||||
|
.start = IRQ_SPI,
|
||||||
|
.end = IRQ_SPI,
|
||||||
.flags = IORESOURCE_IRQ,
|
.flags = IORESOURCE_IRQ,
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
/* SPI controller data */
|
/* SPI controller data */
|
||||||
|
@ -304,6 +304,11 @@ static struct resource bfin_spi0_resource[] = {
|
|||||||
[1] = {
|
[1] = {
|
||||||
.start = CH_SPI,
|
.start = CH_SPI,
|
||||||
.end = CH_SPI,
|
.end = CH_SPI,
|
||||||
|
.flags = IORESOURCE_DMA,
|
||||||
|
},
|
||||||
|
[2] = {
|
||||||
|
.start = IRQ_SPI,
|
||||||
|
.end = IRQ_SPI,
|
||||||
.flags = IORESOURCE_IRQ,
|
.flags = IORESOURCE_IRQ,
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -16,9 +16,21 @@
|
|||||||
void blackfin_invalidate_entire_dcache(void)
|
void blackfin_invalidate_entire_dcache(void)
|
||||||
{
|
{
|
||||||
u32 dmem = bfin_read_DMEM_CONTROL();
|
u32 dmem = bfin_read_DMEM_CONTROL();
|
||||||
SSYNC();
|
|
||||||
bfin_write_DMEM_CONTROL(dmem & ~0xc);
|
bfin_write_DMEM_CONTROL(dmem & ~0xc);
|
||||||
SSYNC();
|
SSYNC();
|
||||||
bfin_write_DMEM_CONTROL(dmem);
|
bfin_write_DMEM_CONTROL(dmem);
|
||||||
SSYNC();
|
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/thread_info.h> /* TIF_NEED_RESCHED */
|
||||||
#include <asm/asm-offsets.h>
|
#include <asm/asm-offsets.h>
|
||||||
#include <asm/trace.h>
|
#include <asm/trace.h>
|
||||||
|
#include <asm/traps.h>
|
||||||
|
|
||||||
#include <asm/context.S>
|
#include <asm/context.S>
|
||||||
|
|
||||||
@ -84,13 +85,15 @@ ENTRY(_ex_workaround_261)
|
|||||||
if !cc jump _bfin_return_from_exception;
|
if !cc jump _bfin_return_from_exception;
|
||||||
/* fall through */
|
/* fall through */
|
||||||
R7 = P4;
|
R7 = P4;
|
||||||
R6 = 0x26; /* Data CPLB Miss */
|
R6 = VEC_CPLB_M; /* Data CPLB Miss */
|
||||||
cc = R6 == R7;
|
cc = R6 == R7;
|
||||||
if cc jump _ex_dcplb_miss (BP);
|
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;
|
cc = R6 == R7;
|
||||||
if cc jump _ex_dcplb_viol (BP);
|
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
|
* and Data CPLB Multiple Hits - Linux Trap Zero
|
||||||
*/
|
*/
|
||||||
jump _ex_trap_c;
|
jump _ex_trap_c;
|
||||||
@ -270,7 +273,7 @@ ENTRY(_bfin_return_from_exception)
|
|||||||
r6.l = lo(SEQSTAT_EXCAUSE);
|
r6.l = lo(SEQSTAT_EXCAUSE);
|
||||||
r6.h = hi(SEQSTAT_EXCAUSE);
|
r6.h = hi(SEQSTAT_EXCAUSE);
|
||||||
r7 = r7 & r6;
|
r7 = r7 & r6;
|
||||||
r6 = 0x25;
|
r6 = VEC_UNCOV;
|
||||||
CC = R7 == R6;
|
CC = R7 == R6;
|
||||||
if CC JUMP _double_fault;
|
if CC JUMP _double_fault;
|
||||||
#endif
|
#endif
|
||||||
@ -1605,6 +1608,7 @@ ENTRY(_sys_call_table)
|
|||||||
.long _sys_inotify_init1 /* 365 */
|
.long _sys_inotify_init1 /* 365 */
|
||||||
.long _sys_preadv
|
.long _sys_preadv
|
||||||
.long _sys_pwritev
|
.long _sys_pwritev
|
||||||
|
.long _sys_rt_tgsigqueueinfo
|
||||||
|
|
||||||
.rept NR_syscalls-(.-_sys_call_table)/4
|
.rept NR_syscalls-(.-_sys_call_table)/4
|
||||||
.long _sys_ni_syscall
|
.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)
|
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;
|
struct ipi_message_queue *msg_queue;
|
||||||
unsigned int cpu = smp_processor_id();
|
unsigned int cpu = smp_processor_id();
|
||||||
|
|
||||||
@ -154,7 +154,8 @@ static irqreturn_t ipi_handler(int irq, void *dev_instance)
|
|||||||
msg_queue->count++;
|
msg_queue->count++;
|
||||||
|
|
||||||
spin_lock(&msg_queue->lock);
|
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);
|
list_del(&msg->list);
|
||||||
switch (msg->type) {
|
switch (msg->type) {
|
||||||
case BFIN_IPI_RESCHEDULE:
|
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) {
|
for_each_cpu_mask(cpu, callmap) {
|
||||||
msg_queue = &per_cpu(ipi_msg_queue, cpu);
|
msg_queue = &per_cpu(ipi_msg_queue, cpu);
|
||||||
spin_lock_irqsave(&msg_queue->lock, flags);
|
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);
|
spin_unlock_irqrestore(&msg_queue->lock, flags);
|
||||||
platform_send_ipi_cpu(cpu);
|
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);
|
msg_queue = &per_cpu(ipi_msg_queue, cpu);
|
||||||
spin_lock_irqsave(&msg_queue->lock, flags);
|
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);
|
spin_unlock_irqrestore(&msg_queue->lock, flags);
|
||||||
platform_send_ipi_cpu(cpu);
|
platform_send_ipi_cpu(cpu);
|
||||||
|
|
||||||
@ -292,7 +293,7 @@ void smp_send_reschedule(int cpu)
|
|||||||
|
|
||||||
msg_queue = &per_cpu(ipi_msg_queue, cpu);
|
msg_queue = &per_cpu(ipi_msg_queue, cpu);
|
||||||
spin_lock_irqsave(&msg_queue->lock, flags);
|
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);
|
spin_unlock_irqrestore(&msg_queue->lock, flags);
|
||||||
platform_send_ipi_cpu(cpu);
|
platform_send_ipi_cpu(cpu);
|
||||||
|
|
||||||
@ -320,7 +321,7 @@ void smp_send_stop(void)
|
|||||||
for_each_cpu_mask(cpu, callmap) {
|
for_each_cpu_mask(cpu, callmap) {
|
||||||
msg_queue = &per_cpu(ipi_msg_queue, cpu);
|
msg_queue = &per_cpu(ipi_msg_queue, cpu);
|
||||||
spin_lock_irqsave(&msg_queue->lock, flags);
|
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);
|
spin_unlock_irqrestore(&msg_queue->lock, flags);
|
||||||
platform_send_ipi_cpu(cpu);
|
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);
|
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
|
#ifdef __ARCH_SYNC_CORE_DCACHE
|
||||||
unsigned long barrier_mask __attribute__ ((__section__(".l2.bss")));
|
unsigned long barrier_mask __attribute__ ((__section__(".l2.bss")));
|
||||||
|
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
#include <linux/sort.h>
|
#include <linux/sort.h>
|
||||||
|
|
||||||
#include <asm/uaccess.h>
|
#include <asm/uaccess.h>
|
||||||
#include <asm/module.h>
|
#include <linux/module.h>
|
||||||
|
|
||||||
static int cmp_ex(const void *a, const void *b)
|
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)
|
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
|
#ifdef CONFIG_MODULES
|
||||||
|
@ -963,7 +963,7 @@ CONFIG_EEPROM_LEGACY=y
|
|||||||
CONFIG_SENSORS_PCF8574=y
|
CONFIG_SENSORS_PCF8574=y
|
||||||
# CONFIG_PCF8575 is not set
|
# CONFIG_PCF8575 is not set
|
||||||
CONFIG_SENSORS_PCF8591=y
|
CONFIG_SENSORS_PCF8591=y
|
||||||
CONFIG_SENSORS_MAX6875=y
|
CONFIG_EEPROM_MAX6875=y
|
||||||
# CONFIG_SENSORS_TSL2550 is not set
|
# CONFIG_SENSORS_TSL2550 is not set
|
||||||
CONFIG_I2C_DEBUG_CORE=y
|
CONFIG_I2C_DEBUG_CORE=y
|
||||||
CONFIG_I2C_DEBUG_ALGO=y
|
CONFIG_I2C_DEBUG_ALGO=y
|
||||||
|
@ -1849,7 +1849,7 @@ CONFIG_EEPROM_LEGACY=m
|
|||||||
CONFIG_SENSORS_PCF8574=m
|
CONFIG_SENSORS_PCF8574=m
|
||||||
CONFIG_SENSORS_PCA9539=m
|
CONFIG_SENSORS_PCA9539=m
|
||||||
CONFIG_SENSORS_PCF8591=m
|
CONFIG_SENSORS_PCF8591=m
|
||||||
CONFIG_SENSORS_MAX6875=m
|
CONFIG_EEPROM_MAX6875=m
|
||||||
# CONFIG_SENSORS_TSL2550 is not set
|
# CONFIG_SENSORS_TSL2550 is not set
|
||||||
# CONFIG_I2C_DEBUG_CORE is not set
|
# CONFIG_I2C_DEBUG_CORE is not set
|
||||||
# CONFIG_I2C_DEBUG_ALGO is not set
|
# CONFIG_I2C_DEBUG_ALGO is not set
|
||||||
|
@ -119,6 +119,8 @@
|
|||||||
#define EOWNERDEAD 165 /* Owner died */
|
#define EOWNERDEAD 165 /* Owner died */
|
||||||
#define ENOTRECOVERABLE 166 /* State not recoverable */
|
#define ENOTRECOVERABLE 166 /* State not recoverable */
|
||||||
|
|
||||||
|
#define ERFKILL 167 /* Operation not possible due to RF-kill */
|
||||||
|
|
||||||
#define EDQUOT 1133 /* Quota exceeded */
|
#define EDQUOT 1133 /* Quota exceeded */
|
||||||
|
|
||||||
#ifdef __KERNEL__
|
#ifdef __KERNEL__
|
||||||
|
@ -120,5 +120,6 @@
|
|||||||
#define EOWNERDEAD 254 /* Owner died */
|
#define EOWNERDEAD 254 /* Owner died */
|
||||||
#define ENOTRECOVERABLE 255 /* State not recoverable */
|
#define ENOTRECOVERABLE 255 /* State not recoverable */
|
||||||
|
|
||||||
|
#define ERFKILL 256 /* Operation not possible due to RF-kill */
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -1808,7 +1808,7 @@ CONFIG_PCF8575=m
|
|||||||
CONFIG_SENSORS_PCA9539=m
|
CONFIG_SENSORS_PCA9539=m
|
||||||
CONFIG_SENSORS_PCF8591=m
|
CONFIG_SENSORS_PCF8591=m
|
||||||
# CONFIG_TPS65010 is not set
|
# CONFIG_TPS65010 is not set
|
||||||
CONFIG_SENSORS_MAX6875=m
|
CONFIG_EEPROM_MAX6875=m
|
||||||
CONFIG_SENSORS_TSL2550=m
|
CONFIG_SENSORS_TSL2550=m
|
||||||
CONFIG_MCU_MPC8349EMITX=m
|
CONFIG_MCU_MPC8349EMITX=m
|
||||||
# CONFIG_I2C_DEBUG_CORE is not set
|
# 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_RMM 0x00001000
|
||||||
#define UCC_GETH_UPSMR_CAM 0x00000400
|
#define UCC_GETH_UPSMR_CAM 0x00000400
|
||||||
#define UCC_GETH_UPSMR_BRO 0x00000200
|
#define UCC_GETH_UPSMR_BRO 0x00000200
|
||||||
|
#define UCC_GETH_UPSMR_SMM 0x00000080
|
||||||
|
#define UCC_GETH_UPSMR_SGMM 0x00000020
|
||||||
|
|
||||||
/* UCC Transmit On Demand Register (UTODR) */
|
/* UCC Transmit On Demand Register (UTODR) */
|
||||||
#define UCC_SLOW_TOD 0x8000
|
#define UCC_SLOW_TOD 0x8000
|
||||||
|
@ -14,6 +14,7 @@
|
|||||||
#include <linux/interrupt.h>
|
#include <linux/interrupt.h>
|
||||||
#include <linux/fsl_devices.h>
|
#include <linux/fsl_devices.h>
|
||||||
#include <linux/mdio-bitbang.h>
|
#include <linux/mdio-bitbang.h>
|
||||||
|
#include <linux/of_mdio.h>
|
||||||
#include <linux/of_platform.h>
|
#include <linux/of_platform.h>
|
||||||
|
|
||||||
#include <asm/io.h>
|
#include <asm/io.h>
|
||||||
@ -115,7 +116,7 @@ static int __devinit ep8248e_mdio_probe(struct of_device *ofdev,
|
|||||||
struct mii_bus *bus;
|
struct mii_bus *bus;
|
||||||
struct resource res;
|
struct resource res;
|
||||||
struct device_node *node;
|
struct device_node *node;
|
||||||
int ret, i;
|
int ret;
|
||||||
|
|
||||||
node = of_get_parent(ofdev->node);
|
node = of_get_parent(ofdev->node);
|
||||||
of_node_put(node);
|
of_node_put(node);
|
||||||
@ -130,17 +131,13 @@ static int __devinit ep8248e_mdio_probe(struct of_device *ofdev,
|
|||||||
if (!bus)
|
if (!bus)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
bus->phy_mask = 0;
|
|
||||||
bus->irq = kmalloc(sizeof(int) * PHY_MAX_ADDR, GFP_KERNEL);
|
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->name = "ep8248e-mdio-bitbang";
|
||||||
bus->parent = &ofdev->dev;
|
bus->parent = &ofdev->dev;
|
||||||
snprintf(bus->id, MII_BUS_ID_SIZE, "%x", res.start);
|
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)
|
static int ep8248e_mdio_remove(struct of_device *ofdev)
|
||||||
|
@ -29,7 +29,7 @@
|
|||||||
#include <linux/ioport.h>
|
#include <linux/ioport.h>
|
||||||
#include <linux/interrupt.h>
|
#include <linux/interrupt.h>
|
||||||
#include <linux/phy.h>
|
#include <linux/phy.h>
|
||||||
#include <linux/platform_device.h>
|
#include <linux/of_mdio.h>
|
||||||
#include <linux/of_platform.h>
|
#include <linux/of_platform.h>
|
||||||
|
|
||||||
#define DELAY 1
|
#define DELAY 1
|
||||||
@ -39,6 +39,7 @@ static void __iomem *gpio_regs;
|
|||||||
struct gpio_priv {
|
struct gpio_priv {
|
||||||
int mdc_pin;
|
int mdc_pin;
|
||||||
int mdio_pin;
|
int mdio_pin;
|
||||||
|
int mdio_irqs[PHY_MAX_ADDR];
|
||||||
};
|
};
|
||||||
|
|
||||||
#define MDC_PIN(bus) (((struct gpio_priv *)bus->priv)->mdc_pin)
|
#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)
|
const struct of_device_id *match)
|
||||||
{
|
{
|
||||||
struct device *dev = &ofdev->dev;
|
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 mii_bus *new_bus;
|
||||||
struct gpio_priv *priv;
|
struct gpio_priv *priv;
|
||||||
const unsigned int *prop;
|
const unsigned int *prop;
|
||||||
int err;
|
int err;
|
||||||
int i;
|
|
||||||
|
|
||||||
err = -ENOMEM;
|
err = -ENOMEM;
|
||||||
priv = kzalloc(sizeof(struct gpio_priv), GFP_KERNEL);
|
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);
|
snprintf(new_bus->id, MII_BUS_ID_SIZE, "%x", *prop);
|
||||||
new_bus->priv = priv;
|
new_bus->priv = priv;
|
||||||
|
|
||||||
new_bus->phy_mask = 0;
|
new_bus->irq = priv->mdio_irqs;
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
prop = of_get_property(np, "mdc-pin", NULL);
|
prop = of_get_property(np, "mdc-pin", NULL);
|
||||||
priv->mdc_pin = *prop;
|
priv->mdc_pin = *prop;
|
||||||
@ -275,7 +255,7 @@ static int __devinit gpio_mdio_probe(struct of_device *ofdev,
|
|||||||
new_bus->parent = dev;
|
new_bus->parent = dev;
|
||||||
dev_set_drvdata(dev, new_bus);
|
dev_set_drvdata(dev, new_bus);
|
||||||
|
|
||||||
err = mdiobus_register(new_bus);
|
err = of_mdiobus_register(new_bus, np);
|
||||||
|
|
||||||
if (err != 0) {
|
if (err != 0) {
|
||||||
printk(KERN_ERR "%s: Cannot register as MDIO bus, err %d\n",
|
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;
|
return 0;
|
||||||
|
|
||||||
out_free_irq:
|
out_free_irq:
|
||||||
kfree(new_bus->irq);
|
|
||||||
out_free_bus:
|
|
||||||
kfree(new_bus);
|
kfree(new_bus);
|
||||||
out_free_priv:
|
out_free_priv:
|
||||||
kfree(priv);
|
kfree(priv);
|
||||||
|
@ -348,6 +348,9 @@ config ARCH_ENABLE_MEMORY_HOTPLUG
|
|||||||
config ARCH_ENABLE_MEMORY_HOTREMOVE
|
config ARCH_ENABLE_MEMORY_HOTREMOVE
|
||||||
def_bool y
|
def_bool y
|
||||||
|
|
||||||
|
config ARCH_HIBERNATION_POSSIBLE
|
||||||
|
def_bool y if 64BIT
|
||||||
|
|
||||||
source "mm/Kconfig"
|
source "mm/Kconfig"
|
||||||
|
|
||||||
comment "I/O subsystem configuration"
|
comment "I/O subsystem configuration"
|
||||||
@ -592,6 +595,12 @@ config SECCOMP
|
|||||||
|
|
||||||
endmenu
|
endmenu
|
||||||
|
|
||||||
|
menu "Power Management"
|
||||||
|
|
||||||
|
source "kernel/power/Kconfig"
|
||||||
|
|
||||||
|
endmenu
|
||||||
|
|
||||||
source "net/Kconfig"
|
source "net/Kconfig"
|
||||||
|
|
||||||
config PCMCIA
|
config PCMCIA
|
||||||
|
@ -88,7 +88,9 @@ LDFLAGS_vmlinux := -e start
|
|||||||
head-y := arch/s390/kernel/head.o arch/s390/kernel/init_task.o
|
head-y := arch/s390/kernel/head.o arch/s390/kernel/init_task.o
|
||||||
|
|
||||||
core-y += arch/s390/mm/ arch/s390/kernel/ arch/s390/crypto/ \
|
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/
|
libs-y += arch/s390/lib/
|
||||||
drivers-y += drivers/s390/
|
drivers-y += drivers/s390/
|
||||||
drivers-$(CONFIG_MATHEMU) += arch/s390/math-emu/
|
drivers-$(CONFIG_MATHEMU) += arch/s390/math-emu/
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
* Exports appldata_register_ops() and appldata_unregister_ops() for the
|
* Exports appldata_register_ops() and appldata_unregister_ops() for the
|
||||||
* data gathering modules.
|
* data gathering modules.
|
||||||
*
|
*
|
||||||
* Copyright IBM Corp. 2003, 2008
|
* Copyright IBM Corp. 2003, 2009
|
||||||
*
|
*
|
||||||
* Author: Gerald Schaefer <gerald.schaefer@de.ibm.com>
|
* Author: Gerald Schaefer <gerald.schaefer@de.ibm.com>
|
||||||
*/
|
*/
|
||||||
@ -26,6 +26,8 @@
|
|||||||
#include <linux/notifier.h>
|
#include <linux/notifier.h>
|
||||||
#include <linux/cpu.h>
|
#include <linux/cpu.h>
|
||||||
#include <linux/workqueue.h>
|
#include <linux/workqueue.h>
|
||||||
|
#include <linux/suspend.h>
|
||||||
|
#include <linux/platform_device.h>
|
||||||
#include <asm/appldata.h>
|
#include <asm/appldata.h>
|
||||||
#include <asm/timer.h>
|
#include <asm/timer.h>
|
||||||
#include <asm/uaccess.h>
|
#include <asm/uaccess.h>
|
||||||
@ -41,6 +43,9 @@
|
|||||||
|
|
||||||
#define TOD_MICRO 0x01000 /* nr. of TOD clock units
|
#define TOD_MICRO 0x01000 /* nr. of TOD clock units
|
||||||
for 1 microsecond */
|
for 1 microsecond */
|
||||||
|
|
||||||
|
static struct platform_device *appldata_pdev;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* /proc entries (sysctl)
|
* /proc entries (sysctl)
|
||||||
*/
|
*/
|
||||||
@ -86,6 +91,7 @@ static atomic_t appldata_expire_count = ATOMIC_INIT(0);
|
|||||||
static DEFINE_SPINLOCK(appldata_timer_lock);
|
static DEFINE_SPINLOCK(appldata_timer_lock);
|
||||||
static int appldata_interval = APPLDATA_CPU_INTERVAL;
|
static int appldata_interval = APPLDATA_CPU_INTERVAL;
|
||||||
static int appldata_timer_active;
|
static int appldata_timer_active;
|
||||||
|
static int appldata_timer_suspended = 0;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Work queue
|
* Work queue
|
||||||
@ -475,6 +481,93 @@ void appldata_unregister_ops(struct appldata_ops *ops)
|
|||||||
/********************** module-ops management <END> **************************/
|
/********************** 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 *********************************/
|
/******************************* init / exit *********************************/
|
||||||
|
|
||||||
static void __cpuinit appldata_online_cpu(int cpu)
|
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)
|
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");
|
appldata_wq = create_singlethread_workqueue("appldata");
|
||||||
if (!appldata_wq)
|
if (!appldata_wq) {
|
||||||
return -ENOMEM;
|
rc = -ENOMEM;
|
||||||
|
goto out_device;
|
||||||
|
}
|
||||||
|
|
||||||
get_online_cpus();
|
get_online_cpus();
|
||||||
for_each_online_cpu(i)
|
for_each_online_cpu(i)
|
||||||
@ -547,6 +652,12 @@ static int __init appldata_init(void)
|
|||||||
|
|
||||||
appldata_sysctl_header = register_sysctl_table(appldata_dir_table);
|
appldata_sysctl_header = register_sysctl_table(appldata_dir_table);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
out_device:
|
||||||
|
platform_device_unregister(appldata_pdev);
|
||||||
|
out_driver:
|
||||||
|
platform_driver_unregister(&appldata_pdrv);
|
||||||
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
__initcall(appldata_init);
|
__initcall(appldata_init);
|
||||||
|
@ -1,11 +1,9 @@
|
|||||||
/*
|
/*
|
||||||
* include/asm-s390/ccwdev.h
|
* Copyright IBM Corp. 2002, 2009
|
||||||
* include/asm-s390x/ccwdev.h
|
|
||||||
*
|
*
|
||||||
* 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_
|
#ifndef _S390_CCWDEV_H_
|
||||||
#define _S390_CCWDEV_H_
|
#define _S390_CCWDEV_H_
|
||||||
@ -104,6 +102,11 @@ struct ccw_device {
|
|||||||
* @set_offline: called when setting device offline
|
* @set_offline: called when setting device offline
|
||||||
* @notify: notify driver of device state changes
|
* @notify: notify driver of device state changes
|
||||||
* @shutdown: called at device shutdown
|
* @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
|
* @driver: embedded device driver structure
|
||||||
* @name: device driver name
|
* @name: device driver name
|
||||||
*/
|
*/
|
||||||
@ -116,6 +119,11 @@ struct ccw_driver {
|
|||||||
int (*set_offline) (struct ccw_device *);
|
int (*set_offline) (struct ccw_device *);
|
||||||
int (*notify) (struct ccw_device *, int);
|
int (*notify) (struct ccw_device *, int);
|
||||||
void (*shutdown) (struct ccw_device *);
|
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;
|
struct device_driver driver;
|
||||||
char *name;
|
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)
|
#define to_ccwdrv(n) container_of(n, struct ccw_driver, driver)
|
||||||
|
|
||||||
extern struct ccw_device *ccw_device_probe_console(void);
|
extern struct ccw_device *ccw_device_probe_console(void);
|
||||||
|
extern int ccw_device_force_console(void);
|
||||||
|
|
||||||
// FIXME: these have to go
|
// FIXME: these have to go
|
||||||
extern int _ccw_device_get_subchannel_number(struct ccw_device *);
|
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_online: function called when device is set online
|
||||||
* @set_offline: function called when device is set offline
|
* @set_offline: function called when device is set offline
|
||||||
* @shutdown: function called when device is shut down
|
* @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
|
* @driver: embedded driver structure
|
||||||
*/
|
*/
|
||||||
struct ccwgroup_driver {
|
struct ccwgroup_driver {
|
||||||
@ -51,6 +56,11 @@ struct ccwgroup_driver {
|
|||||||
int (*set_online) (struct ccwgroup_device *);
|
int (*set_online) (struct ccwgroup_device *);
|
||||||
int (*set_offline) (struct ccwgroup_device *);
|
int (*set_offline) (struct ccwgroup_device *);
|
||||||
void (*shutdown)(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;
|
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
|
* Author(s): Martin Schwidefsky <schwidefsky@de.ibm.com>
|
||||||
* Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
|
|
||||||
* Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com),
|
|
||||||
*
|
|
||||||
* Derived from "include/asm-i386/system.h"
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __ASM_SYSTEM_H
|
#ifndef __ASM_SYSTEM_H
|
||||||
@ -469,6 +465,20 @@ extern psw_t sysc_restore_trace_psw;
|
|||||||
extern psw_t io_restore_trace_psw;
|
extern psw_t io_restore_trace_psw;
|
||||||
#endif
|
#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 /* __KERNEL__ */
|
||||||
|
|
||||||
#endif
|
#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