Resync master with latest Linus upstream
This commit is contained in:
commit
b29e6ece45
|
@ -100,6 +100,7 @@ properties:
|
|||
- pattern
|
||||
# LED is triggered by SD/MMC activity
|
||||
- pattern: "^mmc[0-9]+$"
|
||||
- pattern: "^cpu[0-9]*$"
|
||||
|
||||
led-pattern:
|
||||
description: |
|
||||
|
|
|
@ -1,67 +0,0 @@
|
|||
Qualcomm PM8058 LED driver
|
||||
|
||||
The Qualcomm PM8058 is a multi-functional device which contains
|
||||
an LED driver block for up to six LEDs: three normal LEDs, two
|
||||
"flash" LEDs and one "keypad backlight" LED. The names are
|
||||
quoted because sometimes these LED drivers are used for wildly
|
||||
different things than flash or keypad backlight: their names
|
||||
are more of a suggestion than a hard-wired usecase.
|
||||
|
||||
Hardware-wise the different LEDs support slightly different
|
||||
output currents. The "flash" LEDs do not need to charge nor
|
||||
do they support external triggers. They are just powerful LED
|
||||
drivers.
|
||||
|
||||
The LEDs appear as children to the PM8058 device, with the
|
||||
proper compatible string. For the PM8058 bindings see:
|
||||
mfd/qcom-pm8xxx.txt.
|
||||
|
||||
Each LED is represented as a sub-node of the syscon device. Each
|
||||
node's name represents the name of the corresponding LED.
|
||||
|
||||
LED sub-node properties:
|
||||
|
||||
Required properties:
|
||||
- compatible: one of
|
||||
"qcom,pm8058-led" (for the normal LEDs at 0x131, 0x132 and 0x133)
|
||||
"qcom,pm8058-keypad-led" (for the "keypad" LED at 0x48)
|
||||
"qcom,pm8058-flash-led" (for the "flash" LEDs at 0x49 and 0xFB)
|
||||
|
||||
Optional properties:
|
||||
- label: see Documentation/devicetree/bindings/leds/common.txt
|
||||
- default-state: see Documentation/devicetree/bindings/leds/common.txt
|
||||
- linux,default-trigger: see Documentation/devicetree/bindings/leds/common.txt
|
||||
|
||||
Example:
|
||||
|
||||
qcom,ssbi@500000 {
|
||||
pmicintc: pmic@0 {
|
||||
compatible = "qcom,pm8058";
|
||||
led@48 {
|
||||
compatible = "qcom,pm8058-keypad-led";
|
||||
reg = <0x48>;
|
||||
label = "pm8050:white:keypad";
|
||||
default-state = "off";
|
||||
};
|
||||
led@131 {
|
||||
compatible = "qcom,pm8058-led";
|
||||
reg = <0x131>;
|
||||
label = "pm8058:red";
|
||||
default-state = "off";
|
||||
};
|
||||
led@132 {
|
||||
compatible = "qcom,pm8058-led";
|
||||
reg = <0x132>;
|
||||
label = "pm8058:yellow";
|
||||
default-state = "off";
|
||||
linux,default-trigger = "mmc0";
|
||||
};
|
||||
led@133 {
|
||||
compatible = "qcom,pm8058-led";
|
||||
reg = <0x133>;
|
||||
label = "pm8058:green";
|
||||
default-state = "on";
|
||||
linux,default-trigger = "heartbeat";
|
||||
};
|
||||
};
|
||||
};
|
|
@ -0,0 +1,57 @@
|
|||
# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/leds/qcom,pm8058-led.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Qualcomm PM8058 PMIC LED
|
||||
|
||||
maintainers:
|
||||
- Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
|
||||
|
||||
description: |
|
||||
The Qualcomm PM8058 contains an LED block for up to six LEDs:: three normal
|
||||
LEDs, two "flash" LEDs and one "keypad backlight" LED. The names are quoted
|
||||
because sometimes these LED drivers are used for wildly different things than
|
||||
flash or keypad backlight:: their names are more of a suggestion than a
|
||||
hard-wired usecase.
|
||||
|
||||
Hardware-wise the different LEDs support slightly different output currents.
|
||||
The "flash" LEDs do not need to charge nor do they support external triggers.
|
||||
They are just powerful LED drivers.
|
||||
|
||||
allOf:
|
||||
- $ref: common.yaml#
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- qcom,pm8058-led
|
||||
- qcom,pm8058-keypad-led
|
||||
- qcom,pm8058-flash-led
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/leds/common.h>
|
||||
|
||||
pmic {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
led@131 {
|
||||
compatible = "qcom,pm8058-led";
|
||||
reg = <0x131>;
|
||||
label = "pm8058:red";
|
||||
color = <LED_COLOR_ID_RED>;
|
||||
default-state = "off";
|
||||
};
|
||||
};
|
|
@ -13,6 +13,8 @@ description: |
|
|||
maintainers:
|
||||
- Dmitry Osipenko <digetx@gmail.com>
|
||||
|
||||
$ref: /schemas/power/supply/power-supply.yaml
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
items:
|
||||
|
@ -22,15 +24,13 @@ properties:
|
|||
reg:
|
||||
maxItems: 1
|
||||
|
||||
monitored-battery: true
|
||||
power-supplies: true
|
||||
system-power-controller: true
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
|
||||
additionalProperties: false
|
||||
unevaluatedProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
|
|
|
@ -39,6 +39,10 @@ properties:
|
|||
interrupt-controller: true
|
||||
|
||||
patternProperties:
|
||||
"led@[0-9a-f]+$":
|
||||
type: object
|
||||
$ref: /schemas/leds/qcom,pm8058-led.yaml#
|
||||
|
||||
"rtc@[0-9a-f]+$":
|
||||
type: object
|
||||
$ref: "../rtc/qcom-pm8xxx-rtc.yaml"
|
||||
|
|
|
@ -124,6 +124,8 @@ properties:
|
|||
The child node for the charger to hold additional properties. If a
|
||||
battery is not in use, this node can be omitted.
|
||||
type: object
|
||||
$ref: /schemas/power/supply/power-supply.yaml
|
||||
|
||||
properties:
|
||||
monitored-battery:
|
||||
description: |
|
||||
|
|
|
@ -25,6 +25,9 @@ description: >
|
|||
inactive-delay, the GPIO is driven active again. After a delay specified by wait-delay, the
|
||||
restart handler completes allowing other restart handlers to be attempted.
|
||||
|
||||
allOf:
|
||||
- $ref: restart-handler.yaml#
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: gpio-restart
|
||||
|
@ -41,16 +44,6 @@ properties:
|
|||
in its inactive state.
|
||||
|
||||
priority:
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
description: |
|
||||
A priority ranging from 0 to 255 (default 129) according to the following guidelines:
|
||||
|
||||
0: Restart handler of last resort, with limited restart capabilities.
|
||||
128: Default restart handler; use if no other restart handler is expected to be available,
|
||||
and/or if restart functionality is sufficient to restart the entire system.
|
||||
255: Highest priority restart handler, will preempt all other restart handlers.
|
||||
minimum: 0
|
||||
maximum: 255
|
||||
default: 129
|
||||
|
||||
active-delay:
|
||||
|
|
|
@ -0,0 +1,30 @@
|
|||
# SPDX-License-Identifier: GPL-2.0-only or BSD-2-Clause
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/power/reset/restart-handler.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Restart and shutdown handler generic binding
|
||||
|
||||
maintainers:
|
||||
- Sebastian Reichel <sre@kernel.org>
|
||||
|
||||
description:
|
||||
Restart and shutdown handler device is responsible for powering off the
|
||||
system, e.g. my cutting off the power. System might have several restart
|
||||
handlers, which usually are tried from most precise to last resort.
|
||||
|
||||
properties:
|
||||
priority:
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
description: |
|
||||
A priority ranging from 0 to 255 according to the following guidelines::
|
||||
0:: Restart handler of last resort, with limited restart capabilities.
|
||||
128:: Typical, default restart handler; use if no other restart handler
|
||||
is expected to be available, and/or if restart functionality is
|
||||
sufficient to restart the entire system.
|
||||
255:: Highest priority restart handler, will preempt all other restart handlers.
|
||||
minimum: 0
|
||||
maximum: 255
|
||||
|
||||
additionalProperties: true
|
|
@ -15,11 +15,15 @@ allOf:
|
|||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- ti,bq25890
|
||||
- ti,bq25892
|
||||
- ti,bq25895
|
||||
- ti,bq25896
|
||||
oneOf:
|
||||
- enum:
|
||||
- ti,bq25890
|
||||
- items:
|
||||
- enum:
|
||||
- ti,bq25892
|
||||
- ti,bq25895
|
||||
- ti,bq25896
|
||||
- const: ti,bq25890
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
@ -93,7 +97,7 @@ required:
|
|||
- ti,boost-voltage
|
||||
- ti,boost-max-current
|
||||
|
||||
additionalProperties: false
|
||||
unevaluatedProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
|
|
|
@ -60,13 +60,11 @@ properties:
|
|||
|
||||
monitored-battery:
|
||||
description: |
|
||||
phandle of battery characteristics node.
|
||||
The fuel gauge uses the following battery properties:
|
||||
- energy-full-design-microwatt-hours
|
||||
- charge-full-design-microamp-hours
|
||||
- voltage-min-design-microvolt
|
||||
Both or neither of the *-full-design-*-hours properties must be set.
|
||||
See Documentation/devicetree/bindings/power/supply/battery.yaml
|
||||
|
||||
power-supplies: true
|
||||
|
||||
|
|
|
@ -10,6 +10,8 @@ title: Ingenic JZ47xx battery bindings
|
|||
maintainers:
|
||||
- Artur Rojek <contact@artur-rojek.eu>
|
||||
|
||||
$ref: power-supply.yaml#
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
oneOf:
|
||||
|
@ -28,8 +30,6 @@ properties:
|
|||
|
||||
monitored-battery:
|
||||
description: >
|
||||
phandle to a "simple-battery" compatible node.
|
||||
|
||||
This property must be a phandle to a node using the format described
|
||||
in battery.yaml, with the following properties being required:
|
||||
- voltage-min-design-microvolt: drained battery voltage,
|
||||
|
|
|
@ -59,6 +59,8 @@ properties:
|
|||
Voltage threshold to report battery as over voltage (in mV).
|
||||
Default is not to report over-voltage events.
|
||||
|
||||
power-supplies: true
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
|
|
|
@ -18,4 +18,10 @@ properties:
|
|||
This property is added to a supply in order to list the devices which
|
||||
supply it power, referenced by their phandles.
|
||||
|
||||
monitored-battery:
|
||||
$ref: /schemas/types.yaml#/definitions/phandle
|
||||
description:
|
||||
The battery (with "simple-battery" compatible) being monitored by this
|
||||
power supply.
|
||||
|
||||
additionalProperties: true
|
||||
|
|
|
@ -18,6 +18,7 @@ description: |
|
|||
provides a Dual-source Battery Charger, two port BC1.2 detection and a
|
||||
Battery Monitor.
|
||||
|
||||
$ref: power-supply.yaml#
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
|
|
|
@ -28,7 +28,6 @@ properties:
|
|||
The charger uses the following battery properties
|
||||
- charge-term-current-microamp: current for charge termination phase.
|
||||
- constant-charge-voltage-max-microvolt: maximum constant input voltage.
|
||||
See Documentation/devicetree/bindings/power/supply/battery.yaml
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
|
|
|
@ -0,0 +1,80 @@
|
|||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/watchdog/mediatek,mtk-wdt.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: MediaTek SoCs Watchdog timer
|
||||
|
||||
maintainers:
|
||||
- Matthias Brugger <matthias.bgg@gmail.com>
|
||||
|
||||
description:
|
||||
The watchdog supports a pre-timeout interrupt that fires
|
||||
timeout-sec/2 before the expiry.
|
||||
|
||||
allOf:
|
||||
- $ref: watchdog.yaml#
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
oneOf:
|
||||
- enum:
|
||||
- mediatek,mt2712-wdt
|
||||
- mediatek,mt6589-wdt
|
||||
- mediatek,mt6795-wdt
|
||||
- mediatek,mt7986-wdt
|
||||
- mediatek,mt8183-wdt
|
||||
- mediatek,mt8186-wdt
|
||||
- mediatek,mt8188-wdt
|
||||
- mediatek,mt8192-wdt
|
||||
- mediatek,mt8195-wdt
|
||||
- items:
|
||||
- enum:
|
||||
- mediatek,mt2701-wdt
|
||||
- mediatek,mt6582-wdt
|
||||
- mediatek,mt6797-wdt
|
||||
- mediatek,mt7622-wdt
|
||||
- mediatek,mt7623-wdt
|
||||
- mediatek,mt7629-wdt
|
||||
- mediatek,mt8173-wdt
|
||||
- mediatek,mt8516-wdt
|
||||
- const: mediatek,mt6589-wdt
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
interrupts:
|
||||
items:
|
||||
- description: Watchdog pre-timeout (bark) interrupt
|
||||
|
||||
mediatek,disable-extrst:
|
||||
description: Disable sending output reset signal
|
||||
type: boolean
|
||||
|
||||
'#reset-cells':
|
||||
const: 1
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/interrupt-controller/arm-gic.h>
|
||||
|
||||
soc {
|
||||
#address-cells = <2>;
|
||||
#size-cells = <2>;
|
||||
|
||||
watchdog: watchdog@10007000 {
|
||||
compatible = "mediatek,mt8183-wdt";
|
||||
reg = <0 0x10007000 0 0x100>;
|
||||
interrupts = <GIC_SPI 139 IRQ_TYPE_LEVEL_LOW>;
|
||||
mediatek,disable-extrst;
|
||||
timeout-sec = <10>;
|
||||
#reset-cells = <1>;
|
||||
};
|
||||
};
|
|
@ -1,42 +0,0 @@
|
|||
Mediatek SoCs Watchdog timer
|
||||
|
||||
The watchdog supports a pre-timeout interrupt that fires timeout-sec/2
|
||||
before the expiry.
|
||||
|
||||
Required properties:
|
||||
|
||||
- compatible should contain:
|
||||
"mediatek,mt2701-wdt", "mediatek,mt6589-wdt": for MT2701
|
||||
"mediatek,mt2712-wdt": for MT2712
|
||||
"mediatek,mt6582-wdt", "mediatek,mt6589-wdt": for MT6582
|
||||
"mediatek,mt6589-wdt": for MT6589
|
||||
"mediatek,mt6797-wdt", "mediatek,mt6589-wdt": for MT6797
|
||||
"mediatek,mt7622-wdt", "mediatek,mt6589-wdt": for MT7622
|
||||
"mediatek,mt7623-wdt", "mediatek,mt6589-wdt": for MT7623
|
||||
"mediatek,mt7629-wdt", "mediatek,mt6589-wdt": for MT7629
|
||||
"mediatek,mt7986-wdt", "mediatek,mt6589-wdt": for MT7986
|
||||
"mediatek,mt8183-wdt": for MT8183
|
||||
"mediatek,mt8186-wdt", "mediatek,mt6589-wdt": for MT8186
|
||||
"mediatek,mt8516-wdt", "mediatek,mt6589-wdt": for MT8516
|
||||
"mediatek,mt8192-wdt": for MT8192
|
||||
"mediatek,mt8195-wdt", "mediatek,mt6589-wdt": for MT8195
|
||||
|
||||
- reg : Specifies base physical address and size of the registers.
|
||||
|
||||
Optional properties:
|
||||
- mediatek,disable-extrst: disable send output reset signal
|
||||
- interrupts: Watchdog pre-timeout (bark) interrupt.
|
||||
- timeout-sec: contains the watchdog timeout in seconds.
|
||||
- #reset-cells: Should be 1.
|
||||
|
||||
Example:
|
||||
|
||||
watchdog: watchdog@10007000 {
|
||||
compatible = "mediatek,mt8183-wdt",
|
||||
"mediatek,mt6589-wdt";
|
||||
mediatek,disable-extrst;
|
||||
reg = <0 0x10007000 0 0x100>;
|
||||
interrupts = <GIC_SPI 139 IRQ_TYPE_NONE>;
|
||||
timeout-sec = <10>;
|
||||
#reset-cells = <1>;
|
||||
};
|
|
@ -11732,11 +11732,13 @@ F: scripts/leaking_addresses.pl
|
|||
|
||||
LED SUBSYSTEM
|
||||
M: Pavel Machek <pavel@ucw.cz>
|
||||
M: Lee Jones <lee@kernel.org>
|
||||
L: linux-leds@vger.kernel.org
|
||||
S: Maintained
|
||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/pavel/linux-leds.git
|
||||
F: Documentation/devicetree/bindings/leds/
|
||||
F: drivers/leds/
|
||||
F: include/dt-bindings/leds/
|
||||
F: include/linux/leds.h
|
||||
|
||||
LEGACY EEPROM DRIVER
|
||||
|
|
|
@ -968,7 +968,7 @@ static void ssip_xmit_work(struct work_struct *work)
|
|||
ssip_xmit(cl);
|
||||
}
|
||||
|
||||
static int ssip_pn_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||
static netdev_tx_t ssip_pn_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||
{
|
||||
struct hsi_client *cl = to_hsi_client(dev->dev.parent);
|
||||
struct ssi_protocol *ssi = hsi_client_drvdata(cl);
|
||||
|
@ -1027,7 +1027,7 @@ static int ssip_pn_xmit(struct sk_buff *skb, struct net_device *dev)
|
|||
dev->stats.tx_packets++;
|
||||
dev->stats.tx_bytes += skb->len;
|
||||
|
||||
return 0;
|
||||
return NETDEV_TX_OK;
|
||||
drop2:
|
||||
hsi_free_msg(msg);
|
||||
drop:
|
||||
|
@ -1035,7 +1035,7 @@ drop:
|
|||
inc_dropped:
|
||||
dev->stats.tx_dropped++;
|
||||
|
||||
return 0;
|
||||
return NETDEV_TX_OK;
|
||||
}
|
||||
|
||||
/* CMT reset event handler */
|
||||
|
|
|
@ -502,8 +502,10 @@ static int ssi_probe(struct platform_device *pd)
|
|||
platform_set_drvdata(pd, ssi);
|
||||
|
||||
err = ssi_add_controller(ssi, pd);
|
||||
if (err < 0)
|
||||
if (err < 0) {
|
||||
hsi_put_controller(ssi);
|
||||
goto out1;
|
||||
}
|
||||
|
||||
pm_runtime_enable(&pd->dev);
|
||||
|
||||
|
@ -536,9 +538,9 @@ out3:
|
|||
device_for_each_child(&pd->dev, NULL, ssi_remove_ports);
|
||||
out2:
|
||||
ssi_remove_controller(ssi);
|
||||
pm_runtime_disable(&pd->dev);
|
||||
out1:
|
||||
platform_set_drvdata(pd, NULL);
|
||||
pm_runtime_disable(&pd->dev);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
@ -629,7 +631,13 @@ static int __init ssi_init(void) {
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
return platform_driver_register(&ssi_port_pdriver);
|
||||
ret = platform_driver_register(&ssi_port_pdriver);
|
||||
if (ret) {
|
||||
platform_driver_unregister(&ssi_pdriver);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
module_init(ssi_init);
|
||||
|
||||
|
|
|
@ -785,53 +785,61 @@ out:
|
|||
return ret;
|
||||
}
|
||||
|
||||
static enum resp_states atomic_write_reply(struct rxe_qp *qp,
|
||||
struct rxe_pkt_info *pkt)
|
||||
#ifdef CONFIG_64BIT
|
||||
static enum resp_states do_atomic_write(struct rxe_qp *qp,
|
||||
struct rxe_pkt_info *pkt)
|
||||
{
|
||||
u64 src, *dst;
|
||||
struct resp_res *res = qp->resp.res;
|
||||
struct rxe_mr *mr = qp->resp.mr;
|
||||
int payload = payload_size(pkt);
|
||||
u64 src, *dst;
|
||||
|
||||
if (mr->state != RXE_MR_STATE_VALID)
|
||||
return RESPST_ERR_RKEY_VIOLATION;
|
||||
|
||||
memcpy(&src, payload_addr(pkt), payload);
|
||||
|
||||
dst = iova_to_vaddr(mr, qp->resp.va + qp->resp.offset, payload);
|
||||
/* check vaddr is 8 bytes aligned. */
|
||||
if (!dst || (uintptr_t)dst & 7)
|
||||
return RESPST_ERR_MISALIGNED_ATOMIC;
|
||||
|
||||
/* Do atomic write after all prior operations have completed */
|
||||
smp_store_release(dst, src);
|
||||
|
||||
/* decrease resp.resid to zero */
|
||||
qp->resp.resid -= sizeof(payload);
|
||||
|
||||
qp->resp.msn++;
|
||||
|
||||
/* next expected psn, read handles this separately */
|
||||
qp->resp.psn = (pkt->psn + 1) & BTH_PSN_MASK;
|
||||
qp->resp.ack_psn = qp->resp.psn;
|
||||
|
||||
qp->resp.opcode = pkt->opcode;
|
||||
qp->resp.status = IB_WC_SUCCESS;
|
||||
return RESPST_ACKNOWLEDGE;
|
||||
}
|
||||
#else
|
||||
static enum resp_states do_atomic_write(struct rxe_qp *qp,
|
||||
struct rxe_pkt_info *pkt)
|
||||
{
|
||||
return RESPST_ERR_UNSUPPORTED_OPCODE;
|
||||
}
|
||||
#endif /* CONFIG_64BIT */
|
||||
|
||||
static enum resp_states atomic_write_reply(struct rxe_qp *qp,
|
||||
struct rxe_pkt_info *pkt)
|
||||
{
|
||||
struct resp_res *res = qp->resp.res;
|
||||
|
||||
if (!res) {
|
||||
res = rxe_prepare_res(qp, pkt, RXE_ATOMIC_WRITE_MASK);
|
||||
qp->resp.res = res;
|
||||
}
|
||||
|
||||
if (!res->replay) {
|
||||
#ifdef CONFIG_64BIT
|
||||
if (mr->state != RXE_MR_STATE_VALID)
|
||||
return RESPST_ERR_RKEY_VIOLATION;
|
||||
|
||||
memcpy(&src, payload_addr(pkt), payload);
|
||||
|
||||
dst = iova_to_vaddr(mr, qp->resp.va + qp->resp.offset, payload);
|
||||
/* check vaddr is 8 bytes aligned. */
|
||||
if (!dst || (uintptr_t)dst & 7)
|
||||
return RESPST_ERR_MISALIGNED_ATOMIC;
|
||||
|
||||
/* Do atomic write after all prior operations have completed */
|
||||
smp_store_release(dst, src);
|
||||
|
||||
/* decrease resp.resid to zero */
|
||||
qp->resp.resid -= sizeof(payload);
|
||||
|
||||
qp->resp.msn++;
|
||||
|
||||
/* next expected psn, read handles this separately */
|
||||
qp->resp.psn = (pkt->psn + 1) & BTH_PSN_MASK;
|
||||
qp->resp.ack_psn = qp->resp.psn;
|
||||
|
||||
qp->resp.opcode = pkt->opcode;
|
||||
qp->resp.status = IB_WC_SUCCESS;
|
||||
|
||||
if (res->replay)
|
||||
return RESPST_ACKNOWLEDGE;
|
||||
#else
|
||||
return RESPST_ERR_UNSUPPORTED_OPCODE;
|
||||
#endif /* CONFIG_64BIT */
|
||||
}
|
||||
|
||||
return RESPST_ACKNOWLEDGE;
|
||||
return do_atomic_write(qp, pkt);
|
||||
}
|
||||
|
||||
static struct sk_buff *prepare_ack_packet(struct rxe_qp *qp,
|
||||
|
|
|
@ -29,7 +29,7 @@ static struct page *siw_get_pblpage(struct siw_mem *mem, u64 addr, int *idx)
|
|||
dma_addr_t paddr = siw_pbl_get_buffer(pbl, offset, NULL, idx);
|
||||
|
||||
if (paddr)
|
||||
return virt_to_page((void *)paddr);
|
||||
return virt_to_page((void *)(uintptr_t)paddr);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
|
|
@ -139,11 +139,11 @@ static ssize_t show_color_common(struct device *dev, char *buf, int color)
|
|||
return ret;
|
||||
switch (color) {
|
||||
case RED:
|
||||
return scnprintf(buf, PAGE_SIZE, "%02X\n", data->red);
|
||||
return sysfs_emit(buf, "%02X\n", data->red);
|
||||
case GREEN:
|
||||
return scnprintf(buf, PAGE_SIZE, "%02X\n", data->green);
|
||||
return sysfs_emit(buf, "%02X\n", data->green);
|
||||
case BLUE:
|
||||
return scnprintf(buf, PAGE_SIZE, "%02X\n", data->blue);
|
||||
return sysfs_emit(buf, "%02X\n", data->blue);
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
@ -253,7 +253,7 @@ static DEVICE_ATTR_RW(blue);
|
|||
static ssize_t test_show(struct device *dev, struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
return scnprintf(buf, PAGE_SIZE,
|
||||
return sysfs_emit(buf,
|
||||
"#Write into test to start test sequence!#\n");
|
||||
}
|
||||
|
||||
|
|
|
@ -38,6 +38,7 @@
|
|||
#define IS31FL3190_CURRENT_uA_MIN 5000
|
||||
#define IS31FL3190_CURRENT_uA_DEFAULT 42000
|
||||
#define IS31FL3190_CURRENT_uA_MAX 42000
|
||||
#define IS31FL3190_CURRENT_SHIFT 2
|
||||
#define IS31FL3190_CURRENT_MASK GENMASK(4, 2)
|
||||
#define IS31FL3190_CURRENT_5_mA 0x02
|
||||
#define IS31FL3190_CURRENT_10_mA 0x01
|
||||
|
@ -553,7 +554,7 @@ static int is31fl319x_probe(struct i2c_client *client)
|
|||
is31fl3196_db_to_gain(is31->audio_gain_db));
|
||||
else
|
||||
regmap_update_bits(is31->regmap, IS31FL3190_CURRENT, IS31FL3190_CURRENT_MASK,
|
||||
is31fl3190_microamp_to_cs(dev, aggregated_led_microamp));
|
||||
is31fl3190_microamp_to_cs(dev, aggregated_led_microamp) << IS31FL3190_CURRENT_SHIFT);
|
||||
|
||||
for (i = 0; i < is31->cdef->num_leds; i++) {
|
||||
struct is31fl319x_led *led = &is31->leds[i];
|
||||
|
|
|
@ -314,7 +314,7 @@ static ssize_t show_id(struct device *dev,
|
|||
struct led_classdev *led_cdev = dev_get_drvdata(dev);
|
||||
struct lm3533_led *led = to_lm3533_led(led_cdev);
|
||||
|
||||
return scnprintf(buf, PAGE_SIZE, "%d\n", led->id);
|
||||
return sysfs_emit(buf, "%d\n", led->id);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -344,7 +344,7 @@ static ssize_t show_risefalltime(struct device *dev,
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
return scnprintf(buf, PAGE_SIZE, "%x\n", val);
|
||||
return sysfs_emit(buf, "%x\n", val);
|
||||
}
|
||||
|
||||
static ssize_t show_risetime(struct device *dev,
|
||||
|
@ -415,7 +415,7 @@ static ssize_t show_als_channel(struct device *dev,
|
|||
|
||||
channel = (val & LM3533_REG_CTRLBANK_BCONF_ALS_CHANNEL_MASK) + 1;
|
||||
|
||||
return scnprintf(buf, PAGE_SIZE, "%u\n", channel);
|
||||
return sysfs_emit(buf, "%u\n", channel);
|
||||
}
|
||||
|
||||
static ssize_t store_als_channel(struct device *dev,
|
||||
|
@ -465,7 +465,7 @@ static ssize_t show_als_en(struct device *dev,
|
|||
|
||||
enable = val & LM3533_REG_CTRLBANK_BCONF_ALS_EN_MASK;
|
||||
|
||||
return scnprintf(buf, PAGE_SIZE, "%d\n", enable);
|
||||
return sysfs_emit(buf, "%d\n", enable);
|
||||
}
|
||||
|
||||
static ssize_t store_als_en(struct device *dev,
|
||||
|
@ -518,7 +518,7 @@ static ssize_t show_linear(struct device *dev,
|
|||
else
|
||||
linear = 0;
|
||||
|
||||
return scnprintf(buf, PAGE_SIZE, "%x\n", linear);
|
||||
return sysfs_emit(buf, "%x\n", linear);
|
||||
}
|
||||
|
||||
static ssize_t store_linear(struct device *dev,
|
||||
|
@ -564,7 +564,7 @@ static ssize_t show_pwm(struct device *dev,
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
return scnprintf(buf, PAGE_SIZE, "%u\n", val);
|
||||
return sysfs_emit(buf, "%u\n", val);
|
||||
}
|
||||
|
||||
static ssize_t store_pwm(struct device *dev,
|
||||
|
|
|
@ -469,7 +469,7 @@ static ssize_t lp5521_selftest(struct device *dev,
|
|||
ret = lp5521_run_selftest(chip, buf);
|
||||
mutex_unlock(&chip->lock);
|
||||
|
||||
return scnprintf(buf, PAGE_SIZE, "%s\n", ret ? "FAIL" : "OK");
|
||||
return sysfs_emit(buf, "%s\n", ret ? "FAIL" : "OK");
|
||||
}
|
||||
|
||||
/* device attributes */
|
||||
|
|
|
@ -581,8 +581,8 @@ static ssize_t lp5523_selftest(struct device *dev,
|
|||
struct lp55xx_led *led = i2c_get_clientdata(to_i2c_client(dev));
|
||||
struct lp55xx_chip *chip = led->chip;
|
||||
struct lp55xx_platform_data *pdata = chip->pdata;
|
||||
int i, ret, pos = 0;
|
||||
u8 status, adc, vdd;
|
||||
int ret, pos = 0;
|
||||
u8 status, adc, vdd, i;
|
||||
|
||||
mutex_lock(&chip->lock);
|
||||
|
||||
|
@ -612,20 +612,21 @@ static ssize_t lp5523_selftest(struct device *dev,
|
|||
|
||||
vdd--; /* There may be some fluctuation in measurement */
|
||||
|
||||
for (i = 0; i < LP5523_MAX_LEDS; i++) {
|
||||
/* Skip non-existing channels */
|
||||
for (i = 0; i < pdata->num_channels; i++) {
|
||||
/* Skip disabled channels */
|
||||
if (pdata->led_config[i].led_current == 0)
|
||||
continue;
|
||||
|
||||
/* Set default current */
|
||||
lp55xx_write(chip, LP5523_REG_LED_CURRENT_BASE + i,
|
||||
lp55xx_write(chip, LP5523_REG_LED_CURRENT_BASE + led->chan_nr,
|
||||
pdata->led_config[i].led_current);
|
||||
|
||||
lp55xx_write(chip, LP5523_REG_LED_PWM_BASE + i, 0xff);
|
||||
lp55xx_write(chip, LP5523_REG_LED_PWM_BASE + led->chan_nr,
|
||||
0xff);
|
||||
/* let current stabilize 2 - 4ms before measurements start */
|
||||
usleep_range(2000, 4000);
|
||||
lp55xx_write(chip, LP5523_REG_LED_TEST_CTRL,
|
||||
LP5523_EN_LEDTEST | i);
|
||||
LP5523_EN_LEDTEST | led->chan_nr);
|
||||
/* ADC conversion time is 2.7 ms typically */
|
||||
usleep_range(3000, 6000);
|
||||
ret = lp55xx_read(chip, LP5523_REG_STATUS, &status);
|
||||
|
@ -633,20 +634,22 @@ static ssize_t lp5523_selftest(struct device *dev,
|
|||
goto fail;
|
||||
|
||||
if (!(status & LP5523_LEDTEST_DONE))
|
||||
usleep_range(3000, 6000);/* Was not ready. Wait. */
|
||||
usleep_range(3000, 6000); /* Was not ready. Wait. */
|
||||
|
||||
ret = lp55xx_read(chip, LP5523_REG_LED_TEST_ADC, &adc);
|
||||
if (ret < 0)
|
||||
goto fail;
|
||||
|
||||
if (adc >= vdd || adc < LP5523_ADC_SHORTCIRC_LIM)
|
||||
pos += sprintf(buf + pos, "LED %d FAIL\n", i);
|
||||
pos += sprintf(buf + pos, "LED %d FAIL\n",
|
||||
led->chan_nr);
|
||||
|
||||
lp55xx_write(chip, LP5523_REG_LED_PWM_BASE + i, 0x00);
|
||||
lp55xx_write(chip, LP5523_REG_LED_PWM_BASE + led->chan_nr,
|
||||
0x00);
|
||||
|
||||
/* Restore current */
|
||||
lp55xx_write(chip, LP5523_REG_LED_CURRENT_BASE + i,
|
||||
led->led_current);
|
||||
lp55xx_write(chip, LP5523_REG_LED_CURRENT_BASE + led->chan_nr,
|
||||
led->led_current);
|
||||
led++;
|
||||
}
|
||||
if (pos == 0)
|
||||
|
|
|
@ -88,7 +88,7 @@ static ssize_t led_current_show(struct device *dev,
|
|||
{
|
||||
struct lp55xx_led *led = dev_to_lp55xx_led(dev);
|
||||
|
||||
return scnprintf(buf, PAGE_SIZE, "%d\n", led->led_current);
|
||||
return sysfs_emit(buf, "%d\n", led->led_current);
|
||||
}
|
||||
|
||||
static ssize_t led_current_store(struct device *dev,
|
||||
|
@ -121,7 +121,7 @@ static ssize_t max_current_show(struct device *dev,
|
|||
{
|
||||
struct lp55xx_led *led = dev_to_lp55xx_led(dev);
|
||||
|
||||
return scnprintf(buf, PAGE_SIZE, "%d\n", led->max_current);
|
||||
return sysfs_emit(buf, "%d\n", led->max_current);
|
||||
}
|
||||
|
||||
static DEVICE_ATTR_RW(led_current);
|
||||
|
@ -166,7 +166,7 @@ static int lp55xx_init_led(struct lp55xx_led *led,
|
|||
struct mc_subled *mc_led_info;
|
||||
struct led_classdev *led_cdev;
|
||||
char name[32];
|
||||
int i, j = 0;
|
||||
int i;
|
||||
int ret;
|
||||
|
||||
if (chan >= max_channel) {
|
||||
|
@ -201,7 +201,6 @@ static int lp55xx_init_led(struct lp55xx_led *led,
|
|||
pdata->led_config[chan].color_id[i];
|
||||
mc_led_info[i].channel =
|
||||
pdata->led_config[chan].output_num[i];
|
||||
j++;
|
||||
}
|
||||
|
||||
led->mc_cdev.subled_info = mc_led_info;
|
||||
|
|
|
@ -238,11 +238,6 @@ static int max8997_led_probe(struct platform_device *pdev)
|
|||
char name[20];
|
||||
int ret = 0;
|
||||
|
||||
if (pdata == NULL) {
|
||||
dev_err(&pdev->dev, "no platform data\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
led = devm_kzalloc(&pdev->dev, sizeof(*led), GFP_KERNEL);
|
||||
if (led == NULL)
|
||||
return -ENOMEM;
|
||||
|
@ -258,7 +253,7 @@ static int max8997_led_probe(struct platform_device *pdev)
|
|||
led->iodev = iodev;
|
||||
|
||||
/* initialize mode and brightness according to platform_data */
|
||||
if (pdata->led_pdata) {
|
||||
if (pdata && pdata->led_pdata) {
|
||||
u8 mode = 0, brightness = 0;
|
||||
|
||||
mode = pdata->led_pdata->mode[led->id];
|
||||
|
|
|
@ -145,12 +145,6 @@ static inline int pca95xx_num_input_regs(int bits)
|
|||
return (bits + 7) / 8;
|
||||
}
|
||||
|
||||
/* 4 bits per LED selector register */
|
||||
static inline int pca95xx_num_led_regs(int bits)
|
||||
{
|
||||
return (bits + 3) / 4;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return an LED selector register value based on an existing one, with
|
||||
* the appropriate 2-bit state value set for the given LED number (0-3).
|
||||
|
|
|
@ -602,8 +602,8 @@ static void lpg_brightness_set(struct lpg_led *led, struct led_classdev *cdev,
|
|||
lpg_lut_sync(lpg, lut_mask);
|
||||
}
|
||||
|
||||
static void lpg_brightness_single_set(struct led_classdev *cdev,
|
||||
enum led_brightness value)
|
||||
static int lpg_brightness_single_set(struct led_classdev *cdev,
|
||||
enum led_brightness value)
|
||||
{
|
||||
struct lpg_led *led = container_of(cdev, struct lpg_led, cdev);
|
||||
struct mc_subled info;
|
||||
|
@ -614,10 +614,12 @@ static void lpg_brightness_single_set(struct led_classdev *cdev,
|
|||
lpg_brightness_set(led, cdev, &info);
|
||||
|
||||
mutex_unlock(&led->lpg->lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void lpg_brightness_mc_set(struct led_classdev *cdev,
|
||||
enum led_brightness value)
|
||||
static int lpg_brightness_mc_set(struct led_classdev *cdev,
|
||||
enum led_brightness value)
|
||||
{
|
||||
struct led_classdev_mc *mc = lcdev_to_mccdev(cdev);
|
||||
struct lpg_led *led = container_of(mc, struct lpg_led, mcdev);
|
||||
|
@ -628,6 +630,8 @@ static void lpg_brightness_mc_set(struct led_classdev *cdev,
|
|||
lpg_brightness_set(led, cdev, mc->subled_info);
|
||||
|
||||
mutex_unlock(&led->lpg->lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lpg_blink_set(struct lpg_led *led,
|
||||
|
@ -1118,7 +1122,7 @@ static int lpg_add_led(struct lpg *lpg, struct device_node *np)
|
|||
led->mcdev.num_colors = num_channels;
|
||||
|
||||
cdev = &led->mcdev.led_cdev;
|
||||
cdev->brightness_set = lpg_brightness_mc_set;
|
||||
cdev->brightness_set_blocking = lpg_brightness_mc_set;
|
||||
cdev->blink_set = lpg_blink_mc_set;
|
||||
|
||||
/* Register pattern accessors only if we have a LUT block */
|
||||
|
@ -1132,7 +1136,7 @@ static int lpg_add_led(struct lpg *lpg, struct device_node *np)
|
|||
return ret;
|
||||
|
||||
cdev = &led->cdev;
|
||||
cdev->brightness_set = lpg_brightness_single_set;
|
||||
cdev->brightness_set_blocking = lpg_brightness_single_set;
|
||||
cdev->blink_set = lpg_blink_single_set;
|
||||
|
||||
/* Register pattern accessors only if we have a LUT block */
|
||||
|
@ -1151,7 +1155,7 @@ static int lpg_add_led(struct lpg *lpg, struct device_node *np)
|
|||
else
|
||||
cdev->brightness = LED_OFF;
|
||||
|
||||
cdev->brightness_set(cdev, cdev->brightness);
|
||||
cdev->brightness_set_blocking(cdev, cdev->brightness);
|
||||
|
||||
init_data.fwnode = of_fwnode_handle(np);
|
||||
|
||||
|
|
|
@ -155,7 +155,7 @@ static ssize_t repeat_show(struct device *dev, struct device_attribute *attr,
|
|||
|
||||
mutex_unlock(&data->lock);
|
||||
|
||||
return scnprintf(buf, PAGE_SIZE, "%d\n", repeat);
|
||||
return sysfs_emit(buf, "%d\n", repeat);
|
||||
}
|
||||
|
||||
static ssize_t repeat_store(struct device *dev, struct device_attribute *attr,
|
||||
|
|
|
@ -690,8 +690,7 @@ static int pm860x_charger_probe(struct platform_device *pdev)
|
|||
(chip->id == CHIP_PM8607) ? chip->companion : chip->client;
|
||||
if (!info->i2c_8606) {
|
||||
dev_err(&pdev->dev, "Missed I2C address of 88PM8606!\n");
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
return -EINVAL;
|
||||
}
|
||||
info->dev = &pdev->dev;
|
||||
|
||||
|
@ -704,44 +703,26 @@ static int pm860x_charger_probe(struct platform_device *pdev)
|
|||
psy_cfg.drv_data = info;
|
||||
psy_cfg.supplied_to = pm860x_supplied_to;
|
||||
psy_cfg.num_supplicants = ARRAY_SIZE(pm860x_supplied_to);
|
||||
info->usb = power_supply_register(&pdev->dev, &pm860x_charger_desc,
|
||||
&psy_cfg);
|
||||
info->usb = devm_power_supply_register(&pdev->dev, &pm860x_charger_desc,
|
||||
&psy_cfg);
|
||||
if (IS_ERR(info->usb)) {
|
||||
ret = PTR_ERR(info->usb);
|
||||
goto out;
|
||||
return PTR_ERR(info->usb);
|
||||
}
|
||||
|
||||
pm860x_init_charger(info);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(info->irq); i++) {
|
||||
ret = request_threaded_irq(info->irq[i], NULL,
|
||||
pm860x_irq_descs[i].handler,
|
||||
IRQF_ONESHOT, pm860x_irq_descs[i].name, info);
|
||||
ret = devm_request_threaded_irq(&pdev->dev, info->irq[i], NULL,
|
||||
pm860x_irq_descs[i].handler,
|
||||
IRQF_ONESHOT,
|
||||
pm860x_irq_descs[i].name, info);
|
||||
if (ret < 0) {
|
||||
dev_err(chip->dev, "Failed to request IRQ: #%d: %d\n",
|
||||
info->irq[i], ret);
|
||||
goto out_irq;
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
|
||||
out_irq:
|
||||
power_supply_unregister(info->usb);
|
||||
while (--i >= 0)
|
||||
free_irq(info->irq[i], info);
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int pm860x_charger_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct pm860x_charger_info *info = platform_get_drvdata(pdev);
|
||||
int i;
|
||||
|
||||
power_supply_unregister(info->usb);
|
||||
for (i = 0; i < info->irq_nums; i++)
|
||||
free_irq(info->irq[i], info);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct platform_driver pm860x_charger_driver = {
|
||||
|
@ -749,7 +730,6 @@ static struct platform_driver pm860x_charger_driver = {
|
|||
.name = "88pm860x-charger",
|
||||
},
|
||||
.probe = pm860x_charger_probe,
|
||||
.remove = pm860x_charger_remove,
|
||||
};
|
||||
module_platform_driver(pm860x_charger_driver);
|
||||
|
||||
|
|
|
@ -1940,7 +1940,7 @@ static int ab8500_charger_get_ext_psy_data(struct device *dev, void *data)
|
|||
*
|
||||
* Due to a asic bug it is necessary to lower the input current to the vbus
|
||||
* charger when charging with at some specific levels. This issue is only valid
|
||||
* for below a certain battery voltage. This function makes sure that the
|
||||
* for below a certain battery voltage. This function makes sure that
|
||||
* the allowed current limit isn't exceeded.
|
||||
*/
|
||||
static void ab8500_charger_check_vbat_work(struct work_struct *work)
|
||||
|
@ -3719,7 +3719,14 @@ static int __init ab8500_charger_init(void)
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
return platform_driver_register(&ab8500_charger_driver);
|
||||
ret = platform_driver_register(&ab8500_charger_driver);
|
||||
if (ret) {
|
||||
platform_unregister_drivers(ab8500_charger_component_drivers,
|
||||
ARRAY_SIZE(ab8500_charger_component_drivers));
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __exit ab8500_charger_exit(void)
|
||||
|
|
|
@ -694,8 +694,7 @@ static const struct power_supply_desc adp5061_desc = {
|
|||
.num_properties = ARRAY_SIZE(adp5061_props),
|
||||
};
|
||||
|
||||
static int adp5061_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
static int adp5061_probe(struct i2c_client *client)
|
||||
{
|
||||
struct power_supply_config psy_cfg = {};
|
||||
struct adp5061_state *st;
|
||||
|
@ -737,7 +736,7 @@ static struct i2c_driver adp5061_driver = {
|
|||
.driver = {
|
||||
.name = KBUILD_MODNAME,
|
||||
},
|
||||
.probe = adp5061_probe,
|
||||
.probe_new = adp5061_probe,
|
||||
.id_table = adp5061_id,
|
||||
};
|
||||
module_i2c_driver(adp5061_driver);
|
||||
|
|
|
@ -768,27 +768,13 @@ static const struct power_supply_desc bd9995x_power_supply_desc = {
|
|||
* Describe the setting in linear_range table.
|
||||
*/
|
||||
static const struct linear_range input_current_limit_ranges[] = {
|
||||
{
|
||||
.min = 0,
|
||||
.step = 32000,
|
||||
.min_sel = 0x0,
|
||||
.max_sel = 0x1ff,
|
||||
},
|
||||
LINEAR_RANGE(0, 0x0, 0x1ff, 32000),
|
||||
};
|
||||
|
||||
/* Possible trickle, pre-charging and termination current values */
|
||||
static const struct linear_range charging_current_ranges[] = {
|
||||
{
|
||||
.min = 0,
|
||||
.step = 64000,
|
||||
.min_sel = 0x0,
|
||||
.max_sel = 0x10,
|
||||
}, {
|
||||
.min = 1024000,
|
||||
.step = 0,
|
||||
.min_sel = 0x11,
|
||||
.max_sel = 0x1f,
|
||||
},
|
||||
LINEAR_RANGE(0, 0x0, 0x10, 64000),
|
||||
LINEAR_RANGE(1024000, 0x11, 0x1f, 0),
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -796,72 +782,28 @@ static const struct linear_range charging_current_ranges[] = {
|
|||
* and battery over voltage protection have same possible values
|
||||
*/
|
||||
static const struct linear_range charge_voltage_regulation_ranges[] = {
|
||||
{
|
||||
.min = 2560000,
|
||||
.step = 0,
|
||||
.min_sel = 0,
|
||||
.max_sel = 0xA0,
|
||||
}, {
|
||||
.min = 2560000,
|
||||
.step = 16000,
|
||||
.min_sel = 0xA0,
|
||||
.max_sel = 0x4B0,
|
||||
}, {
|
||||
.min = 19200000,
|
||||
.step = 0,
|
||||
.min_sel = 0x4B0,
|
||||
.max_sel = 0x7FF,
|
||||
},
|
||||
LINEAR_RANGE(2560000, 0, 0xA0, 0),
|
||||
LINEAR_RANGE(2560000, 0xA0, 0x4B0, 16000),
|
||||
LINEAR_RANGE(19200000, 0x4B0, 0x7FF, 0),
|
||||
};
|
||||
|
||||
/* Possible VSYS voltage regulation values */
|
||||
static const struct linear_range vsys_voltage_regulation_ranges[] = {
|
||||
{
|
||||
.min = 2560000,
|
||||
.step = 0,
|
||||
.min_sel = 0,
|
||||
.max_sel = 0x28,
|
||||
}, {
|
||||
.min = 2560000,
|
||||
.step = 64000,
|
||||
.min_sel = 0x28,
|
||||
.max_sel = 0x12C,
|
||||
}, {
|
||||
.min = 19200000,
|
||||
.step = 0,
|
||||
.min_sel = 0x12C,
|
||||
.max_sel = 0x1FF,
|
||||
},
|
||||
LINEAR_RANGE(2560000, 0, 0x28, 0),
|
||||
LINEAR_RANGE(2560000, 0x28, 0x12C, 64000),
|
||||
LINEAR_RANGE(19200000, 0x12C, 0x1FF, 0),
|
||||
};
|
||||
|
||||
/* Possible settings for switching from trickle to pre-charging limits */
|
||||
static const struct linear_range trickle_to_pre_threshold_ranges[] = {
|
||||
{
|
||||
.min = 2048000,
|
||||
.step = 0,
|
||||
.min_sel = 0,
|
||||
.max_sel = 0x20,
|
||||
}, {
|
||||
.min = 2048000,
|
||||
.step = 64000,
|
||||
.min_sel = 0x20,
|
||||
.max_sel = 0x12C,
|
||||
}, {
|
||||
.min = 19200000,
|
||||
.step = 0,
|
||||
.min_sel = 0x12C,
|
||||
.max_sel = 0x1FF
|
||||
}
|
||||
LINEAR_RANGE(2048000, 0, 0x20, 0),
|
||||
LINEAR_RANGE(2048000, 0x20, 0x12C, 64000),
|
||||
LINEAR_RANGE(19200000, 0x12C, 0x1FF, 0),
|
||||
};
|
||||
|
||||
/* Possible current values for fast-charging constant current phase */
|
||||
static const struct linear_range fast_charge_current_ranges[] = {
|
||||
{
|
||||
.min = 0,
|
||||
.step = 64000,
|
||||
.min_sel = 0,
|
||||
.max_sel = 0xFF,
|
||||
}
|
||||
LINEAR_RANGE(0, 0, 0xFF, 64000),
|
||||
};
|
||||
|
||||
struct battery_init {
|
||||
|
|
|
@ -1520,9 +1520,9 @@ static int bq2415x_power_supply_init(struct bq2415x_device *bq)
|
|||
}
|
||||
|
||||
/* main bq2415x probe function */
|
||||
static int bq2415x_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
static int bq2415x_probe(struct i2c_client *client)
|
||||
{
|
||||
const struct i2c_device_id *id = i2c_client_get_device_id(client);
|
||||
int ret;
|
||||
int num;
|
||||
char *name = NULL;
|
||||
|
@ -1780,7 +1780,7 @@ static struct i2c_driver bq2415x_driver = {
|
|||
.of_match_table = of_match_ptr(bq2415x_of_match_table),
|
||||
.acpi_match_table = ACPI_PTR(bq2415x_i2c_acpi_match),
|
||||
},
|
||||
.probe = bq2415x_probe,
|
||||
.probe_new = bq2415x_probe,
|
||||
.remove = bq2415x_remove,
|
||||
.id_table = bq2415x_i2c_id_table,
|
||||
};
|
||||
|
|
|
@ -1767,9 +1767,9 @@ static int bq24190_get_config(struct bq24190_dev_info *bdi)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int bq24190_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
static int bq24190_probe(struct i2c_client *client)
|
||||
{
|
||||
const struct i2c_device_id *id = i2c_client_get_device_id(client);
|
||||
struct i2c_adapter *adapter = client->adapter;
|
||||
struct device *dev = &client->dev;
|
||||
struct power_supply_config charger_cfg = {}, battery_cfg = {};
|
||||
|
@ -2032,7 +2032,7 @@ static const struct of_device_id bq24190_of_match[] = {
|
|||
MODULE_DEVICE_TABLE(of, bq24190_of_match);
|
||||
|
||||
static struct i2c_driver bq24190_driver = {
|
||||
.probe = bq24190_probe,
|
||||
.probe_new = bq24190_probe,
|
||||
.remove = bq24190_remove,
|
||||
.shutdown = bq24190_shutdown,
|
||||
.id_table = bq24190_i2c_ids,
|
||||
|
|
|
@ -947,9 +947,9 @@ static int bq24257_fw_probe(struct bq24257_device *bq)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int bq24257_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
static int bq24257_probe(struct i2c_client *client)
|
||||
{
|
||||
const struct i2c_device_id *id = i2c_client_get_device_id(client);
|
||||
struct i2c_adapter *adapter = client->adapter;
|
||||
struct device *dev = &client->dev;
|
||||
const struct acpi_device_id *acpi_id;
|
||||
|
@ -1167,7 +1167,7 @@ static struct i2c_driver bq24257_driver = {
|
|||
.acpi_match_table = ACPI_PTR(bq24257_acpi_match),
|
||||
.pm = &bq24257_pm,
|
||||
},
|
||||
.probe = bq24257_probe,
|
||||
.probe_new = bq24257_probe,
|
||||
.remove = bq24257_remove,
|
||||
.id_table = bq24257_i2c_ids,
|
||||
};
|
||||
|
|
|
@ -352,8 +352,7 @@ static struct bq24735_platform *bq24735_parse_dt_data(struct i2c_client *client)
|
|||
return pdata;
|
||||
}
|
||||
|
||||
static int bq24735_charger_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
static int bq24735_charger_probe(struct i2c_client *client)
|
||||
{
|
||||
int ret;
|
||||
struct bq24735 *charger;
|
||||
|
@ -506,7 +505,7 @@ static struct i2c_driver bq24735_charger_driver = {
|
|||
.name = "bq24735-charger",
|
||||
.of_match_table = bq24735_match_ids,
|
||||
},
|
||||
.probe = bq24735_charger_probe,
|
||||
.probe_new = bq24735_charger_probe,
|
||||
.id_table = bq24735_charger_id,
|
||||
};
|
||||
|
||||
|
|
|
@ -1078,9 +1078,9 @@ static const struct regmap_config bq25155_regmap_config = {
|
|||
.volatile_reg = bq2515x_volatile_register,
|
||||
};
|
||||
|
||||
static int bq2515x_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
static int bq2515x_probe(struct i2c_client *client)
|
||||
{
|
||||
const struct i2c_device_id *id = i2c_client_get_device_id(client);
|
||||
struct device *dev = &client->dev;
|
||||
struct bq2515x_device *bq2515x;
|
||||
struct power_supply_config charger_cfg = {};
|
||||
|
@ -1158,7 +1158,7 @@ static struct i2c_driver bq2515x_driver = {
|
|||
.name = "bq2515x-charger",
|
||||
.of_match_table = bq2515x_of_match,
|
||||
},
|
||||
.probe = bq2515x_probe,
|
||||
.probe_new = bq2515x_probe,
|
||||
.id_table = bq2515x_i2c_ids,
|
||||
};
|
||||
module_i2c_driver(bq2515x_driver);
|
||||
|
|
|
@ -1619,9 +1619,9 @@ static int bq256xx_parse_dt(struct bq256xx_device *bq,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int bq256xx_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
static int bq256xx_probe(struct i2c_client *client)
|
||||
{
|
||||
const struct i2c_device_id *id = i2c_client_get_device_id(client);
|
||||
struct device *dev = &client->dev;
|
||||
struct bq256xx_device *bq;
|
||||
struct power_supply_config psy_cfg = { };
|
||||
|
@ -1744,7 +1744,7 @@ static struct i2c_driver bq256xx_driver = {
|
|||
.of_match_table = bq256xx_of_match,
|
||||
.acpi_match_table = bq256xx_acpi_match,
|
||||
},
|
||||
.probe = bq256xx_probe,
|
||||
.probe_new = bq256xx_probe,
|
||||
.id_table = bq256xx_i2c_ids,
|
||||
};
|
||||
module_i2c_driver(bq256xx_driver);
|
||||
|
|
|
@ -529,40 +529,6 @@ static int bq25890_power_supply_get_property(struct power_supply *psy,
|
|||
val->intval = POWER_SUPPLY_HEALTH_UNSPEC_FAILURE;
|
||||
break;
|
||||
|
||||
case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX:
|
||||
val->intval = bq25890_find_val(bq->init_data.ichg, TBL_ICHG);
|
||||
|
||||
/* When temperature is too low, charge current is decreased */
|
||||
if (bq->state.ntc_fault == NTC_FAULT_COOL) {
|
||||
ret = bq25890_field_read(bq, F_JEITA_ISET);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if (ret)
|
||||
val->intval /= 5;
|
||||
else
|
||||
val->intval /= 2;
|
||||
}
|
||||
break;
|
||||
|
||||
case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE:
|
||||
if (!state.online) {
|
||||
val->intval = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
ret = bq25890_field_read(bq, F_BATV); /* read measured value */
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/* converted_val = 2.304V + ADC_val * 20mV (table 10.3.15) */
|
||||
val->intval = 2304000 + ret * 20000;
|
||||
break;
|
||||
|
||||
case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE_MAX:
|
||||
val->intval = bq25890_find_val(bq->init_data.vreg, TBL_VREG);
|
||||
break;
|
||||
|
||||
case POWER_SUPPLY_PROP_PRECHARGE_CURRENT:
|
||||
val->intval = bq25890_find_val(bq->init_data.iprechg, TBL_ITERM);
|
||||
break;
|
||||
|
@ -579,8 +545,71 @@ static int bq25890_power_supply_get_property(struct power_supply *psy,
|
|||
val->intval = bq25890_find_val(ret, TBL_IINLIM);
|
||||
break;
|
||||
|
||||
case POWER_SUPPLY_PROP_VOLTAGE_NOW:
|
||||
ret = bq25890_field_read(bq, F_SYSV); /* read measured value */
|
||||
case POWER_SUPPLY_PROP_CURRENT_NOW: /* I_BAT now */
|
||||
/*
|
||||
* This is ADC-sampled immediate charge current supplied
|
||||
* from charger to battery. The property name is confusing,
|
||||
* for clarification refer to:
|
||||
* Documentation/ABI/testing/sysfs-class-power
|
||||
* /sys/class/power_supply/<supply_name>/current_now
|
||||
*/
|
||||
ret = bq25890_field_read(bq, F_ICHGR); /* read measured value */
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/* converted_val = ADC_val * 50mA (table 10.3.19) */
|
||||
val->intval = ret * -50000;
|
||||
break;
|
||||
|
||||
case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT: /* I_BAT user limit */
|
||||
/*
|
||||
* This is user-configured constant charge current supplied
|
||||
* from charger to battery in first phase of charging, when
|
||||
* battery voltage is below constant charge voltage.
|
||||
*
|
||||
* This value reflects the current hardware setting.
|
||||
*
|
||||
* The POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX is the
|
||||
* maximum value of this property.
|
||||
*/
|
||||
ret = bq25890_field_read(bq, F_ICHG);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
val->intval = bq25890_find_val(ret, TBL_ICHG);
|
||||
|
||||
/* When temperature is too low, charge current is decreased */
|
||||
if (bq->state.ntc_fault == NTC_FAULT_COOL) {
|
||||
ret = bq25890_field_read(bq, F_JEITA_ISET);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if (ret)
|
||||
val->intval /= 5;
|
||||
else
|
||||
val->intval /= 2;
|
||||
}
|
||||
break;
|
||||
|
||||
case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX: /* I_BAT max */
|
||||
/*
|
||||
* This is maximum allowed constant charge current supplied
|
||||
* from charger to battery in first phase of charging, when
|
||||
* battery voltage is below constant charge voltage.
|
||||
*
|
||||
* This value is constant for each battery and set from DT.
|
||||
*/
|
||||
val->intval = bq25890_find_val(bq->init_data.ichg, TBL_ICHG);
|
||||
break;
|
||||
|
||||
case POWER_SUPPLY_PROP_VOLTAGE_NOW: /* V_BAT now */
|
||||
/*
|
||||
* This is ADC-sampled immediate charge voltage supplied
|
||||
* from charger to battery. The property name is confusing,
|
||||
* for clarification refer to:
|
||||
* Documentation/ABI/testing/sysfs-class-power
|
||||
* /sys/class/power_supply/<supply_name>/voltage_now
|
||||
*/
|
||||
ret = bq25890_field_read(bq, F_BATV); /* read measured value */
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
|
@ -588,13 +617,33 @@ static int bq25890_power_supply_get_property(struct power_supply *psy,
|
|||
val->intval = 2304000 + ret * 20000;
|
||||
break;
|
||||
|
||||
case POWER_SUPPLY_PROP_CURRENT_NOW:
|
||||
ret = bq25890_field_read(bq, F_ICHGR); /* read measured value */
|
||||
case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE: /* V_BAT user limit */
|
||||
/*
|
||||
* This is user-configured constant charge voltage supplied
|
||||
* from charger to battery in second phase of charging, when
|
||||
* battery voltage reached constant charge voltage.
|
||||
*
|
||||
* This value reflects the current hardware setting.
|
||||
*
|
||||
* The POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE_MAX is the
|
||||
* maximum value of this property.
|
||||
*/
|
||||
ret = bq25890_field_read(bq, F_VREG);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/* converted_val = ADC_val * 50mA (table 10.3.19) */
|
||||
val->intval = ret * -50000;
|
||||
val->intval = bq25890_find_val(ret, TBL_VREG);
|
||||
break;
|
||||
|
||||
case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE_MAX: /* V_BAT max */
|
||||
/*
|
||||
* This is maximum allowed constant charge voltage supplied
|
||||
* from charger to battery in second phase of charging, when
|
||||
* battery voltage reached constant charge voltage.
|
||||
*
|
||||
* This value is constant for each battery and set from DT.
|
||||
*/
|
||||
val->intval = bq25890_find_val(bq->init_data.vreg, TBL_VREG);
|
||||
break;
|
||||
|
||||
case POWER_SUPPLY_PROP_TEMP:
|
||||
|
@ -618,9 +667,18 @@ static int bq25890_power_supply_set_property(struct power_supply *psy,
|
|||
const union power_supply_propval *val)
|
||||
{
|
||||
struct bq25890_device *bq = power_supply_get_drvdata(psy);
|
||||
int maxval;
|
||||
u8 lval;
|
||||
|
||||
switch (psp) {
|
||||
case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT:
|
||||
maxval = bq25890_find_val(bq->init_data.ichg, TBL_ICHG);
|
||||
lval = bq25890_find_idx(min(val->intval, maxval), TBL_ICHG);
|
||||
return bq25890_field_write(bq, F_ICHG, lval);
|
||||
case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE:
|
||||
maxval = bq25890_find_val(bq->init_data.vreg, TBL_VREG);
|
||||
lval = bq25890_find_idx(min(val->intval, maxval), TBL_VREG);
|
||||
return bq25890_field_write(bq, F_VREG, lval);
|
||||
case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT:
|
||||
lval = bq25890_find_idx(val->intval, TBL_IINLIM);
|
||||
return bq25890_field_write(bq, F_IINLIM, lval);
|
||||
|
@ -633,6 +691,8 @@ static int bq25890_power_supply_property_is_writeable(struct power_supply *psy,
|
|||
enum power_supply_property psp)
|
||||
{
|
||||
switch (psp) {
|
||||
case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT:
|
||||
case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE:
|
||||
case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT:
|
||||
return true;
|
||||
default:
|
||||
|
@ -880,6 +940,7 @@ static const enum power_supply_property bq25890_power_supply_props[] = {
|
|||
POWER_SUPPLY_PROP_CHARGE_TYPE,
|
||||
POWER_SUPPLY_PROP_ONLINE,
|
||||
POWER_SUPPLY_PROP_HEALTH,
|
||||
POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT,
|
||||
POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX,
|
||||
POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE,
|
||||
POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE_MAX,
|
||||
|
@ -1034,10 +1095,32 @@ static int bq25890_vbus_is_enabled(struct regulator_dev *rdev)
|
|||
return bq25890_field_read(bq, F_OTG_CFG);
|
||||
}
|
||||
|
||||
static int bq25890_vbus_get_voltage(struct regulator_dev *rdev)
|
||||
{
|
||||
struct bq25890_device *bq = rdev_get_drvdata(rdev);
|
||||
|
||||
return bq25890_get_vbus_voltage(bq);
|
||||
}
|
||||
|
||||
static int bq25890_vsys_get_voltage(struct regulator_dev *rdev)
|
||||
{
|
||||
struct bq25890_device *bq = rdev_get_drvdata(rdev);
|
||||
int ret;
|
||||
|
||||
/* Should be some output voltage ? */
|
||||
ret = bq25890_field_read(bq, F_SYSV); /* read measured value */
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/* converted_val = 2.304V + ADC_val * 20mV (table 10.3.15) */
|
||||
return 2304000 + ret * 20000;
|
||||
}
|
||||
|
||||
static const struct regulator_ops bq25890_vbus_ops = {
|
||||
.enable = bq25890_vbus_enable,
|
||||
.disable = bq25890_vbus_disable,
|
||||
.is_enabled = bq25890_vbus_is_enabled,
|
||||
.get_voltage = bq25890_vbus_get_voltage,
|
||||
};
|
||||
|
||||
static const struct regulator_desc bq25890_vbus_desc = {
|
||||
|
@ -1046,9 +1129,54 @@ static const struct regulator_desc bq25890_vbus_desc = {
|
|||
.type = REGULATOR_VOLTAGE,
|
||||
.owner = THIS_MODULE,
|
||||
.ops = &bq25890_vbus_ops,
|
||||
.fixed_uV = 5000000,
|
||||
.n_voltages = 1,
|
||||
};
|
||||
|
||||
static const struct regulator_ops bq25890_vsys_ops = {
|
||||
.get_voltage = bq25890_vsys_get_voltage,
|
||||
};
|
||||
|
||||
static const struct regulator_desc bq25890_vsys_desc = {
|
||||
.name = "vsys",
|
||||
.of_match = "vsys",
|
||||
.type = REGULATOR_VOLTAGE,
|
||||
.owner = THIS_MODULE,
|
||||
.ops = &bq25890_vsys_ops,
|
||||
};
|
||||
|
||||
static int bq25890_register_regulator(struct bq25890_device *bq)
|
||||
{
|
||||
struct bq25890_platform_data *pdata = dev_get_platdata(bq->dev);
|
||||
struct regulator_config cfg = {
|
||||
.dev = bq->dev,
|
||||
.driver_data = bq,
|
||||
};
|
||||
struct regulator_dev *reg;
|
||||
|
||||
if (pdata)
|
||||
cfg.init_data = pdata->regulator_init_data;
|
||||
|
||||
reg = devm_regulator_register(bq->dev, &bq25890_vbus_desc, &cfg);
|
||||
if (IS_ERR(reg)) {
|
||||
return dev_err_probe(bq->dev, PTR_ERR(reg),
|
||||
"registering vbus regulator");
|
||||
}
|
||||
|
||||
/* pdata->regulator_init_data is for vbus only */
|
||||
cfg.init_data = NULL;
|
||||
reg = devm_regulator_register(bq->dev, &bq25890_vsys_desc, &cfg);
|
||||
if (IS_ERR(reg)) {
|
||||
return dev_err_probe(bq->dev, PTR_ERR(reg),
|
||||
"registering vsys regulator");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
static inline int
|
||||
bq25890_register_regulator(struct bq25890_device *bq)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int bq25890_get_chip_version(struct bq25890_device *bq)
|
||||
|
@ -1189,8 +1317,14 @@ static int bq25890_fw_probe(struct bq25890_device *bq)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int bq25890_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
static void bq25890_non_devm_cleanup(void *data)
|
||||
{
|
||||
struct bq25890_device *bq = data;
|
||||
|
||||
cancel_delayed_work_sync(&bq->pump_express_work);
|
||||
}
|
||||
|
||||
static int bq25890_probe(struct i2c_client *client)
|
||||
{
|
||||
struct device *dev = &client->dev;
|
||||
struct bq25890_device *bq;
|
||||
|
@ -1244,56 +1378,47 @@ static int bq25890_probe(struct i2c_client *client,
|
|||
|
||||
/* OTG reporting */
|
||||
bq->usb_phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB2);
|
||||
if (!IS_ERR_OR_NULL(bq->usb_phy)) {
|
||||
INIT_WORK(&bq->usb_work, bq25890_usb_work);
|
||||
bq->usb_nb.notifier_call = bq25890_usb_notifier;
|
||||
usb_register_notifier(bq->usb_phy, &bq->usb_nb);
|
||||
}
|
||||
#ifdef CONFIG_REGULATOR
|
||||
else {
|
||||
struct bq25890_platform_data *pdata = dev_get_platdata(dev);
|
||||
struct regulator_config cfg = { };
|
||||
struct regulator_dev *reg;
|
||||
|
||||
cfg.dev = dev;
|
||||
cfg.driver_data = bq;
|
||||
if (pdata)
|
||||
cfg.init_data = pdata->regulator_init_data;
|
||||
/*
|
||||
* This must be before bq25890_power_supply_init(), so that it runs
|
||||
* after devm unregisters the power_supply.
|
||||
*/
|
||||
ret = devm_add_action_or_reset(dev, bq25890_non_devm_cleanup, bq);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
reg = devm_regulator_register(dev, &bq25890_vbus_desc, &cfg);
|
||||
if (IS_ERR(reg))
|
||||
return dev_err_probe(dev, PTR_ERR(reg), "registering regulator");
|
||||
}
|
||||
#endif
|
||||
ret = bq25890_register_regulator(bq);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = bq25890_power_supply_init(bq);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "Failed to register power supply\n");
|
||||
goto err_unregister_usb_notifier;
|
||||
}
|
||||
if (ret < 0)
|
||||
return dev_err_probe(dev, ret, "registering power supply\n");
|
||||
|
||||
ret = devm_request_threaded_irq(dev, client->irq, NULL,
|
||||
bq25890_irq_handler_thread,
|
||||
IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
|
||||
BQ25890_IRQ_PIN, bq);
|
||||
if (ret)
|
||||
goto err_unregister_usb_notifier;
|
||||
return ret;
|
||||
|
||||
if (!IS_ERR_OR_NULL(bq->usb_phy)) {
|
||||
INIT_WORK(&bq->usb_work, bq25890_usb_work);
|
||||
bq->usb_nb.notifier_call = bq25890_usb_notifier;
|
||||
usb_register_notifier(bq->usb_phy, &bq->usb_nb);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
err_unregister_usb_notifier:
|
||||
if (!IS_ERR_OR_NULL(bq->usb_phy))
|
||||
usb_unregister_notifier(bq->usb_phy, &bq->usb_nb);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void bq25890_remove(struct i2c_client *client)
|
||||
{
|
||||
struct bq25890_device *bq = i2c_get_clientdata(client);
|
||||
|
||||
if (!IS_ERR_OR_NULL(bq->usb_phy))
|
||||
if (!IS_ERR_OR_NULL(bq->usb_phy)) {
|
||||
usb_unregister_notifier(bq->usb_phy, &bq->usb_nb);
|
||||
cancel_work_sync(&bq->usb_work);
|
||||
}
|
||||
|
||||
if (!bq->skip_reset) {
|
||||
/* reset all registers to default values */
|
||||
|
@ -1400,7 +1525,7 @@ static struct i2c_driver bq25890_driver = {
|
|||
.acpi_match_table = ACPI_PTR(bq25890_acpi_match),
|
||||
.pm = &bq25890_pm,
|
||||
},
|
||||
.probe = bq25890_probe,
|
||||
.probe_new = bq25890_probe,
|
||||
.remove = bq25890_remove,
|
||||
.shutdown = bq25890_shutdown,
|
||||
.id_table = bq25890_i2c_ids,
|
||||
|
|
|
@ -1207,9 +1207,9 @@ static int bq25980_parse_dt(struct bq25980_device *bq)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int bq25980_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
static int bq25980_probe(struct i2c_client *client)
|
||||
{
|
||||
const struct i2c_device_id *id = i2c_client_get_device_id(client);
|
||||
struct device *dev = &client->dev;
|
||||
struct bq25980_device *bq;
|
||||
int ret;
|
||||
|
@ -1287,7 +1287,7 @@ static struct i2c_driver bq25980_driver = {
|
|||
.name = "bq25980-charger",
|
||||
.of_match_table = bq25980_of_match,
|
||||
},
|
||||
.probe = bq25980_probe,
|
||||
.probe_new = bq25980_probe,
|
||||
.id_table = bq25980_i2c_ids,
|
||||
};
|
||||
module_i2c_driver(bq25980_driver);
|
||||
|
|
|
@ -136,9 +136,9 @@ static int bq27xxx_battery_i2c_bulk_write(struct bq27xxx_device_info *di,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int bq27xxx_battery_i2c_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
static int bq27xxx_battery_i2c_probe(struct i2c_client *client)
|
||||
{
|
||||
const struct i2c_device_id *id = i2c_client_get_device_id(client);
|
||||
struct bq27xxx_device_info *di;
|
||||
int ret;
|
||||
char *name;
|
||||
|
@ -295,7 +295,7 @@ static struct i2c_driver bq27xxx_battery_i2c_driver = {
|
|||
.name = "bq27xxx-battery",
|
||||
.of_match_table = of_match_ptr(bq27xxx_battery_i2c_of_match_table),
|
||||
},
|
||||
.probe = bq27xxx_battery_i2c_probe,
|
||||
.probe_new = bq27xxx_battery_i2c_probe,
|
||||
.remove = bq27xxx_battery_i2c_remove,
|
||||
.id_table = bq27xxx_i2c_id_table,
|
||||
};
|
||||
|
|
|
@ -699,6 +699,9 @@ static int cw_bat_probe(struct i2c_client *client)
|
|||
}
|
||||
|
||||
cw_bat->battery_workqueue = create_singlethread_workqueue("rk_battery");
|
||||
if (!cw_bat->battery_workqueue)
|
||||
return -ENOMEM;
|
||||
|
||||
devm_delayed_work_autocancel(&client->dev,
|
||||
&cw_bat->battery_delay_work, cw_bat_work);
|
||||
queue_delayed_work(cw_bat->battery_workqueue,
|
||||
|
|
|
@ -368,9 +368,9 @@ static const struct ds278x_battery_ops ds278x_ops[] = {
|
|||
}
|
||||
};
|
||||
|
||||
static int ds278x_battery_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
static int ds278x_battery_probe(struct i2c_client *client)
|
||||
{
|
||||
const struct i2c_device_id *id = i2c_client_get_device_id(client);
|
||||
struct ds278x_platform_data *pdata = client->dev.platform_data;
|
||||
struct power_supply_config psy_cfg = {};
|
||||
struct ds278x_info *info;
|
||||
|
@ -458,7 +458,7 @@ static struct i2c_driver ds278x_battery_driver = {
|
|||
.name = "ds2782-battery",
|
||||
.pm = &ds278x_battery_pm_ops,
|
||||
},
|
||||
.probe = ds278x_battery_probe,
|
||||
.probe_new = ds278x_battery_probe,
|
||||
.remove = ds278x_battery_remove,
|
||||
.id_table = ds278x_id,
|
||||
};
|
||||
|
|
|
@ -540,7 +540,7 @@ static struct lp8727_platform_data *lp8727_parse_dt(struct device *dev)
|
|||
}
|
||||
#endif
|
||||
|
||||
static int lp8727_probe(struct i2c_client *cl, const struct i2c_device_id *id)
|
||||
static int lp8727_probe(struct i2c_client *cl)
|
||||
{
|
||||
struct lp8727_chg *pchg;
|
||||
struct lp8727_platform_data *pdata;
|
||||
|
@ -615,7 +615,7 @@ static struct i2c_driver lp8727_driver = {
|
|||
.name = "lp8727",
|
||||
.of_match_table = of_match_ptr(lp8727_dt_ids),
|
||||
},
|
||||
.probe = lp8727_probe,
|
||||
.probe_new = lp8727_probe,
|
||||
.remove = lp8727_remove,
|
||||
.id_table = lp8727_ids,
|
||||
};
|
||||
|
|
|
@ -520,7 +520,7 @@ err_free_irq:
|
|||
static int lp8788_irq_register(struct platform_device *pdev,
|
||||
struct lp8788_charger *pchg)
|
||||
{
|
||||
const char *name[] = {
|
||||
static const char * const name[] = {
|
||||
LP8788_CHG_IRQ, LP8788_PRSW_IRQ, LP8788_BATT_IRQ
|
||||
};
|
||||
int i;
|
||||
|
|
|
@ -439,8 +439,7 @@ static enum power_supply_property ltc294x_properties[] = {
|
|||
POWER_SUPPLY_PROP_CURRENT_NOW,
|
||||
};
|
||||
|
||||
static int ltc294x_i2c_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
static int ltc294x_i2c_probe(struct i2c_client *client)
|
||||
{
|
||||
struct power_supply_config psy_cfg = {};
|
||||
struct ltc294x_info *info;
|
||||
|
@ -636,7 +635,7 @@ static struct i2c_driver ltc294x_driver = {
|
|||
.of_match_table = ltc294x_i2c_of_match,
|
||||
.pm = LTC294X_PM_OPS,
|
||||
},
|
||||
.probe = ltc294x_i2c_probe,
|
||||
.probe_new = ltc294x_i2c_probe,
|
||||
.shutdown = ltc294x_i2c_shutdown,
|
||||
.id_table = ltc294x_i2c_id,
|
||||
};
|
||||
|
|
|
@ -819,8 +819,7 @@ static void ltc4162l_clear_interrupts(struct ltc4162l_info *info)
|
|||
regmap_write(info->regmap, LTC4162L_CHARGE_STATUS_ALERTS_REG, 0);
|
||||
}
|
||||
|
||||
static int ltc4162l_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
static int ltc4162l_probe(struct i2c_client *client)
|
||||
{
|
||||
struct i2c_adapter *adapter = client->adapter;
|
||||
struct device *dev = &client->dev;
|
||||
|
@ -916,7 +915,7 @@ static const struct of_device_id ltc4162l_of_match[] = {
|
|||
MODULE_DEVICE_TABLE(of, ltc4162l_of_match);
|
||||
|
||||
static struct i2c_driver ltc4162l_driver = {
|
||||
.probe = ltc4162l_probe,
|
||||
.probe_new = ltc4162l_probe,
|
||||
.alert = ltc4162l_alert,
|
||||
.id_table = ltc4162l_i2c_id_table,
|
||||
.driver = {
|
||||
|
|
|
@ -234,8 +234,7 @@ static enum power_supply_property max14656_battery_props[] = {
|
|||
POWER_SUPPLY_PROP_MANUFACTURER,
|
||||
};
|
||||
|
||||
static int max14656_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
static int max14656_probe(struct i2c_client *client)
|
||||
{
|
||||
struct i2c_adapter *adapter = client->adapter;
|
||||
struct device *dev = &client->dev;
|
||||
|
@ -317,7 +316,7 @@ static struct i2c_driver max14656_i2c_driver = {
|
|||
.name = "max14656",
|
||||
.of_match_table = max14656_match_table,
|
||||
},
|
||||
.probe = max14656_probe,
|
||||
.probe_new = max14656_probe,
|
||||
.id_table = max14656_id,
|
||||
};
|
||||
module_i2c_driver(max14656_i2c_driver);
|
||||
|
|
|
@ -430,9 +430,9 @@ static const struct power_supply_desc max17040_battery_desc = {
|
|||
.num_properties = ARRAY_SIZE(max17040_battery_props),
|
||||
};
|
||||
|
||||
static int max17040_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
static int max17040_probe(struct i2c_client *client)
|
||||
{
|
||||
const struct i2c_device_id *id = i2c_client_get_device_id(client);
|
||||
struct i2c_adapter *adapter = client->adapter;
|
||||
struct power_supply_config psy_cfg = {};
|
||||
struct max17040_chip *chip;
|
||||
|
@ -599,7 +599,7 @@ static struct i2c_driver max17040_i2c_driver = {
|
|||
.of_match_table = max17040_of_match,
|
||||
.pm = MAX17040_PM_OPS,
|
||||
},
|
||||
.probe = max17040_probe,
|
||||
.probe_new = max17040_probe,
|
||||
.id_table = max17040_id,
|
||||
};
|
||||
module_i2c_driver(max17040_i2c_driver);
|
||||
|
|
|
@ -1031,9 +1031,9 @@ static const struct power_supply_desc max17042_no_current_sense_psy_desc = {
|
|||
.num_properties = ARRAY_SIZE(max17042_battery_props) - 2,
|
||||
};
|
||||
|
||||
static int max17042_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
static int max17042_probe(struct i2c_client *client)
|
||||
{
|
||||
const struct i2c_device_id *id = i2c_client_get_device_id(client);
|
||||
struct i2c_adapter *adapter = client->adapter;
|
||||
const struct power_supply_desc *max17042_desc = &max17042_psy_desc;
|
||||
struct power_supply_config psy_cfg = {};
|
||||
|
@ -1220,7 +1220,7 @@ static struct i2c_driver max17042_i2c_driver = {
|
|||
.of_match_table = of_match_ptr(max17042_dt_match),
|
||||
.pm = &max17042_pm_ops,
|
||||
},
|
||||
.probe = max17042_probe,
|
||||
.probe_new = max17042_probe,
|
||||
.id_table = max17042_id,
|
||||
};
|
||||
module_i2c_driver(max17042_i2c_driver);
|
||||
|
|
|
@ -113,16 +113,13 @@ enum {
|
|||
MT6360_RANGE_MAX,
|
||||
};
|
||||
|
||||
#define MT6360_LINEAR_RANGE(idx, _min, _min_sel, _max_sel, _step) \
|
||||
[idx] = REGULATOR_LINEAR_RANGE(_min, _min_sel, _max_sel, _step)
|
||||
|
||||
static const struct linear_range mt6360_chg_range[MT6360_RANGE_MAX] = {
|
||||
MT6360_LINEAR_RANGE(MT6360_RANGE_VMIVR, 3900000, 0, 0x5F, 100000),
|
||||
MT6360_LINEAR_RANGE(MT6360_RANGE_ICHG, 100000, 0, 0x31, 100000),
|
||||
MT6360_LINEAR_RANGE(MT6360_RANGE_VOREG, 3900000, 0, 0x51, 10000),
|
||||
MT6360_LINEAR_RANGE(MT6360_RANGE_AICR, 100000, 0, 0x3F, 50000),
|
||||
MT6360_LINEAR_RANGE(MT6360_RANGE_IPREC, 100000, 0, 0x0F, 50000),
|
||||
MT6360_LINEAR_RANGE(MT6360_RANGE_IEOC, 100000, 0, 0x0F, 50000),
|
||||
LINEAR_RANGE_IDX(MT6360_RANGE_VMIVR, 3900000, 0, 0x5F, 100000),
|
||||
LINEAR_RANGE_IDX(MT6360_RANGE_ICHG, 100000, 0, 0x31, 100000),
|
||||
LINEAR_RANGE_IDX(MT6360_RANGE_VOREG, 3900000, 0, 0x51, 10000),
|
||||
LINEAR_RANGE_IDX(MT6360_RANGE_AICR, 100000, 0, 0x3F, 50000),
|
||||
LINEAR_RANGE_IDX(MT6360_RANGE_IPREC, 100000, 0, 0x0F, 50000),
|
||||
LINEAR_RANGE_IDX(MT6360_RANGE_IEOC, 100000, 0, 0x0F, 50000),
|
||||
};
|
||||
|
||||
struct mt6360_chg_info {
|
||||
|
|
|
@ -750,6 +750,11 @@ int power_supply_get_battery_info(struct power_supply *psy,
|
|||
int i, tab_len, size;
|
||||
|
||||
propname = kasprintf(GFP_KERNEL, "ocv-capacity-table-%d", index);
|
||||
if (!propname) {
|
||||
power_supply_put_battery_info(psy, info);
|
||||
err = -ENOMEM;
|
||||
goto out_put_node;
|
||||
}
|
||||
list = of_get_property(battery_np, propname, &size);
|
||||
if (!list || !size) {
|
||||
dev_err(&psy->dev, "failed to get %s\n", propname);
|
||||
|
@ -870,7 +875,6 @@ EXPORT_SYMBOL_GPL(power_supply_temp2resist_simple);
|
|||
* power_supply_vbat2ri() - find the battery internal resistance
|
||||
* from the battery voltage
|
||||
* @info: The battery information container
|
||||
* @table: Pointer to battery resistance temperature table
|
||||
* @vbat_uv: The battery voltage in microvolt
|
||||
* @charging: If we are charging (true) or not (false)
|
||||
*
|
||||
|
@ -1387,8 +1391,8 @@ create_triggers_failed:
|
|||
register_cooler_failed:
|
||||
psy_unregister_thermal(psy);
|
||||
register_thermal_failed:
|
||||
device_del(dev);
|
||||
wakeup_init_failed:
|
||||
device_del(dev);
|
||||
device_add_failed:
|
||||
check_supplies_failed:
|
||||
dev_set_name_failed:
|
||||
|
|
|
@ -1060,8 +1060,10 @@ static int rk817_charger_probe(struct platform_device *pdev)
|
|||
return -ENODEV;
|
||||
|
||||
charger = devm_kzalloc(&pdev->dev, sizeof(*charger), GFP_KERNEL);
|
||||
if (!charger)
|
||||
if (!charger) {
|
||||
of_node_put(node);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
charger->rk808 = rk808;
|
||||
|
||||
|
|
|
@ -112,8 +112,7 @@ static const struct power_supply_desc rt5033_battery_desc = {
|
|||
.num_properties = ARRAY_SIZE(rt5033_battery_props),
|
||||
};
|
||||
|
||||
static int rt5033_battery_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
static int rt5033_battery_probe(struct i2c_client *client)
|
||||
{
|
||||
struct i2c_adapter *adapter = client->adapter;
|
||||
struct power_supply_config psy_cfg = {};
|
||||
|
@ -173,7 +172,7 @@ static struct i2c_driver rt5033_battery_driver = {
|
|||
.name = "rt5033-battery",
|
||||
.of_match_table = rt5033_battery_of_match,
|
||||
},
|
||||
.probe = rt5033_battery_probe,
|
||||
.probe_new = rt5033_battery_probe,
|
||||
.remove = rt5033_battery_remove,
|
||||
.id_table = rt5033_battery_id,
|
||||
};
|
||||
|
|
|
@ -1581,8 +1581,7 @@ static const struct regmap_config rt9455_regmap_config = {
|
|||
.cache_type = REGCACHE_RBTREE,
|
||||
};
|
||||
|
||||
static int rt9455_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
static int rt9455_probe(struct i2c_client *client)
|
||||
{
|
||||
struct i2c_adapter *adapter = client->adapter;
|
||||
struct device *dev = &client->dev;
|
||||
|
@ -1738,7 +1737,7 @@ MODULE_DEVICE_TABLE(acpi, rt9455_i2c_acpi_match);
|
|||
#endif
|
||||
|
||||
static struct i2c_driver rt9455_driver = {
|
||||
.probe = rt9455_probe,
|
||||
.probe_new = rt9455_probe,
|
||||
.remove = rt9455_remove,
|
||||
.id_table = rt9455_i2c_id_table,
|
||||
.driver = {
|
||||
|
|
|
@ -162,8 +162,7 @@ static const struct power_supply_desc sbs_desc = {
|
|||
.get_property = sbs_get_property,
|
||||
};
|
||||
|
||||
static int sbs_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
static int sbs_probe(struct i2c_client *client)
|
||||
{
|
||||
struct power_supply_config psy_cfg = {};
|
||||
struct sbs_info *chip;
|
||||
|
@ -241,7 +240,7 @@ static const struct i2c_device_id sbs_id[] = {
|
|||
MODULE_DEVICE_TABLE(i2c, sbs_id);
|
||||
|
||||
static struct i2c_driver sbs_driver = {
|
||||
.probe = sbs_probe,
|
||||
.probe_new = sbs_probe,
|
||||
.id_table = sbs_id,
|
||||
.driver = {
|
||||
.name = "sbs-charger",
|
||||
|
|
|
@ -315,9 +315,9 @@ static void sbsm_del_mux_adapter(void *data)
|
|||
i2c_mux_del_adapters(sbsm->muxc);
|
||||
}
|
||||
|
||||
static int sbsm_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
static int sbsm_probe(struct i2c_client *client)
|
||||
{
|
||||
const struct i2c_device_id *id = i2c_client_get_device_id(client);
|
||||
struct i2c_adapter *adapter = client->adapter;
|
||||
struct sbsm_data *data;
|
||||
struct device *dev = &client->dev;
|
||||
|
@ -409,7 +409,7 @@ static struct i2c_driver sbsm_driver = {
|
|||
.name = "sbsm",
|
||||
.of_match_table = of_match_ptr(sbsm_dt_ids),
|
||||
},
|
||||
.probe = sbsm_probe,
|
||||
.probe_new = sbsm_probe,
|
||||
.alert = sbsm_alert,
|
||||
.id_table = sbsm_ids
|
||||
};
|
||||
|
|
|
@ -1528,9 +1528,9 @@ static const struct regulator_desc smb347_usb_vbus_regulator_desc = {
|
|||
.n_voltages = 1,
|
||||
};
|
||||
|
||||
static int smb347_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
static int smb347_probe(struct i2c_client *client)
|
||||
{
|
||||
const struct i2c_device_id *id = i2c_client_get_device_id(client);
|
||||
struct power_supply_config mains_usb_cfg = {};
|
||||
struct regulator_config usb_rdev_cfg = {};
|
||||
struct device *dev = &client->dev;
|
||||
|
@ -1629,7 +1629,7 @@ static struct i2c_driver smb347_driver = {
|
|||
.name = "smb347",
|
||||
.of_match_table = smb3xx_of_match,
|
||||
},
|
||||
.probe = smb347_probe,
|
||||
.probe_new = smb347_probe,
|
||||
.remove = smb347_remove,
|
||||
.shutdown = smb347_shutdown,
|
||||
.id_table = smb347_id,
|
||||
|
|
|
@ -532,8 +532,7 @@ static const struct regulator_desc ucs1002_regulator_descriptor = {
|
|||
.n_voltages = 1,
|
||||
};
|
||||
|
||||
static int ucs1002_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *dev_id)
|
||||
static int ucs1002_probe(struct i2c_client *client)
|
||||
{
|
||||
struct device *dev = &client->dev;
|
||||
struct power_supply_config charger_config = {};
|
||||
|
@ -681,7 +680,7 @@ static struct i2c_driver ucs1002_driver = {
|
|||
.name = "ucs1002",
|
||||
.of_match_table = ucs1002_of_match,
|
||||
},
|
||||
.probe = ucs1002_probe,
|
||||
.probe_new = ucs1002_probe,
|
||||
};
|
||||
module_i2c_driver(ucs1002_driver);
|
||||
|
||||
|
|
|
@ -176,8 +176,7 @@ static int z2_batt_ps_init(struct z2_charger *charger, int props)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int z2_batt_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
static int z2_batt_probe(struct i2c_client *client)
|
||||
{
|
||||
int ret = 0;
|
||||
int props = 1; /* POWER_SUPPLY_PROP_PRESENT */
|
||||
|
@ -206,10 +205,12 @@ static int z2_batt_probe(struct i2c_client *client,
|
|||
|
||||
charger->charge_gpiod = devm_gpiod_get_optional(&client->dev,
|
||||
NULL, GPIOD_IN);
|
||||
if (IS_ERR(charger->charge_gpiod))
|
||||
return dev_err_probe(&client->dev,
|
||||
if (IS_ERR(charger->charge_gpiod)) {
|
||||
ret = dev_err_probe(&client->dev,
|
||||
PTR_ERR(charger->charge_gpiod),
|
||||
"failed to get charge GPIO\n");
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (charger->charge_gpiod) {
|
||||
gpiod_set_consumer_name(charger->charge_gpiod, "BATT CHRG");
|
||||
|
@ -306,7 +307,7 @@ static struct i2c_driver z2_batt_driver = {
|
|||
.name = "z2-battery",
|
||||
.pm = Z2_BATTERY_PM_OPS
|
||||
},
|
||||
.probe = z2_batt_probe,
|
||||
.probe_new = z2_batt_probe,
|
||||
.remove = z2_batt_remove,
|
||||
.id_table = z2_batt_id,
|
||||
};
|
||||
|
|
|
@ -1055,6 +1055,13 @@ config ADVANTECH_WDT
|
|||
feature. More information can be found at
|
||||
<https://www.advantech.com.tw/products/>
|
||||
|
||||
config ADVANTECH_EC_WDT
|
||||
tristate "Advantech Embedded Controller Watchdog Timer"
|
||||
depends on X86
|
||||
help
|
||||
This driver supports Advantech products with ITE based Embedded Controller.
|
||||
It does not support Advantech products with other ECs or without EC.
|
||||
|
||||
config ALIM1535_WDT
|
||||
tristate "ALi M1535 PMU Watchdog Timer"
|
||||
depends on X86 && PCI
|
||||
|
|
|
@ -102,6 +102,7 @@ obj-$(CONFIG_SUNPLUS_WATCHDOG) += sunplus_wdt.o
|
|||
# X86 (i386 + ia64 + x86_64) Architecture
|
||||
obj-$(CONFIG_ACQUIRE_WDT) += acquirewdt.o
|
||||
obj-$(CONFIG_ADVANTECH_WDT) += advantechwdt.o
|
||||
obj-$(CONFIG_ADVANTECH_EC_WDT) += advantech_ec_wdt.o
|
||||
obj-$(CONFIG_ALIM1535_WDT) += alim1535_wdt.o
|
||||
obj-$(CONFIG_ALIM7101_WDT) += alim7101_wdt.o
|
||||
obj-$(CONFIG_EBC_C384_WDT) += ebc-c384_wdt.o
|
||||
|
|
|
@ -0,0 +1,205 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Advantech Embedded Controller Watchdog Driver
|
||||
*
|
||||
* This driver supports Advantech products with ITE based Embedded Controller.
|
||||
* It does not support Advantech products with other ECs or without EC.
|
||||
*
|
||||
* Copyright (C) 2022 Advantech Europe B.V.
|
||||
*/
|
||||
|
||||
#include <linux/delay.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/isa.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/moduleparam.h>
|
||||
#include <linux/watchdog.h>
|
||||
|
||||
#define DRIVER_NAME "advantech_ec_wdt"
|
||||
|
||||
/* EC IO region */
|
||||
#define EC_BASE_ADDR 0x299
|
||||
#define EC_ADDR_EXTENT 2
|
||||
|
||||
/* EC minimum IO access delay in ms */
|
||||
#define EC_MIN_DELAY 10
|
||||
|
||||
/* EC interface definitions */
|
||||
#define EC_ADDR_CMD (EC_BASE_ADDR + 1)
|
||||
#define EC_ADDR_DATA EC_BASE_ADDR
|
||||
#define EC_CMD_EC_PROBE 0x30
|
||||
#define EC_CMD_COMM 0x89
|
||||
#define EC_CMD_WDT_START 0x28
|
||||
#define EC_CMD_WDT_STOP 0x29
|
||||
#define EC_CMD_WDT_RESET 0x2A
|
||||
#define EC_DAT_EN_DLY_H 0x58
|
||||
#define EC_DAT_EN_DLY_L 0x59
|
||||
#define EC_DAT_RST_DLY_H 0x5E
|
||||
#define EC_DAT_RST_DLY_L 0x5F
|
||||
#define EC_MAGIC 0x95
|
||||
|
||||
/* module parameters */
|
||||
#define MIN_TIME 1
|
||||
#define MAX_TIME 6000 /* 100 minutes */
|
||||
#define DEFAULT_TIME 60
|
||||
|
||||
static unsigned int timeout;
|
||||
static ktime_t ec_timestamp;
|
||||
|
||||
module_param(timeout, uint, 0);
|
||||
MODULE_PARM_DESC(timeout,
|
||||
"Default Watchdog timer setting (" __MODULE_STRING(DEFAULT_TIME) "s). The range is from " __MODULE_STRING(MIN_TIME) " to " __MODULE_STRING(MAX_TIME) ".");
|
||||
|
||||
static void adv_ec_wdt_timing_gate(void)
|
||||
{
|
||||
ktime_t time_cur, time_delta;
|
||||
|
||||
/* ensure minimum delay between IO accesses*/
|
||||
time_cur = ktime_get();
|
||||
time_delta = ktime_to_ms(ktime_sub(time_cur, ec_timestamp));
|
||||
if (time_delta < EC_MIN_DELAY) {
|
||||
time_delta = EC_MIN_DELAY - time_delta;
|
||||
usleep_range(time_delta * 1000, (time_delta + 1) * 1000);
|
||||
}
|
||||
ec_timestamp = ktime_get();
|
||||
}
|
||||
|
||||
static void adv_ec_wdt_outb(unsigned char value, unsigned short port)
|
||||
{
|
||||
adv_ec_wdt_timing_gate();
|
||||
outb(value, port);
|
||||
}
|
||||
|
||||
static unsigned char adv_ec_wdt_inb(unsigned short port)
|
||||
{
|
||||
adv_ec_wdt_timing_gate();
|
||||
return inb(port);
|
||||
}
|
||||
|
||||
static int adv_ec_wdt_ping(struct watchdog_device *wdd)
|
||||
{
|
||||
adv_ec_wdt_outb(EC_CMD_WDT_RESET, EC_ADDR_CMD);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int adv_ec_wdt_set_timeout(struct watchdog_device *wdd, unsigned int t)
|
||||
{
|
||||
unsigned int val;
|
||||
|
||||
/* scale time to EC 100 ms base */
|
||||
val = t * 10;
|
||||
|
||||
/* reset enable delay, just in case it was set by BIOS etc. */
|
||||
adv_ec_wdt_outb(EC_CMD_COMM, EC_ADDR_CMD);
|
||||
adv_ec_wdt_outb(EC_DAT_EN_DLY_H, EC_ADDR_DATA);
|
||||
adv_ec_wdt_outb(0, EC_ADDR_DATA);
|
||||
|
||||
adv_ec_wdt_outb(EC_CMD_COMM, EC_ADDR_CMD);
|
||||
adv_ec_wdt_outb(EC_DAT_EN_DLY_L, EC_ADDR_DATA);
|
||||
adv_ec_wdt_outb(0, EC_ADDR_DATA);
|
||||
|
||||
/* set reset delay */
|
||||
adv_ec_wdt_outb(EC_CMD_COMM, EC_ADDR_CMD);
|
||||
adv_ec_wdt_outb(EC_DAT_RST_DLY_H, EC_ADDR_DATA);
|
||||
adv_ec_wdt_outb(val >> 8, EC_ADDR_DATA);
|
||||
|
||||
adv_ec_wdt_outb(EC_CMD_COMM, EC_ADDR_CMD);
|
||||
adv_ec_wdt_outb(EC_DAT_RST_DLY_L, EC_ADDR_DATA);
|
||||
adv_ec_wdt_outb(val & 0xFF, EC_ADDR_DATA);
|
||||
|
||||
wdd->timeout = t;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int adv_ec_wdt_start(struct watchdog_device *wdd)
|
||||
{
|
||||
adv_ec_wdt_set_timeout(wdd, wdd->timeout);
|
||||
adv_ec_wdt_outb(EC_CMD_WDT_START, EC_ADDR_CMD);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int adv_ec_wdt_stop(struct watchdog_device *wdd)
|
||||
{
|
||||
adv_ec_wdt_outb(EC_CMD_WDT_STOP, EC_ADDR_CMD);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct watchdog_info adv_ec_wdt_info = {
|
||||
.identity = DRIVER_NAME,
|
||||
.options = WDIOF_SETTIMEOUT |
|
||||
WDIOF_MAGICCLOSE |
|
||||
WDIOF_KEEPALIVEPING,
|
||||
};
|
||||
|
||||
static const struct watchdog_ops adv_ec_wdt_ops = {
|
||||
.owner = THIS_MODULE,
|
||||
.start = adv_ec_wdt_start,
|
||||
.stop = adv_ec_wdt_stop,
|
||||
.ping = adv_ec_wdt_ping,
|
||||
.set_timeout = adv_ec_wdt_set_timeout,
|
||||
};
|
||||
|
||||
static struct watchdog_device adv_ec_wdt_dev = {
|
||||
.info = &adv_ec_wdt_info,
|
||||
.ops = &adv_ec_wdt_ops,
|
||||
.min_timeout = MIN_TIME,
|
||||
.max_timeout = MAX_TIME,
|
||||
.timeout = DEFAULT_TIME,
|
||||
};
|
||||
|
||||
static int adv_ec_wdt_probe(struct device *dev, unsigned int id)
|
||||
{
|
||||
if (!devm_request_region(dev, EC_BASE_ADDR, EC_ADDR_EXTENT, dev_name(dev))) {
|
||||
dev_err(dev, "Unable to lock port addresses (0x%X-0x%X)\n",
|
||||
EC_BASE_ADDR, EC_BASE_ADDR + EC_ADDR_EXTENT);
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
watchdog_init_timeout(&adv_ec_wdt_dev, timeout, dev);
|
||||
watchdog_stop_on_reboot(&adv_ec_wdt_dev);
|
||||
watchdog_stop_on_unregister(&adv_ec_wdt_dev);
|
||||
|
||||
return devm_watchdog_register_device(dev, &adv_ec_wdt_dev);
|
||||
}
|
||||
|
||||
static struct isa_driver adv_ec_wdt_driver = {
|
||||
.probe = adv_ec_wdt_probe,
|
||||
.driver = {
|
||||
.name = DRIVER_NAME,
|
||||
},
|
||||
};
|
||||
|
||||
static int __init adv_ec_wdt_init(void)
|
||||
{
|
||||
unsigned int val;
|
||||
|
||||
/* quick probe for EC */
|
||||
if (!request_region(EC_BASE_ADDR, EC_ADDR_EXTENT, DRIVER_NAME))
|
||||
return -EBUSY;
|
||||
|
||||
adv_ec_wdt_outb(EC_CMD_EC_PROBE, EC_ADDR_CMD);
|
||||
val = adv_ec_wdt_inb(EC_ADDR_DATA);
|
||||
release_region(EC_BASE_ADDR, EC_ADDR_EXTENT);
|
||||
|
||||
if (val != EC_MAGIC)
|
||||
return -ENODEV;
|
||||
|
||||
return isa_register_driver(&adv_ec_wdt_driver, 1);
|
||||
}
|
||||
|
||||
static void __exit adv_ec_wdt_exit(void)
|
||||
{
|
||||
isa_unregister_driver(&adv_ec_wdt_driver);
|
||||
}
|
||||
|
||||
module_init(adv_ec_wdt_init);
|
||||
module_exit(adv_ec_wdt_exit);
|
||||
|
||||
MODULE_AUTHOR("Thomas Kastner <thomas.kastner@advantech.com>");
|
||||
MODULE_DESCRIPTION("Advantech Embedded Controller Watchdog Device Driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_VERSION("20221019");
|
||||
MODULE_ALIAS("isa:" DRIVER_NAME);
|
|
@ -5,11 +5,14 @@
|
|||
* Joel Stanley <joel@jms.id.au>
|
||||
*/
|
||||
|
||||
#include <linux/bits.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_irq.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/watchdog.h>
|
||||
|
||||
|
@ -18,28 +21,41 @@ module_param(nowayout, bool, 0);
|
|||
MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default="
|
||||
__MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
|
||||
|
||||
struct aspeed_wdt_config {
|
||||
u32 ext_pulse_width_mask;
|
||||
u32 irq_shift;
|
||||
u32 irq_mask;
|
||||
};
|
||||
|
||||
struct aspeed_wdt {
|
||||
struct watchdog_device wdd;
|
||||
void __iomem *base;
|
||||
u32 ctrl;
|
||||
};
|
||||
|
||||
struct aspeed_wdt_config {
|
||||
u32 ext_pulse_width_mask;
|
||||
const struct aspeed_wdt_config *cfg;
|
||||
};
|
||||
|
||||
static const struct aspeed_wdt_config ast2400_config = {
|
||||
.ext_pulse_width_mask = 0xff,
|
||||
.irq_shift = 0,
|
||||
.irq_mask = 0,
|
||||
};
|
||||
|
||||
static const struct aspeed_wdt_config ast2500_config = {
|
||||
.ext_pulse_width_mask = 0xfffff,
|
||||
.irq_shift = 12,
|
||||
.irq_mask = GENMASK(31, 12),
|
||||
};
|
||||
|
||||
static const struct aspeed_wdt_config ast2600_config = {
|
||||
.ext_pulse_width_mask = 0xfffff,
|
||||
.irq_shift = 0,
|
||||
.irq_mask = GENMASK(31, 10),
|
||||
};
|
||||
|
||||
static const struct of_device_id aspeed_wdt_of_table[] = {
|
||||
{ .compatible = "aspeed,ast2400-wdt", .data = &ast2400_config },
|
||||
{ .compatible = "aspeed,ast2500-wdt", .data = &ast2500_config },
|
||||
{ .compatible = "aspeed,ast2600-wdt", .data = &ast2500_config },
|
||||
{ .compatible = "aspeed,ast2600-wdt", .data = &ast2600_config },
|
||||
{ },
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, aspeed_wdt_of_table);
|
||||
|
@ -58,6 +74,7 @@ MODULE_DEVICE_TABLE(of, aspeed_wdt_of_table);
|
|||
#define WDT_CTRL_RESET_SYSTEM BIT(1)
|
||||
#define WDT_CTRL_ENABLE BIT(0)
|
||||
#define WDT_TIMEOUT_STATUS 0x10
|
||||
#define WDT_TIMEOUT_STATUS_IRQ BIT(2)
|
||||
#define WDT_TIMEOUT_STATUS_BOOT_SECONDARY BIT(1)
|
||||
#define WDT_CLEAR_TIMEOUT_STATUS 0x14
|
||||
#define WDT_CLEAR_TIMEOUT_AND_BOOT_CODE_SELECTION BIT(0)
|
||||
|
@ -160,6 +177,26 @@ static int aspeed_wdt_set_timeout(struct watchdog_device *wdd,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int aspeed_wdt_set_pretimeout(struct watchdog_device *wdd,
|
||||
unsigned int pretimeout)
|
||||
{
|
||||
struct aspeed_wdt *wdt = to_aspeed_wdt(wdd);
|
||||
u32 actual = pretimeout * WDT_RATE_1MHZ;
|
||||
u32 s = wdt->cfg->irq_shift;
|
||||
u32 m = wdt->cfg->irq_mask;
|
||||
|
||||
wdd->pretimeout = pretimeout;
|
||||
wdt->ctrl &= ~m;
|
||||
if (pretimeout)
|
||||
wdt->ctrl |= ((actual << s) & m) | WDT_CTRL_WDT_INTR;
|
||||
else
|
||||
wdt->ctrl &= ~WDT_CTRL_WDT_INTR;
|
||||
|
||||
writel(wdt->ctrl, wdt->base + WDT_CTRL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int aspeed_wdt_restart(struct watchdog_device *wdd,
|
||||
unsigned long action, void *data)
|
||||
{
|
||||
|
@ -232,6 +269,7 @@ static const struct watchdog_ops aspeed_wdt_ops = {
|
|||
.stop = aspeed_wdt_stop,
|
||||
.ping = aspeed_wdt_ping,
|
||||
.set_timeout = aspeed_wdt_set_timeout,
|
||||
.set_pretimeout = aspeed_wdt_set_pretimeout,
|
||||
.restart = aspeed_wdt_restart,
|
||||
.owner = THIS_MODULE,
|
||||
};
|
||||
|
@ -243,10 +281,29 @@ static const struct watchdog_info aspeed_wdt_info = {
|
|||
.identity = KBUILD_MODNAME,
|
||||
};
|
||||
|
||||
static const struct watchdog_info aspeed_wdt_pretimeout_info = {
|
||||
.options = WDIOF_KEEPALIVEPING
|
||||
| WDIOF_PRETIMEOUT
|
||||
| WDIOF_MAGICCLOSE
|
||||
| WDIOF_SETTIMEOUT,
|
||||
.identity = KBUILD_MODNAME,
|
||||
};
|
||||
|
||||
static irqreturn_t aspeed_wdt_irq(int irq, void *arg)
|
||||
{
|
||||
struct watchdog_device *wdd = arg;
|
||||
struct aspeed_wdt *wdt = to_aspeed_wdt(wdd);
|
||||
u32 status = readl(wdt->base + WDT_TIMEOUT_STATUS);
|
||||
|
||||
if (status & WDT_TIMEOUT_STATUS_IRQ)
|
||||
watchdog_notify_pretimeout(wdd);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static int aspeed_wdt_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
const struct aspeed_wdt_config *config;
|
||||
const struct of_device_id *ofdid;
|
||||
struct aspeed_wdt *wdt;
|
||||
struct device_node *np;
|
||||
|
@ -259,11 +316,33 @@ static int aspeed_wdt_probe(struct platform_device *pdev)
|
|||
if (!wdt)
|
||||
return -ENOMEM;
|
||||
|
||||
np = dev->of_node;
|
||||
|
||||
ofdid = of_match_node(aspeed_wdt_of_table, np);
|
||||
if (!ofdid)
|
||||
return -EINVAL;
|
||||
wdt->cfg = ofdid->data;
|
||||
|
||||
wdt->base = devm_platform_ioremap_resource(pdev, 0);
|
||||
if (IS_ERR(wdt->base))
|
||||
return PTR_ERR(wdt->base);
|
||||
|
||||
wdt->wdd.info = &aspeed_wdt_info;
|
||||
|
||||
if (wdt->cfg->irq_mask) {
|
||||
int irq = platform_get_irq_optional(pdev, 0);
|
||||
|
||||
if (irq > 0) {
|
||||
ret = devm_request_irq(dev, irq, aspeed_wdt_irq,
|
||||
IRQF_SHARED, dev_name(dev),
|
||||
wdt);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
wdt->wdd.info = &aspeed_wdt_pretimeout_info;
|
||||
}
|
||||
}
|
||||
|
||||
wdt->wdd.ops = &aspeed_wdt_ops;
|
||||
wdt->wdd.max_hw_heartbeat_ms = WDT_MAX_TIMEOUT_MS;
|
||||
wdt->wdd.parent = dev;
|
||||
|
@ -273,13 +352,6 @@ static int aspeed_wdt_probe(struct platform_device *pdev)
|
|||
|
||||
watchdog_set_nowayout(&wdt->wdd, nowayout);
|
||||
|
||||
np = dev->of_node;
|
||||
|
||||
ofdid = of_match_node(aspeed_wdt_of_table, np);
|
||||
if (!ofdid)
|
||||
return -EINVAL;
|
||||
config = ofdid->data;
|
||||
|
||||
/*
|
||||
* On clock rates:
|
||||
* - ast2400 wdt can run at PCLK, or 1MHz
|
||||
|
@ -331,7 +403,7 @@ static int aspeed_wdt_probe(struct platform_device *pdev)
|
|||
(of_device_is_compatible(np, "aspeed,ast2600-wdt"))) {
|
||||
u32 reg = readl(wdt->base + WDT_RESET_WIDTH);
|
||||
|
||||
reg &= config->ext_pulse_width_mask;
|
||||
reg &= wdt->cfg->ext_pulse_width_mask;
|
||||
if (of_property_read_bool(np, "aspeed,ext-active-high"))
|
||||
reg |= WDT_ACTIVE_HIGH_MAGIC;
|
||||
else
|
||||
|
@ -339,7 +411,7 @@ static int aspeed_wdt_probe(struct platform_device *pdev)
|
|||
|
||||
writel(reg, wdt->base + WDT_RESET_WIDTH);
|
||||
|
||||
reg &= config->ext_pulse_width_mask;
|
||||
reg &= wdt->cfg->ext_pulse_width_mask;
|
||||
if (of_property_read_bool(np, "aspeed,ext-push-pull"))
|
||||
reg |= WDT_PUSH_PULL_MAGIC;
|
||||
else
|
||||
|
@ -349,7 +421,7 @@ static int aspeed_wdt_probe(struct platform_device *pdev)
|
|||
}
|
||||
|
||||
if (!of_property_read_u32(np, "aspeed,ext-pulse-duration", &duration)) {
|
||||
u32 max_duration = config->ext_pulse_width_mask + 1;
|
||||
u32 max_duration = wdt->cfg->ext_pulse_width_mask + 1;
|
||||
|
||||
if (duration == 0 || duration > max_duration) {
|
||||
dev_err(dev, "Invalid pulse duration: %uus\n",
|
||||
|
|
|
@ -278,8 +278,6 @@ static void at91wdt_shutdown(struct platform_device *pdev)
|
|||
at91_wdt_stop();
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
|
||||
static int at91wdt_suspend(struct platform_device *pdev, pm_message_t message)
|
||||
{
|
||||
at91_wdt_stop();
|
||||
|
@ -293,11 +291,6 @@ static int at91wdt_resume(struct platform_device *pdev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
#else
|
||||
#define at91wdt_suspend NULL
|
||||
#define at91wdt_resume NULL
|
||||
#endif
|
||||
|
||||
static const struct of_device_id at91_wdt_dt_ids[] = {
|
||||
{ .compatible = "atmel,at91rm9200-wdt" },
|
||||
{ /* sentinel */ }
|
||||
|
@ -308,8 +301,8 @@ static struct platform_driver at91wdt_driver = {
|
|||
.probe = at91wdt_probe,
|
||||
.remove = at91wdt_remove,
|
||||
.shutdown = at91wdt_shutdown,
|
||||
.suspend = at91wdt_suspend,
|
||||
.resume = at91wdt_resume,
|
||||
.suspend = pm_ptr(at91wdt_suspend),
|
||||
.resume = pm_ptr(at91wdt_resume),
|
||||
.driver = {
|
||||
.name = "atmel_st_watchdog",
|
||||
.of_match_table = at91_wdt_dt_ids,
|
||||
|
|
|
@ -105,7 +105,6 @@ static int db8500_wdt_probe(struct platform_device *pdev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
static int db8500_wdt_suspend(struct platform_device *pdev,
|
||||
pm_message_t state)
|
||||
{
|
||||
|
@ -130,15 +129,11 @@ static int db8500_wdt_resume(struct platform_device *pdev)
|
|||
}
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
#define db8500_wdt_suspend NULL
|
||||
#define db8500_wdt_resume NULL
|
||||
#endif
|
||||
|
||||
static struct platform_driver db8500_wdt_driver = {
|
||||
.probe = db8500_wdt_probe,
|
||||
.suspend = db8500_wdt_suspend,
|
||||
.resume = db8500_wdt_resume,
|
||||
.suspend = pm_ptr(db8500_wdt_suspend),
|
||||
.resume = pm_ptr(db8500_wdt_resume),
|
||||
.driver = {
|
||||
.name = "db8500_wdt",
|
||||
},
|
||||
|
|
|
@ -423,14 +423,18 @@ static unsigned int iTCO_wdt_get_timeleft(struct watchdog_device *wd_dev)
|
|||
return time_left;
|
||||
}
|
||||
|
||||
static void iTCO_wdt_set_running(struct iTCO_wdt_private *p)
|
||||
/* Returns true if the watchdog was running */
|
||||
static bool iTCO_wdt_set_running(struct iTCO_wdt_private *p)
|
||||
{
|
||||
u16 val;
|
||||
|
||||
/* Bit 11: TCO Timer Halt -> 0 = The TCO timer is * enabled */
|
||||
/* Bit 11: TCO Timer Halt -> 0 = The TCO timer is enabled */
|
||||
val = inw(TCO1_CNT(p));
|
||||
if (!(val & BIT(11)))
|
||||
if (!(val & BIT(11))) {
|
||||
set_bit(WDOG_HW_RUNNING, &p->wddev.status);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -518,9 +522,6 @@ static int iTCO_wdt_probe(struct platform_device *pdev)
|
|||
return -ENODEV; /* Cannot reset NO_REBOOT bit */
|
||||
}
|
||||
|
||||
/* Set the NO_REBOOT bit to prevent later reboots, just for sure */
|
||||
p->update_no_reboot_bit(p->no_reboot_priv, true);
|
||||
|
||||
if (turn_SMI_watchdog_clear_off >= p->iTCO_version) {
|
||||
/*
|
||||
* Bit 13: TCO_EN -> 0
|
||||
|
@ -572,7 +573,13 @@ static int iTCO_wdt_probe(struct platform_device *pdev)
|
|||
watchdog_set_drvdata(&p->wddev, p);
|
||||
platform_set_drvdata(pdev, p);
|
||||
|
||||
iTCO_wdt_set_running(p);
|
||||
if (!iTCO_wdt_set_running(p)) {
|
||||
/*
|
||||
* If the watchdog was not running set NO_REBOOT now to
|
||||
* prevent later reboots.
|
||||
*/
|
||||
p->update_no_reboot_bit(p->no_reboot_priv, true);
|
||||
}
|
||||
|
||||
/* Check that the heartbeat value is within it's range;
|
||||
if not reset to the default */
|
||||
|
|
|
@ -75,9 +75,7 @@ struct kempld_wdt_data {
|
|||
struct watchdog_device wdd;
|
||||
unsigned int pretimeout;
|
||||
struct kempld_wdt_stage stage[KEMPLD_WDT_MAX_STAGES];
|
||||
#ifdef CONFIG_PM
|
||||
u8 pm_status_store;
|
||||
#endif
|
||||
};
|
||||
|
||||
#define DEFAULT_TIMEOUT 30 /* seconds */
|
||||
|
@ -495,7 +493,6 @@ static int kempld_wdt_probe(struct platform_device *pdev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
/* Disable watchdog if it is active during suspend */
|
||||
static int kempld_wdt_suspend(struct platform_device *pdev,
|
||||
pm_message_t message)
|
||||
|
@ -531,18 +528,14 @@ static int kempld_wdt_resume(struct platform_device *pdev)
|
|||
else
|
||||
return kempld_wdt_stop(wdd);
|
||||
}
|
||||
#else
|
||||
#define kempld_wdt_suspend NULL
|
||||
#define kempld_wdt_resume NULL
|
||||
#endif
|
||||
|
||||
static struct platform_driver kempld_wdt_driver = {
|
||||
.driver = {
|
||||
.name = "kempld-wdt",
|
||||
},
|
||||
.probe = kempld_wdt_probe,
|
||||
.suspend = kempld_wdt_suspend,
|
||||
.resume = kempld_wdt_resume,
|
||||
.suspend = pm_ptr(kempld_wdt_suspend),
|
||||
.resume = pm_ptr(kempld_wdt_resume),
|
||||
};
|
||||
|
||||
module_platform_driver(kempld_wdt_driver);
|
||||
|
|
|
@ -10,9 +10,11 @@
|
|||
*/
|
||||
|
||||
#include <dt-bindings/reset/mt2712-resets.h>
|
||||
#include <dt-bindings/reset/mediatek,mt6795-resets.h>
|
||||
#include <dt-bindings/reset/mt7986-resets.h>
|
||||
#include <dt-bindings/reset/mt8183-resets.h>
|
||||
#include <dt-bindings/reset/mt8186-resets.h>
|
||||
#include <dt-bindings/reset/mt8188-resets.h>
|
||||
#include <dt-bindings/reset/mt8192-resets.h>
|
||||
#include <dt-bindings/reset/mt8195-resets.h>
|
||||
#include <linux/delay.h>
|
||||
|
@ -78,6 +80,10 @@ static const struct mtk_wdt_data mt2712_data = {
|
|||
.toprgu_sw_rst_num = MT2712_TOPRGU_SW_RST_NUM,
|
||||
};
|
||||
|
||||
static const struct mtk_wdt_data mt6795_data = {
|
||||
.toprgu_sw_rst_num = MT6795_TOPRGU_SW_RST_NUM,
|
||||
};
|
||||
|
||||
static const struct mtk_wdt_data mt7986_data = {
|
||||
.toprgu_sw_rst_num = MT7986_TOPRGU_SW_RST_NUM,
|
||||
};
|
||||
|
@ -90,6 +96,10 @@ static const struct mtk_wdt_data mt8186_data = {
|
|||
.toprgu_sw_rst_num = MT8186_TOPRGU_SW_RST_NUM,
|
||||
};
|
||||
|
||||
static const struct mtk_wdt_data mt8188_data = {
|
||||
.toprgu_sw_rst_num = MT8188_TOPRGU_SW_RST_NUM,
|
||||
};
|
||||
|
||||
static const struct mtk_wdt_data mt8192_data = {
|
||||
.toprgu_sw_rst_num = MT8192_TOPRGU_SW_RST_NUM,
|
||||
};
|
||||
|
@ -426,9 +436,11 @@ static int mtk_wdt_resume(struct device *dev)
|
|||
static const struct of_device_id mtk_wdt_dt_ids[] = {
|
||||
{ .compatible = "mediatek,mt2712-wdt", .data = &mt2712_data },
|
||||
{ .compatible = "mediatek,mt6589-wdt" },
|
||||
{ .compatible = "mediatek,mt6795-wdt", .data = &mt6795_data },
|
||||
{ .compatible = "mediatek,mt7986-wdt", .data = &mt7986_data },
|
||||
{ .compatible = "mediatek,mt8183-wdt", .data = &mt8183_data },
|
||||
{ .compatible = "mediatek,mt8186-wdt", .data = &mt8186_data },
|
||||
{ .compatible = "mediatek,mt8188-wdt", .data = &mt8188_data },
|
||||
{ .compatible = "mediatek,mt8192-wdt", .data = &mt8192_data },
|
||||
{ .compatible = "mediatek,mt8195-wdt", .data = &mt8195_data },
|
||||
{ /* sentinel */ }
|
||||
|
|
|
@ -316,8 +316,6 @@ static int omap_wdt_remove(struct platform_device *pdev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
|
||||
/* REVISIT ... not clear this is the best way to handle system suspend; and
|
||||
* it's very inappropriate for selective device suspend (e.g. suspending this
|
||||
* through sysfs rather than by stopping the watchdog daemon). Also, this
|
||||
|
@ -353,11 +351,6 @@ static int omap_wdt_resume(struct platform_device *pdev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
#else
|
||||
#define omap_wdt_suspend NULL
|
||||
#define omap_wdt_resume NULL
|
||||
#endif
|
||||
|
||||
static const struct of_device_id omap_wdt_of_match[] = {
|
||||
{ .compatible = "ti,omap3-wdt", },
|
||||
{},
|
||||
|
@ -368,8 +361,8 @@ static struct platform_driver omap_wdt_driver = {
|
|||
.probe = omap_wdt_probe,
|
||||
.remove = omap_wdt_remove,
|
||||
.shutdown = omap_wdt_shutdown,
|
||||
.suspend = omap_wdt_suspend,
|
||||
.resume = omap_wdt_resume,
|
||||
.suspend = pm_ptr(omap_wdt_suspend),
|
||||
.resume = pm_ptr(omap_wdt_resume),
|
||||
.driver = {
|
||||
.name = "omap_wdt",
|
||||
.of_match_table = omap_wdt_of_match,
|
||||
|
|
|
@ -144,6 +144,8 @@ static int rn5t618_wdt_probe(struct platform_device *pdev)
|
|||
struct rn5t618 *rn5t618 = dev_get_drvdata(dev->parent);
|
||||
struct rn5t618_wdt *wdt;
|
||||
int min_timeout, max_timeout;
|
||||
int ret;
|
||||
unsigned int val;
|
||||
|
||||
wdt = devm_kzalloc(dev, sizeof(struct rn5t618_wdt), GFP_KERNEL);
|
||||
if (!wdt)
|
||||
|
@ -160,6 +162,16 @@ static int rn5t618_wdt_probe(struct platform_device *pdev)
|
|||
wdt->wdt_dev.timeout = max_timeout;
|
||||
wdt->wdt_dev.parent = dev;
|
||||
|
||||
/* Read out previous power-off factor */
|
||||
ret = regmap_read(wdt->rn5t618->regmap, RN5T618_POFFHIS, &val);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (val & RN5T618_POFFHIS_VINDET)
|
||||
wdt->wdt_dev.bootstatus = WDIOF_POWERUNDER;
|
||||
else if (val & RN5T618_POFFHIS_WDG)
|
||||
wdt->wdt_dev.bootstatus = WDIOF_CARDRESET;
|
||||
|
||||
watchdog_set_drvdata(&wdt->wdt_dev, wdt);
|
||||
watchdog_init_timeout(&wdt->wdt_dev, timeout, dev);
|
||||
watchdog_set_nowayout(&wdt->wdt_dev, nowayout);
|
||||
|
|
|
@ -81,7 +81,6 @@ static int twl4030_wdt_probe(struct platform_device *pdev)
|
|||
return devm_watchdog_register_device(dev, wdt);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
static int twl4030_wdt_suspend(struct platform_device *pdev, pm_message_t state)
|
||||
{
|
||||
struct watchdog_device *wdt = platform_get_drvdata(pdev);
|
||||
|
@ -99,10 +98,6 @@ static int twl4030_wdt_resume(struct platform_device *pdev)
|
|||
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
#define twl4030_wdt_suspend NULL
|
||||
#define twl4030_wdt_resume NULL
|
||||
#endif
|
||||
|
||||
static const struct of_device_id twl_wdt_of_match[] = {
|
||||
{ .compatible = "ti,twl4030-wdt", },
|
||||
|
@ -112,8 +107,8 @@ MODULE_DEVICE_TABLE(of, twl_wdt_of_match);
|
|||
|
||||
static struct platform_driver twl4030_wdt_driver = {
|
||||
.probe = twl4030_wdt_probe,
|
||||
.suspend = twl4030_wdt_suspend,
|
||||
.resume = twl4030_wdt_resume,
|
||||
.suspend = pm_ptr(twl4030_wdt_suspend),
|
||||
.resume = pm_ptr(twl4030_wdt_resume),
|
||||
.driver = {
|
||||
.name = "twl4030_wdt",
|
||||
.of_match_table = twl_wdt_of_match,
|
||||
|
|
|
@ -427,8 +427,6 @@ static int stuffed_readpage(struct gfs2_inode *ip, struct page *page)
|
|||
return error;
|
||||
|
||||
kaddr = kmap_atomic(page);
|
||||
if (dsize > gfs2_max_stuffed_size(ip))
|
||||
dsize = gfs2_max_stuffed_size(ip);
|
||||
memcpy(kaddr, dibh->b_data + sizeof(struct gfs2_dinode), dsize);
|
||||
memset(kaddr + dsize, 0, PAGE_SIZE - dsize);
|
||||
kunmap_atomic(kaddr);
|
||||
|
|
|
@ -61,9 +61,6 @@ static int gfs2_unstuffer_page(struct gfs2_inode *ip, struct buffer_head *dibh,
|
|||
void *kaddr = kmap(page);
|
||||
u64 dsize = i_size_read(inode);
|
||||
|
||||
if (dsize > gfs2_max_stuffed_size(ip))
|
||||
dsize = gfs2_max_stuffed_size(ip);
|
||||
|
||||
memcpy(kaddr, dibh->b_data + sizeof(struct gfs2_dinode), dsize);
|
||||
memset(kaddr + dsize, 0, PAGE_SIZE - dsize);
|
||||
kunmap(page);
|
||||
|
|
|
@ -1445,14 +1445,13 @@ static int gfs2_lock(struct file *file, int cmd, struct file_lock *fl)
|
|||
|
||||
static void __flock_holder_uninit(struct file *file, struct gfs2_holder *fl_gh)
|
||||
{
|
||||
struct gfs2_glock *gl = fl_gh->gh_gl;
|
||||
struct gfs2_glock *gl = gfs2_glock_hold(fl_gh->gh_gl);
|
||||
|
||||
/*
|
||||
* Make sure gfs2_glock_put() won't sleep under the file->f_lock
|
||||
* spinlock.
|
||||
*/
|
||||
|
||||
gfs2_glock_hold(gl);
|
||||
spin_lock(&file->f_lock);
|
||||
gfs2_holder_uninit(fl_gh);
|
||||
spin_unlock(&file->f_lock);
|
||||
|
|
269
fs/gfs2/glock.c
269
fs/gfs2/glock.c
|
@ -186,10 +186,11 @@ void gfs2_glock_free(struct gfs2_glock *gl)
|
|||
*
|
||||
*/
|
||||
|
||||
void gfs2_glock_hold(struct gfs2_glock *gl)
|
||||
struct gfs2_glock *gfs2_glock_hold(struct gfs2_glock *gl)
|
||||
{
|
||||
GLOCK_BUG_ON(gl, __lockref_is_dead(&gl->gl_lockref));
|
||||
lockref_get(&gl->gl_lockref);
|
||||
return gl;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -205,12 +206,6 @@ static int demote_ok(const struct gfs2_glock *gl)
|
|||
|
||||
if (gl->gl_state == LM_ST_UNLOCKED)
|
||||
return 0;
|
||||
/*
|
||||
* Note that demote_ok is used for the lru process of disposing of
|
||||
* glocks. For this purpose, we don't care if the glock's holders
|
||||
* have the HIF_MAY_DEMOTE flag set or not. If someone is using
|
||||
* them, don't demote.
|
||||
*/
|
||||
if (!list_empty(&gl->gl_holders))
|
||||
return 0;
|
||||
if (glops->go_demote_ok)
|
||||
|
@ -393,7 +388,7 @@ static void do_error(struct gfs2_glock *gl, const int ret)
|
|||
struct gfs2_holder *gh, *tmp;
|
||||
|
||||
list_for_each_entry_safe(gh, tmp, &gl->gl_holders, gh_list) {
|
||||
if (!test_bit(HIF_WAIT, &gh->gh_iflags))
|
||||
if (test_bit(HIF_HOLDER, &gh->gh_iflags))
|
||||
continue;
|
||||
if (ret & LM_OUT_ERROR)
|
||||
gh->gh_error = -EIO;
|
||||
|
@ -407,45 +402,6 @@ static void do_error(struct gfs2_glock *gl, const int ret)
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* demote_incompat_holders - demote incompatible demoteable holders
|
||||
* @gl: the glock we want to promote
|
||||
* @current_gh: the newly promoted holder
|
||||
*
|
||||
* We're passing the newly promoted holder in @current_gh, but actually, any of
|
||||
* the strong holders would do.
|
||||
*/
|
||||
static void demote_incompat_holders(struct gfs2_glock *gl,
|
||||
struct gfs2_holder *current_gh)
|
||||
{
|
||||
struct gfs2_holder *gh, *tmp;
|
||||
|
||||
/*
|
||||
* Demote incompatible holders before we make ourselves eligible.
|
||||
* (This holder may or may not allow auto-demoting, but we don't want
|
||||
* to demote the new holder before it's even granted.)
|
||||
*/
|
||||
list_for_each_entry_safe(gh, tmp, &gl->gl_holders, gh_list) {
|
||||
/*
|
||||
* Since holders are at the front of the list, we stop when we
|
||||
* find the first non-holder.
|
||||
*/
|
||||
if (!test_bit(HIF_HOLDER, &gh->gh_iflags))
|
||||
return;
|
||||
if (gh == current_gh)
|
||||
continue;
|
||||
if (test_bit(HIF_MAY_DEMOTE, &gh->gh_iflags) &&
|
||||
!may_grant(gl, current_gh, gh)) {
|
||||
/*
|
||||
* We should not recurse into do_promote because
|
||||
* __gfs2_glock_dq only calls handle_callback,
|
||||
* gfs2_glock_add_to_lru and __gfs2_glock_queue_work.
|
||||
*/
|
||||
__gfs2_glock_dq(gh);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* find_first_holder - find the first "holder" gh
|
||||
* @gl: the glock
|
||||
|
@ -464,26 +420,6 @@ static inline struct gfs2_holder *find_first_holder(const struct gfs2_glock *gl)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* find_first_strong_holder - find the first non-demoteable holder
|
||||
* @gl: the glock
|
||||
*
|
||||
* Find the first holder that doesn't have the HIF_MAY_DEMOTE flag set.
|
||||
*/
|
||||
static inline struct gfs2_holder *
|
||||
find_first_strong_holder(struct gfs2_glock *gl)
|
||||
{
|
||||
struct gfs2_holder *gh;
|
||||
|
||||
list_for_each_entry(gh, &gl->gl_holders, gh_list) {
|
||||
if (!test_bit(HIF_HOLDER, &gh->gh_iflags))
|
||||
return NULL;
|
||||
if (!test_bit(HIF_MAY_DEMOTE, &gh->gh_iflags))
|
||||
return gh;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* gfs2_instantiate - Call the glops instantiate function
|
||||
* @gh: The glock holder
|
||||
|
@ -540,9 +476,8 @@ done:
|
|||
static int do_promote(struct gfs2_glock *gl)
|
||||
{
|
||||
struct gfs2_holder *gh, *current_gh;
|
||||
bool incompat_holders_demoted = false;
|
||||
|
||||
current_gh = find_first_strong_holder(gl);
|
||||
current_gh = find_first_holder(gl);
|
||||
list_for_each_entry(gh, &gl->gl_holders, gh_list) {
|
||||
if (test_bit(HIF_HOLDER, &gh->gh_iflags))
|
||||
continue;
|
||||
|
@ -561,11 +496,8 @@ static int do_promote(struct gfs2_glock *gl)
|
|||
set_bit(HIF_HOLDER, &gh->gh_iflags);
|
||||
trace_gfs2_promote(gh);
|
||||
gfs2_holder_wake(gh);
|
||||
if (!incompat_holders_demoted) {
|
||||
if (!current_gh)
|
||||
current_gh = gh;
|
||||
demote_incompat_holders(gl, current_gh);
|
||||
incompat_holders_demoted = true;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -927,6 +859,48 @@ out_unlock:
|
|||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* glock_set_object - set the gl_object field of a glock
|
||||
* @gl: the glock
|
||||
* @object: the object
|
||||
*/
|
||||
void glock_set_object(struct gfs2_glock *gl, void *object)
|
||||
{
|
||||
void *prev_object;
|
||||
|
||||
spin_lock(&gl->gl_lockref.lock);
|
||||
prev_object = gl->gl_object;
|
||||
gl->gl_object = object;
|
||||
spin_unlock(&gl->gl_lockref.lock);
|
||||
if (gfs2_assert_warn(gl->gl_name.ln_sbd, prev_object == NULL)) {
|
||||
pr_warn("glock=%u/%llx\n",
|
||||
gl->gl_name.ln_type,
|
||||
(unsigned long long)gl->gl_name.ln_number);
|
||||
gfs2_dump_glock(NULL, gl, true);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* glock_clear_object - clear the gl_object field of a glock
|
||||
* @gl: the glock
|
||||
*/
|
||||
void glock_clear_object(struct gfs2_glock *gl, void *object)
|
||||
{
|
||||
void *prev_object;
|
||||
|
||||
spin_lock(&gl->gl_lockref.lock);
|
||||
prev_object = gl->gl_object;
|
||||
gl->gl_object = NULL;
|
||||
spin_unlock(&gl->gl_lockref.lock);
|
||||
if (gfs2_assert_warn(gl->gl_name.ln_sbd,
|
||||
prev_object == object || prev_object == NULL)) {
|
||||
pr_warn("glock=%u/%llx\n",
|
||||
gl->gl_name.ln_type,
|
||||
(unsigned long long)gl->gl_name.ln_number);
|
||||
gfs2_dump_glock(NULL, gl, true);
|
||||
}
|
||||
}
|
||||
|
||||
void gfs2_inode_remember_delete(struct gfs2_glock *gl, u64 generation)
|
||||
{
|
||||
struct gfs2_inode_lvb *ri = (void *)gl->gl_lksb.sb_lvbptr;
|
||||
|
@ -980,8 +954,6 @@ static bool gfs2_try_evict(struct gfs2_glock *gl)
|
|||
ip = NULL;
|
||||
spin_unlock(&gl->gl_lockref.lock);
|
||||
if (ip) {
|
||||
struct gfs2_glock *inode_gl = NULL;
|
||||
|
||||
gl->gl_no_formal_ino = ip->i_no_formal_ino;
|
||||
set_bit(GIF_DEFERRED_DELETE, &ip->i_flags);
|
||||
d_prune_aliases(&ip->i_inode);
|
||||
|
@ -991,14 +963,14 @@ static bool gfs2_try_evict(struct gfs2_glock *gl)
|
|||
spin_lock(&gl->gl_lockref.lock);
|
||||
ip = gl->gl_object;
|
||||
if (ip) {
|
||||
inode_gl = ip->i_gl;
|
||||
lockref_get(&inode_gl->gl_lockref);
|
||||
clear_bit(GIF_DEFERRED_DELETE, &ip->i_flags);
|
||||
if (!igrab(&ip->i_inode))
|
||||
ip = NULL;
|
||||
}
|
||||
spin_unlock(&gl->gl_lockref.lock);
|
||||
if (inode_gl) {
|
||||
gfs2_glock_poke(inode_gl);
|
||||
gfs2_glock_put(inode_gl);
|
||||
if (ip) {
|
||||
gfs2_glock_poke(ip->i_gl);
|
||||
iput(&ip->i_inode);
|
||||
}
|
||||
evicted = !ip;
|
||||
}
|
||||
|
@ -1039,6 +1011,7 @@ static void delete_work_func(struct work_struct *work)
|
|||
if (gfs2_queue_delete_work(gl, 5 * HZ))
|
||||
return;
|
||||
}
|
||||
goto out;
|
||||
}
|
||||
|
||||
inode = gfs2_lookup_by_inum(sdp, no_addr, gl->gl_no_formal_ino,
|
||||
|
@ -1051,6 +1024,7 @@ static void delete_work_func(struct work_struct *work)
|
|||
d_prune_aliases(inode);
|
||||
iput(inode);
|
||||
}
|
||||
out:
|
||||
gfs2_glock_put(gl);
|
||||
}
|
||||
|
||||
|
@ -1256,13 +1230,12 @@ void __gfs2_holder_init(struct gfs2_glock *gl, unsigned int state, u16 flags,
|
|||
struct gfs2_holder *gh, unsigned long ip)
|
||||
{
|
||||
INIT_LIST_HEAD(&gh->gh_list);
|
||||
gh->gh_gl = gl;
|
||||
gh->gh_gl = gfs2_glock_hold(gl);
|
||||
gh->gh_ip = ip;
|
||||
gh->gh_owner_pid = get_pid(task_pid(current));
|
||||
gh->gh_state = state;
|
||||
gh->gh_flags = flags;
|
||||
gh->gh_iflags = 0;
|
||||
gfs2_glock_hold(gl);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1496,7 +1469,7 @@ __acquires(&gl->gl_lockref.lock)
|
|||
if (test_bit(GLF_LOCK, &gl->gl_flags)) {
|
||||
struct gfs2_holder *current_gh;
|
||||
|
||||
current_gh = find_first_strong_holder(gl);
|
||||
current_gh = find_first_holder(gl);
|
||||
try_futile = !may_grant(gl, current_gh, gh);
|
||||
}
|
||||
if (test_bit(GLF_INVALIDATE_IN_PROGRESS, &gl->gl_flags))
|
||||
|
@ -1508,8 +1481,6 @@ __acquires(&gl->gl_lockref.lock)
|
|||
continue;
|
||||
if (gh->gh_gl->gl_ops->go_type == LM_TYPE_FLOCK)
|
||||
continue;
|
||||
if (test_bit(HIF_MAY_DEMOTE, &gh2->gh_iflags))
|
||||
continue;
|
||||
if (!pid_is_meaningful(gh2))
|
||||
continue;
|
||||
goto trap_recursive;
|
||||
|
@ -1619,69 +1590,28 @@ static inline bool needs_demote(struct gfs2_glock *gl)
|
|||
static void __gfs2_glock_dq(struct gfs2_holder *gh)
|
||||
{
|
||||
struct gfs2_glock *gl = gh->gh_gl;
|
||||
struct gfs2_sbd *sdp = gl->gl_name.ln_sbd;
|
||||
unsigned delay = 0;
|
||||
int fast_path = 0;
|
||||
|
||||
/*
|
||||
* This while loop is similar to function demote_incompat_holders:
|
||||
* If the glock is due to be demoted (which may be from another node
|
||||
* or even if this holder is GL_NOCACHE), the weak holders are
|
||||
* demoted as well, allowing the glock to be demoted.
|
||||
* This holder should not be cached, so mark it for demote.
|
||||
* Note: this should be done before the check for needs_demote
|
||||
* below.
|
||||
*/
|
||||
while (gh) {
|
||||
/*
|
||||
* If we're in the process of file system withdraw, we cannot
|
||||
* just dequeue any glocks until our journal is recovered, lest
|
||||
* we introduce file system corruption. We need two exceptions
|
||||
* to this rule: We need to allow unlocking of nondisk glocks
|
||||
* and the glock for our own journal that needs recovery.
|
||||
*/
|
||||
if (test_bit(SDF_WITHDRAW_RECOVERY, &sdp->sd_flags) &&
|
||||
glock_blocked_by_withdraw(gl) &&
|
||||
gh->gh_gl != sdp->sd_jinode_gl) {
|
||||
sdp->sd_glock_dqs_held++;
|
||||
spin_unlock(&gl->gl_lockref.lock);
|
||||
might_sleep();
|
||||
wait_on_bit(&sdp->sd_flags, SDF_WITHDRAW_RECOVERY,
|
||||
TASK_UNINTERRUPTIBLE);
|
||||
spin_lock(&gl->gl_lockref.lock);
|
||||
}
|
||||
if (gh->gh_flags & GL_NOCACHE)
|
||||
handle_callback(gl, LM_ST_UNLOCKED, 0, false);
|
||||
|
||||
/*
|
||||
* This holder should not be cached, so mark it for demote.
|
||||
* Note: this should be done before the check for needs_demote
|
||||
* below.
|
||||
*/
|
||||
if (gh->gh_flags & GL_NOCACHE)
|
||||
handle_callback(gl, LM_ST_UNLOCKED, 0, false);
|
||||
list_del_init(&gh->gh_list);
|
||||
clear_bit(HIF_HOLDER, &gh->gh_iflags);
|
||||
trace_gfs2_glock_queue(gh, 0);
|
||||
|
||||
list_del_init(&gh->gh_list);
|
||||
clear_bit(HIF_HOLDER, &gh->gh_iflags);
|
||||
trace_gfs2_glock_queue(gh, 0);
|
||||
|
||||
/*
|
||||
* If there hasn't been a demote request we are done.
|
||||
* (Let the remaining holders, if any, keep holding it.)
|
||||
*/
|
||||
if (!needs_demote(gl)) {
|
||||
if (list_empty(&gl->gl_holders))
|
||||
fast_path = 1;
|
||||
break;
|
||||
}
|
||||
/*
|
||||
* If we have another strong holder (we cannot auto-demote)
|
||||
* we are done. It keeps holding it until it is done.
|
||||
*/
|
||||
if (find_first_strong_holder(gl))
|
||||
break;
|
||||
|
||||
/*
|
||||
* If we have a weak holder at the head of the list, it
|
||||
* (and all others like it) must be auto-demoted. If there
|
||||
* are no more weak holders, we exit the while loop.
|
||||
*/
|
||||
gh = find_first_holder(gl);
|
||||
/*
|
||||
* If there hasn't been a demote request we are done.
|
||||
* (Let the remaining holders, if any, keep holding it.)
|
||||
*/
|
||||
if (!needs_demote(gl)) {
|
||||
if (list_empty(&gl->gl_holders))
|
||||
fast_path = 1;
|
||||
}
|
||||
|
||||
if (!test_bit(GLF_LFLUSH, &gl->gl_flags) && demote_ok(gl))
|
||||
|
@ -1705,8 +1635,17 @@ static void __gfs2_glock_dq(struct gfs2_holder *gh)
|
|||
void gfs2_glock_dq(struct gfs2_holder *gh)
|
||||
{
|
||||
struct gfs2_glock *gl = gh->gh_gl;
|
||||
struct gfs2_sbd *sdp = gl->gl_name.ln_sbd;
|
||||
|
||||
spin_lock(&gl->gl_lockref.lock);
|
||||
if (!gfs2_holder_queued(gh)) {
|
||||
/*
|
||||
* May have already been dequeued because the locking request
|
||||
* was GL_ASYNC and it has failed in the meantime.
|
||||
*/
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (list_is_first(&gh->gh_list, &gl->gl_holders) &&
|
||||
!test_bit(HIF_HOLDER, &gh->gh_iflags)) {
|
||||
spin_unlock(&gl->gl_lockref.lock);
|
||||
|
@ -1715,7 +1654,26 @@ void gfs2_glock_dq(struct gfs2_holder *gh)
|
|||
spin_lock(&gl->gl_lockref.lock);
|
||||
}
|
||||
|
||||
/*
|
||||
* If we're in the process of file system withdraw, we cannot just
|
||||
* dequeue any glocks until our journal is recovered, lest we introduce
|
||||
* file system corruption. We need two exceptions to this rule: We need
|
||||
* to allow unlocking of nondisk glocks and the glock for our own
|
||||
* journal that needs recovery.
|
||||
*/
|
||||
if (test_bit(SDF_WITHDRAW_RECOVERY, &sdp->sd_flags) &&
|
||||
glock_blocked_by_withdraw(gl) &&
|
||||
gh->gh_gl != sdp->sd_jinode_gl) {
|
||||
sdp->sd_glock_dqs_held++;
|
||||
spin_unlock(&gl->gl_lockref.lock);
|
||||
might_sleep();
|
||||
wait_on_bit(&sdp->sd_flags, SDF_WITHDRAW_RECOVERY,
|
||||
TASK_UNINTERRUPTIBLE);
|
||||
spin_lock(&gl->gl_lockref.lock);
|
||||
}
|
||||
|
||||
__gfs2_glock_dq(gh);
|
||||
out:
|
||||
spin_unlock(&gl->gl_lockref.lock);
|
||||
}
|
||||
|
||||
|
@ -1888,33 +1846,6 @@ void gfs2_glock_cb(struct gfs2_glock *gl, unsigned int state)
|
|||
if (test_bit(GLF_REPLY_PENDING, &gl->gl_flags))
|
||||
delay = gl->gl_hold_time;
|
||||
}
|
||||
/*
|
||||
* Note 1: We cannot call demote_incompat_holders from handle_callback
|
||||
* or gfs2_set_demote due to recursion problems like: gfs2_glock_dq ->
|
||||
* handle_callback -> demote_incompat_holders -> gfs2_glock_dq
|
||||
* Plus, we only want to demote the holders if the request comes from
|
||||
* a remote cluster node because local holder conflicts are resolved
|
||||
* elsewhere.
|
||||
*
|
||||
* Note 2: if a remote node wants this glock in EX mode, lock_dlm will
|
||||
* request that we set our state to UNLOCKED. Here we mock up a holder
|
||||
* to make it look like someone wants the lock EX locally. Any SH
|
||||
* and DF requests should be able to share the lock without demoting.
|
||||
*
|
||||
* Note 3: We only want to demote the demoteable holders when there
|
||||
* are no more strong holders. The demoteable holders might as well
|
||||
* keep the glock until the last strong holder is done with it.
|
||||
*/
|
||||
if (!find_first_strong_holder(gl)) {
|
||||
struct gfs2_holder mock_gh = {
|
||||
.gh_gl = gl,
|
||||
.gh_state = (state == LM_ST_UNLOCKED) ?
|
||||
LM_ST_EXCLUSIVE : state,
|
||||
.gh_iflags = BIT(HIF_HOLDER)
|
||||
};
|
||||
|
||||
demote_incompat_holders(gl, &mock_gh);
|
||||
}
|
||||
handle_callback(gl, state, delay, true);
|
||||
__gfs2_glock_queue_work(gl, delay);
|
||||
spin_unlock(&gl->gl_lockref.lock);
|
||||
|
@ -2306,8 +2237,6 @@ static const char *hflags2str(char *buf, u16 flags, unsigned long iflags)
|
|||
*p++ = 'H';
|
||||
if (test_bit(HIF_WAIT, &iflags))
|
||||
*p++ = 'W';
|
||||
if (test_bit(HIF_MAY_DEMOTE, &iflags))
|
||||
*p++ = 'D';
|
||||
if (flags & GL_SKIP)
|
||||
*p++ = 's';
|
||||
*p = 0;
|
||||
|
|
|
@ -156,8 +156,6 @@ static inline struct gfs2_holder *gfs2_glock_is_locked_by_me(struct gfs2_glock *
|
|||
list_for_each_entry(gh, &gl->gl_holders, gh_list) {
|
||||
if (!test_bit(HIF_HOLDER, &gh->gh_iflags))
|
||||
break;
|
||||
if (test_bit(HIF_MAY_DEMOTE, &gh->gh_iflags))
|
||||
continue;
|
||||
if (gh->gh_owner_pid == pid)
|
||||
goto out;
|
||||
}
|
||||
|
@ -196,7 +194,7 @@ static inline struct address_space *gfs2_glock2aspace(struct gfs2_glock *gl)
|
|||
extern int gfs2_glock_get(struct gfs2_sbd *sdp, u64 number,
|
||||
const struct gfs2_glock_operations *glops,
|
||||
int create, struct gfs2_glock **glp);
|
||||
extern void gfs2_glock_hold(struct gfs2_glock *gl);
|
||||
extern struct gfs2_glock *gfs2_glock_hold(struct gfs2_glock *gl);
|
||||
extern void gfs2_glock_put(struct gfs2_glock *gl);
|
||||
extern void gfs2_glock_queue_put(struct gfs2_glock *gl);
|
||||
|
||||
|
@ -288,6 +286,9 @@ extern void gfs2_delete_debugfs_file(struct gfs2_sbd *sdp);
|
|||
extern void gfs2_register_debugfs(void);
|
||||
extern void gfs2_unregister_debugfs(void);
|
||||
|
||||
extern void glock_set_object(struct gfs2_glock *gl, void *object);
|
||||
extern void glock_clear_object(struct gfs2_glock *gl, void *object);
|
||||
|
||||
extern const struct lm_lockops gfs2_dlm_ops;
|
||||
|
||||
static inline void gfs2_holder_mark_uninitialized(struct gfs2_holder *gh)
|
||||
|
@ -305,64 +306,6 @@ static inline bool gfs2_holder_queued(struct gfs2_holder *gh)
|
|||
return !list_empty(&gh->gh_list);
|
||||
}
|
||||
|
||||
/**
|
||||
* glock_set_object - set the gl_object field of a glock
|
||||
* @gl: the glock
|
||||
* @object: the object
|
||||
*/
|
||||
static inline void glock_set_object(struct gfs2_glock *gl, void *object)
|
||||
{
|
||||
spin_lock(&gl->gl_lockref.lock);
|
||||
if (gfs2_assert_warn(gl->gl_name.ln_sbd, gl->gl_object == NULL))
|
||||
gfs2_dump_glock(NULL, gl, true);
|
||||
gl->gl_object = object;
|
||||
spin_unlock(&gl->gl_lockref.lock);
|
||||
}
|
||||
|
||||
/**
|
||||
* glock_clear_object - clear the gl_object field of a glock
|
||||
* @gl: the glock
|
||||
* @object: the object
|
||||
*
|
||||
* I'd love to similarly add this:
|
||||
* else if (gfs2_assert_warn(gl->gl_sbd, gl->gl_object == object))
|
||||
* gfs2_dump_glock(NULL, gl, true);
|
||||
* Unfortunately, that's not possible because as soon as gfs2_delete_inode
|
||||
* frees the block in the rgrp, another process can reassign it for an I_NEW
|
||||
* inode in gfs2_create_inode because that calls new_inode, not gfs2_iget.
|
||||
* That means gfs2_delete_inode may subsequently try to call this function
|
||||
* for a glock that's already pointing to a brand new inode. If we clear the
|
||||
* new inode's gl_object, we'll introduce metadata corruption. Function
|
||||
* gfs2_delete_inode calls clear_inode which calls gfs2_clear_inode which also
|
||||
* tries to clear gl_object, so it's more than just gfs2_delete_inode.
|
||||
*
|
||||
*/
|
||||
static inline void glock_clear_object(struct gfs2_glock *gl, void *object)
|
||||
{
|
||||
spin_lock(&gl->gl_lockref.lock);
|
||||
if (gl->gl_object == object)
|
||||
gl->gl_object = NULL;
|
||||
spin_unlock(&gl->gl_lockref.lock);
|
||||
}
|
||||
|
||||
static inline void gfs2_holder_allow_demote(struct gfs2_holder *gh)
|
||||
{
|
||||
struct gfs2_glock *gl = gh->gh_gl;
|
||||
|
||||
spin_lock(&gl->gl_lockref.lock);
|
||||
set_bit(HIF_MAY_DEMOTE, &gh->gh_iflags);
|
||||
spin_unlock(&gl->gl_lockref.lock);
|
||||
}
|
||||
|
||||
static inline void gfs2_holder_disallow_demote(struct gfs2_holder *gh)
|
||||
{
|
||||
struct gfs2_glock *gl = gh->gh_gl;
|
||||
|
||||
spin_lock(&gl->gl_lockref.lock);
|
||||
clear_bit(HIF_MAY_DEMOTE, &gh->gh_iflags);
|
||||
spin_unlock(&gl->gl_lockref.lock);
|
||||
}
|
||||
|
||||
extern void gfs2_inode_remember_delete(struct gfs2_glock *gl, u64 generation);
|
||||
extern bool gfs2_inode_already_deleted(struct gfs2_glock *gl, u64 generation);
|
||||
|
||||
|
|
|
@ -397,38 +397,39 @@ static int gfs2_dinode_in(struct gfs2_inode *ip, const void *buf)
|
|||
struct timespec64 atime;
|
||||
u16 height, depth;
|
||||
umode_t mode = be32_to_cpu(str->di_mode);
|
||||
bool is_new = ip->i_inode.i_state & I_NEW;
|
||||
struct inode *inode = &ip->i_inode;
|
||||
bool is_new = inode->i_state & I_NEW;
|
||||
|
||||
if (unlikely(ip->i_no_addr != be64_to_cpu(str->di_num.no_addr)))
|
||||
goto corrupt;
|
||||
if (unlikely(!is_new && inode_wrong_type(&ip->i_inode, mode)))
|
||||
if (unlikely(!is_new && inode_wrong_type(inode, mode)))
|
||||
goto corrupt;
|
||||
ip->i_no_formal_ino = be64_to_cpu(str->di_num.no_formal_ino);
|
||||
ip->i_inode.i_mode = mode;
|
||||
inode->i_mode = mode;
|
||||
if (is_new) {
|
||||
ip->i_inode.i_rdev = 0;
|
||||
inode->i_rdev = 0;
|
||||
switch (mode & S_IFMT) {
|
||||
case S_IFBLK:
|
||||
case S_IFCHR:
|
||||
ip->i_inode.i_rdev = MKDEV(be32_to_cpu(str->di_major),
|
||||
be32_to_cpu(str->di_minor));
|
||||
inode->i_rdev = MKDEV(be32_to_cpu(str->di_major),
|
||||
be32_to_cpu(str->di_minor));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
i_uid_write(&ip->i_inode, be32_to_cpu(str->di_uid));
|
||||
i_gid_write(&ip->i_inode, be32_to_cpu(str->di_gid));
|
||||
set_nlink(&ip->i_inode, be32_to_cpu(str->di_nlink));
|
||||
i_size_write(&ip->i_inode, be64_to_cpu(str->di_size));
|
||||
gfs2_set_inode_blocks(&ip->i_inode, be64_to_cpu(str->di_blocks));
|
||||
i_uid_write(inode, be32_to_cpu(str->di_uid));
|
||||
i_gid_write(inode, be32_to_cpu(str->di_gid));
|
||||
set_nlink(inode, be32_to_cpu(str->di_nlink));
|
||||
i_size_write(inode, be64_to_cpu(str->di_size));
|
||||
gfs2_set_inode_blocks(inode, be64_to_cpu(str->di_blocks));
|
||||
atime.tv_sec = be64_to_cpu(str->di_atime);
|
||||
atime.tv_nsec = be32_to_cpu(str->di_atime_nsec);
|
||||
if (timespec64_compare(&ip->i_inode.i_atime, &atime) < 0)
|
||||
ip->i_inode.i_atime = atime;
|
||||
ip->i_inode.i_mtime.tv_sec = be64_to_cpu(str->di_mtime);
|
||||
ip->i_inode.i_mtime.tv_nsec = be32_to_cpu(str->di_mtime_nsec);
|
||||
ip->i_inode.i_ctime.tv_sec = be64_to_cpu(str->di_ctime);
|
||||
ip->i_inode.i_ctime.tv_nsec = be32_to_cpu(str->di_ctime_nsec);
|
||||
if (timespec64_compare(&inode->i_atime, &atime) < 0)
|
||||
inode->i_atime = atime;
|
||||
inode->i_mtime.tv_sec = be64_to_cpu(str->di_mtime);
|
||||
inode->i_mtime.tv_nsec = be32_to_cpu(str->di_mtime_nsec);
|
||||
inode->i_ctime.tv_sec = be64_to_cpu(str->di_ctime);
|
||||
inode->i_ctime.tv_nsec = be32_to_cpu(str->di_ctime_nsec);
|
||||
|
||||
ip->i_goal = be64_to_cpu(str->di_goal_meta);
|
||||
ip->i_generation = be64_to_cpu(str->di_generation);
|
||||
|
@ -436,7 +437,7 @@ static int gfs2_dinode_in(struct gfs2_inode *ip, const void *buf)
|
|||
ip->i_diskflags = be32_to_cpu(str->di_flags);
|
||||
ip->i_eattr = be64_to_cpu(str->di_eattr);
|
||||
/* i_diskflags and i_eattr must be set before gfs2_set_inode_flags() */
|
||||
gfs2_set_inode_flags(&ip->i_inode);
|
||||
gfs2_set_inode_flags(inode);
|
||||
height = be16_to_cpu(str->di_height);
|
||||
if (unlikely(height > GFS2_MAX_META_HEIGHT))
|
||||
goto corrupt;
|
||||
|
@ -448,8 +449,11 @@ static int gfs2_dinode_in(struct gfs2_inode *ip, const void *buf)
|
|||
ip->i_depth = (u8)depth;
|
||||
ip->i_entries = be32_to_cpu(str->di_entries);
|
||||
|
||||
if (S_ISREG(ip->i_inode.i_mode))
|
||||
gfs2_set_aops(&ip->i_inode);
|
||||
if (gfs2_is_stuffed(ip) && inode->i_size > gfs2_max_stuffed_size(ip))
|
||||
goto corrupt;
|
||||
|
||||
if (S_ISREG(inode->i_mode))
|
||||
gfs2_set_aops(inode);
|
||||
|
||||
return 0;
|
||||
corrupt:
|
||||
|
|
|
@ -252,7 +252,6 @@ struct gfs2_lkstats {
|
|||
|
||||
enum {
|
||||
/* States */
|
||||
HIF_MAY_DEMOTE = 1,
|
||||
HIF_HOLDER = 6, /* Set for gh that "holds" the glock */
|
||||
HIF_WAIT = 10,
|
||||
};
|
||||
|
|
|
@ -142,6 +142,11 @@ struct inode *gfs2_inode_lookup(struct super_block *sb, unsigned int type,
|
|||
if (unlikely(error))
|
||||
goto fail;
|
||||
|
||||
/*
|
||||
* The only caller that sets @blktype to GFS2_BLKST_UNLINKED is
|
||||
* delete_work_func(). Make sure not to cancel the delete work
|
||||
* from within itself here.
|
||||
*/
|
||||
if (blktype == GFS2_BLKST_UNLINKED)
|
||||
extra_flags |= LM_FLAG_TRY;
|
||||
else
|
||||
|
@ -403,12 +408,17 @@ static int alloc_dinode(struct gfs2_inode *ip, u32 flags, unsigned *dblocks)
|
|||
goto out_ipreserv;
|
||||
|
||||
error = gfs2_alloc_blocks(ip, &ip->i_no_addr, dblocks, 1, &ip->i_generation);
|
||||
if (error)
|
||||
goto out_trans_end;
|
||||
|
||||
ip->i_no_formal_ino = ip->i_generation;
|
||||
ip->i_inode.i_ino = ip->i_no_addr;
|
||||
ip->i_goal = ip->i_no_addr;
|
||||
if (*dblocks > 1)
|
||||
ip->i_eattr = ip->i_no_addr + 1;
|
||||
|
||||
out_trans_end:
|
||||
gfs2_trans_end(sdp);
|
||||
|
||||
out_ipreserv:
|
||||
gfs2_inplace_release(ip);
|
||||
out_quota:
|
||||
|
@ -586,6 +596,12 @@ static int gfs2_initxattrs(struct inode *inode, const struct xattr *xattr_array,
|
|||
* @size: The initial size of the inode (ignored for directories)
|
||||
* @excl: Force fail if inode exists
|
||||
*
|
||||
* FIXME: Change to allocate the disk blocks and write them out in the same
|
||||
* transaction. That way, we can no longer end up in a situation in which an
|
||||
* inode is allocated, the node crashes, and the block looks like a valid
|
||||
* inode. (With atomic creates in place, we will also no longer need to zero
|
||||
* the link count and dirty the inode here on failure.)
|
||||
*
|
||||
* Returns: 0 on success, or error code
|
||||
*/
|
||||
|
||||
|
@ -596,12 +612,12 @@ static int gfs2_create_inode(struct inode *dir, struct dentry *dentry,
|
|||
{
|
||||
const struct qstr *name = &dentry->d_name;
|
||||
struct posix_acl *default_acl, *acl;
|
||||
struct gfs2_holder ghs[2];
|
||||
struct gfs2_holder d_gh, gh;
|
||||
struct inode *inode = NULL;
|
||||
struct gfs2_inode *dip = GFS2_I(dir), *ip;
|
||||
struct gfs2_sbd *sdp = GFS2_SB(&dip->i_inode);
|
||||
struct gfs2_glock *io_gl;
|
||||
int error, free_vfs_inode = 1;
|
||||
int error;
|
||||
u32 aflags = 0;
|
||||
unsigned blocks = 1;
|
||||
struct gfs2_diradd da = { .bh = NULL, .save_loc = 1, };
|
||||
|
@ -617,10 +633,10 @@ static int gfs2_create_inode(struct inode *dir, struct dentry *dentry,
|
|||
if (error)
|
||||
goto fail;
|
||||
|
||||
error = gfs2_glock_nq_init(dip->i_gl, LM_ST_EXCLUSIVE, 0, ghs);
|
||||
error = gfs2_glock_nq_init(dip->i_gl, LM_ST_EXCLUSIVE, 0, &d_gh);
|
||||
if (error)
|
||||
goto fail;
|
||||
gfs2_holder_mark_uninitialized(ghs + 1);
|
||||
gfs2_holder_mark_uninitialized(&gh);
|
||||
|
||||
error = create_ok(dip, name, mode);
|
||||
if (error)
|
||||
|
@ -642,7 +658,7 @@ static int gfs2_create_inode(struct inode *dir, struct dentry *dentry,
|
|||
else
|
||||
error = finish_no_open(file, NULL);
|
||||
}
|
||||
gfs2_glock_dq_uninit(ghs);
|
||||
gfs2_glock_dq_uninit(&d_gh);
|
||||
goto fail;
|
||||
} else if (error != -ENOENT) {
|
||||
goto fail_gunlock;
|
||||
|
@ -656,12 +672,12 @@ static int gfs2_create_inode(struct inode *dir, struct dentry *dentry,
|
|||
error = -ENOMEM;
|
||||
if (!inode)
|
||||
goto fail_gunlock;
|
||||
ip = GFS2_I(inode);
|
||||
|
||||
error = posix_acl_create(dir, &mode, &default_acl, &acl);
|
||||
if (error)
|
||||
goto fail_gunlock;
|
||||
|
||||
ip = GFS2_I(inode);
|
||||
error = gfs2_qa_get(ip);
|
||||
if (error)
|
||||
goto fail_free_acls;
|
||||
|
@ -723,15 +739,19 @@ static int gfs2_create_inode(struct inode *dir, struct dentry *dentry,
|
|||
goto fail_free_inode;
|
||||
gfs2_cancel_delete_work(io_gl);
|
||||
|
||||
retry:
|
||||
error = insert_inode_locked4(inode, ip->i_no_addr, iget_test, &ip->i_no_addr);
|
||||
BUG_ON(error);
|
||||
if (error == -EBUSY)
|
||||
goto retry;
|
||||
if (error)
|
||||
goto fail_gunlock2;
|
||||
|
||||
error = gfs2_glock_nq_init(io_gl, LM_ST_SHARED, GL_EXACT | GL_NOPID,
|
||||
&ip->i_iopen_gh);
|
||||
if (error)
|
||||
goto fail_gunlock2;
|
||||
|
||||
error = gfs2_glock_nq_init(ip->i_gl, LM_ST_EXCLUSIVE, GL_SKIP, ghs + 1);
|
||||
error = gfs2_glock_nq_init(ip->i_gl, LM_ST_EXCLUSIVE, GL_SKIP, &gh);
|
||||
if (error)
|
||||
goto fail_gunlock3;
|
||||
|
||||
|
@ -739,10 +759,8 @@ static int gfs2_create_inode(struct inode *dir, struct dentry *dentry,
|
|||
if (error)
|
||||
goto fail_gunlock3;
|
||||
|
||||
if (blocks > 1) {
|
||||
ip->i_eattr = ip->i_no_addr + 1;
|
||||
if (blocks > 1)
|
||||
gfs2_init_xattr(ip);
|
||||
}
|
||||
init_dinode(dip, ip, symname);
|
||||
gfs2_trans_end(sdp);
|
||||
|
||||
|
@ -750,9 +768,6 @@ static int gfs2_create_inode(struct inode *dir, struct dentry *dentry,
|
|||
glock_set_object(io_gl, ip);
|
||||
gfs2_set_iop(inode);
|
||||
|
||||
free_vfs_inode = 0; /* After this point, the inode is no longer
|
||||
considered free. Any failures need to undo
|
||||
the gfs2 structures. */
|
||||
if (default_acl) {
|
||||
error = __gfs2_set_acl(inode, default_acl, ACL_TYPE_DEFAULT);
|
||||
if (error)
|
||||
|
@ -785,9 +800,9 @@ static int gfs2_create_inode(struct inode *dir, struct dentry *dentry,
|
|||
file->f_mode |= FMODE_CREATED;
|
||||
error = finish_open(file, dentry, gfs2_open_common);
|
||||
}
|
||||
gfs2_glock_dq_uninit(ghs);
|
||||
gfs2_glock_dq_uninit(&d_gh);
|
||||
gfs2_qa_put(ip);
|
||||
gfs2_glock_dq_uninit(ghs + 1);
|
||||
gfs2_glock_dq_uninit(&gh);
|
||||
gfs2_glock_put(io_gl);
|
||||
gfs2_qa_put(dip);
|
||||
unlock_new_inode(inode);
|
||||
|
@ -801,10 +816,6 @@ fail_gunlock3:
|
|||
fail_gunlock2:
|
||||
gfs2_glock_put(io_gl);
|
||||
fail_free_inode:
|
||||
if (ip->i_gl) {
|
||||
if (free_vfs_inode) /* else evict will do the put for us */
|
||||
gfs2_glock_put(ip->i_gl);
|
||||
}
|
||||
gfs2_rs_deltree(&ip->i_res);
|
||||
gfs2_qa_put(ip);
|
||||
fail_free_acls:
|
||||
|
@ -812,20 +823,19 @@ fail_free_acls:
|
|||
posix_acl_release(acl);
|
||||
fail_gunlock:
|
||||
gfs2_dir_no_add(&da);
|
||||
gfs2_glock_dq_uninit(ghs);
|
||||
gfs2_glock_dq_uninit(&d_gh);
|
||||
if (!IS_ERR_OR_NULL(inode)) {
|
||||
set_bit(GIF_ALLOC_FAILED, &ip->i_flags);
|
||||
clear_nlink(inode);
|
||||
if (!free_vfs_inode)
|
||||
if (ip->i_no_addr)
|
||||
mark_inode_dirty(inode);
|
||||
set_bit(free_vfs_inode ? GIF_FREE_VFS_INODE : GIF_ALLOC_FAILED,
|
||||
&GFS2_I(inode)->i_flags);
|
||||
if (inode->i_state & I_NEW)
|
||||
iget_failed(inode);
|
||||
else
|
||||
iput(inode);
|
||||
}
|
||||
if (gfs2_holder_initialized(ghs + 1))
|
||||
gfs2_glock_dq_uninit(ghs + 1);
|
||||
if (gfs2_holder_initialized(&gh))
|
||||
gfs2_glock_dq_uninit(&gh);
|
||||
fail:
|
||||
gfs2_qa_put(dip);
|
||||
return error;
|
||||
|
|
|
@ -442,6 +442,12 @@ void gfs2_journal_wipe(struct gfs2_inode *ip, u64 bstart, u32 blen)
|
|||
struct buffer_head *bh;
|
||||
int ty;
|
||||
|
||||
if (!ip->i_gl) {
|
||||
/* This can only happen during incomplete inode creation. */
|
||||
BUG_ON(!test_bit(GIF_ALLOC_FAILED, &ip->i_flags));
|
||||
return;
|
||||
}
|
||||
|
||||
gfs2_ail1_wipe(sdp, bstart, blen);
|
||||
while (blen) {
|
||||
ty = REMOVE_META;
|
||||
|
|
|
@ -379,6 +379,7 @@ out:
|
|||
|
||||
void gfs2_dinode_out(const struct gfs2_inode *ip, void *buf)
|
||||
{
|
||||
const struct inode *inode = &ip->i_inode;
|
||||
struct gfs2_dinode *str = buf;
|
||||
|
||||
str->di_header.mh_magic = cpu_to_be32(GFS2_MAGIC);
|
||||
|
@ -386,15 +387,15 @@ void gfs2_dinode_out(const struct gfs2_inode *ip, void *buf)
|
|||
str->di_header.mh_format = cpu_to_be32(GFS2_FORMAT_DI);
|
||||
str->di_num.no_addr = cpu_to_be64(ip->i_no_addr);
|
||||
str->di_num.no_formal_ino = cpu_to_be64(ip->i_no_formal_ino);
|
||||
str->di_mode = cpu_to_be32(ip->i_inode.i_mode);
|
||||
str->di_uid = cpu_to_be32(i_uid_read(&ip->i_inode));
|
||||
str->di_gid = cpu_to_be32(i_gid_read(&ip->i_inode));
|
||||
str->di_nlink = cpu_to_be32(ip->i_inode.i_nlink);
|
||||
str->di_size = cpu_to_be64(i_size_read(&ip->i_inode));
|
||||
str->di_blocks = cpu_to_be64(gfs2_get_inode_blocks(&ip->i_inode));
|
||||
str->di_atime = cpu_to_be64(ip->i_inode.i_atime.tv_sec);
|
||||
str->di_mtime = cpu_to_be64(ip->i_inode.i_mtime.tv_sec);
|
||||
str->di_ctime = cpu_to_be64(ip->i_inode.i_ctime.tv_sec);
|
||||
str->di_mode = cpu_to_be32(inode->i_mode);
|
||||
str->di_uid = cpu_to_be32(i_uid_read(inode));
|
||||
str->di_gid = cpu_to_be32(i_gid_read(inode));
|
||||
str->di_nlink = cpu_to_be32(inode->i_nlink);
|
||||
str->di_size = cpu_to_be64(i_size_read(inode));
|
||||
str->di_blocks = cpu_to_be64(gfs2_get_inode_blocks(inode));
|
||||
str->di_atime = cpu_to_be64(inode->i_atime.tv_sec);
|
||||
str->di_mtime = cpu_to_be64(inode->i_mtime.tv_sec);
|
||||
str->di_ctime = cpu_to_be64(inode->i_ctime.tv_sec);
|
||||
|
||||
str->di_goal_meta = cpu_to_be64(ip->i_goal);
|
||||
str->di_goal_data = cpu_to_be64(ip->i_goal);
|
||||
|
@ -402,16 +403,16 @@ void gfs2_dinode_out(const struct gfs2_inode *ip, void *buf)
|
|||
|
||||
str->di_flags = cpu_to_be32(ip->i_diskflags);
|
||||
str->di_height = cpu_to_be16(ip->i_height);
|
||||
str->di_payload_format = cpu_to_be32(S_ISDIR(ip->i_inode.i_mode) &&
|
||||
str->di_payload_format = cpu_to_be32(S_ISDIR(inode->i_mode) &&
|
||||
!(ip->i_diskflags & GFS2_DIF_EXHASH) ?
|
||||
GFS2_FORMAT_DE : 0);
|
||||
str->di_depth = cpu_to_be16(ip->i_depth);
|
||||
str->di_entries = cpu_to_be32(ip->i_entries);
|
||||
|
||||
str->di_eattr = cpu_to_be64(ip->i_eattr);
|
||||
str->di_atime_nsec = cpu_to_be32(ip->i_inode.i_atime.tv_nsec);
|
||||
str->di_mtime_nsec = cpu_to_be32(ip->i_inode.i_mtime.tv_nsec);
|
||||
str->di_ctime_nsec = cpu_to_be32(ip->i_inode.i_ctime.tv_nsec);
|
||||
str->di_atime_nsec = cpu_to_be32(inode->i_atime.tv_nsec);
|
||||
str->di_mtime_nsec = cpu_to_be32(inode->i_mtime.tv_nsec);
|
||||
str->di_ctime_nsec = cpu_to_be32(inode->i_ctime.tv_nsec);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -475,6 +476,12 @@ static void gfs2_dirty_inode(struct inode *inode, int flags)
|
|||
int need_endtrans = 0;
|
||||
int ret;
|
||||
|
||||
if (unlikely(!ip->i_gl)) {
|
||||
/* This can only happen during incomplete inode creation. */
|
||||
BUG_ON(!test_bit(GIF_ALLOC_FAILED, &ip->i_flags));
|
||||
return;
|
||||
}
|
||||
|
||||
if (unlikely(gfs2_withdrawn(sdp)))
|
||||
return;
|
||||
if (!gfs2_glock_is_locked_by_me(ip->i_gl)) {
|
||||
|
@ -927,8 +934,7 @@ static int gfs2_drop_inode(struct inode *inode)
|
|||
{
|
||||
struct gfs2_inode *ip = GFS2_I(inode);
|
||||
|
||||
if (!test_bit(GIF_FREE_VFS_INODE, &ip->i_flags) &&
|
||||
inode->i_nlink &&
|
||||
if (inode->i_nlink &&
|
||||
gfs2_holder_initialized(&ip->i_iopen_gh)) {
|
||||
struct gfs2_glock *gl = ip->i_iopen_gh.gh_gl;
|
||||
if (test_bit(GLF_DEMOTE, &gl->gl_flags))
|
||||
|
@ -1076,7 +1082,13 @@ static void gfs2_final_release_pages(struct gfs2_inode *ip)
|
|||
struct inode *inode = &ip->i_inode;
|
||||
struct gfs2_glock *gl = ip->i_gl;
|
||||
|
||||
truncate_inode_pages(gfs2_glock2aspace(ip->i_gl), 0);
|
||||
if (unlikely(!gl)) {
|
||||
/* This can only happen during incomplete inode creation. */
|
||||
BUG_ON(!test_bit(GIF_ALLOC_FAILED, &ip->i_flags));
|
||||
return;
|
||||
}
|
||||
|
||||
truncate_inode_pages(gfs2_glock2aspace(gl), 0);
|
||||
truncate_inode_pages(&inode->i_data, 0);
|
||||
|
||||
if (atomic_read(&gl->gl_revokes) == 0) {
|
||||
|
@ -1218,10 +1230,8 @@ static enum dinode_demise evict_should_delete(struct inode *inode,
|
|||
struct gfs2_sbd *sdp = sb->s_fs_info;
|
||||
int ret;
|
||||
|
||||
if (test_bit(GIF_ALLOC_FAILED, &ip->i_flags)) {
|
||||
BUG_ON(!gfs2_glock_is_locked_by_me(ip->i_gl));
|
||||
if (unlikely(test_bit(GIF_ALLOC_FAILED, &ip->i_flags)))
|
||||
goto should_delete;
|
||||
}
|
||||
|
||||
if (test_bit(GIF_DEFERRED_DELETE, &ip->i_flags))
|
||||
return SHOULD_DEFER_EVICTION;
|
||||
|
@ -1294,13 +1304,22 @@ static int evict_unlinked_inode(struct inode *inode)
|
|||
goto out;
|
||||
}
|
||||
|
||||
/* We're about to clear the bitmap for the dinode, but as soon as we
|
||||
do, gfs2_create_inode can create another inode at the same block
|
||||
location and try to set gl_object again. We clear gl_object here so
|
||||
that subsequent inode creates don't see an old gl_object. */
|
||||
glock_clear_object(ip->i_gl, ip);
|
||||
if (ip->i_gl)
|
||||
gfs2_inode_remember_delete(ip->i_gl, ip->i_no_formal_ino);
|
||||
|
||||
/*
|
||||
* As soon as we clear the bitmap for the dinode, gfs2_create_inode()
|
||||
* can get called to recreate it, or even gfs2_inode_lookup() if the
|
||||
* inode was recreated on another node in the meantime.
|
||||
*
|
||||
* However, inserting the new inode into the inode hash table will not
|
||||
* succeed until the old inode is removed, and that only happens after
|
||||
* ->evict_inode() returns. The new inode is attached to its inode and
|
||||
* iopen glocks after inserting it into the inode hash table, so at
|
||||
* that point we can be sure that both glocks are unused.
|
||||
*/
|
||||
|
||||
ret = gfs2_dinode_dealloc(ip);
|
||||
gfs2_inode_remember_delete(ip->i_gl, ip->i_no_formal_ino);
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
@ -1367,12 +1386,7 @@ static void gfs2_evict_inode(struct inode *inode)
|
|||
struct gfs2_holder gh;
|
||||
int ret;
|
||||
|
||||
if (test_bit(GIF_FREE_VFS_INODE, &ip->i_flags)) {
|
||||
clear_inode(inode);
|
||||
return;
|
||||
}
|
||||
|
||||
if (inode->i_nlink || sb_rdonly(sb))
|
||||
if (inode->i_nlink || sb_rdonly(sb) || !ip->i_no_addr)
|
||||
goto out;
|
||||
|
||||
gfs2_holder_mark_uninitialized(&gh);
|
||||
|
@ -1405,12 +1419,9 @@ out:
|
|||
struct gfs2_glock *gl = ip->i_iopen_gh.gh_gl;
|
||||
|
||||
glock_clear_object(gl, ip);
|
||||
if (test_bit(HIF_HOLDER, &ip->i_iopen_gh.gh_iflags)) {
|
||||
ip->i_iopen_gh.gh_flags |= GL_NOCACHE;
|
||||
gfs2_glock_dq(&ip->i_iopen_gh);
|
||||
}
|
||||
gfs2_glock_hold(gl);
|
||||
gfs2_holder_uninit(&ip->i_iopen_gh);
|
||||
ip->i_iopen_gh.gh_flags |= GL_NOCACHE;
|
||||
gfs2_glock_dq_uninit(&ip->i_iopen_gh);
|
||||
gfs2_glock_put_eventually(gl);
|
||||
}
|
||||
if (ip->i_gl) {
|
||||
|
@ -1429,6 +1440,7 @@ static struct inode *gfs2_alloc_inode(struct super_block *sb)
|
|||
ip = alloc_inode_sb(sb, gfs2_inode_cachep, GFP_KERNEL);
|
||||
if (!ip)
|
||||
return NULL;
|
||||
ip->i_no_addr = 0;
|
||||
ip->i_flags = 0;
|
||||
ip->i_gl = NULL;
|
||||
gfs2_holder_mark_uninitialized(&ip->i_iopen_gh);
|
||||
|
|
|
@ -1412,11 +1412,13 @@ static int ea_dealloc_block(struct gfs2_inode *ip)
|
|||
ip->i_eattr = 0;
|
||||
gfs2_add_inode_blocks(&ip->i_inode, -1);
|
||||
|
||||
error = gfs2_meta_inode_buffer(ip, &dibh);
|
||||
if (!error) {
|
||||
gfs2_trans_add_meta(ip->i_gl, dibh);
|
||||
gfs2_dinode_out(ip, dibh->b_data);
|
||||
brelse(dibh);
|
||||
if (likely(!test_bit(GIF_ALLOC_FAILED, &ip->i_flags))) {
|
||||
error = gfs2_meta_inode_buffer(ip, &dibh);
|
||||
if (!error) {
|
||||
gfs2_trans_add_meta(ip->i_gl, dibh);
|
||||
gfs2_dinode_out(ip, dibh->b_data);
|
||||
brelse(dibh);
|
||||
}
|
||||
}
|
||||
|
||||
gfs2_trans_end(sdp);
|
||||
|
@ -1445,14 +1447,16 @@ int gfs2_ea_dealloc(struct gfs2_inode *ip)
|
|||
if (error)
|
||||
return error;
|
||||
|
||||
error = ea_foreach(ip, ea_dealloc_unstuffed, NULL);
|
||||
if (error)
|
||||
goto out_quota;
|
||||
|
||||
if (ip->i_diskflags & GFS2_DIF_EA_INDIRECT) {
|
||||
error = ea_dealloc_indirect(ip);
|
||||
if (likely(!test_bit(GIF_ALLOC_FAILED, &ip->i_flags))) {
|
||||
error = ea_foreach(ip, ea_dealloc_unstuffed, NULL);
|
||||
if (error)
|
||||
goto out_quota;
|
||||
|
||||
if (ip->i_diskflags & GFS2_DIF_EA_INDIRECT) {
|
||||
error = ea_dealloc_indirect(ip);
|
||||
if (error)
|
||||
goto out_quota;
|
||||
}
|
||||
}
|
||||
|
||||
error = ea_dealloc_block(ip);
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
/* SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)*/
|
||||
/*
|
||||
* Copyright (c) 2022 MediaTek Inc.
|
||||
* Author: Runyang Chen <runyang.chen@mediatek.com>
|
||||
*/
|
||||
|
||||
#ifndef _DT_BINDINGS_RESET_CONTROLLER_MT8188
|
||||
#define _DT_BINDINGS_RESET_CONTROLLER_MT8188
|
||||
|
||||
#define MT8188_TOPRGU_CONN_MCU_SW_RST 0
|
||||
#define MT8188_TOPRGU_INFRA_GRST_SW_RST 1
|
||||
#define MT8188_TOPRGU_IPU0_SW_RST 2
|
||||
#define MT8188_TOPRGU_IPU1_SW_RST 3
|
||||
#define MT8188_TOPRGU_IPU2_SW_RST 4
|
||||
#define MT8188_TOPRGU_AUD_ASRC_SW_RST 5
|
||||
#define MT8188_TOPRGU_INFRA_SW_RST 6
|
||||
#define MT8188_TOPRGU_MMSYS_SW_RST 7
|
||||
#define MT8188_TOPRGU_MFG_SW_RST 8
|
||||
#define MT8188_TOPRGU_VENC_SW_RST 9
|
||||
#define MT8188_TOPRGU_VDEC_SW_RST 10
|
||||
#define MT8188_TOPRGU_CAM_VCORE_SW_RST 11
|
||||
#define MT8188_TOPRGU_SCP_SW_RST 12
|
||||
#define MT8188_TOPRGU_APMIXEDSYS_SW_RST 13
|
||||
#define MT8188_TOPRGU_AUDIO_SW_RST 14
|
||||
#define MT8188_TOPRGU_CAMSYS_SW_RST 15
|
||||
#define MT8188_TOPRGU_MJC_SW_RST 16
|
||||
#define MT8188_TOPRGU_PERI_SW_RST 17
|
||||
#define MT8188_TOPRGU_PERI_AO_SW_RST 18
|
||||
#define MT8188_TOPRGU_PCIE_SW_RST 19
|
||||
#define MT8188_TOPRGU_ADSPSYS_SW_RST 21
|
||||
#define MT8188_TOPRGU_DPTX_SW_RST 22
|
||||
#define MT8188_TOPRGU_SPMI_MST_SW_RST 23
|
||||
|
||||
#define MT8188_TOPRGU_SW_RST_NUM 24
|
||||
|
||||
#endif /* _DT_BINDINGS_RESET_CONTROLLER_MT8188 */
|
|
@ -227,6 +227,15 @@
|
|||
#define RN5T618_WATCHDOG_WDOGTIM_S 0
|
||||
#define RN5T618_PWRIRQ_IR_WDOG BIT(6)
|
||||
|
||||
#define RN5T618_POFFHIS_PWRON BIT(0)
|
||||
#define RN5T618_POFFHIS_TSHUT BIT(1)
|
||||
#define RN5T618_POFFHIS_VINDET BIT(2)
|
||||
#define RN5T618_POFFHIS_IODET BIT(3)
|
||||
#define RN5T618_POFFHIS_CPU BIT(4)
|
||||
#define RN5T618_POFFHIS_WDG BIT(5)
|
||||
#define RN5T618_POFFHIS_DCLIM BIT(6)
|
||||
#define RN5T618_POFFHIS_N_OE BIT(7)
|
||||
|
||||
enum {
|
||||
RN5T618_DCDC1,
|
||||
RN5T618_DCDC2,
|
||||
|
|
|
@ -6,20 +6,6 @@
|
|||
*
|
||||
* Contact: Kai Vehmanen <kai.vehmanen@nokia.com>
|
||||
* Original author: Peter Ujfalusi <peter.ujfalusi@nokia.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
|
||||
* 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef _CS_PROTOCOL_H
|
||||
|
|
|
@ -5,20 +5,6 @@
|
|||
* Copyright (C) 2010 Nokia Corporation. All rights reserved.
|
||||
*
|
||||
* Contact: Andras Domokos <andras.domokos at nokia.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
|
||||
* 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef __HSI_CHAR_H
|
||||
|
|
Loading…
Reference in New Issue