Merge "serial: msm_geni_serial: Prevent geni register access while suspend is in progress"

This commit is contained in:
QCTECMDR Service 2024-08-28 03:07:31 -07:00 committed by Gerrit - the friendly Code Review server
commit c0db2be621

View File

@ -6,19 +6,22 @@
#include <linux/bitmap.h>
#include <linux/bitops.h>
#include <linux/console.h>
#include <linux/debugfs.h>
#include <linux/delay.h>
#include <linux/console.h>
#include <linux/dma-mapping.h>
#include <linux/dmaengine.h>
#include <linux/dma-mapping.h>
#include <linux/io.h>
#include <linux/ioctl.h>
#include <linux/ipc_logging.h>
#include <linux/irq.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/msm_gpi.h>
#include <linux/mutex.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/pinctrl/consumer.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
#include <linux/qcom-geni-se-common.h>
@ -28,9 +31,6 @@
#include <linux/suspend.h>
#include <linux/tty.h>
#include <linux/tty_flip.h>
#include <linux/ioctl.h>
#include <linux/pinctrl/consumer.h>
#include <linux/dma-mapping.h>
#include <uapi/linux/msm_geni_serial.h>
static bool con_enabled = IS_ENABLED(CONFIG_SERIAL_MSM_GENI_CONSOLE_DEFAULT_ENABLED);
@ -457,6 +457,12 @@ struct msm_geni_serial_port {
int hs_uart_operation;
struct msm_geni_serial_ssr uart_ssr;
struct geni_se_rsc rsc;
/**
* mutex to prevent race condition between runtime
* suspend and get_mctrl which tries to access IOS registers
* when runtime suspend was in progress
*/
struct mutex suspend_resume_lock;
};
static const struct uart_ops msm_geni_serial_pops;
@ -1403,17 +1409,26 @@ static unsigned int msm_geni_serial_get_mctrl(struct uart_port *uport)
return 0;
}
if (!uart_console(uport) && device_pending_suspend(uport)) {
UART_LOG_DBG(port->ipc_log_misc, uport->dev,
"%s.Device is suspended, %s\n",
__func__, current->comm);
return TIOCM_DSR | TIOCM_CAR | TIOCM_CTS;
if (!uart_console(uport)) {
if (!mutex_trylock(&port->suspend_resume_lock)) {
UART_LOG_DBG(port->ipc_log_misc, uport->dev,
"%s.Device is being suspended, %s\n",
__func__, current->comm);
return mctrl;
}
if (device_pending_suspend(uport)) {
UART_LOG_DBG(port->ipc_log_misc, uport->dev,
"%s.Device is suspended, %s\n",
__func__, current->comm);
mutex_unlock(&port->suspend_resume_lock);
return mctrl | TIOCM_CTS;
}
}
geni_ios = geni_read_reg(uport->membase, SE_GENI_IOS);
if (!(geni_ios & IO2_DATA_IN))
mctrl |= TIOCM_CTS;
else
else if (!uart_console(uport))
msm_geni_update_uart_error_code(port, SOC_ERROR_START_TX_IOS_SOC_RFR_HIGH);
if (!port->manual_flow)
@ -1421,6 +1436,10 @@ static unsigned int msm_geni_serial_get_mctrl(struct uart_port *uport)
UART_LOG_DBG(port->ipc_log_misc, uport->dev, "%s: geni_ios:0x%x, mctrl:0x%x\n",
__func__, geni_ios, mctrl);
if (!uart_console(uport))
mutex_unlock(&port->suspend_resume_lock);
return mctrl;
}
@ -5596,6 +5615,8 @@ static int msm_geni_serial_probe(struct platform_device *pdev)
if (!dev_port->is_console)
spin_lock_init(&dev_port->rx_lock);
mutex_init(&dev_port->suspend_resume_lock);
ret = uart_add_one_port(drv, uport);
if (ret)
dev_err(&pdev->dev, "Failed to register uart_port: %d\n", ret);
@ -5694,7 +5715,7 @@ static int msm_geni_serial_runtime_suspend(struct device *dev)
unsigned long long start_time;
u32 geni_status = geni_read_reg(port->uport.membase,
SE_GENI_STATUS);
mutex_lock(&port->suspend_resume_lock);
UART_LOG_DBG(port->ipc_log_pwr, dev,
"%s: Start geni_status : 0x%x\n", __func__, geni_status);
@ -5720,7 +5741,8 @@ static int msm_geni_serial_runtime_suspend(struct device *dev)
*/
if (port->wakeup_byte && port->wakeup_irq)
msm_geni_serial_allow_rx(port);
return -EBUSY;
ret = -EBUSY;
goto exit_runtime_suspend;
}
}
/*
@ -5737,7 +5759,8 @@ static int msm_geni_serial_runtime_suspend(struct device *dev)
*/
if (port->wakeup_byte && port->wakeup_irq)
msm_geni_serial_allow_rx(port);
return -EBUSY;
ret = -EBUSY;
goto exit_runtime_suspend;
}
geni_status = geni_read_reg(port->uport.membase, SE_GENI_STATUS);
@ -5768,7 +5791,8 @@ static int msm_geni_serial_runtime_suspend(struct device *dev)
UART_LOG_DBG(port->ipc_log_pwr, dev,
"%s: return, stop_rx_seq busy\n", __func__);
enable_irq(port->uport.irq);
return -EBUSY;
ret = -EBUSY;
goto exit_runtime_suspend;
}
}
if (count)
@ -5804,6 +5828,7 @@ static int msm_geni_serial_runtime_suspend(struct device *dev)
UART_LOG_DBG(port->ipc_log_pwr, dev, "%s: End %d\n", __func__, ret);
__pm_relax(port->geni_wake);
exit_runtime_suspend:
mutex_unlock(&port->suspend_resume_lock);
return ret;
}