Merge e21ee273e6 ("Merge tag 'clk-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/clk/linux") into android-mainline
Steps on the way to v7.1-rc8 Change-Id: Iaefbcf941f1ce64eba724011db6346bd4eb9f773 Signed-off-by: Carlos Llamas <cmllamas@google.com>
This commit is contained in:
commit
b26e879f6c
15 files changed
+140
-113
No files matched your search
@@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
title: GPIO-based I2C Bus Mux
|
||||
|
||||
maintainers:
|
||||
- Wolfram Sang <wsa@kernel.org>
|
||||
- Peter Korsgaard <peter.korsgaard@barco.com>
|
||||
|
||||
description: |
|
||||
This binding describes an I2C bus multiplexer that uses GPIOs to route the I2C signals.
|
||||
|
||||
+3
-3
@@ -10772,6 +10772,7 @@ GENERIC GPIO I2C MULTIPLEXER DRIVER
|
||||
M: Peter Korsgaard <peter.korsgaard@barco.com>
|
||||
L: linux-i2c@vger.kernel.org
|
||||
S: Supported
|
||||
F: Documentation/devicetree/bindings/i2c/i2c-mux-gpio.yaml
|
||||
F: Documentation/i2c/muxes/i2c-mux-gpio.rst
|
||||
F: drivers/i2c/muxes/i2c-mux-gpio.c
|
||||
F: include/linux/platform_data/i2c-mux-gpio.h
|
||||
@@ -12095,11 +12096,11 @@ F: Documentation/i2c/busses/i2c-parport.rst
|
||||
F: drivers/i2c/busses/i2c-parport.c
|
||||
|
||||
I2C SUBSYSTEM
|
||||
M: Wolfram Sang <wsa+renesas@sang-engineering.com>
|
||||
M: Andi Shyti <andi.shyti@kernel.org>
|
||||
L: linux-i2c@vger.kernel.org
|
||||
S: Maintained
|
||||
Q: https://patchwork.ozlabs.org/project/linux-i2c/list/
|
||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux.git
|
||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/andi.shyti/linux.git
|
||||
F: Documentation/i2c/
|
||||
F: drivers/i2c/*
|
||||
F: include/dt-bindings/i2c/i2c.h
|
||||
@@ -25934,7 +25935,6 @@ F: drivers/media/platform/synopsys/hdmirx/*
|
||||
SYNOPSYS DESIGNWARE I2C DRIVER
|
||||
M: Mika Westerberg <mika.westerberg@linux.intel.com>
|
||||
R: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
|
||||
R: Jan Dabros <jsd@semihalf.com>
|
||||
L: linux-i2c@vger.kernel.org
|
||||
S: Supported
|
||||
F: drivers/i2c/busses/i2c-designware-*
|
||||
|
||||
@@ -977,7 +977,7 @@ static struct clk_rcg2 disp0_cc_mdss_mdp_clk_src = {
|
||||
.name = "disp0_cc_mdss_mdp_clk_src",
|
||||
.parent_data = disp0_cc_parent_data_5,
|
||||
.num_parents = ARRAY_SIZE(disp0_cc_parent_data_5),
|
||||
.ops = &clk_rcg2_shared_ops,
|
||||
.ops = &clk_rcg2_shared_no_init_park_ops,
|
||||
},
|
||||
};
|
||||
|
||||
@@ -991,7 +991,7 @@ static struct clk_rcg2 disp1_cc_mdss_mdp_clk_src = {
|
||||
.name = "disp1_cc_mdss_mdp_clk_src",
|
||||
.parent_data = disp1_cc_parent_data_5,
|
||||
.num_parents = ARRAY_SIZE(disp1_cc_parent_data_5),
|
||||
.ops = &clk_rcg2_shared_ops,
|
||||
.ops = &clk_rcg2_shared_no_init_park_ops,
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
@@ -580,7 +580,7 @@ static struct clk_rcg2 disp_cc_mdss_mdp_clk_src = {
|
||||
.parent_data = disp_cc_parent_data_6,
|
||||
.num_parents = ARRAY_SIZE(disp_cc_parent_data_6),
|
||||
.flags = CLK_SET_RATE_PARENT,
|
||||
.ops = &clk_rcg2_shared_ops,
|
||||
.ops = &clk_rcg2_shared_no_init_park_ops,
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
@@ -3921,7 +3921,7 @@ static const unsigned long peric0_clk_regs[] __initconst = {
|
||||
CLK_CON_DIV_DIV_CLK_PERIC0_USI4_USI,
|
||||
CLK_CON_DIV_DIV_CLK_PERIC0_USI5_USI,
|
||||
CLK_CON_DIV_DIV_CLK_PERIC0_USI6_USI,
|
||||
CLK_CON_DIV_DIV_CLK_PERIC0_USI6_USI,
|
||||
CLK_CON_DIV_DIV_CLK_PERIC0_USI7_USI,
|
||||
CLK_CON_DIV_DIV_CLK_PERIC0_USI8_USI,
|
||||
CLK_CON_BUF_CLKBUF_PERIC0_IP,
|
||||
CLK_CON_GAT_CLK_BLK_PERIC0_UID_PERIC0_CMU_PERIC0_IPCLKPORT_PCLK,
|
||||
|
||||
@@ -1383,55 +1383,66 @@ static int lpi2c_imx_init_recovery_info(struct lpi2c_imx_struct *lpi2c_imx,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void dma_exit(struct device *dev, struct lpi2c_imx_dma *dma)
|
||||
{
|
||||
if (dma->chan_rx)
|
||||
dma_release_channel(dma->chan_rx);
|
||||
|
||||
if (dma->chan_tx)
|
||||
dma_release_channel(dma->chan_tx);
|
||||
|
||||
devm_kfree(dev, dma);
|
||||
}
|
||||
|
||||
static int lpi2c_dma_init(struct device *dev, dma_addr_t phy_addr)
|
||||
{
|
||||
struct lpi2c_imx_struct *lpi2c_imx = dev_get_drvdata(dev);
|
||||
struct lpi2c_imx_dma *dma;
|
||||
void *group;
|
||||
int ret;
|
||||
|
||||
dma = devm_kzalloc(dev, sizeof(*dma), GFP_KERNEL);
|
||||
if (!dma)
|
||||
/*
|
||||
* Open a devres group so that all resources allocated within
|
||||
* this function can be released together if DMA init fails but
|
||||
* probe continues in PIO mode.
|
||||
*/
|
||||
group = devres_open_group(dev, NULL, GFP_KERNEL);
|
||||
if (!group)
|
||||
return -ENOMEM;
|
||||
|
||||
dma = devm_kzalloc(dev, sizeof(*dma), GFP_KERNEL);
|
||||
if (!dma) {
|
||||
ret = -ENOMEM;
|
||||
goto release_group;
|
||||
}
|
||||
|
||||
dma->phy_addr = phy_addr;
|
||||
|
||||
/* Prepare for TX DMA: */
|
||||
dma->chan_tx = dma_request_chan(dev, "tx");
|
||||
dma->chan_tx = devm_dma_request_chan(dev, "tx");
|
||||
if (IS_ERR(dma->chan_tx)) {
|
||||
ret = PTR_ERR(dma->chan_tx);
|
||||
if (ret != -ENODEV && ret != -EPROBE_DEFER)
|
||||
dev_err(dev, "can't request DMA tx channel (%d)\n", ret);
|
||||
dma->chan_tx = NULL;
|
||||
goto dma_exit;
|
||||
goto release_group;
|
||||
}
|
||||
|
||||
/* Prepare for RX DMA: */
|
||||
dma->chan_rx = dma_request_chan(dev, "rx");
|
||||
dma->chan_rx = devm_dma_request_chan(dev, "rx");
|
||||
if (IS_ERR(dma->chan_rx)) {
|
||||
ret = PTR_ERR(dma->chan_rx);
|
||||
if (ret != -ENODEV && ret != -EPROBE_DEFER)
|
||||
dev_err(dev, "can't request DMA rx channel (%d)\n", ret);
|
||||
dma->chan_rx = NULL;
|
||||
goto dma_exit;
|
||||
goto release_group;
|
||||
}
|
||||
|
||||
/*
|
||||
* DMA init succeeded. Remove the group marker but keep all resources
|
||||
* bound to the device, they will be freed at device removal.
|
||||
*/
|
||||
devres_remove_group(dev, group);
|
||||
|
||||
lpi2c_imx->can_use_dma = true;
|
||||
lpi2c_imx->dma = dma;
|
||||
return 0;
|
||||
|
||||
dma_exit:
|
||||
dma_exit(dev, dma);
|
||||
release_group:
|
||||
/*
|
||||
* DMA init failed. Release ALL resources allocated inside this
|
||||
* group (dma memory, TX channel if already acquired, etc.) so
|
||||
* that a successful PIO-mode probe does not hold unused resources
|
||||
* for the entire device lifetime.
|
||||
*/
|
||||
devres_release_group(dev, group);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
@@ -1892,9 +1892,15 @@ static void i2c_imx_remove(struct platform_device *pdev)
|
||||
static int i2c_imx_runtime_suspend(struct device *dev)
|
||||
{
|
||||
struct imx_i2c_struct *i2c_imx = dev_get_drvdata(dev);
|
||||
int ret;
|
||||
|
||||
ret = pinctrl_pm_select_sleep_state(dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
clk_disable(i2c_imx->clk);
|
||||
return pinctrl_pm_select_sleep_state(dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int i2c_imx_runtime_resume(struct device *dev)
|
||||
@@ -1907,10 +1913,13 @@ static int i2c_imx_runtime_resume(struct device *dev)
|
||||
return ret;
|
||||
|
||||
ret = clk_enable(i2c_imx->clk);
|
||||
if (ret)
|
||||
if (ret) {
|
||||
dev_err(dev, "can't enable I2C clock, ret=%d\n", ret);
|
||||
pinctrl_pm_select_sleep_state(dev);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int i2c_imx_suspend(struct device *dev)
|
||||
|
||||
@@ -660,8 +660,8 @@ static void cci_remove(struct platform_device *pdev)
|
||||
if (cci->master[i].cci) {
|
||||
i2c_del_adapter(&cci->master[i].adap);
|
||||
of_node_put(cci->master[i].adap.dev.of_node);
|
||||
cci_halt(cci, i);
|
||||
}
|
||||
cci_halt(cci, i);
|
||||
}
|
||||
|
||||
disable_irq(cci->irq);
|
||||
|
||||
@@ -725,8 +725,10 @@ static int riic_i2c_resume_noirq(struct device *dev)
|
||||
return ret;
|
||||
|
||||
ret = pm_runtime_force_resume(dev);
|
||||
if (ret)
|
||||
if (ret) {
|
||||
reset_control_assert(riic->rstc);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = riic_init_hw(riic);
|
||||
if (ret) {
|
||||
|
||||
@@ -694,6 +694,9 @@ static int stm32f7_i2c_setup_timing(struct stm32f7_i2c_dev *i2c_dev,
|
||||
if (!of_property_read_bool(i2c_dev->dev->of_node, "i2c-digital-filter"))
|
||||
i2c_dev->dnf_dt = STM32F7_I2C_DNF_DEFAULT;
|
||||
|
||||
i2c_dev->analog_filter = of_property_read_bool(i2c_dev->dev->of_node,
|
||||
"i2c-analog-filter");
|
||||
|
||||
do {
|
||||
ret = stm32f7_i2c_compute_timing(i2c_dev, setup,
|
||||
&i2c_dev->timing);
|
||||
@@ -715,9 +718,6 @@ static int stm32f7_i2c_setup_timing(struct stm32f7_i2c_dev *i2c_dev,
|
||||
return ret;
|
||||
}
|
||||
|
||||
i2c_dev->analog_filter = of_property_read_bool(i2c_dev->dev->of_node,
|
||||
"i2c-analog-filter");
|
||||
|
||||
dev_dbg(i2c_dev->dev, "I2C Speed(%i), Clk Source(%i)\n",
|
||||
setup->speed_freq, setup->clock_src);
|
||||
dev_dbg(i2c_dev->dev, "I2C Rise(%i) and Fall(%i) Time\n",
|
||||
|
||||
@@ -2115,9 +2115,9 @@ static const struct tegra_i2c_hw_feature tegra264_i2c_hw = {
|
||||
static const struct tegra_i2c_hw_feature tegra410_i2c_hw = {
|
||||
.has_continue_xfer_support = true,
|
||||
.has_per_pkt_xfer_complete_irq = true,
|
||||
.clk_divisor_hs_mode = 1,
|
||||
.clk_divisor_hs_mode = 2,
|
||||
.clk_divisor_std_mode = 0x3f,
|
||||
.clk_divisor_fast_mode = 0x2c,
|
||||
.clk_divisor_fast_mode = 0x2f,
|
||||
.clk_divisor_fast_plus_mode = 0x11,
|
||||
.has_config_load_reg = true,
|
||||
.has_multi_master_mode = true,
|
||||
@@ -2133,8 +2133,8 @@ static const struct tegra_i2c_hw_feature tegra410_i2c_hw = {
|
||||
.thigh_fast_mode = 0x2,
|
||||
.tlow_fastplus_mode = 0x2,
|
||||
.thigh_fastplus_mode = 0x2,
|
||||
.tlow_hs_mode = 0x8,
|
||||
.thigh_hs_mode = 0x6,
|
||||
.tlow_hs_mode = 0x5,
|
||||
.thigh_hs_mode = 0x2,
|
||||
.setup_hold_time_std_mode = 0x08080808,
|
||||
.setup_hold_time_fast_mode = 0x02020202,
|
||||
.setup_hold_time_fastplus_mode = 0x02020202,
|
||||
@@ -2401,29 +2401,38 @@ static int __maybe_unused tegra_i2c_runtime_suspend(struct device *dev)
|
||||
}
|
||||
|
||||
static int __maybe_unused tegra_i2c_suspend(struct device *dev)
|
||||
{
|
||||
/*
|
||||
* Bring the controller up and hold a usage count so it stays
|
||||
* available until the noirq phase.
|
||||
*/
|
||||
return pm_runtime_resume_and_get(dev);
|
||||
}
|
||||
|
||||
static int __maybe_unused tegra_i2c_suspend_noirq(struct device *dev)
|
||||
{
|
||||
struct tegra_i2c_dev *i2c_dev = dev_get_drvdata(dev);
|
||||
int err;
|
||||
|
||||
i2c_mark_adapter_suspended(&i2c_dev->adapter);
|
||||
|
||||
if (!pm_runtime_status_suspended(dev)) {
|
||||
err = tegra_i2c_runtime_suspend(dev);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
/*
|
||||
* Runtime PM is already disabled at this point, so invoke the
|
||||
* runtime_suspend callback directly to put the controller down.
|
||||
*/
|
||||
return tegra_i2c_runtime_suspend(dev);
|
||||
}
|
||||
|
||||
static int __maybe_unused tegra_i2c_resume(struct device *dev)
|
||||
static int __maybe_unused tegra_i2c_resume_noirq(struct device *dev)
|
||||
{
|
||||
struct tegra_i2c_dev *i2c_dev = dev_get_drvdata(dev);
|
||||
int err;
|
||||
|
||||
/*
|
||||
* We need to ensure that clocks are enabled so that registers can be
|
||||
* restored in tegra_i2c_init().
|
||||
* Runtime PM is still disabled at this point, so invoke the
|
||||
* runtime_resume callback directly to bring the controller back up
|
||||
* before re-initializing the hardware. The adapter is then marked
|
||||
* resumed so that consumers can issue transfers from their own
|
||||
* resume_noirq() handlers and onwards.
|
||||
*/
|
||||
err = tegra_i2c_runtime_resume(dev);
|
||||
if (err)
|
||||
@@ -2433,24 +2442,22 @@ static int __maybe_unused tegra_i2c_resume(struct device *dev)
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
/*
|
||||
* In case we are runtime suspended, disable clocks again so that we
|
||||
* don't unbalance the clock reference counts during the next runtime
|
||||
* resume transition.
|
||||
*/
|
||||
if (pm_runtime_status_suspended(dev)) {
|
||||
err = tegra_i2c_runtime_suspend(dev);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
|
||||
i2c_mark_adapter_resumed(&i2c_dev->adapter);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __maybe_unused tegra_i2c_resume(struct device *dev)
|
||||
{
|
||||
pm_runtime_put(dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct dev_pm_ops tegra_i2c_pm = {
|
||||
SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(tegra_i2c_suspend, tegra_i2c_resume)
|
||||
SET_SYSTEM_SLEEP_PM_OPS(tegra_i2c_suspend, tegra_i2c_resume)
|
||||
SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(tegra_i2c_suspend_noirq,
|
||||
tegra_i2c_resume_noirq)
|
||||
SET_RUNTIME_PM_OPS(tegra_i2c_runtime_suspend, tegra_i2c_runtime_resume,
|
||||
NULL)
|
||||
};
|
||||
|
||||
@@ -26,7 +26,6 @@
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/pinctrl/pinconf.h>
|
||||
#include <linux/dmi.h>
|
||||
#include <linux/pinctrl/pinconf-generic.h>
|
||||
#include <linux/pinctrl/pinmux.h>
|
||||
#include <linux/string_choices.h>
|
||||
@@ -40,39 +39,6 @@
|
||||
static struct amd_gpio *pinctrl_dev;
|
||||
#endif
|
||||
|
||||
static const struct dmi_system_id amd_gpio_quirk_yoga7_14agp11[] = {
|
||||
{
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "83TD"),
|
||||
DMI_MATCH(DMI_BOARD_NAME, "LNVNB161216"),
|
||||
},
|
||||
},
|
||||
{ }
|
||||
};
|
||||
|
||||
static void amd_gpio_apply_quirks(struct amd_gpio *gpio_dev)
|
||||
{
|
||||
const unsigned int pin = 157; /* WACF2200 GpioInt per ACPI _CRS */
|
||||
unsigned long flags;
|
||||
u32 reg;
|
||||
|
||||
if (!dmi_check_system(amd_gpio_quirk_yoga7_14agp11))
|
||||
return;
|
||||
if (pin >= gpio_dev->gc.ngpio)
|
||||
return;
|
||||
|
||||
raw_spin_lock_irqsave(&gpio_dev->lock, flags);
|
||||
reg = readl(gpio_dev->base + pin * 4);
|
||||
reg |= BIT(INTERRUPT_ENABLE_OFF) | BIT(INTERRUPT_MASK_OFF);
|
||||
writel(reg, gpio_dev->base + pin * 4);
|
||||
raw_spin_unlock_irqrestore(&gpio_dev->lock, flags);
|
||||
|
||||
dev_info(&gpio_dev->pdev->dev,
|
||||
"Enabled IRQ for GPIO %u (Yoga 7 14AGP11 touchscreen)\n",
|
||||
pin);
|
||||
}
|
||||
|
||||
static int amd_gpio_get_direction(struct gpio_chip *gc, unsigned offset)
|
||||
{
|
||||
unsigned long flags;
|
||||
@@ -1253,7 +1219,6 @@ static int amd_gpio_probe(struct platform_device *pdev)
|
||||
|
||||
/* Disable and mask interrupts */
|
||||
amd_gpio_irq_init(gpio_dev);
|
||||
amd_gpio_apply_quirks(gpio_dev);
|
||||
|
||||
girq = &gpio_dev->gc.irq;
|
||||
gpio_irq_chip_set_chip(girq, &amd_gpio_irqchip);
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#include "pinctrl-mcp23s08.h"
|
||||
|
||||
#define MCP_MAX_DEV_PER_CS 8
|
||||
#define MCP23S08_SPI_BASE 0x40
|
||||
|
||||
/*
|
||||
* A given spi_device can represent up to eight mcp23sxx chips
|
||||
@@ -143,13 +144,13 @@ static int mcp23s08_probe(struct spi_device *spi)
|
||||
unsigned int addr;
|
||||
int chips;
|
||||
int ret;
|
||||
u32 v;
|
||||
u8 v;
|
||||
|
||||
info = spi_get_device_match_data(spi);
|
||||
|
||||
ret = device_property_read_u32(dev, "microchip,spi-present-mask", &v);
|
||||
ret = device_property_read_u8(dev, "microchip,spi-present-mask", &v);
|
||||
if (ret) {
|
||||
ret = device_property_read_u32(dev, "mcp,spi-present-mask", &v);
|
||||
ret = device_property_read_u8(dev, "mcp,spi-present-mask", &v);
|
||||
if (ret) {
|
||||
dev_err(dev, "missing spi-present-mask");
|
||||
return ret;
|
||||
@@ -173,6 +174,8 @@ static int mcp23s08_probe(struct spi_device *spi)
|
||||
for_each_set_bit(addr, &spi_present_mask, MCP_MAX_DEV_PER_CS) {
|
||||
data->mcp[addr] = &data->chip[--chips];
|
||||
data->mcp[addr]->irq = spi->irq;
|
||||
data->mcp[addr]->dev = dev;
|
||||
data->mcp[addr]->addr = MCP23S08_SPI_BASE | (addr << 1);
|
||||
|
||||
ret = mcp23s08_spi_regmap_init(data->mcp[addr], dev, addr, info);
|
||||
if (ret)
|
||||
@@ -184,7 +187,7 @@ static int mcp23s08_probe(struct spi_device *spi)
|
||||
if (!data->mcp[addr]->pinctrl_desc.name)
|
||||
return -ENOMEM;
|
||||
|
||||
ret = mcp23s08_probe_one(data->mcp[addr], dev, 0x40 | (addr << 1),
|
||||
ret = mcp23s08_probe_one(data->mcp[addr], dev, MCP23S08_SPI_BASE | (addr << 1),
|
||||
info->type, -1);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
+37
-9
@@ -720,6 +720,41 @@ static inline bool debug_objects_is_pi_blocked_on(void)
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline bool can_fill_pool(void)
|
||||
{
|
||||
/*
|
||||
* On !RT enabled kernels there are no restrictions and spinlock_t and
|
||||
* raw_spinlock_t are the same types.
|
||||
*/
|
||||
if (!IS_ENABLED(CONFIG_PREEMPT_RT))
|
||||
return true;
|
||||
|
||||
/*
|
||||
* On RT enabled kernels, the task must not be blocked on a lock as
|
||||
* that could corrupt the PI state when blocking on a lock in the
|
||||
* allocation path.
|
||||
*/
|
||||
if (debug_objects_is_pi_blocked_on())
|
||||
return false;
|
||||
|
||||
/*
|
||||
* On RT enabled kernels the pool refill should happen in preemptible
|
||||
* context.
|
||||
*/
|
||||
if (preemptible())
|
||||
return true;
|
||||
|
||||
/*
|
||||
* Though during system boot before scheduling is set up, preemption is
|
||||
* disabled and the pool can get exhausted. Before scheduling is active
|
||||
* a task cannot be blocked on a sleeping lock, but it might hold a lock
|
||||
* and if interrupted then hard interrupt context might run into a lock
|
||||
* inversion. So exclude hard interrupt context from allocations before
|
||||
* scheduling is active.
|
||||
*/
|
||||
return system_state < SYSTEM_SCHEDULING && !in_hardirq();
|
||||
}
|
||||
|
||||
static void debug_objects_fill_pool(void)
|
||||
{
|
||||
if (!static_branch_likely(&obj_cache_enabled))
|
||||
@@ -734,18 +769,11 @@ static void debug_objects_fill_pool(void)
|
||||
if (likely(!pool_should_refill(&pool_global)))
|
||||
return;
|
||||
|
||||
/*
|
||||
* On RT enabled kernels the pool refill must happen in preemptible
|
||||
* context and not enqueued on an rt_mutex -- for !RT kernels we rely
|
||||
* on the fact that spinlock_t and raw_spinlock_t are basically the
|
||||
* same type and this lock-type inversion works just fine.
|
||||
*/
|
||||
if (!IS_ENABLED(CONFIG_PREEMPT_RT) || system_state < SYSTEM_SCHEDULING ||
|
||||
(preemptible() && !debug_objects_is_pi_blocked_on())) {
|
||||
if (can_fill_pool()) {
|
||||
/*
|
||||
* Annotate away the spinlock_t inside raw_spinlock_t warning
|
||||
* by temporarily raising the wait-type to LD_WAIT_CONFIG, matching
|
||||
* the preemptible() condition above.
|
||||
* the preemptible() condition in can_fill_pool().
|
||||
*/
|
||||
static DEFINE_WAIT_OVERRIDE_MAP(fill_pool_map, LD_WAIT_CONFIG);
|
||||
lock_map_acquire_try(&fill_pool_map);
|
||||
|
||||
+3
-1
@@ -405,7 +405,9 @@ impl I2cAdapter {
|
||||
|
||||
// SAFETY: `adapter` is non-null and points to a live `i2c_adapter`.
|
||||
// `I2cAdapter` is #[repr(transparent)], so this cast is valid.
|
||||
Ok(unsafe { (&*adapter.as_ptr().cast::<I2cAdapter<device::Normal>>()).into() })
|
||||
// `i2c_get_adapter` returned the adapter with an incremented refcount, which we pass to
|
||||
// the `ARef`.
|
||||
Ok(unsafe { ARef::from_raw(adapter.cast::<I2cAdapter<device::Normal>>()) })
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user