blob: c6c7740472aa34045f86a01dbc510bf01a44e39e [file] [log] [blame]
Introduction
============
Glink packet drivers are companion adaptation driver which use the kernel APIs
to expose the Glink core logical channels as charecter devices to the
user-space clients.
The Glink core APIs are detailed in Documentation/arm/msm/glink.txt.
Software description
====================
Glink packet drivers supports the Glink core APIs to user-space client through
standard file operations like open, read, write, ioctl, poll and release etc.
The standard Linux permissions are used for the device node and SELinux does
further security checks.
Device node [0..n]
|
|
-------------------
| VFS Framework |
-------------------
| |
| |
------- -------
| CDEV | | CDEV |
| Dev 0 |...| Dev n |
----------------------
| Glink packet driver |
----------------------
|
|
-----------------
| |
| G-Link core |
| |
-----------------
|
|
To Remote System
The file operations map to the G-link client API as follows:
Open():
----------
The Open system call is mapped to glink_open() which opens a channel. The
expected channel configuration has to done through DT files. The full DT schema
is detailed in Documentation/devicetree/bindings/arm/msm/glinkpkt.txt.
Open on the glink packet character device is a blocking call which blocks until
the channel is fully open by both local processor and remote processor.
Clients can configure the blocking time through a device configurable parameter
defined per device.
The timeout value is specified in seconds with a default timeout of 1 second.
A negative value indicates an infinite wait.
Example:
# get open timeout value
cat /sys/class/glinkpkt/device_name/open_timeout
# set to 20 seconds value
echo 20 > /sys/class/glinkpkt/device_name/open_timeout
If the channel is not opened by remote processor or any other problem which
fails the channel to be ready will result in timeout and -ETIMEOUT will return
to client. Open on success returns the valid file descriptor to client and on
fail case standard Linux error codes.
The same device can be opened by multiple clients but passing the same file
descriptor from multiple threads may lead unexpected results.
Write():
----------
The Write system call is mapped to glink_tx() which transmits the data over the
glink channel.
Read():
----------
The Read system call consumes any pending data on the channel. Glink signals
incoming data through the glink_notify_rx() call back and the glink packet
driver queues the data internally and provides to client through read system
call. Once the Read is completed, the glink packet driver calls glink_rx_done()
API to notify the completion of receiving operation to Glink core.
+
User-Space | Kernel-Space
|
|
+---------+ | +----------+ +------------+
| Local | | | GlinkPKT | | |
| Client | | | Driver | | Glink core |
| | | | | | |
+---------+ | +----------+ +------------+
|
+ | + +
| | | |
| open() | glink_pkt_open() | glink_open() |
| +--------------> | +-----------------> | +-----------------> |
| | | |
| File Handle[fd]| Valid Fd | Handle |
| <--------------+ | <-----------------+ | <-----------------+ |
| | | |
| Ioctl() | | |
| QUEUE_RX_INTENT | glink_pkt_ioctl() | glink_queue_rx_intent()
| +--------------> | +-----------------> | +-----------------> |
| | | |
| | | |
| <----------------------------------------------------------+ |
| | | |
| Read() | glink_pkt_read() | |
| +--------------> | +-----------------> | +---+ |
| | | | |
| | Wait for data |
| | | <---+ |
| | | glink_notify_rx() |
| | | <-----------------+ |
| | Wake-up read() | |
| | copy_to_user() | |
| read() return | <-----------------+ | |
| <--------------+ | | |
+ | + +
|
|
+
Clients can also poll on device node for POLLIN mask to get notification for
any incoming data. Clients have to call the GLINK_PKT_IOCTL_QUEUE_RX_INTENT
ioctl to queue the RX buffer to glink core in advance.
Release():
----------
The Release system call is mapped to glink_close() to close a channel and free
the resources.
Poll():
----------
The Poll system call provides waiting operation like wait for incoming data on
POLLIN mask and to get the TIOCM signal notification on POLLPRI mask. Clients
can wait on poll for POLLPRI mask to get any notification regarding TICOM
signals. In SSR case Poll call will return with POLLHUP mask and in this case
client has to close and re-open the port.
* POLLPRI - TIOCM bits changed
* POLLIN - RX data available
* POLLHUP - link is down due to either remote side closing or an SSR
Ioctl():
----------
Multiple ioctls are supported to get the TICOM signal status and to queue the
Rx intent with Glink core. Supported ioctls are TIOCMSET, TIOCMGET, TIOCMBIS,
TIOCMBIC and GLINK_PKT_IOCTL_QUEUE_RX_INTENT.
The GLINK_PKT_IOCTL_QUEUE_RX_INTENT ioctl is mapped to glink_queue_rx_intent()
API which queues an RX intent with Glink core.
Signals:
==========
Glink protocol provoide 32-bit control signal field to pass through for the
clients-specific signaling where as Glink packet driver client which are from
user space can use the signal filed as mentioned below.
* 31:28 - Reserved for SMD RS-232 signals
* 27:16 - Pass through for client usage
* 15:0 - TICOM bits
SSR operation:
==============
On remote subsystem restart all open channels on that edge will be closed and
local clients have to close and re-open the channel to re-start the
communication. All blocking calls such as open, read and write will be returned
with -ENETRESET and the poll call will be return with the POLLHUP error codes.
Files:
==========
Documentation/devicetree/bindings/arm/msm/glinkpkt.txt
drivers/soc/qcom/msm_glink_pkt.c
Wakelock:
==========
By default, GLINK PKT will acquire a wakelock for 2 seconds. To optimize this
behavior, use the poll() function:
1. Client calls poll() which blocks until data is available to read
2. Data comes in, GLINK PKT grabs a wakelock and poll()is unblocked
3. Client grabs wakelock to prevent system from suspending
4. Client calls GLINK PKT read() to read the data
5. GLINK PKT releases its wakelock
6. Client Processes the data
7. Client releases the wakelock
Logging:
==========
cat /d/ipc_logging/glink_pkt/log_cont