Merge 'v5.11-rc6' into android-mainline
Linux 5.11-rc6 Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> Change-Id: I71e0a7924b31e3de90d189a0012b29923b573dc4
This commit is contained in:
@@ -100,6 +100,11 @@ Instruction Macros
|
||||
~~~~~~~~~~~~~~~~~~
|
||||
This section covers ``SYM_FUNC_*`` and ``SYM_CODE_*`` enumerated above.
|
||||
|
||||
``objtool`` requires that all code must be contained in an ELF symbol. Symbol
|
||||
names that have a ``.L`` prefix do not emit symbol table entries. ``.L``
|
||||
prefixed symbols can be used within a code region, but should be avoided for
|
||||
denoting a range of code via ``SYM_*_START/END`` annotations.
|
||||
|
||||
* ``SYM_FUNC_START`` and ``SYM_FUNC_START_LOCAL`` are supposed to be **the
|
||||
most frequent markings**. They are used for functions with standard calling
|
||||
conventions -- global and local. Like in C, they both align the functions to
|
||||
|
||||
111
Documentation/devicetree/bindings/leds/richtek,rt8515.yaml
Normal file
111
Documentation/devicetree/bindings/leds/richtek,rt8515.yaml
Normal file
@@ -0,0 +1,111 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/leds/richtek,rt8515.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Richtek RT8515 1.5A dual channel LED driver
|
||||
|
||||
maintainers:
|
||||
- Linus Walleij <linus.walleij@linaro.org>
|
||||
|
||||
description: |
|
||||
The Richtek RT8515 is a dual channel (two mode) LED driver that
|
||||
supports driving a white LED in flash or torch mode. The maximum
|
||||
current for each mode is defined in hardware using two resistors
|
||||
RFS and RTS.
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: richtek,rt8515
|
||||
|
||||
enf-gpios:
|
||||
maxItems: 1
|
||||
description: A connection to the 'ENF' (enable flash) pin.
|
||||
|
||||
ent-gpios:
|
||||
maxItems: 1
|
||||
description: A connection to the 'ENT' (enable torch) pin.
|
||||
|
||||
richtek,rfs-ohms:
|
||||
minimum: 7680
|
||||
maximum: 367000
|
||||
description: The resistance value of the RFS resistor. This
|
||||
resistors limits the maximum flash current. This must be set
|
||||
for the property flash-max-microamp to work, the RFS resistor
|
||||
defines the range of the dimmer setting (brightness) of the
|
||||
flash LED.
|
||||
|
||||
richtek,rts-ohms:
|
||||
minimum: 7680
|
||||
maximum: 367000
|
||||
description: The resistance value of the RTS resistor. This
|
||||
resistors limits the maximum torch current. This must be set
|
||||
for the property torch-max-microamp to work, the RTS resistor
|
||||
defines the range of the dimmer setting (brightness) of the
|
||||
torch LED.
|
||||
|
||||
led:
|
||||
type: object
|
||||
$ref: common.yaml#
|
||||
properties:
|
||||
function: true
|
||||
color: true
|
||||
flash-max-timeout-us: true
|
||||
|
||||
flash-max-microamp:
|
||||
maximum: 700000
|
||||
description: The maximum current for flash mode
|
||||
is hardwired to the component using the RFS resistor to
|
||||
ground. The maximum hardware current setting is calculated
|
||||
according to the formula Imax = 5500 / RFS. The lowest
|
||||
allowed resistance value is 7.86 kOhm giving an absolute
|
||||
maximum current of 700mA. By setting this attribute in
|
||||
the device tree, you can further restrict the maximum
|
||||
current below the hardware limit. This requires the RFS
|
||||
to be defined as it defines the maximum range.
|
||||
|
||||
led-max-microamp:
|
||||
maximum: 700000
|
||||
description: The maximum current for torch mode
|
||||
is hardwired to the component using the RTS resistor to
|
||||
ground. The maximum hardware current setting is calculated
|
||||
according to the formula Imax = 5500 / RTS. The lowest
|
||||
allowed resistance value is 7.86 kOhm giving an absolute
|
||||
maximum current of 700mA. By setting this attribute in
|
||||
the device tree, you can further restrict the maximum
|
||||
current below the hardware limit. This requires the RTS
|
||||
to be defined as it defines the maximum range.
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- ent-gpios
|
||||
- enf-gpios
|
||||
- led
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/gpio/gpio.h>
|
||||
#include <dt-bindings/leds/common.h>
|
||||
|
||||
led-controller {
|
||||
compatible = "richtek,rt8515";
|
||||
enf-gpios = <&gpio4 12 GPIO_ACTIVE_HIGH>;
|
||||
ent-gpios = <&gpio4 13 GPIO_ACTIVE_HIGH>;
|
||||
richtek,rfs-ohms = <16000>;
|
||||
richtek,rts-ohms = <100000>;
|
||||
|
||||
led {
|
||||
function = LED_FUNCTION_FLASH;
|
||||
color = <LED_COLOR_ID_WHITE>;
|
||||
flash-max-timeout-us = <250000>;
|
||||
flash-max-microamp = <150000>;
|
||||
led-max-microamp = <25000>;
|
||||
};
|
||||
};
|
||||
|
||||
...
|
||||
2
Makefile
2
Makefile
@@ -2,7 +2,7 @@
|
||||
VERSION = 5
|
||||
PATCHLEVEL = 11
|
||||
SUBLEVEL = 0
|
||||
EXTRAVERSION = -rc5
|
||||
EXTRAVERSION = -rc6
|
||||
NAME = Kleptomaniac Octopus
|
||||
|
||||
# *DOCUMENTATION*
|
||||
|
||||
@@ -180,14 +180,19 @@ void notrace restore_interrupts(void)
|
||||
|
||||
void replay_soft_interrupts(void)
|
||||
{
|
||||
/*
|
||||
* We use local_paca rather than get_paca() to avoid all
|
||||
* the debug_smp_processor_id() business in this low level
|
||||
* function
|
||||
*/
|
||||
unsigned char happened = local_paca->irq_happened;
|
||||
struct pt_regs regs;
|
||||
|
||||
/*
|
||||
* Be careful here, calling these interrupt handlers can cause
|
||||
* softirqs to be raised, which they may run when calling irq_exit,
|
||||
* which will cause local_irq_enable() to be run, which can then
|
||||
* recurse into this function. Don't keep any state across
|
||||
* interrupt handler calls which may change underneath us.
|
||||
*
|
||||
* We use local_paca rather than get_paca() to avoid all the
|
||||
* debug_smp_processor_id() business in this low level function.
|
||||
*/
|
||||
|
||||
ppc_save_regs(®s);
|
||||
regs.softe = IRQS_ENABLED;
|
||||
|
||||
@@ -209,7 +214,7 @@ again:
|
||||
* This is a higher priority interrupt than the others, so
|
||||
* replay it first.
|
||||
*/
|
||||
if (IS_ENABLED(CONFIG_PPC_BOOK3S) && (happened & PACA_IRQ_HMI)) {
|
||||
if (IS_ENABLED(CONFIG_PPC_BOOK3S) && (local_paca->irq_happened & PACA_IRQ_HMI)) {
|
||||
local_paca->irq_happened &= ~PACA_IRQ_HMI;
|
||||
regs.trap = 0xe60;
|
||||
handle_hmi_exception(®s);
|
||||
@@ -217,7 +222,7 @@ again:
|
||||
hard_irq_disable();
|
||||
}
|
||||
|
||||
if (happened & PACA_IRQ_DEC) {
|
||||
if (local_paca->irq_happened & PACA_IRQ_DEC) {
|
||||
local_paca->irq_happened &= ~PACA_IRQ_DEC;
|
||||
regs.trap = 0x900;
|
||||
timer_interrupt(®s);
|
||||
@@ -225,7 +230,7 @@ again:
|
||||
hard_irq_disable();
|
||||
}
|
||||
|
||||
if (happened & PACA_IRQ_EE) {
|
||||
if (local_paca->irq_happened & PACA_IRQ_EE) {
|
||||
local_paca->irq_happened &= ~PACA_IRQ_EE;
|
||||
regs.trap = 0x500;
|
||||
do_IRQ(®s);
|
||||
@@ -233,7 +238,7 @@ again:
|
||||
hard_irq_disable();
|
||||
}
|
||||
|
||||
if (IS_ENABLED(CONFIG_PPC_DOORBELL) && (happened & PACA_IRQ_DBELL)) {
|
||||
if (IS_ENABLED(CONFIG_PPC_DOORBELL) && (local_paca->irq_happened & PACA_IRQ_DBELL)) {
|
||||
local_paca->irq_happened &= ~PACA_IRQ_DBELL;
|
||||
if (IS_ENABLED(CONFIG_PPC_BOOK3E))
|
||||
regs.trap = 0x280;
|
||||
@@ -245,7 +250,7 @@ again:
|
||||
}
|
||||
|
||||
/* Book3E does not support soft-masking PMI interrupts */
|
||||
if (IS_ENABLED(CONFIG_PPC_BOOK3S) && (happened & PACA_IRQ_PMI)) {
|
||||
if (IS_ENABLED(CONFIG_PPC_BOOK3S) && (local_paca->irq_happened & PACA_IRQ_PMI)) {
|
||||
local_paca->irq_happened &= ~PACA_IRQ_PMI;
|
||||
regs.trap = 0xf00;
|
||||
performance_monitor_exception(®s);
|
||||
@@ -253,8 +258,7 @@ again:
|
||||
hard_irq_disable();
|
||||
}
|
||||
|
||||
happened = local_paca->irq_happened;
|
||||
if (happened & ~PACA_IRQ_HARD_DIS) {
|
||||
if (local_paca->irq_happened & ~PACA_IRQ_HARD_DIS) {
|
||||
/*
|
||||
* We are responding to the next interrupt, so interrupt-off
|
||||
* latencies should be reset here.
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
#include <asm/export.h>
|
||||
|
||||
/* rdi: arg1 ... normal C conventions. rax is saved/restored. */
|
||||
.macro THUNK name, func, put_ret_addr_in_rdi=0
|
||||
.macro THUNK name, func
|
||||
SYM_FUNC_START_NOALIGN(\name)
|
||||
pushq %rbp
|
||||
movq %rsp, %rbp
|
||||
@@ -25,13 +25,8 @@ SYM_FUNC_START_NOALIGN(\name)
|
||||
pushq %r10
|
||||
pushq %r11
|
||||
|
||||
.if \put_ret_addr_in_rdi
|
||||
/* 8(%rbp) is return addr on stack */
|
||||
movq 8(%rbp), %rdi
|
||||
.endif
|
||||
|
||||
call \func
|
||||
jmp .L_restore
|
||||
jmp __thunk_restore
|
||||
SYM_FUNC_END(\name)
|
||||
_ASM_NOKPROBE(\name)
|
||||
.endm
|
||||
@@ -44,7 +39,7 @@ SYM_FUNC_END(\name)
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_PREEMPTION
|
||||
SYM_CODE_START_LOCAL_NOALIGN(.L_restore)
|
||||
SYM_CODE_START_LOCAL_NOALIGN(__thunk_restore)
|
||||
popq %r11
|
||||
popq %r10
|
||||
popq %r9
|
||||
@@ -56,6 +51,6 @@ SYM_CODE_START_LOCAL_NOALIGN(.L_restore)
|
||||
popq %rdi
|
||||
popq %rbp
|
||||
ret
|
||||
_ASM_NOKPROBE(.L_restore)
|
||||
SYM_CODE_END(.L_restore)
|
||||
_ASM_NOKPROBE(__thunk_restore)
|
||||
SYM_CODE_END(__thunk_restore)
|
||||
#endif
|
||||
|
||||
@@ -3,8 +3,9 @@
|
||||
* apple-properties.c - EFI device properties on Macs
|
||||
* Copyright (C) 2016 Lukas Wunner <lukas@wunner.de>
|
||||
*
|
||||
* Note, all properties are considered as u8 arrays.
|
||||
* To get a value of any of them the caller must use device_property_read_u8_array().
|
||||
* Properties are stored either as:
|
||||
* u8 arrays which can be retrieved with device_property_read_u8_array() or
|
||||
* booleans which can be queried with device_property_present().
|
||||
*/
|
||||
|
||||
#define pr_fmt(fmt) "apple-properties: " fmt
|
||||
@@ -88,8 +89,12 @@ static void __init unmarshal_key_value_pairs(struct dev_header *dev_header,
|
||||
|
||||
entry_data = ptr + key_len + sizeof(val_len);
|
||||
entry_len = val_len - sizeof(val_len);
|
||||
entry[i] = PROPERTY_ENTRY_U8_ARRAY_LEN(key, entry_data,
|
||||
entry_len);
|
||||
if (entry_len)
|
||||
entry[i] = PROPERTY_ENTRY_U8_ARRAY_LEN(key, entry_data,
|
||||
entry_len);
|
||||
else
|
||||
entry[i] = PROPERTY_ENTRY_BOOL(key);
|
||||
|
||||
if (dump_properties) {
|
||||
dev_info(dev, "property: %s\n", key);
|
||||
print_hex_dump(KERN_INFO, pr_fmt(), DUMP_PREFIX_OFFSET,
|
||||
|
||||
@@ -1275,7 +1275,8 @@ static int mtk_i2c_probe(struct platform_device *pdev)
|
||||
mtk_i2c_clock_disable(i2c);
|
||||
|
||||
ret = devm_request_irq(&pdev->dev, irq, mtk_i2c_irq,
|
||||
IRQF_TRIGGER_NONE, I2C_DRV_NAME, i2c);
|
||||
IRQF_NO_SUSPEND | IRQF_TRIGGER_NONE,
|
||||
I2C_DRV_NAME, i2c);
|
||||
if (ret < 0) {
|
||||
dev_err(&pdev->dev,
|
||||
"Request I2C IRQ %d fail\n", irq);
|
||||
@@ -1302,7 +1303,16 @@ static int mtk_i2c_remove(struct platform_device *pdev)
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
static int mtk_i2c_resume(struct device *dev)
|
||||
static int mtk_i2c_suspend_noirq(struct device *dev)
|
||||
{
|
||||
struct mtk_i2c *i2c = dev_get_drvdata(dev);
|
||||
|
||||
i2c_mark_adapter_suspended(&i2c->adap);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mtk_i2c_resume_noirq(struct device *dev)
|
||||
{
|
||||
int ret;
|
||||
struct mtk_i2c *i2c = dev_get_drvdata(dev);
|
||||
@@ -1317,12 +1327,15 @@ static int mtk_i2c_resume(struct device *dev)
|
||||
|
||||
mtk_i2c_clock_disable(i2c);
|
||||
|
||||
i2c_mark_adapter_resumed(&i2c->adap);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static const struct dev_pm_ops mtk_i2c_pm = {
|
||||
SET_SYSTEM_SLEEP_PM_OPS(NULL, mtk_i2c_resume)
|
||||
SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(mtk_i2c_suspend_noirq,
|
||||
mtk_i2c_resume_noirq)
|
||||
};
|
||||
|
||||
static struct platform_driver mtk_i2c_driver = {
|
||||
|
||||
@@ -928,6 +928,9 @@ config LEDS_ACER_A500
|
||||
This option enables support for the Power Button LED of
|
||||
Acer Iconia Tab A500.
|
||||
|
||||
comment "Flash and Torch LED drivers"
|
||||
source "drivers/leds/flash/Kconfig"
|
||||
|
||||
comment "LED Triggers"
|
||||
source "drivers/leds/trigger/Kconfig"
|
||||
|
||||
|
||||
@@ -103,5 +103,8 @@ obj-$(CONFIG_LEDS_SPI_BYTE) += leds-spi-byte.o
|
||||
# LED Userspace Drivers
|
||||
obj-$(CONFIG_LEDS_USER) += uleds.o
|
||||
|
||||
# Flash and Torch LED Drivers
|
||||
obj-$(CONFIG_LEDS_CLASS_FLASH) += flash/
|
||||
|
||||
# LED Triggers
|
||||
obj-$(CONFIG_LEDS_TRIGGERS) += trigger/
|
||||
|
||||
15
drivers/leds/flash/Kconfig
Normal file
15
drivers/leds/flash/Kconfig
Normal file
@@ -0,0 +1,15 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
if LEDS_CLASS_FLASH
|
||||
|
||||
config LEDS_RT8515
|
||||
tristate "LED support for Richtek RT8515 flash/torch LED"
|
||||
depends on GPIOLIB
|
||||
help
|
||||
This option enables support for the Richtek RT8515 flash
|
||||
and torch LEDs found on some mobile phones.
|
||||
|
||||
To compile this driver as a module, choose M here: the module
|
||||
will be called leds-rt8515.
|
||||
|
||||
endif # LEDS_CLASS_FLASH
|
||||
3
drivers/leds/flash/Makefile
Normal file
3
drivers/leds/flash/Makefile
Normal file
@@ -0,0 +1,3 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
obj-$(CONFIG_LEDS_RT8515) += leds-rt8515.o
|
||||
397
drivers/leds/flash/leds-rt8515.c
Normal file
397
drivers/leds/flash/leds-rt8515.c
Normal file
@@ -0,0 +1,397 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/*
|
||||
* LED driver for Richtek RT8515 flash/torch white LEDs
|
||||
* found on some Samsung mobile phones.
|
||||
*
|
||||
* This is a 1.5A Boost dual channel driver produced around 2011.
|
||||
*
|
||||
* The component lacks a datasheet, but in the schematic picture
|
||||
* from the LG P970 service manual you can see the connections
|
||||
* from the RT8515 to the LED, with two resistors connected
|
||||
* from the pins "RFS" and "RTS" to ground.
|
||||
*
|
||||
* On the LG P970:
|
||||
* RFS (resistance flash setting?) is 20 kOhm
|
||||
* RTS (resistance torch setting?) is 39 kOhm
|
||||
*
|
||||
* Some sleuthing finds us the RT9387A which we have a datasheet for:
|
||||
* https://static5.arrow.com/pdfs/2014/7/27/8/21/12/794/rtt_/manual/94download_ds.jspprt9387a.jspprt9387a.pdf
|
||||
* This apparently works the same way so in theory this driver
|
||||
* should cover RT9387A as well. This has not been tested, please
|
||||
* update the compatibles if you add RT9387A support.
|
||||
*
|
||||
* Linus Walleij <linus.walleij@linaro.org>
|
||||
*/
|
||||
#include <linux/delay.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/led-class-flash.h>
|
||||
#include <linux/mod_devicetable.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/property.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
|
||||
#include <media/v4l2-flash-led-class.h>
|
||||
|
||||
/* We can provide 15-700 mA out to the LED */
|
||||
#define RT8515_MIN_IOUT_MA 15
|
||||
#define RT8515_MAX_IOUT_MA 700
|
||||
/* The maximum intensity is 1-16 for flash and 1-100 for torch */
|
||||
#define RT8515_FLASH_MAX 16
|
||||
#define RT8515_TORCH_MAX 100
|
||||
|
||||
#define RT8515_TIMEOUT_US 250000U
|
||||
#define RT8515_MAX_TIMEOUT_US 300000U
|
||||
|
||||
struct rt8515 {
|
||||
struct led_classdev_flash fled;
|
||||
struct device *dev;
|
||||
struct v4l2_flash *v4l2_flash;
|
||||
struct mutex lock;
|
||||
struct regulator *reg;
|
||||
struct gpio_desc *enable_torch;
|
||||
struct gpio_desc *enable_flash;
|
||||
struct timer_list powerdown_timer;
|
||||
u32 max_timeout; /* Flash max timeout */
|
||||
int flash_max_intensity;
|
||||
int torch_max_intensity;
|
||||
};
|
||||
|
||||
static struct rt8515 *to_rt8515(struct led_classdev_flash *fled)
|
||||
{
|
||||
return container_of(fled, struct rt8515, fled);
|
||||
}
|
||||
|
||||
static void rt8515_gpio_led_off(struct rt8515 *rt)
|
||||
{
|
||||
gpiod_set_value(rt->enable_flash, 0);
|
||||
gpiod_set_value(rt->enable_torch, 0);
|
||||
}
|
||||
|
||||
static void rt8515_gpio_brightness_commit(struct gpio_desc *gpiod,
|
||||
int brightness)
|
||||
{
|
||||
int i;
|
||||
|
||||
/*
|
||||
* Toggling a GPIO line with a small delay increases the
|
||||
* brightness one step at a time.
|
||||
*/
|
||||
for (i = 0; i < brightness; i++) {
|
||||
gpiod_set_value(gpiod, 0);
|
||||
udelay(1);
|
||||
gpiod_set_value(gpiod, 1);
|
||||
udelay(1);
|
||||
}
|
||||
}
|
||||
|
||||
/* This is setting the torch light level */
|
||||
static int rt8515_led_brightness_set(struct led_classdev *led,
|
||||
enum led_brightness brightness)
|
||||
{
|
||||
struct led_classdev_flash *fled = lcdev_to_flcdev(led);
|
||||
struct rt8515 *rt = to_rt8515(fled);
|
||||
|
||||
mutex_lock(&rt->lock);
|
||||
|
||||
if (brightness == LED_OFF) {
|
||||
/* Off */
|
||||
rt8515_gpio_led_off(rt);
|
||||
} else if (brightness < RT8515_TORCH_MAX) {
|
||||
/* Step it up to movie mode brightness using the flash pin */
|
||||
rt8515_gpio_brightness_commit(rt->enable_torch, brightness);
|
||||
} else {
|
||||
/* Max torch brightness requested */
|
||||
gpiod_set_value(rt->enable_torch, 1);
|
||||
}
|
||||
|
||||
mutex_unlock(&rt->lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rt8515_led_flash_strobe_set(struct led_classdev_flash *fled,
|
||||
bool state)
|
||||
{
|
||||
struct rt8515 *rt = to_rt8515(fled);
|
||||
struct led_flash_setting *timeout = &fled->timeout;
|
||||
int brightness = rt->flash_max_intensity;
|
||||
|
||||
mutex_lock(&rt->lock);
|
||||
|
||||
if (state) {
|
||||
/* Enable LED flash mode and set brightness */
|
||||
rt8515_gpio_brightness_commit(rt->enable_flash, brightness);
|
||||
/* Set timeout */
|
||||
mod_timer(&rt->powerdown_timer,
|
||||
jiffies + usecs_to_jiffies(timeout->val));
|
||||
} else {
|
||||
del_timer_sync(&rt->powerdown_timer);
|
||||
/* Turn the LED off */
|
||||
rt8515_gpio_led_off(rt);
|
||||
}
|
||||
|
||||
fled->led_cdev.brightness = LED_OFF;
|
||||
/* After this the torch LED will be disabled */
|
||||
|
||||
mutex_unlock(&rt->lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rt8515_led_flash_strobe_get(struct led_classdev_flash *fled,
|
||||
bool *state)
|
||||
{
|
||||
struct rt8515 *rt = to_rt8515(fled);
|
||||
|
||||
*state = timer_pending(&rt->powerdown_timer);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rt8515_led_flash_timeout_set(struct led_classdev_flash *fled,
|
||||
u32 timeout)
|
||||
{
|
||||
/* The timeout is stored in the led-class-flash core */
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct led_flash_ops rt8515_flash_ops = {
|
||||
.strobe_set = rt8515_led_flash_strobe_set,
|
||||
.strobe_get = rt8515_led_flash_strobe_get,
|
||||
.timeout_set = rt8515_led_flash_timeout_set,
|
||||
};
|
||||
|
||||
static void rt8515_powerdown_timer(struct timer_list *t)
|
||||
{
|
||||
struct rt8515 *rt = from_timer(rt, t, powerdown_timer);
|
||||
|
||||
/* Turn the LED off */
|
||||
rt8515_gpio_led_off(rt);
|
||||
}
|
||||
|
||||
static void rt8515_init_flash_timeout(struct rt8515 *rt)
|
||||
{
|
||||
struct led_classdev_flash *fled = &rt->fled;
|
||||
struct led_flash_setting *s;
|
||||
|
||||
/* Init flash timeout setting */
|
||||
s = &fled->timeout;
|
||||
s->min = 1;
|
||||
s->max = rt->max_timeout;
|
||||
s->step = 1;
|
||||
/*
|
||||
* Set default timeout to RT8515_TIMEOUT_US except if
|
||||
* max_timeout from DT is lower.
|
||||
*/
|
||||
s->val = min(rt->max_timeout, RT8515_TIMEOUT_US);
|
||||
}
|
||||
|
||||
#if IS_ENABLED(CONFIG_V4L2_FLASH_LED_CLASS)
|
||||
/* Configure the V2L2 flash subdevice */
|
||||
static void rt8515_init_v4l2_flash_config(struct rt8515 *rt,
|
||||
struct v4l2_flash_config *v4l2_sd_cfg)
|
||||
{
|
||||
struct led_classdev *led = &rt->fled.led_cdev;
|
||||
struct led_flash_setting *s;
|
||||
|
||||
strscpy(v4l2_sd_cfg->dev_name, led->dev->kobj.name,
|
||||
sizeof(v4l2_sd_cfg->dev_name));
|
||||
|
||||
/*
|
||||
* Init flash intensity setting: this is a linear scale
|
||||
* capped from the device tree max intensity setting
|
||||
* 1..flash_max_intensity
|
||||
*/
|
||||
s = &v4l2_sd_cfg->intensity;
|
||||
s->min = 1;
|
||||
s->max = rt->flash_max_intensity;
|
||||
s->step = 1;
|
||||
s->val = s->max;
|
||||
}
|
||||
|
||||
static void rt8515_v4l2_flash_release(struct rt8515 *rt)
|
||||
{
|
||||
v4l2_flash_release(rt->v4l2_flash);
|
||||
}
|
||||
|
||||
#else
|
||||
static void rt8515_init_v4l2_flash_config(struct rt8515 *rt,
|
||||
struct v4l2_flash_config *v4l2_sd_cfg)
|
||||
{
|
||||
}
|
||||
|
||||
static void rt8515_v4l2_flash_release(struct rt8515 *rt)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
static void rt8515_determine_max_intensity(struct rt8515 *rt,
|
||||
struct fwnode_handle *led,
|
||||
const char *resistance,
|
||||
const char *max_ua_prop, int hw_max,
|
||||
int *max_intensity_setting)
|
||||
{
|
||||
u32 res = 0; /* Can't be 0 so 0 is undefined */
|
||||
u32 ua;
|
||||
u32 max_ma;
|
||||
int max_intensity;
|
||||
int ret;
|
||||
|
||||
fwnode_property_read_u32(rt->dev->fwnode, resistance, &res);
|
||||
ret = fwnode_property_read_u32(led, max_ua_prop, &ua);
|
||||
|
||||
/* Missing info in DT, OK go with hardware maxima */
|
||||
if (ret || res == 0) {
|
||||
dev_err(rt->dev,
|
||||
"either %s or %s missing from DT, using HW max\n",
|
||||
resistance, max_ua_prop);
|
||||
max_ma = RT8515_MAX_IOUT_MA;
|
||||
max_intensity = hw_max;
|
||||
goto out_assign_max;
|
||||
}
|
||||
|
||||
/*
|
||||
* Formula from the datasheet, this is the maximum current
|
||||
* defined by the hardware.
|
||||
*/
|
||||
max_ma = (5500 * 1000) / res;
|
||||
/*
|
||||
* Calculate max intensity (linear scaling)
|
||||
* Formula is ((ua / 1000) / max_ma) * 100, then simplified
|
||||
*/
|
||||
max_intensity = (ua / 10) / max_ma;
|
||||
|
||||
dev_info(rt->dev,
|
||||
"current restricted from %u to %u mA, max intensity %d/100\n",
|
||||
max_ma, (ua / 1000), max_intensity);
|
||||
|
||||
out_assign_max:
|
||||
dev_info(rt->dev, "max intensity %d/%d = %d mA\n",
|
||||
max_intensity, hw_max, max_ma);
|
||||
*max_intensity_setting = max_intensity;
|
||||
}
|
||||
|
||||
static int rt8515_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
struct fwnode_handle *child;
|
||||
struct rt8515 *rt;
|
||||
struct led_classdev *led;
|
||||
struct led_classdev_flash *fled;
|
||||
struct led_init_data init_data = {};
|
||||
struct v4l2_flash_config v4l2_sd_cfg = {};
|
||||
int ret;
|
||||
|
||||
rt = devm_kzalloc(dev, sizeof(*rt), GFP_KERNEL);
|
||||
if (!rt)
|
||||
return -ENOMEM;
|
||||
|
||||
rt->dev = dev;
|
||||
fled = &rt->fled;
|
||||
led = &fled->led_cdev;
|
||||
|
||||
/* ENF - Enable Flash line */
|
||||
rt->enable_flash = devm_gpiod_get(dev, "enf", GPIOD_OUT_LOW);
|
||||
if (IS_ERR(rt->enable_flash))
|
||||
return dev_err_probe(dev, PTR_ERR(rt->enable_flash),
|
||||
"cannot get ENF (enable flash) GPIO\n");
|
||||
|
||||
/* ENT - Enable Torch line */
|
||||
rt->enable_torch = devm_gpiod_get(dev, "ent", GPIOD_OUT_LOW);
|
||||
if (IS_ERR(rt->enable_torch))
|
||||
return dev_err_probe(dev, PTR_ERR(rt->enable_torch),
|
||||
"cannot get ENT (enable torch) GPIO\n");
|
||||
|
||||
child = fwnode_get_next_available_child_node(dev->fwnode, NULL);
|
||||
if (!child) {
|
||||
dev_err(dev,
|
||||
"No fwnode child node found for connected LED.\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
init_data.fwnode = child;
|
||||
|
||||
rt8515_determine_max_intensity(rt, child, "richtek,rfs-ohms",
|
||||
"flash-max-microamp",
|
||||
RT8515_FLASH_MAX,
|
||||
&rt->flash_max_intensity);
|
||||
rt8515_determine_max_intensity(rt, child, "richtek,rts-ohms",
|
||||
"led-max-microamp",
|
||||
RT8515_TORCH_MAX,
|
||||
&rt->torch_max_intensity);
|
||||
|
||||
ret = fwnode_property_read_u32(child, "flash-max-timeout-us",
|
||||
&rt->max_timeout);
|
||||
if (ret) {
|
||||
rt->max_timeout = RT8515_MAX_TIMEOUT_US;
|
||||
dev_warn(dev,
|
||||
"flash-max-timeout-us property missing\n");
|
||||
}
|
||||
timer_setup(&rt->powerdown_timer, rt8515_powerdown_timer, 0);
|
||||
rt8515_init_flash_timeout(rt);
|
||||
|
||||
fled->ops = &rt8515_flash_ops;
|
||||
|
||||
led->max_brightness = rt->torch_max_intensity;
|
||||
led->brightness_set_blocking = rt8515_led_brightness_set;
|
||||
led->flags |= LED_CORE_SUSPENDRESUME | LED_DEV_CAP_FLASH;
|
||||
|
||||
mutex_init(&rt->lock);
|
||||
|
||||
platform_set_drvdata(pdev, rt);
|
||||
|
||||
ret = devm_led_classdev_flash_register_ext(dev, fled, &init_data);
|
||||
if (ret) {
|
||||
dev_err(dev, "can't register LED %s\n", led->name);
|
||||
mutex_destroy(&rt->lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
rt8515_init_v4l2_flash_config(rt, &v4l2_sd_cfg);
|
||||
|
||||
/* Create a V4L2 Flash device if V4L2 flash is enabled */
|
||||
rt->v4l2_flash = v4l2_flash_init(dev, child, fled, NULL, &v4l2_sd_cfg);
|
||||
if (IS_ERR(rt->v4l2_flash)) {
|
||||
ret = PTR_ERR(rt->v4l2_flash);
|
||||
dev_err(dev, "failed to register V4L2 flash device (%d)\n",
|
||||
ret);
|
||||
/*
|
||||
* Continue without the V4L2 flash
|
||||
* (we still have the classdev)
|
||||
*/
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rt8515_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct rt8515 *rt = platform_get_drvdata(pdev);
|
||||
|
||||
rt8515_v4l2_flash_release(rt);
|
||||
del_timer_sync(&rt->powerdown_timer);
|
||||
mutex_destroy(&rt->lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct of_device_id rt8515_match[] = {
|
||||
{ .compatible = "richtek,rt8515", },
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, rt8515_match);
|
||||
|
||||
static struct platform_driver rt8515_driver = {
|
||||
.driver = {
|
||||
.name = "rt8515",
|
||||
.of_match_table = rt8515_match,
|
||||
},
|
||||
.probe = rt8515_probe,
|
||||
.remove = rt8515_remove,
|
||||
};
|
||||
module_platform_driver(rt8515_driver);
|
||||
|
||||
MODULE_AUTHOR("Linus Walleij <linus.walleij@linaro.org>");
|
||||
MODULE_DESCRIPTION("Richtek RT8515 LED driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
@@ -378,14 +378,15 @@ void led_trigger_event(struct led_trigger *trig,
|
||||
enum led_brightness brightness)
|
||||
{
|
||||
struct led_classdev *led_cdev;
|
||||
unsigned long flags;
|
||||
|
||||
if (!trig)
|
||||
return;
|
||||
|
||||
read_lock(&trig->leddev_list_lock);
|
||||
read_lock_irqsave(&trig->leddev_list_lock, flags);
|
||||
list_for_each_entry(led_cdev, &trig->led_cdevs, trig_list)
|
||||
led_set_brightness(led_cdev, brightness);
|
||||
read_unlock(&trig->leddev_list_lock);
|
||||
read_unlock_irqrestore(&trig->leddev_list_lock, flags);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(led_trigger_event);
|
||||
|
||||
@@ -396,11 +397,12 @@ static void led_trigger_blink_setup(struct led_trigger *trig,
|
||||
int invert)
|
||||
{
|
||||
struct led_classdev *led_cdev;
|
||||
unsigned long flags;
|
||||
|
||||
if (!trig)
|
||||
return;
|
||||
|
||||
read_lock(&trig->leddev_list_lock);
|
||||
read_lock_irqsave(&trig->leddev_list_lock, flags);
|
||||
list_for_each_entry(led_cdev, &trig->led_cdevs, trig_list) {
|
||||
if (oneshot)
|
||||
led_blink_set_oneshot(led_cdev, delay_on, delay_off,
|
||||
@@ -408,7 +410,7 @@ static void led_trigger_blink_setup(struct led_trigger *trig,
|
||||
else
|
||||
led_blink_set(led_cdev, delay_on, delay_off);
|
||||
}
|
||||
read_unlock(&trig->leddev_list_lock);
|
||||
read_unlock_irqrestore(&trig->leddev_list_lock, flags);
|
||||
}
|
||||
|
||||
void led_trigger_blink(struct led_trigger *trig,
|
||||
|
||||
@@ -96,14 +96,14 @@ static int ariel_led_probe(struct platform_device *pdev)
|
||||
return -ENOMEM;
|
||||
|
||||
leds[0].ec_index = EC_BLUE_LED;
|
||||
leds[0].led_cdev.name = "blue:power",
|
||||
leds[0].led_cdev.name = "blue:power";
|
||||
leds[0].led_cdev.default_trigger = "default-on";
|
||||
|
||||
leds[1].ec_index = EC_AMBER_LED;
|
||||
leds[1].led_cdev.name = "amber:status",
|
||||
leds[1].led_cdev.name = "amber:status";
|
||||
|
||||
leds[2].ec_index = EC_GREEN_LED;
|
||||
leds[2].led_cdev.name = "green:status",
|
||||
leds[2].led_cdev.name = "green:status";
|
||||
leds[2].led_cdev.default_trigger = "default-on";
|
||||
|
||||
for (i = 0; i < NLEDS; i++) {
|
||||
|
||||
@@ -679,7 +679,7 @@ static int lm3533_led_probe(struct platform_device *pdev)
|
||||
led->cdev.brightness_get = lm3533_led_get;
|
||||
led->cdev.blink_set = lm3533_led_blink_set;
|
||||
led->cdev.brightness = LED_OFF;
|
||||
led->cdev.groups = lm3533_led_attribute_groups,
|
||||
led->cdev.groups = lm3533_led_attribute_groups;
|
||||
led->id = pdev->id;
|
||||
|
||||
mutex_init(&led->mutex);
|
||||
|
||||
@@ -805,6 +805,14 @@ cmos_do_probe(struct device *dev, struct resource *ports, int rtc_irq)
|
||||
|
||||
spin_lock_irq(&rtc_lock);
|
||||
|
||||
/* Ensure that the RTC is accessible. Bit 0-6 must be 0! */
|
||||
if ((CMOS_READ(RTC_VALID) & 0x7f) != 0) {
|
||||
spin_unlock_irq(&rtc_lock);
|
||||
dev_warn(dev, "not accessible\n");
|
||||
retval = -ENXIO;
|
||||
goto cleanup1;
|
||||
}
|
||||
|
||||
if (!(flags & CMOS_RTC_FLAGS_NOFREQ)) {
|
||||
/* force periodic irq to CMOS reset default of 1024Hz;
|
||||
*
|
||||
|
||||
@@ -21,6 +21,13 @@ unsigned int mc146818_get_time(struct rtc_time *time)
|
||||
|
||||
again:
|
||||
spin_lock_irqsave(&rtc_lock, flags);
|
||||
/* Ensure that the RTC is accessible. Bit 0-6 must be 0! */
|
||||
if (WARN_ON_ONCE((CMOS_READ(RTC_VALID) & 0x7f) != 0)) {
|
||||
spin_unlock_irqrestore(&rtc_lock, flags);
|
||||
memset(time, 0xff, sizeof(*time));
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check whether there is an update in progress during which the
|
||||
* readout is unspecified. The maximum update time is ~2ms. Poll
|
||||
|
||||
@@ -324,6 +324,21 @@ pnfs_grab_inode_layout_hdr(struct pnfs_layout_hdr *lo)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Compare 2 layout stateid sequence ids, to see which is newer,
|
||||
* taking into account wraparound issues.
|
||||
*/
|
||||
static bool pnfs_seqid_is_newer(u32 s1, u32 s2)
|
||||
{
|
||||
return (s32)(s1 - s2) > 0;
|
||||
}
|
||||
|
||||
static void pnfs_barrier_update(struct pnfs_layout_hdr *lo, u32 newseq)
|
||||
{
|
||||
if (pnfs_seqid_is_newer(newseq, lo->plh_barrier))
|
||||
lo->plh_barrier = newseq;
|
||||
}
|
||||
|
||||
static void
|
||||
pnfs_set_plh_return_info(struct pnfs_layout_hdr *lo, enum pnfs_iomode iomode,
|
||||
u32 seq)
|
||||
@@ -335,6 +350,7 @@ pnfs_set_plh_return_info(struct pnfs_layout_hdr *lo, enum pnfs_iomode iomode,
|
||||
if (seq != 0) {
|
||||
WARN_ON_ONCE(lo->plh_return_seq != 0 && lo->plh_return_seq != seq);
|
||||
lo->plh_return_seq = seq;
|
||||
pnfs_barrier_update(lo, seq);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -639,15 +655,6 @@ static int mark_lseg_invalid(struct pnfs_layout_segment *lseg,
|
||||
return rv;
|
||||
}
|
||||
|
||||
/*
|
||||
* Compare 2 layout stateid sequence ids, to see which is newer,
|
||||
* taking into account wraparound issues.
|
||||
*/
|
||||
static bool pnfs_seqid_is_newer(u32 s1, u32 s2)
|
||||
{
|
||||
return (s32)(s1 - s2) > 0;
|
||||
}
|
||||
|
||||
static bool
|
||||
pnfs_should_free_range(const struct pnfs_layout_range *lseg_range,
|
||||
const struct pnfs_layout_range *recall_range)
|
||||
@@ -984,8 +991,7 @@ pnfs_set_layout_stateid(struct pnfs_layout_hdr *lo, const nfs4_stateid *new,
|
||||
new_barrier = be32_to_cpu(new->seqid);
|
||||
else if (new_barrier == 0)
|
||||
return;
|
||||
if (pnfs_seqid_is_newer(new_barrier, lo->plh_barrier))
|
||||
lo->plh_barrier = new_barrier;
|
||||
pnfs_barrier_update(lo, new_barrier);
|
||||
}
|
||||
|
||||
static bool
|
||||
@@ -994,7 +1000,7 @@ pnfs_layout_stateid_blocked(const struct pnfs_layout_hdr *lo,
|
||||
{
|
||||
u32 seqid = be32_to_cpu(stateid->seqid);
|
||||
|
||||
return !pnfs_seqid_is_newer(seqid, lo->plh_barrier);
|
||||
return !pnfs_seqid_is_newer(seqid, lo->plh_barrier) && lo->plh_barrier;
|
||||
}
|
||||
|
||||
/* lget is set to 1 if called from inside send_layoutget call chain */
|
||||
@@ -1183,20 +1189,17 @@ pnfs_prepare_layoutreturn(struct pnfs_layout_hdr *lo,
|
||||
return false;
|
||||
set_bit(NFS_LAYOUT_RETURN, &lo->plh_flags);
|
||||
pnfs_get_layout_hdr(lo);
|
||||
nfs4_stateid_copy(stateid, &lo->plh_stateid);
|
||||
*cred = get_cred(lo->plh_lc_cred);
|
||||
if (test_bit(NFS_LAYOUT_RETURN_REQUESTED, &lo->plh_flags)) {
|
||||
nfs4_stateid_copy(stateid, &lo->plh_stateid);
|
||||
*cred = get_cred(lo->plh_lc_cred);
|
||||
if (lo->plh_return_seq != 0)
|
||||
stateid->seqid = cpu_to_be32(lo->plh_return_seq);
|
||||
if (iomode != NULL)
|
||||
*iomode = lo->plh_return_iomode;
|
||||
pnfs_clear_layoutreturn_info(lo);
|
||||
return true;
|
||||
}
|
||||
nfs4_stateid_copy(stateid, &lo->plh_stateid);
|
||||
*cred = get_cred(lo->plh_lc_cred);
|
||||
if (iomode != NULL)
|
||||
} else if (iomode != NULL)
|
||||
*iomode = IOMODE_ANY;
|
||||
pnfs_barrier_update(lo, be32_to_cpu(stateid->seqid));
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1909,6 +1912,11 @@ static void nfs_layoutget_end(struct pnfs_layout_hdr *lo)
|
||||
wake_up_var(&lo->plh_outstanding);
|
||||
}
|
||||
|
||||
static bool pnfs_is_first_layoutget(struct pnfs_layout_hdr *lo)
|
||||
{
|
||||
return test_bit(NFS_LAYOUT_FIRST_LAYOUTGET, &lo->plh_flags);
|
||||
}
|
||||
|
||||
static void pnfs_clear_first_layoutget(struct pnfs_layout_hdr *lo)
|
||||
{
|
||||
unsigned long *bitlock = &lo->plh_flags;
|
||||
@@ -2383,23 +2391,34 @@ pnfs_layout_process(struct nfs4_layoutget *lgp)
|
||||
goto out_forget;
|
||||
}
|
||||
|
||||
if (!pnfs_layout_is_valid(lo)) {
|
||||
/* We have a completely new layout */
|
||||
pnfs_set_layout_stateid(lo, &res->stateid, lgp->cred, true);
|
||||
} else if (nfs4_stateid_match_other(&lo->plh_stateid, &res->stateid)) {
|
||||
if (nfs4_stateid_match_other(&lo->plh_stateid, &res->stateid)) {
|
||||
/* existing state ID, make sure the sequence number matches. */
|
||||
if (pnfs_layout_stateid_blocked(lo, &res->stateid)) {
|
||||
if (!pnfs_layout_is_valid(lo) &&
|
||||
pnfs_is_first_layoutget(lo))
|
||||
lo->plh_barrier = 0;
|
||||
dprintk("%s forget reply due to sequence\n", __func__);
|
||||
goto out_forget;
|
||||
}
|
||||
pnfs_set_layout_stateid(lo, &res->stateid, lgp->cred, false);
|
||||
} else {
|
||||
} else if (pnfs_layout_is_valid(lo)) {
|
||||
/*
|
||||
* We got an entirely new state ID. Mark all segments for the
|
||||
* inode invalid, and retry the layoutget
|
||||
*/
|
||||
pnfs_mark_layout_stateid_invalid(lo, &free_me);
|
||||
struct pnfs_layout_range range = {
|
||||
.iomode = IOMODE_ANY,
|
||||
.length = NFS4_MAX_UINT64,
|
||||
};
|
||||
pnfs_set_plh_return_info(lo, IOMODE_ANY, 0);
|
||||
pnfs_mark_matching_lsegs_return(lo, &lo->plh_return_segs,
|
||||
&range, 0);
|
||||
goto out_forget;
|
||||
} else {
|
||||
/* We have a completely new layout */
|
||||
if (!pnfs_is_first_layoutget(lo))
|
||||
goto out_forget;
|
||||
pnfs_set_layout_stateid(lo, &res->stateid, lgp->cred, true);
|
||||
}
|
||||
|
||||
pnfs_get_lseg(lseg);
|
||||
|
||||
@@ -178,6 +178,11 @@
|
||||
* Objtool generates debug info for both FUNC & CODE, but needs special
|
||||
* annotations for each CODE's start (to describe the actual stack frame).
|
||||
*
|
||||
* Objtool requires that all code must be contained in an ELF symbol. Symbol
|
||||
* names that have a .L prefix do not emit symbol table entries. .L
|
||||
* prefixed symbols can be used within a code region, but should be avoided for
|
||||
* denoting a range of code via ``SYM_*_START/END`` annotations.
|
||||
*
|
||||
* ALIAS -- does not generate debug info -- the aliased function will
|
||||
*/
|
||||
|
||||
|
||||
@@ -25,8 +25,7 @@ struct rpc_rqst;
|
||||
#define XDR_QUADLEN(l) (((l) + 3) >> 2)
|
||||
|
||||
/*
|
||||
* Generic opaque `network object.' At the kernel level, this type
|
||||
* is used only by lockd.
|
||||
* Generic opaque `network object.'
|
||||
*/
|
||||
#define XDR_MAX_NETOBJ 1024
|
||||
struct xdr_netobj {
|
||||
|
||||
@@ -222,7 +222,7 @@ static inline bool report_single_step(unsigned long work)
|
||||
*/
|
||||
static inline bool report_single_step(unsigned long work)
|
||||
{
|
||||
if (!(work & SYSCALL_WORK_SYSCALL_EMU))
|
||||
if (work & SYSCALL_WORK_SYSCALL_EMU)
|
||||
return false;
|
||||
|
||||
return !!(current_thread_info()->flags & _TIF_SINGLESTEP);
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
#include <linux/uaccess.h>
|
||||
#include <linux/hashtable.h>
|
||||
|
||||
#include "auth_gss_internal.h"
|
||||
#include "../netns.h"
|
||||
|
||||
#include <trace/events/rpcgss.h>
|
||||
@@ -125,35 +126,6 @@ gss_cred_set_ctx(struct rpc_cred *cred, struct gss_cl_ctx *ctx)
|
||||
clear_bit(RPCAUTH_CRED_NEW, &cred->cr_flags);
|
||||
}
|
||||
|
||||
static const void *
|
||||
simple_get_bytes(const void *p, const void *end, void *res, size_t len)
|
||||
{
|
||||
const void *q = (const void *)((const char *)p + len);
|
||||
if (unlikely(q > end || q < p))
|
||||
return ERR_PTR(-EFAULT);
|
||||
memcpy(res, p, len);
|
||||
return q;
|
||||
}
|
||||
|
||||
static inline const void *
|
||||
simple_get_netobj(const void *p, const void *end, struct xdr_netobj *dest)
|
||||
{
|
||||
const void *q;
|
||||
unsigned int len;
|
||||
|
||||
p = simple_get_bytes(p, end, &len, sizeof(len));
|
||||
if (IS_ERR(p))
|
||||
return p;
|
||||
q = (const void *)((const char *)p + len);
|
||||
if (unlikely(q > end || q < p))
|
||||
return ERR_PTR(-EFAULT);
|
||||
dest->data = kmemdup(p, len, GFP_NOFS);
|
||||
if (unlikely(dest->data == NULL))
|
||||
return ERR_PTR(-ENOMEM);
|
||||
dest->len = len;
|
||||
return q;
|
||||
}
|
||||
|
||||
static struct gss_cl_ctx *
|
||||
gss_cred_get_ctx(struct rpc_cred *cred)
|
||||
{
|
||||
|
||||
45
net/sunrpc/auth_gss/auth_gss_internal.h
Normal file
45
net/sunrpc/auth_gss/auth_gss_internal.h
Normal file
@@ -0,0 +1,45 @@
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
/*
|
||||
* linux/net/sunrpc/auth_gss/auth_gss_internal.h
|
||||
*
|
||||
* Internal definitions for RPCSEC_GSS client authentication
|
||||
*
|
||||
* Copyright (c) 2000 The Regents of the University of Michigan.
|
||||
* All rights reserved.
|
||||
*
|
||||
*/
|
||||
#include <linux/err.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/sunrpc/xdr.h>
|
||||
|
||||
static inline const void *
|
||||
simple_get_bytes(const void *p, const void *end, void *res, size_t len)
|
||||
{
|
||||
const void *q = (const void *)((const char *)p + len);
|
||||
if (unlikely(q > end || q < p))
|
||||
return ERR_PTR(-EFAULT);
|
||||
memcpy(res, p, len);
|
||||
return q;
|
||||
}
|
||||
|
||||
static inline const void *
|
||||
simple_get_netobj(const void *p, const void *end, struct xdr_netobj *dest)
|
||||
{
|
||||
const void *q;
|
||||
unsigned int len;
|
||||
|
||||
p = simple_get_bytes(p, end, &len, sizeof(len));
|
||||
if (IS_ERR(p))
|
||||
return p;
|
||||
q = (const void *)((const char *)p + len);
|
||||
if (unlikely(q > end || q < p))
|
||||
return ERR_PTR(-EFAULT);
|
||||
if (len) {
|
||||
dest->data = kmemdup(p, len, GFP_NOFS);
|
||||
if (unlikely(dest->data == NULL))
|
||||
return ERR_PTR(-ENOMEM);
|
||||
} else
|
||||
dest->data = NULL;
|
||||
dest->len = len;
|
||||
return q;
|
||||
}
|
||||
@@ -21,6 +21,8 @@
|
||||
#include <linux/sunrpc/xdr.h>
|
||||
#include <linux/sunrpc/gss_krb5_enctypes.h>
|
||||
|
||||
#include "auth_gss_internal.h"
|
||||
|
||||
#if IS_ENABLED(CONFIG_SUNRPC_DEBUG)
|
||||
# define RPCDBG_FACILITY RPCDBG_AUTH
|
||||
#endif
|
||||
@@ -143,35 +145,6 @@ get_gss_krb5_enctype(int etype)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static const void *
|
||||
simple_get_bytes(const void *p, const void *end, void *res, int len)
|
||||
{
|
||||
const void *q = (const void *)((const char *)p + len);
|
||||
if (unlikely(q > end || q < p))
|
||||
return ERR_PTR(-EFAULT);
|
||||
memcpy(res, p, len);
|
||||
return q;
|
||||
}
|
||||
|
||||
static const void *
|
||||
simple_get_netobj(const void *p, const void *end, struct xdr_netobj *res)
|
||||
{
|
||||
const void *q;
|
||||
unsigned int len;
|
||||
|
||||
p = simple_get_bytes(p, end, &len, sizeof(len));
|
||||
if (IS_ERR(p))
|
||||
return p;
|
||||
q = (const void *)((const char *)p + len);
|
||||
if (unlikely(q > end || q < p))
|
||||
return ERR_PTR(-EFAULT);
|
||||
res->data = kmemdup(p, len, GFP_NOFS);
|
||||
if (unlikely(res->data == NULL))
|
||||
return ERR_PTR(-ENOMEM);
|
||||
res->len = len;
|
||||
return q;
|
||||
}
|
||||
|
||||
static inline const void *
|
||||
get_key(const void *p, const void *end,
|
||||
struct krb5_ctx *ctx, struct crypto_sync_skcipher **res)
|
||||
|
||||
Reference in New Issue
Block a user