diff options
author | Thomas Zimmermann <tzimmermann@suse.de> | 2022-06-20 18:21:25 +0200 |
---|---|---|
committer | Thomas Zimmermann <tzimmermann@suse.de> | 2022-06-20 18:21:25 +0200 |
commit | 2b1333b80885b896807ffb6ccf4bc21d29aa65e0 (patch) | |
tree | 51cc2d13d65603383db82c87f01a0aa93bd26010 /Documentation/driver-api | |
parent | cad564ca557f8d3bb3b1fa965d9a2b3f6490ec69 (diff) | |
parent | 0f95ee9a0c579ebed0309657f6918673927189f2 (diff) | |
download | linux-stable-2b1333b80885b896807ffb6ccf4bc21d29aa65e0.tar.gz linux-stable-2b1333b80885b896807ffb6ccf4bc21d29aa65e0.tar.bz2 linux-stable-2b1333b80885b896807ffb6ccf4bc21d29aa65e0.zip |
Merge drm/drm-next into drm-misc-next
Backmerging to get new regmap APIs of v5.19-rc1.
Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
Diffstat (limited to 'Documentation/driver-api')
29 files changed, 1230 insertions, 237 deletions
diff --git a/Documentation/driver-api/dmaengine/provider.rst b/Documentation/driver-api/dmaengine/provider.rst index 0072c9c7efd3..1e0f1f85d10e 100644 --- a/Documentation/driver-api/dmaengine/provider.rst +++ b/Documentation/driver-api/dmaengine/provider.rst @@ -206,6 +206,12 @@ Currently, the types available are: - The device is able to perform parity check using RAID6 P+Q algorithm against a memory buffer. +- DMA_MEMSET + + - The device is able to fill memory with the provided pattern + + - The pattern is treated as a single byte signed value. + - DMA_INTERRUPT - The device is able to trigger a dummy transfer that will @@ -457,7 +463,7 @@ supported. - Should use dma_set_residue to report it - In the case of a cyclic transfer, it should only take into - account the current period. + account the total size of the cyclic buffer. - Should return DMA_OUT_OF_ORDER if the device does not support in order completion and is completing the operation out of order. diff --git a/Documentation/driver-api/driver-model/devres.rst b/Documentation/driver-api/driver-model/devres.rst index 5018403fe82f..2d39967bafcc 100644 --- a/Documentation/driver-api/driver-model/devres.rst +++ b/Documentation/driver-api/driver-model/devres.rst @@ -249,7 +249,7 @@ CLOCK devm_clk_bulk_get() devm_clk_bulk_get_all() devm_clk_bulk_get_optional() - devm_get_clk_from_childl() + devm_get_clk_from_child() devm_clk_hw_register() devm_of_clk_add_hw_provider() devm_clk_hw_register_clkdev() diff --git a/Documentation/driver-api/firmware/fw_upload.rst b/Documentation/driver-api/firmware/fw_upload.rst new file mode 100644 index 000000000000..76922591e446 --- /dev/null +++ b/Documentation/driver-api/firmware/fw_upload.rst @@ -0,0 +1,126 @@ +.. SPDX-License-Identifier: GPL-2.0 + +=================== +Firmware Upload API +=================== + +A device driver that registers with the firmware loader will expose +persistent sysfs nodes to enable users to initiate firmware updates for +that device. It is the responsibility of the device driver and/or the +device itself to perform any validation on the data received. Firmware +upload uses the same *loading* and *data* sysfs files described in the +documentation for firmware fallback. It also adds additional sysfs files +to provide status on the transfer of the firmware image to the device. + +Register for firmware upload +============================ + +A device driver registers for firmware upload by calling +firmware_upload_register(). Among the parameter list is a name to +identify the device under /sys/class/firmware. A user may initiate a +firmware upload by echoing a 1 to the *loading* sysfs file for the target +device. Next, the user writes the firmware image to the *data* sysfs +file. After writing the firmware data, the user echos 0 to the *loading* +sysfs file to signal completion. Echoing 0 to *loading* also triggers the +transfer of the firmware to the lower-lever device driver in the context +of a kernel worker thread. + +To use the firmware upload API, write a driver that implements a set of +ops. The probe function calls firmware_upload_register() and the remove +function calls firmware_upload_unregister() such as:: + + static const struct fw_upload_ops m10bmc_ops = { + .prepare = m10bmc_sec_prepare, + .write = m10bmc_sec_write, + .poll_complete = m10bmc_sec_poll_complete, + .cancel = m10bmc_sec_cancel, + .cleanup = m10bmc_sec_cleanup, + }; + + static int m10bmc_sec_probe(struct platform_device *pdev) + { + const char *fw_name, *truncate; + struct m10bmc_sec *sec; + struct fw_upload *fwl; + unsigned int len; + + sec = devm_kzalloc(&pdev->dev, sizeof(*sec), GFP_KERNEL); + if (!sec) + return -ENOMEM; + + sec->dev = &pdev->dev; + sec->m10bmc = dev_get_drvdata(pdev->dev.parent); + dev_set_drvdata(&pdev->dev, sec); + + fw_name = dev_name(sec->dev); + truncate = strstr(fw_name, ".auto"); + len = (truncate) ? truncate - fw_name : strlen(fw_name); + sec->fw_name = kmemdup_nul(fw_name, len, GFP_KERNEL); + + fwl = firmware_upload_register(sec->dev, sec->fw_name, &m10bmc_ops, sec); + if (IS_ERR(fwl)) { + dev_err(sec->dev, "Firmware Upload driver failed to start\n"); + kfree(sec->fw_name); + return PTR_ERR(fwl); + } + + sec->fwl = fwl; + return 0; + } + + static int m10bmc_sec_remove(struct platform_device *pdev) + { + struct m10bmc_sec *sec = dev_get_drvdata(&pdev->dev); + + firmware_upload_unregister(sec->fwl); + kfree(sec->fw_name); + return 0; + } + +firmware_upload_register +------------------------ +.. kernel-doc:: drivers/base/firmware_loader/sysfs_upload.c + :identifiers: firmware_upload_register + +firmware_upload_unregister +-------------------------- +.. kernel-doc:: drivers/base/firmware_loader/sysfs_upload.c + :identifiers: firmware_upload_unregister + +Firmware Upload Ops +------------------- +.. kernel-doc:: include/linux/firmware.h + :identifiers: fw_upload_ops + +Firmware Upload Progress Codes +------------------------------ +The following progress codes are used internally by the firmware loader. +Corresponding strings are reported through the status sysfs node that +is described below and are documented in the ABI documentation. + +.. kernel-doc:: drivers/base/firmware_loader/sysfs_upload.h + :identifiers: fw_upload_prog + +Firmware Upload Error Codes +--------------------------- +The following error codes may be returned by the driver ops in case of +failure: + +.. kernel-doc:: include/linux/firmware.h + :identifiers: fw_upload_err + +Sysfs Attributes +================ + +In addition to the *loading* and *data* sysfs files, there are additional +sysfs files to monitor the status of the data transfer to the target +device and to determine the final pass/fail status of the transfer. +Depending on the device and the size of the firmware image, a firmware +update could take milliseconds or minutes. + +The additional sysfs files are: + +* status - provides an indication of the progress of a firmware update +* error - provides error information for a failed firmware update +* remaining_size - tracks the data transfer portion of an update +* cancel - echo 1 to this file to cancel the update diff --git a/Documentation/driver-api/firmware/index.rst b/Documentation/driver-api/firmware/index.rst index 57415d657173..9d2c19dc8e36 100644 --- a/Documentation/driver-api/firmware/index.rst +++ b/Documentation/driver-api/firmware/index.rst @@ -8,6 +8,7 @@ Linux Firmware API core efi/index request_firmware + fw_upload other_interfaces .. only:: subproject and html diff --git a/Documentation/driver-api/gpio/driver.rst b/Documentation/driver-api/gpio/driver.rst index bbc53920d4dd..70ff43ac4fcc 100644 --- a/Documentation/driver-api/gpio/driver.rst +++ b/Documentation/driver-api/gpio/driver.rst @@ -417,30 +417,68 @@ struct gpio_irq_chip inside struct gpio_chip before adding the gpio_chip. If you do this, the additional irq_chip will be set up by gpiolib at the same time as setting up the rest of the GPIO functionality. The following is a typical example of a chained cascaded interrupt handler using -the gpio_irq_chip: +the gpio_irq_chip. Note how the mask/unmask (or disable/enable) functions +call into the core gpiolib code: .. code-block:: c - /* Typical state container with dynamic irqchip */ + /* Typical state container */ struct my_gpio { struct gpio_chip gc; - struct irq_chip irq; + }; + + static void my_gpio_mask_irq(struct irq_data *d) + { + struct gpio_chip *gc = irq_data_get_irq_chip_data(d); + irq_hw_number_t hwirq = irqd_to_hwirq(d); + + /* + * Perform any necessary action to mask the interrupt, + * and then call into the core code to synchronise the + * state. + */ + + gpiochip_disable_irq(gc, hwirq); + } + + static void my_gpio_unmask_irq(struct irq_data *d) + { + struct gpio_chip *gc = irq_data_get_irq_chip_data(d); + irq_hw_number_t hwirq = irqd_to_hwirq(d); + + gpiochip_enable_irq(gc, hwirq); + + /* + * Perform any necessary action to unmask the interrupt, + * after having called into the core code to synchronise + * the state. + */ + } + + /* + * Statically populate the irqchip. Note that it is made const + * (further indicated by the IRQCHIP_IMMUTABLE flag), and that + * the GPIOCHIP_IRQ_RESOURCE_HELPER macro adds some extra + * callbacks to the structure. + */ + static const struct irq_chip my_gpio_irq_chip = { + .name = "my_gpio_irq", + .irq_ack = my_gpio_ack_irq, + .irq_mask = my_gpio_mask_irq, + .irq_unmask = my_gpio_unmask_irq, + .irq_set_type = my_gpio_set_irq_type, + .flags = IRQCHIP_IMMUTABLE, + /* Provide the gpio resource callbacks */ + GPIOCHIP_IRQ_RESOURCE_HELPERS, }; int irq; /* from platform etc */ struct my_gpio *g; struct gpio_irq_chip *girq; - /* Set up the irqchip dynamically */ - g->irq.name = "my_gpio_irq"; - g->irq.irq_ack = my_gpio_ack_irq; - g->irq.irq_mask = my_gpio_mask_irq; - g->irq.irq_unmask = my_gpio_unmask_irq; - g->irq.irq_set_type = my_gpio_set_irq_type; - /* Get a pointer to the gpio_irq_chip */ girq = &g->gc.irq; - girq->chip = &g->irq; + gpio_irq_chip_set_chip(girq, &my_gpio_irq_chip); girq->parent_handler = ftgpio_gpio_irq_handler; girq->num_parents = 1; girq->parents = devm_kcalloc(dev, 1, sizeof(*girq->parents), @@ -458,23 +496,60 @@ the interrupt separately and go with it: .. code-block:: c - /* Typical state container with dynamic irqchip */ + /* Typical state container */ struct my_gpio { struct gpio_chip gc; - struct irq_chip irq; + }; + + static void my_gpio_mask_irq(struct irq_data *d) + { + struct gpio_chip *gc = irq_data_get_irq_chip_data(d); + irq_hw_number_t hwirq = irqd_to_hwirq(d); + + /* + * Perform any necessary action to mask the interrupt, + * and then call into the core code to synchronise the + * state. + */ + + gpiochip_disable_irq(gc, hwirq); + } + + static void my_gpio_unmask_irq(struct irq_data *d) + { + struct gpio_chip *gc = irq_data_get_irq_chip_data(d); + irq_hw_number_t hwirq = irqd_to_hwirq(d); + + gpiochip_enable_irq(gc, hwirq); + + /* + * Perform any necessary action to unmask the interrupt, + * after having called into the core code to synchronise + * the state. + */ + } + + /* + * Statically populate the irqchip. Note that it is made const + * (further indicated by the IRQCHIP_IMMUTABLE flag), and that + * the GPIOCHIP_IRQ_RESOURCE_HELPER macro adds some extra + * callbacks to the structure. + */ + static const struct irq_chip my_gpio_irq_chip = { + .name = "my_gpio_irq", + .irq_ack = my_gpio_ack_irq, + .irq_mask = my_gpio_mask_irq, + .irq_unmask = my_gpio_unmask_irq, + .irq_set_type = my_gpio_set_irq_type, + .flags = IRQCHIP_IMMUTABLE, + /* Provide the gpio resource callbacks */ + GPIOCHIP_IRQ_RESOURCE_HELPERS, }; int irq; /* from platform etc */ struct my_gpio *g; struct gpio_irq_chip *girq; - /* Set up the irqchip dynamically */ - g->irq.name = "my_gpio_irq"; - g->irq.irq_ack = my_gpio_ack_irq; - g->irq.irq_mask = my_gpio_mask_irq; - g->irq.irq_unmask = my_gpio_unmask_irq; - g->irq.irq_set_type = my_gpio_set_irq_type; - ret = devm_request_threaded_irq(dev, irq, NULL, irq_thread_fn, IRQF_ONESHOT, "my-chip", g); if (ret < 0) @@ -482,7 +557,7 @@ the interrupt separately and go with it: /* Get a pointer to the gpio_irq_chip */ girq = &g->gc.irq; - girq->chip = &g->irq; + gpio_irq_chip_set_chip(girq, &my_gpio_irq_chip); /* This will let us handle the parent IRQ in the driver */ girq->parent_handler = NULL; girq->num_parents = 0; @@ -500,24 +575,63 @@ In this case the typical set-up will look like this: /* Typical state container with dynamic irqchip */ struct my_gpio { struct gpio_chip gc; - struct irq_chip irq; struct fwnode_handle *fwnode; }; - int irq; /* from platform etc */ + static void my_gpio_mask_irq(struct irq_data *d) + { + struct gpio_chip *gc = irq_data_get_irq_chip_data(d); + irq_hw_number_t hwirq = irqd_to_hwirq(d); + + /* + * Perform any necessary action to mask the interrupt, + * and then call into the core code to synchronise the + * state. + */ + + gpiochip_disable_irq(gc, hwirq); + irq_mask_mask_parent(d); + } + + static void my_gpio_unmask_irq(struct irq_data *d) + { + struct gpio_chip *gc = irq_data_get_irq_chip_data(d); + irq_hw_number_t hwirq = irqd_to_hwirq(d); + + gpiochip_enable_irq(gc, hwirq); + + /* + * Perform any necessary action to unmask the interrupt, + * after having called into the core code to synchronise + * the state. + */ + + irq_mask_unmask_parent(d); + } + + /* + * Statically populate the irqchip. Note that it is made const + * (further indicated by the IRQCHIP_IMMUTABLE flag), and that + * the GPIOCHIP_IRQ_RESOURCE_HELPER macro adds some extra + * callbacks to the structure. + */ + static const struct irq_chip my_gpio_irq_chip = { + .name = "my_gpio_irq", + .irq_ack = my_gpio_ack_irq, + .irq_mask = my_gpio_mask_irq, + .irq_unmask = my_gpio_unmask_irq, + .irq_set_type = my_gpio_set_irq_type, + .flags = IRQCHIP_IMMUTABLE, + /* Provide the gpio resource callbacks */ + GPIOCHIP_IRQ_RESOURCE_HELPERS, + }; + struct my_gpio *g; struct gpio_irq_chip *girq; - /* Set up the irqchip dynamically */ - g->irq.name = "my_gpio_irq"; - g->irq.irq_ack = my_gpio_ack_irq; - g->irq.irq_mask = my_gpio_mask_irq; - g->irq.irq_unmask = my_gpio_unmask_irq; - g->irq.irq_set_type = my_gpio_set_irq_type; - /* Get a pointer to the gpio_irq_chip */ girq = &g->gc.irq; - girq->chip = &g->irq; + gpio_irq_chip_set_chip(girq, &my_gpio_irq_chip); girq->default_type = IRQ_TYPE_NONE; girq->handler = handle_bad_irq; girq->fwnode = g->fwnode; @@ -605,8 +719,9 @@ When implementing an irqchip inside a GPIO driver, these two functions should typically be called in the .irq_disable() and .irq_enable() callbacks from the irqchip. -When using the gpiolib irqchip helpers, these callbacks are automatically -assigned. +When IRQCHIP_IMMUTABLE is not advertised by the irqchip, these callbacks +are automatically assigned. This behaviour is deprecated and on its way +to be removed from the kernel. Real-Time compliance for GPIO IRQ chips diff --git a/Documentation/driver-api/hte/hte.rst b/Documentation/driver-api/hte/hte.rst new file mode 100644 index 000000000000..153f3233c100 --- /dev/null +++ b/Documentation/driver-api/hte/hte.rst @@ -0,0 +1,79 @@ +.. SPDX-License-Identifier: GPL-2.0+ + +============================================ +The Linux Hardware Timestamping Engine (HTE) +============================================ + +:Author: Dipen Patel + +Introduction +------------ + +Certain devices have built in hardware timestamping engines which can +monitor sets of system signals, lines, buses etc... in realtime for state +change; upon detecting the change they can automatically store the timestamp at +the moment of occurrence. Such functionality may help achieve better accuracy +in obtaining timestamps than using software counterparts i.e. ktime and +friends. + +This document describes the API that can be used by hardware timestamping +engine provider and consumer drivers that want to use the hardware timestamping +engine (HTE) framework. Both consumers and providers must include +``#include <linux/hte.h>``. + +The HTE framework APIs for the providers +---------------------------------------- + +.. kernel-doc:: drivers/hte/hte.c + :functions: devm_hte_register_chip hte_push_ts_ns + +The HTE framework APIs for the consumers +---------------------------------------- + +.. kernel-doc:: drivers/hte/hte.c + :functions: hte_init_line_attr hte_ts_get hte_ts_put devm_hte_request_ts_ns hte_request_ts_ns hte_enable_ts hte_disable_ts of_hte_req_count hte_get_clk_src_info + +The HTE framework public structures +----------------------------------- +.. kernel-doc:: include/linux/hte.h + +More on the HTE timestamp data +------------------------------ +The ``struct hte_ts_data`` is used to pass timestamp details between the +consumers and the providers. It expresses timestamp data in nanoseconds in +u64. An example of the typical timestamp data life cycle, for the GPIO line is +as follows:: + + - Monitors GPIO line change. + - Detects the state change on GPIO line. + - Converts timestamps in nanoseconds. + - Stores GPIO raw level in raw_level variable if the provider has that + hardware capability. + - Pushes this hte_ts_data object to HTE subsystem. + - HTE subsystem increments seq counter and invokes consumer provided callback. + Based on callback return value, the HTE core invokes secondary callback in + the thread context. + +HTE subsystem debugfs attributes +-------------------------------- +HTE subsystem creates debugfs attributes at ``/sys/kernel/debug/hte/``. +It also creates line/signal-related debugfs attributes at +``/sys/kernel/debug/hte/<provider>/<label or line id>/``. Note that these +attributes are read-only. + +`ts_requested` + The total number of entities requested from the given provider, + where entity is specified by the provider and could represent + lines, GPIO, chip signals, buses etc... + The attribute will be available at + ``/sys/kernel/debug/hte/<provider>/``. + +`total_ts` + The total number of entities supported by the provider. + The attribute will be available at + ``/sys/kernel/debug/hte/<provider>/``. + +`dropped_timestamps` + The dropped timestamps for a given line. + The attribute will be available at + ``/sys/kernel/debug/hte/<provider>/<label or line id>/``. diff --git a/Documentation/driver-api/hte/index.rst b/Documentation/driver-api/hte/index.rst new file mode 100644 index 000000000000..9f43301c05dc --- /dev/null +++ b/Documentation/driver-api/hte/index.rst @@ -0,0 +1,22 @@ +.. SPDX-License-Identifier: GPL-2.0 + +============================================ +The Linux Hardware Timestamping Engine (HTE) +============================================ + +The HTE Subsystem +================= + +.. toctree:: + :maxdepth: 1 + + hte + +HTE Tegra Provider +================== + +.. toctree:: + :maxdepth: 1 + + tegra194-hte + diff --git a/Documentation/driver-api/hte/tegra194-hte.rst b/Documentation/driver-api/hte/tegra194-hte.rst new file mode 100644 index 000000000000..41983e04d2a0 --- /dev/null +++ b/Documentation/driver-api/hte/tegra194-hte.rst @@ -0,0 +1,49 @@ +.. SPDX-License-Identifier: GPL-2.0+ + +HTE Kernel provider driver +========================== + +Description +----------- +The Nvidia tegra194 HTE provider driver implements two GTE +(Generic Timestamping Engine) instances: 1) GPIO GTE and 2) LIC +(Legacy Interrupt Controller) IRQ GTE. Both GTE instances get the +timestamp from the system counter TSC which has 31.25MHz clock rate, and the +driver converts clock tick rate to nanoseconds before storing it as timestamp +value. + +GPIO GTE +-------- + +This GTE instance timestamps GPIO in real time. For that to happen GPIO +needs to be configured as input. The always on (AON) GPIO controller instance +supports timestamping GPIOs in real time and it has 39 GPIO lines. The GPIO GTE +and AON GPIO controller are tightly coupled as it requires very specific bits +to be set in GPIO config register before GPIO GTE can be used, for that GPIOLIB +adds two optional APIs as below. The GPIO GTE code supports both kernel +and userspace consumers. The kernel space consumers can directly talk to HTE +subsystem while userspace consumers timestamp requests go through GPIOLIB CDEV +framework to HTE subsystem. + +.. kernel-doc:: drivers/gpio/gpiolib.c + :functions: gpiod_enable_hw_timestamp_ns gpiod_disable_hw_timestamp_ns + +For userspace consumers, GPIO_V2_LINE_FLAG_EVENT_CLOCK_HTE flag must be +specified during IOCTL calls. Refer to ``tools/gpio/gpio-event-mon.c``, which +returns the timestamp in nanoseconds. + +LIC (Legacy Interrupt Controller) IRQ GTE +----------------------------------------- + +This GTE instance timestamps LIC IRQ lines in real time. There are 352 IRQ +lines which this instance can add timestamps to in real time. The hte +devicetree binding described at ``Documentation/devicetree/bindings/hte/`` +provides an example of how a consumer can request an IRQ line. Since it is a +one-to-one mapping with IRQ GTE provider, consumers can simply specify the IRQ +number that they are interested in. There is no userspace consumer support for +this GTE instance in the HTE framework. + +The provider source code of both IRQ and GPIO GTE instances is located at +``drivers/hte/hte-tegra194.c``. The test driver +``drivers/hte/hte-tegra194-test.c`` demonstrates HTE API usage for both IRQ +and GPIO GTE. diff --git a/Documentation/driver-api/index.rst b/Documentation/driver-api/index.rst index a7b0223e2886..a6d525cd9fc4 100644 --- a/Documentation/driver-api/index.rst +++ b/Documentation/driver-api/index.rst @@ -101,12 +101,14 @@ available subsections can be seen below. surface_aggregator/index switchtec sync_file + tty/index vfio-mediated-device vfio vfio-pci-device-specific-driver-acceptance xilinx/index xillybus zorro + hte/index .. only:: subproject and html diff --git a/Documentation/driver-api/libata.rst b/Documentation/driver-api/libata.rst index d477e296bda5..311af516a3fd 100644 --- a/Documentation/driver-api/libata.rst +++ b/Documentation/driver-api/libata.rst @@ -424,12 +424,6 @@ How commands are issued ----------------------- Internal commands - First, qc is allocated and initialized using :c:func:`ata_qc_new_init`. - Although :c:func:`ata_qc_new_init` doesn't implement any wait or retry - mechanism when qc is not available, internal commands are currently - issued only during initialization and error recovery, so no other - command is active and allocation is guaranteed to succeed. - Once allocated qc's taskfile is initialized for the command to be executed. qc currently has two mechanisms to notify completion. One is via ``qc->complete_fn()`` callback and the other is completion @@ -447,11 +441,6 @@ SCSI commands translated. No qc is involved in processing a simulated scmd. The result is computed right away and the scmd is completed. - For a translated scmd, :c:func:`ata_qc_new_init` is invoked to allocate a - qc and the scmd is translated into the qc. SCSI midlayer's - completion notification function pointer is stored into - ``qc->scsidone``. - ``qc->complete_fn()`` callback is used for completion notification. ATA commands use :c:func:`ata_scsi_qc_complete` while ATAPI commands use :c:func:`atapi_qc_complete`. Both functions end up calling ``qc->scsidone`` diff --git a/Documentation/driver-api/media/cec-core.rst b/Documentation/driver-api/media/cec-core.rst index c6194ee81c41..ae0d20798edc 100644 --- a/Documentation/driver-api/media/cec-core.rst +++ b/Documentation/driver-api/media/cec-core.rst @@ -109,6 +109,7 @@ your driver: int (*adap_monitor_all_enable)(struct cec_adapter *adap, bool enable); int (*adap_monitor_pin_enable)(struct cec_adapter *adap, bool enable); int (*adap_log_addr)(struct cec_adapter *adap, u8 logical_addr); + void (*adap_configured)(struct cec_adapter *adap, bool configured); int (*adap_transmit)(struct cec_adapter *adap, u8 attempts, u32 signal_free_time, struct cec_msg *msg); void (*adap_status)(struct cec_adapter *adap, struct seq_file *file); @@ -117,7 +118,7 @@ your driver: /* Error injection callbacks */ ... - /* High-level callbacks */ + /* High-level callback */ ... }; @@ -178,6 +179,16 @@ can receive directed messages to that address. Note that adap_log_addr must return 0 if logical_addr is CEC_LOG_ADDR_INVALID. +Called when the adapter is fully configured or unconfigured:: + + void (*adap_configured)(struct cec_adapter *adap, bool configured); + +If configured == true, then the adapter is fully configured, i.e. all logical +addresses have been successfully claimed. If configured == false, then the +adapter is unconfigured. If the driver has to take specific actions after +(un)configuration, then that can be done through this optional callback. + + To transmit a new message:: int (*adap_transmit)(struct cec_adapter *adap, u8 attempts, diff --git a/Documentation/driver-api/media/mc-core.rst b/Documentation/driver-api/media/mc-core.rst index 57b5bbba944e..02481a2513b9 100644 --- a/Documentation/driver-api/media/mc-core.rst +++ b/Documentation/driver-api/media/mc-core.rst @@ -42,9 +42,16 @@ Allocation of the structure is handled by the media device driver, usually by embedding the :c:type:`media_device` instance in a larger driver-specific structure. -Drivers register media device instances by calling -:c:func:`__media_device_register()` via the macro ``media_device_register()`` -and unregistered by calling :c:func:`media_device_unregister()`. +Drivers initialise media device instances by calling +:c:func:`media_device_init()`. After initialising a media device instance, it is +registered by calling :c:func:`__media_device_register()` via the macro +``media_device_register()`` and unregistered by calling +:c:func:`media_device_unregister()`. An initialised media device must be +eventually cleaned up by calling :c:func:`media_device_cleanup()`. + +Note that it is not allowed to unregister a media device instance that was not +previously registered, or clean up a media device instance that was not +previously initialised. Entities ^^^^^^^^ diff --git a/Documentation/driver-api/media/v4l2-subdev.rst b/Documentation/driver-api/media/v4l2-subdev.rst index 08ea2673b19e..cf3b52bdbfb9 100644 --- a/Documentation/driver-api/media/v4l2-subdev.rst +++ b/Documentation/driver-api/media/v4l2-subdev.rst @@ -518,6 +518,75 @@ The :c:func:`v4l2_i2c_new_subdev` function will call :c:type:`i2c_board_info` structure using the ``client_type`` and the ``addr`` to fill it. +Centrally managed subdev active state +------------------------------------- + +Traditionally V4L2 subdev drivers maintained internal state for the active +device configuration. This is often implemented as e.g. an array of struct +v4l2_mbus_framefmt, one entry for each pad, and similarly for crop and compose +rectangles. + +In addition to the active configuration, each subdev file handle has an array of +struct v4l2_subdev_pad_config, managed by the V4L2 core, which contains the try +configuration. + +To simplify the subdev drivers the V4L2 subdev API now optionally supports a +centrally managed active configuration represented by +:c:type:`v4l2_subdev_state`. One instance of state, which contains the active +device configuration, is stored in the sub-device itself as part of +the :c:type:`v4l2_subdev` structure, while the core associates a try state to +each open file handle, to store the try configuration related to that file +handle. + +Sub-device drivers can opt-in and use state to manage their active configuration +by initializing the subdevice state with a call to v4l2_subdev_init_finalize() +before registering the sub-device. They must also call v4l2_subdev_cleanup() +to release all the allocated resources before unregistering the sub-device. +The core automatically allocates and initializes a state for each open file +handle to store the try configurations and frees it when closing the file +handle. + +V4L2 sub-device operations that use both the :ref:`ACTIVE and TRY formats +<v4l2-subdev-format-whence>` receive the correct state to operate on through +the 'state' parameter. The state must be locked and unlocked by the +caller by calling :c:func:`v4l2_subdev_lock_state()` and +:c:func:`v4l2_subdev_unlock_state()`. The caller can do so by calling the subdev +operation through the :c:func:`v4l2_subdev_call_state_active()` macro. + +Operations that do not receive a state parameter implicitly operate on the +subdevice active state, which drivers can exclusively access by +calling :c:func:`v4l2_subdev_lock_and_get_active_state()`. The sub-device active +state must equally be released by calling :c:func:`v4l2_subdev_unlock_state()`. + +Drivers must never manually access the state stored in the :c:type:`v4l2_subdev` +or in the file handle without going through the designated helpers. + +While the V4L2 core passes the correct try or active state to the subdevice +operations, many existing device drivers pass a NULL state when calling +operations with :c:func:`v4l2_subdev_call()`. This legacy construct causes +issues with subdevice drivers that let the V4L2 core manage the active state, +as they expect to receive the appropriate state as a parameter. To help the +conversion of subdevice drivers to a managed active state without having to +convert all callers at the same time, an additional wrapper layer has been +added to v4l2_subdev_call(), which handles the NULL case by geting and locking +the callee's active state with :c:func:`v4l2_subdev_lock_and_get_active_state()`, +and unlocking the state after the call. + +The whole subdev state is in reality split into three parts: the +v4l2_subdev_state, subdev controls and subdev driver's internal state. In the +future these parts should be combined into a single state. For the time being +we need a way to handle the locking for these parts. This can be accomplished +by sharing a lock. The v4l2_ctrl_handler already supports this via its 'lock' +pointer and the same model is used with states. The driver can do the following +before calling v4l2_subdev_init_finalize(): + +.. code-block:: c + + sd->ctrl_handler->lock = &priv->mutex; + sd->state_lock = &priv->mutex; + +This shares the driver's private mutex between the controls and the states. + V4L2 sub-device functions and data structures --------------------------------------------- diff --git a/Documentation/driver-api/pwm.rst b/Documentation/driver-api/pwm.rst index ccb06e485756..fd26c3d895b6 100644 --- a/Documentation/driver-api/pwm.rst +++ b/Documentation/driver-api/pwm.rst @@ -49,6 +49,12 @@ After being requested, a PWM has to be configured using:: This API controls both the PWM period/duty_cycle config and the enable/disable state. + +As a consumer, don't rely on the output's state for a disabled PWM. If it's +easily possible, drivers are supposed to emit the inactive state, but some +drivers cannot. If you rely on getting the inactive state, use .duty_cycle=0, +.enabled=true. + There is also a usage_power setting: If set, the PWM driver is only required to maintain the power output but has more freedom regarding signal form. If supported by the driver, the signal can be optimized, for example to improve diff --git a/Documentation/driver-api/serial/driver.rst b/Documentation/driver-api/serial/driver.rst index 06ec04ba086f..7ef83fd3917b 100644 --- a/Documentation/driver-api/serial/driver.rst +++ b/Documentation/driver-api/serial/driver.rst @@ -311,7 +311,7 @@ hardware. This call must not sleep set_ldisc(port,termios) - Notifier for discipline change. See Documentation/tty/tty_ldisc.rst. + Notifier for discipline change. See ../tty/tty_ldisc.rst. Locking: caller holds tty_port->mutex diff --git a/Documentation/driver-api/serial/index.rst b/Documentation/driver-api/serial/index.rst index 7eb21a695fc3..03a55b987a1d 100644 --- a/Documentation/driver-api/serial/index.rst +++ b/Documentation/driver-api/serial/index.rst @@ -16,8 +16,6 @@ Serial drivers .. toctree:: :maxdepth: 1 - moxa-smartio - n_gsm serial-iso7816 serial-rs485 diff --git a/Documentation/driver-api/serial/n_gsm.rst b/Documentation/driver-api/serial/n_gsm.rst deleted file mode 100644 index 49956509ad73..000000000000 --- a/Documentation/driver-api/serial/n_gsm.rst +++ /dev/null @@ -1,159 +0,0 @@ -============================== -GSM 0710 tty multiplexor HOWTO -============================== - -This line discipline implements the GSM 07.10 multiplexing protocol -detailed in the following 3GPP document: - - https://www.3gpp.org/ftp/Specs/archive/07_series/07.10/0710-720.zip - -This document give some hints on how to use this driver with GPRS and 3G -modems connected to a physical serial port. - -How to use it -------------- -1. config initiator -^^^^^^^^^^^^^^^^^^^^^ - -1.1 initialize the modem in 0710 mux mode (usually AT+CMUX= command) through - its serial port. Depending on the modem used, you can pass more or less - parameters to this command. - -1.2 switch the serial line to using the n_gsm line discipline by using - TIOCSETD ioctl. - -1.3 configure the mux using GSMIOC_GETCONF / GSMIOC_SETCONF ioctl. - -1.4 obtain base gsmtty number for the used serial port. - -Major parts of the initialization program : -(a good starting point is util-linux-ng/sys-utils/ldattach.c):: - - #include <stdio.h> - #include <stdint.h> - #include <linux/gsmmux.h> - #include <linux/tty.h> - #define DEFAULT_SPEED B115200 - #define SERIAL_PORT /dev/ttyS0 - - int ldisc = N_GSM0710; - struct gsm_config c; - struct termios configuration; - uint32_t first; - - /* open the serial port connected to the modem */ - fd = open(SERIAL_PORT, O_RDWR | O_NOCTTY | O_NDELAY); - - /* configure the serial port : speed, flow control ... */ - - /* send the AT commands to switch the modem to CMUX mode - and check that it's successful (should return OK) */ - write(fd, "AT+CMUX=0\r", 10); - - /* experience showed that some modems need some time before - being able to answer to the first MUX packet so a delay - may be needed here in some case */ - sleep(3); - - /* use n_gsm line discipline */ - ioctl(fd, TIOCSETD, &ldisc); - - /* get n_gsm configuration */ - ioctl(fd, GSMIOC_GETCONF, &c); - /* we are initiator and need encoding 0 (basic) */ - c.initiator = 1; - c.encapsulation = 0; - /* our modem defaults to a maximum size of 127 bytes */ - c.mru = 127; - c.mtu = 127; - /* set the new configuration */ - ioctl(fd, GSMIOC_SETCONF, &c); - /* get first gsmtty device node */ - ioctl(fd, GSMIOC_GETFIRST, &first); - printf("first muxed line: /dev/gsmtty%i\n", first); - - /* and wait for ever to keep the line discipline enabled */ - daemon(0,0); - pause(); - -1.5 use these devices as plain serial ports. - - for example, it's possible: - - - and to use gnokii to send / receive SMS on ttygsm1 - - to use ppp to establish a datalink on ttygsm2 - -1.6 first close all virtual ports before closing the physical port. - - Note that after closing the physical port the modem is still in multiplexing - mode. This may prevent a successful re-opening of the port later. To avoid - this situation either reset the modem if your hardware allows that or send - a disconnect command frame manually before initializing the multiplexing mode - for the second time. The byte sequence for the disconnect command frame is:: - - 0xf9, 0x03, 0xef, 0x03, 0xc3, 0x16, 0xf9. - -2. config requester -^^^^^^^^^^^^^^^^^^^^^ - -2.1 receive string "AT+CMUX= command" through its serial port,initialize - mux mode config - -2.2 switch the serial line to using the n_gsm line discipline by using - TIOCSETD ioctl. - -2.3 configure the mux using GSMIOC_GETCONF / GSMIOC_SETCONF ioctl. - -2.4 obtain base gsmtty number for the used serial port:: - - #include <stdio.h> - #include <stdint.h> - #include <linux/gsmmux.h> - #include <linux/tty.h> - #define DEFAULT_SPEED B115200 - #define SERIAL_PORT /dev/ttyS0 - - int ldisc = N_GSM0710; - struct gsm_config c; - struct termios configuration; - uint32_t first; - - /* open the serial port */ - fd = open(SERIAL_PORT, O_RDWR | O_NOCTTY | O_NDELAY); - - /* configure the serial port : speed, flow control ... */ - - /* get serial data and check "AT+CMUX=command" parameter ... */ - - /* use n_gsm line discipline */ - ioctl(fd, TIOCSETD, &ldisc); - - /* get n_gsm configuration */ - ioctl(fd, GSMIOC_GETCONF, &c); - /* we are requester and need encoding 0 (basic) */ - c.initiator = 0; - c.encapsulation = 0; - /* our modem defaults to a maximum size of 127 bytes */ - c.mru = 127; - c.mtu = 127; - /* set the new configuration */ - ioctl(fd, GSMIOC_SETCONF, &c); - /* get first gsmtty device node */ - ioctl(fd, GSMIOC_GETFIRST, &first); - printf("first muxed line: /dev/gsmtty%i\n", first); - - /* and wait for ever to keep the line discipline enabled */ - daemon(0,0); - pause(); - -Additional Documentation ------------------------- -More practical details on the protocol and how it's supported by industrial -modems can be found in the following documents : - -- http://www.telit.com/module/infopool/download.php?id=616 -- http://www.u-blox.com/images/downloads/Product_Docs/LEON-G100-G200-MuxImplementation_ApplicationNote_%28GSM%20G1-CS-10002%29.pdf -- http://www.sierrawireless.com/Support/Downloads/AirPrime/WMP_Series/~/media/Support_Downloads/AirPrime/Application_notes/CMUX_Feature_Application_Note-Rev004.ashx -- http://wm.sim.com/sim/News/photo/2010721161442.pdf - -11-03-08 - Eric Bénard - <eric@eukrea.com> diff --git a/Documentation/driver-api/thermal/intel_dptf.rst b/Documentation/driver-api/thermal/intel_dptf.rst index 96668dca753a..372bdb4d04c6 100644 --- a/Documentation/driver-api/thermal/intel_dptf.rst +++ b/Documentation/driver-api/thermal/intel_dptf.rst @@ -4,7 +4,7 @@ Intel(R) Dynamic Platform and Thermal Framework Sysfs Interface =============================================================== -:Copyright: |copy| 2022 Intel Corporation +:Copyright: © 2022 Intel Corporation :Author: Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com> diff --git a/Documentation/driver-api/tty/index.rst b/Documentation/driver-api/tty/index.rst new file mode 100644 index 000000000000..2d32606a4278 --- /dev/null +++ b/Documentation/driver-api/tty/index.rst @@ -0,0 +1,73 @@ +.. SPDX-License-Identifier: GPL-2.0 + +=== +TTY +=== + +Teletypewriter (TTY) layer takes care of all those serial devices. Including +the virtual ones like pseudoterminal (PTY). + +TTY structures +============== + +There are several major TTY structures. Every TTY device in a system has a +corresponding struct tty_port. These devices are maintained by a TTY driver +which is struct tty_driver. This structure describes the driver but also +contains a reference to operations which could be performed on the TTYs. It is +struct tty_operations. Then, upon open, a struct tty_struct is allocated and +lives until the final close. During this time, several callbacks from struct +tty_operations are invoked by the TTY layer. + +Every character received by the kernel (both from devices and users) is passed +through a preselected :doc:`tty_ldisc` (in +short ldisc; in C, struct tty_ldisc_ops). Its task is to transform characters +as defined by a particular ldisc or by user too. The default one is n_tty, +implementing echoes, signal handling, jobs control, special characters +processing, and more. The transformed characters are passed further to +user/device, depending on the source. + +In-detail description of the named TTY structures is in separate documents: + +.. toctree:: + :maxdepth: 2 + + tty_driver + tty_port + tty_struct + tty_ldisc + tty_buffer + tty_internals + +Writing TTY Driver +================== + +Before one starts writing a TTY driver, they must consider +:doc:`Serial <../serial/driver>` and :doc:`USB Serial <../../usb/usb-serial>` +layers first. Drivers for serial devices can often use one of these specific +layers to implement a serial driver. Only special devices should be handled +directly by the TTY Layer. If you are about to write such a driver, read on. + +A *typical* sequence a TTY driver performs is as follows: + +#. Allocate and register a TTY driver (module init) +#. Create and register TTY devices as they are probed (probe function) +#. Handle TTY operations and events like interrupts (TTY core invokes the + former, the device the latter) +#. Remove devices as they are going away (remove function) +#. Unregister and free the TTY driver (module exit) + +Steps regarding driver, i.e. 1., 3., and 5. are described in detail in +:doc:`tty_driver`. For the other two (devices handling), look into +:doc:`tty_port`. + +Other Documentation +=================== + +Miscellaneous documentation can be further found in these documents: + +.. toctree:: + :maxdepth: 2 + + moxa-smartio + n_gsm + n_tty diff --git a/Documentation/driver-api/serial/moxa-smartio.rst b/Documentation/driver-api/tty/moxa-smartio.rst index af25bc5cc3e6..af25bc5cc3e6 100644 --- a/Documentation/driver-api/serial/moxa-smartio.rst +++ b/Documentation/driver-api/tty/moxa-smartio.rst diff --git a/Documentation/driver-api/tty/n_gsm.rst b/Documentation/driver-api/tty/n_gsm.rst new file mode 100644 index 000000000000..35d7381515b0 --- /dev/null +++ b/Documentation/driver-api/tty/n_gsm.rst @@ -0,0 +1,153 @@ +============================== +GSM 0710 tty multiplexor HOWTO +============================== + +.. contents:: :local: + +This line discipline implements the GSM 07.10 multiplexing protocol +detailed in the following 3GPP document: + + https://www.3gpp.org/ftp/Specs/archive/07_series/07.10/0710-720.zip + +This document give some hints on how to use this driver with GPRS and 3G +modems connected to a physical serial port. + +How to use it +============= + +Config Initiator +---------------- + +#. Initialize the modem in 0710 mux mode (usually ``AT+CMUX=`` command) through + its serial port. Depending on the modem used, you can pass more or less + parameters to this command. + +#. Switch the serial line to using the n_gsm line discipline by using + ``TIOCSETD`` ioctl. + +#. Configure the mux using ``GSMIOC_GETCONF``/``GSMIOC_SETCONF`` ioctl. + +#. Obtain base gsmtty number for the used serial port. + + Major parts of the initialization program + (a good starting point is util-linux-ng/sys-utils/ldattach.c):: + + #include <stdio.h> + #include <stdint.h> + #include <linux/gsmmux.h> + #include <linux/tty.h> + + #define DEFAULT_SPEED B115200 + #define SERIAL_PORT /dev/ttyS0 + + int ldisc = N_GSM0710; + struct gsm_config c; + struct termios configuration; + uint32_t first; + + /* open the serial port connected to the modem */ + fd = open(SERIAL_PORT, O_RDWR | O_NOCTTY | O_NDELAY); + + /* configure the serial port : speed, flow control ... */ + + /* send the AT commands to switch the modem to CMUX mode + and check that it's successful (should return OK) */ + write(fd, "AT+CMUX=0\r", 10); + + /* experience showed that some modems need some time before + being able to answer to the first MUX packet so a delay + may be needed here in some case */ + sleep(3); + + /* use n_gsm line discipline */ + ioctl(fd, TIOCSETD, &ldisc); + + /* get n_gsm configuration */ + ioctl(fd, GSMIOC_GETCONF, &c); + /* we are initiator and need encoding 0 (basic) */ + c.initiator = 1; + c.encapsulation = 0; + /* our modem defaults to a maximum size of 127 bytes */ + c.mru = 127; + c.mtu = 127; + /* set the new configuration */ + ioctl(fd, GSMIOC_SETCONF, &c); + /* get first gsmtty device node */ + ioctl(fd, GSMIOC_GETFIRST, &first); + printf("first muxed line: /dev/gsmtty%i\n", first); + + /* and wait for ever to keep the line discipline enabled */ + daemon(0,0); + pause(); + +#. Use these devices as plain serial ports. + + For example, it's possible: + + - to use *gnokii* to send / receive SMS on ``ttygsm1`` + - to use *ppp* to establish a datalink on ``ttygsm2`` + +#. First close all virtual ports before closing the physical port. + + Note that after closing the physical port the modem is still in multiplexing + mode. This may prevent a successful re-opening of the port later. To avoid + this situation either reset the modem if your hardware allows that or send + a disconnect command frame manually before initializing the multiplexing mode + for the second time. The byte sequence for the disconnect command frame is:: + + 0xf9, 0x03, 0xef, 0x03, 0xc3, 0x16, 0xf9 + +Config Requester +---------------- + +#. Receive ``AT+CMUX=`` command through its serial port, initialize mux mode + config. + +#. Switch the serial line to using the *n_gsm* line discipline by using + ``TIOCSETD`` ioctl. + +#. Configure the mux using ``GSMIOC_GETCONF``/``GSMIOC_SETCONF`` ioctl. + +#. Obtain base gsmtty number for the used serial port:: + + #include <stdio.h> + #include <stdint.h> + #include <linux/gsmmux.h> + #include <linux/tty.h> + #define DEFAULT_SPEED B115200 + #define SERIAL_PORT /dev/ttyS0 + + int ldisc = N_GSM0710; + struct gsm_config c; + struct termios configuration; + uint32_t first; + + /* open the serial port */ + fd = open(SERIAL_PORT, O_RDWR | O_NOCTTY | O_NDELAY); + + /* configure the serial port : speed, flow control ... */ + + /* get serial data and check "AT+CMUX=command" parameter ... */ + + /* use n_gsm line discipline */ + ioctl(fd, TIOCSETD, &ldisc); + + /* get n_gsm configuration */ + ioctl(fd, GSMIOC_GETCONF, &c); + /* we are requester and need encoding 0 (basic) */ + c.initiator = 0; + c.encapsulation = 0; + /* our modem defaults to a maximum size of 127 bytes */ + c.mru = 127; + c.mtu = 127; + /* set the new configuration */ + ioctl(fd, GSMIOC_SETCONF, &c); + /* get first gsmtty device node */ + ioctl(fd, GSMIOC_GETFIRST, &first); + printf("first muxed line: /dev/gsmtty%i\n", first); + + /* and wait for ever to keep the line discipline enabled */ + daemon(0,0); + pause(); + +11-03-08 - Eric Bénard - <eric@eukrea.com> diff --git a/Documentation/driver-api/tty/n_tty.rst b/Documentation/driver-api/tty/n_tty.rst new file mode 100644 index 000000000000..15b70faee72d --- /dev/null +++ b/Documentation/driver-api/tty/n_tty.rst @@ -0,0 +1,22 @@ +.. SPDX-License-Identifier: GPL-2.0 + +===== +N_TTY +===== + +.. contents:: :local: + +The default (and fallback) :doc:`TTY line discipline <tty_ldisc>`. It tries to +handle characters as per POSIX. + +External Functions +================== + +.. kernel-doc:: drivers/tty/n_tty.c + :export: + +Internal Functions +================== + +.. kernel-doc:: drivers/tty/n_tty.c + :internal: diff --git a/Documentation/driver-api/tty/tty_buffer.rst b/Documentation/driver-api/tty/tty_buffer.rst new file mode 100644 index 000000000000..a39d4781e0d2 --- /dev/null +++ b/Documentation/driver-api/tty/tty_buffer.rst @@ -0,0 +1,46 @@ +.. SPDX-License-Identifier: GPL-2.0 + +========== +TTY Buffer +========== + +.. contents:: :local: + +Here, we document functions for taking care of tty buffer and their flipping. +Drivers are supposed to fill the buffer by one of those functions below and +then flip the buffer, so that the data are passed to :doc:`line discipline +<tty_ldisc>` for further processing. + +Flip Buffer Management +====================== + +.. kernel-doc:: drivers/tty/tty_buffer.c + :identifiers: tty_prepare_flip_string tty_insert_flip_string_fixed_flag + tty_insert_flip_string_flags __tty_insert_flip_char + tty_flip_buffer_push tty_ldisc_receive_buf + +---- + +Other Functions +=============== + +.. kernel-doc:: drivers/tty/tty_buffer.c + :identifiers: tty_buffer_space_avail tty_buffer_set_limit + +---- + +Buffer Locking +============== + +These are used only in special circumstances. Avoid them. + +.. kernel-doc:: drivers/tty/tty_buffer.c + :identifiers: tty_buffer_lock_exclusive tty_buffer_unlock_exclusive + +---- + +Internal Functions +================== + +.. kernel-doc:: drivers/tty/tty_buffer.c + :internal: diff --git a/Documentation/driver-api/tty/tty_driver.rst b/Documentation/driver-api/tty/tty_driver.rst new file mode 100644 index 000000000000..cc529f863406 --- /dev/null +++ b/Documentation/driver-api/tty/tty_driver.rst @@ -0,0 +1,128 @@ +.. SPDX-License-Identifier: GPL-2.0 + +============================= +TTY Driver and TTY Operations +============================= + +.. contents:: :local: + +Allocation +========== + +The first thing a driver needs to do is to allocate a struct tty_driver. This +is done by tty_alloc_driver() (or __tty_alloc_driver()). Next, the newly +allocated structure is filled with information. See `TTY Driver Reference`_ at +the end of this document on what actually shall be filled in. + +The allocation routines expect a number of devices the driver can handle at +most and flags. Flags are those starting ``TTY_DRIVER_`` listed and described +in `TTY Driver Flags`_ below. + +When the driver is about to be freed, tty_driver_kref_put() is called on that. +It will decrements the reference count and if it reaches zero, the driver is +freed. + +For reference, both allocation and deallocation functions are explained here in +detail: + +.. kernel-doc:: drivers/tty/tty_io.c + :identifiers: __tty_alloc_driver tty_driver_kref_put + +TTY Driver Flags +---------------- + +Here comes the documentation of flags accepted by tty_alloc_driver() (or +__tty_alloc_driver()): + +.. kernel-doc:: include/linux/tty_driver.h + :doc: TTY Driver Flags + +---- + +Registration +============ + +When a struct tty_driver is allocated and filled in, it can be registered using +tty_register_driver(). It is recommended to pass ``TTY_DRIVER_DYNAMIC_DEV`` in +flags of tty_alloc_driver(). If it is not passed, *all* devices are also +registered during tty_register_driver() and the following paragraph of +registering devices can be skipped for such drivers. However, the struct +tty_port part in `Registering Devices`_ is still relevant there. + +.. kernel-doc:: drivers/tty/tty_io.c + :identifiers: tty_register_driver tty_unregister_driver + +Registering Devices +------------------- + +Every TTY device shall be backed by a struct tty_port. Usually, TTY drivers +embed tty_port into device's private structures. Further details about handling +tty_port can be found in :doc:`tty_port`. The driver is also recommended to use +tty_port's reference counting by tty_port_get() and tty_port_put(). The final +put is supposed to free the tty_port including the device's private struct. + +Unless ``TTY_DRIVER_DYNAMIC_DEV`` was passed as flags to tty_alloc_driver(), +TTY driver is supposed to register every device discovered in the system +(the latter is preferred). This is performed by tty_register_device(). Or by +tty_register_device_attr() if the driver wants to expose some information +through struct attribute_group. Both of them register ``index``'th device and +upon return, the device can be opened. There are also preferred tty_port +variants described in `Linking Devices to Ports`_ later. It is up to driver to +manage free indices and choosing the right one. The TTY layer only refuses to +register more devices than passed to tty_alloc_driver(). + +When the device is opened, the TTY layer allocates struct tty_struct and starts +calling operations from :c:member:`tty_driver.ops`, see `TTY Operations +Reference`_. + +The registration routines are documented as follows: + +.. kernel-doc:: drivers/tty/tty_io.c + :identifiers: tty_register_device tty_register_device_attr + tty_unregister_device + +---- + +Linking Devices to Ports +------------------------ +As stated earlier, every TTY device shall have a struct tty_port assigned to +it. It must be known to the TTY layer at :c:member:`tty_driver.ops.install()` +at latest. There are few helpers to *link* the two. Ideally, the driver uses +tty_port_register_device() or tty_port_register_device_attr() instead of +tty_register_device() and tty_register_device_attr() at the registration time. +This way, the driver needs not care about linking later on. + +If that is not possible, the driver still can link the tty_port to a specific +index *before* the actual registration by tty_port_link_device(). If it still +does not fit, tty_port_install() can be used from the +:c:member:`tty_driver.ops.install` hook as a last resort. The last one is +dedicated mostly for in-memory devices like PTY where tty_ports are allocated +on demand. + +The linking routines are documented here: + +.. kernel-doc:: drivers/tty/tty_port.c + :identifiers: tty_port_link_device tty_port_register_device + tty_port_register_device_attr + +---- + +TTY Driver Reference +==================== + +All members of struct tty_driver are documented here. The required members are +noted at the end. struct tty_operations are documented next. + +.. kernel-doc:: include/linux/tty_driver.h + :identifiers: tty_driver + +---- + +TTY Operations Reference +======================== + +When a TTY is registered, these driver hooks can be invoked by the TTY layer: + +.. kernel-doc:: include/linux/tty_driver.h + :identifiers: tty_operations + diff --git a/Documentation/driver-api/tty/tty_internals.rst b/Documentation/driver-api/tty/tty_internals.rst new file mode 100644 index 000000000000..d0d415820300 --- /dev/null +++ b/Documentation/driver-api/tty/tty_internals.rst @@ -0,0 +1,31 @@ +.. SPDX-License-Identifier: GPL-2.0 + +============= +TTY Internals +============= + +.. contents:: :local: + +Kopen +===== + +These functions serve for opening a TTY from the kernelspace: + +.. kernel-doc:: drivers/tty/tty_io.c + :identifiers: tty_kopen_exclusive tty_kopen_shared tty_kclose + +---- + +Exported Internal Functions +=========================== + +.. kernel-doc:: drivers/tty/tty_io.c + :identifiers: tty_release_struct tty_dev_name_to_number tty_get_icount + +---- + +Internal Functions +================== + +.. kernel-doc:: drivers/tty/tty_io.c + :internal: diff --git a/Documentation/driver-api/tty/tty_ldisc.rst b/Documentation/driver-api/tty/tty_ldisc.rst new file mode 100644 index 000000000000..5144751be804 --- /dev/null +++ b/Documentation/driver-api/tty/tty_ldisc.rst @@ -0,0 +1,85 @@ +.. SPDX-License-Identifier: GPL-2.0 + +=================== +TTY Line Discipline +=================== + +.. contents:: :local: + +TTY line discipline process all incoming and outgoing character from/to a tty +device. The default line discipline is :doc:`N_TTY <n_tty>`. It is also a +fallback if establishing any other discipline for a tty fails. If even N_TTY +fails, N_NULL takes over. That never fails, but also does not process any +characters -- it throws them away. + +Registration +============ + +Line disciplines are registered with tty_register_ldisc() passing the ldisc +structure. At the point of registration the discipline must be ready to use and +it is possible it will get used before the call returns success. If the call +returns an error then it won’t get called. Do not re-use ldisc numbers as they +are part of the userspace ABI and writing over an existing ldisc will cause +demons to eat your computer. You must not re-register over the top of the line +discipline even with the same data or your computer again will be eaten by +demons. In order to remove a line discipline call tty_unregister_ldisc(). + +Heed this warning: the reference count field of the registered copies of the +tty_ldisc structure in the ldisc table counts the number of lines using this +discipline. The reference count of the tty_ldisc structure within a tty counts +the number of active users of the ldisc at this instant. In effect it counts +the number of threads of execution within an ldisc method (plus those about to +enter and exit although this detail matters not). + +.. kernel-doc:: drivers/tty/tty_ldisc.c + :identifiers: tty_register_ldisc tty_unregister_ldisc + +Other Functions +=============== + +.. kernel-doc:: drivers/tty/tty_ldisc.c + :identifiers: tty_set_ldisc tty_ldisc_flush + +Line Discipline Operations Reference +==================================== + +.. kernel-doc:: include/linux/tty_ldisc.h + :identifiers: tty_ldisc_ops + +Driver Access +============= + +Line discipline methods can call the methods of the underlying hardware driver. +These are documented as a part of struct tty_operations. + +TTY Flags +========= + +Line discipline methods have access to :c:member:`tty_struct.flags` field. See +:doc:`tty_struct`. + +Locking +======= + +Callers to the line discipline functions from the tty layer are required to +take line discipline locks. The same is true of calls from the driver side +but not yet enforced. + +.. kernel-doc:: drivers/tty/tty_ldisc.c + :identifiers: tty_ldisc_ref_wait tty_ldisc_ref tty_ldisc_deref + +While these functions are slightly slower than the old code they should have +minimal impact as most receive logic uses the flip buffers and they only +need to take a reference when they push bits up through the driver. + +A caution: The :c:member:`tty_ldisc_ops.open()`, +:c:member:`tty_ldisc_ops.close()` and :c:member:`tty_driver.set_ldisc()` +functions are called with the ldisc unavailable. Thus tty_ldisc_ref() will fail +in this situation if used within these functions. Ldisc and driver code +calling its own functions must be careful in this case. + +Internal Functions +================== + +.. kernel-doc:: drivers/tty/tty_ldisc.c + :internal: diff --git a/Documentation/driver-api/tty/tty_port.rst b/Documentation/driver-api/tty/tty_port.rst new file mode 100644 index 000000000000..5cb90e954fcf --- /dev/null +++ b/Documentation/driver-api/tty/tty_port.rst @@ -0,0 +1,70 @@ +.. SPDX-License-Identifier: GPL-2.0 + +======== +TTY Port +======== + +.. contents:: :local: + +The TTY drivers are advised to use struct tty_port helpers as much as possible. +If the drivers implement :c:member:`tty_port.ops.activate()` and +:c:member:`tty_port.ops.shutdown()`, they can use tty_port_open(), +tty_port_close(), and tty_port_hangup() in respective +:c:member:`tty_struct.ops` hooks. + +The reference and details are contained in the `TTY Port Reference`_ and `TTY +Port Operations Reference`_ sections at the bottom. + +TTY Port Functions +================== + +Init & Destroy +-------------- + +.. kernel-doc:: drivers/tty/tty_port.c + :identifiers: tty_port_init tty_port_destroy + tty_port_get tty_port_put + +Open/Close/Hangup Helpers +------------------------- + +.. kernel-doc:: drivers/tty/tty_port.c + :identifiers: tty_port_install tty_port_open tty_port_block_til_ready + tty_port_close tty_port_close_start tty_port_close_end tty_port_hangup + tty_port_shutdown + +TTY Refcounting +--------------- + +.. kernel-doc:: drivers/tty/tty_port.c + :identifiers: tty_port_tty_get tty_port_tty_set + +TTY Helpers +----------- + +.. kernel-doc:: drivers/tty/tty_port.c + :identifiers: tty_port_tty_hangup tty_port_tty_wakeup + + +Modem Signals +------------- + +.. kernel-doc:: drivers/tty/tty_port.c + :identifiers: tty_port_carrier_raised tty_port_raise_dtr_rts + tty_port_lower_dtr_rts + +---- + +TTY Port Reference +================== + +.. kernel-doc:: include/linux/tty_port.h + :identifiers: tty_port + +---- + +TTY Port Operations Reference +============================= + +.. kernel-doc:: include/linux/tty_port.h + :identifiers: tty_port_operations diff --git a/Documentation/driver-api/tty/tty_struct.rst b/Documentation/driver-api/tty/tty_struct.rst new file mode 100644 index 000000000000..c72f5a4293b2 --- /dev/null +++ b/Documentation/driver-api/tty/tty_struct.rst @@ -0,0 +1,81 @@ +.. SPDX-License-Identifier: GPL-2.0 + +========== +TTY Struct +========== + +.. contents:: :local: + +struct tty_struct is allocated by the TTY layer upon the first open of the TTY +device and released after the last close. The TTY layer passes this structure +to most of struct tty_operation's hooks. Members of tty_struct are documented +in `TTY Struct Reference`_ at the bottom. + +Initialization +============== + +.. kernel-doc:: drivers/tty/tty_io.c + :identifiers: tty_init_termios + +Name +==== + +.. kernel-doc:: drivers/tty/tty_io.c + :identifiers: tty_name + +Reference counting +================== + +.. kernel-doc:: include/linux/tty.h + :identifiers: tty_kref_get + +.. kernel-doc:: drivers/tty/tty_io.c + :identifiers: tty_kref_put + +Install +======= + +.. kernel-doc:: drivers/tty/tty_io.c + :identifiers: tty_standard_install + +Read & Write +============ + +.. kernel-doc:: drivers/tty/tty_io.c + :identifiers: tty_put_char + +Start & Stop +============ + +.. kernel-doc:: drivers/tty/tty_io.c + :identifiers: start_tty stop_tty + +Wakeup +====== + +.. kernel-doc:: drivers/tty/tty_io.c + :identifiers: tty_wakeup + +Hangup +====== + +.. kernel-doc:: drivers/tty/tty_io.c + :identifiers: tty_hangup tty_vhangup tty_hung_up_p + +Misc +==== + +.. kernel-doc:: drivers/tty/tty_io.c + :identifiers: tty_do_resize + +TTY Struct Flags +================ + +.. kernel-doc:: include/linux/tty.h + :doc: TTY Struct Flags + +TTY Struct Reference +==================== + +.. kernel-doc:: include/linux/tty.h + :identifiers: tty_struct diff --git a/Documentation/driver-api/vfio-mediated-device.rst b/Documentation/driver-api/vfio-mediated-device.rst index 9f26079cacae..eded8719180f 100644 --- a/Documentation/driver-api/vfio-mediated-device.rst +++ b/Documentation/driver-api/vfio-mediated-device.rst @@ -105,6 +105,7 @@ structure to represent a mediated device's driver:: struct mdev_driver { int (*probe) (struct mdev_device *dev); void (*remove) (struct mdev_device *dev); + struct attribute_group **supported_type_groups; struct device_driver driver; }; @@ -119,33 +120,15 @@ to register and unregister itself with the core driver: extern void mdev_unregister_driver(struct mdev_driver *drv); -The mediated bus driver is responsible for adding mediated devices to the VFIO -group when devices are bound to the driver and removing mediated devices from -the VFIO when devices are unbound from the driver. - - -Physical Device Driver Interface --------------------------------- - -The physical device driver interface provides the mdev_parent_ops[3] structure -to define the APIs to manage work in the mediated core driver that is related -to the physical device. - -The structures in the mdev_parent_ops structure are as follows: - -* dev_attr_groups: attributes of the parent device -* mdev_attr_groups: attributes of the mediated device -* supported_config: attributes to define supported configurations -* device_driver: device driver to bind for mediated device instances - -The mdev_parent_ops also still has various functions pointers. Theses exist -for historical reasons only and shall not be used for new drivers. +The mediated bus driver's probe function should create a vfio_device on top of +the mdev_device and connect it to an appropriate implementation of +vfio_device_ops. When a driver wants to add the GUID creation sysfs to an existing device it has probe'd to then it should call:: extern int mdev_register_device(struct device *dev, - const struct mdev_parent_ops *ops); + struct mdev_driver *mdev_driver); This will provide the 'mdev_supported_types/XX/create' files which can then be used to trigger the creation of a mdev_device. The created mdev_device will be @@ -279,10 +262,10 @@ Translation APIs for Mediated Devices The following APIs are provided for translating user pfn to host pfn in a VFIO driver:: - extern int vfio_pin_pages(struct device *dev, unsigned long *user_pfn, + int vfio_pin_pages(struct vfio_device *device, unsigned long *user_pfn, int npage, int prot, unsigned long *phys_pfn); - extern int vfio_unpin_pages(struct device *dev, unsigned long *user_pfn, + int vfio_unpin_pages(struct vfio_device *device, unsigned long *user_pfn, int npage); These functions call back into the back-end IOMMU module by using the pin_pages |