mirror of
https://github.com/torvalds/linux.git
synced 2026-07-30 03:01:41 +02:00
msm: pcie: Dump PCIe registers for hang event
Dump limited set of pcie PARF, DBI and PHY registers for hang event. Change-Id: I6b8cd599da230968018587d10f326a9e6f10d4ac Signed-off-by: Vivek Pernamitta <vpernami@codeaurora.org> Signed-off-by: Krishna chaitanya chundru <quic_krichai@quicinc.com> Signed-off-by: Paras Sharma <quic_parass@quicinc.com> Signed-off-by: Prudhvi Yarlagadda <quic_pyarlaga@quicinc.com>
This commit is contained in:
parent
392f42735d
commit
d45e5fa01c
|
|
@ -96,6 +96,17 @@
|
|||
#define PCIE20_PARF_INT_ALL_2_MASK (0X508)
|
||||
#define MSM_PCIE_BW_MGT_INT_STATUS (BIT(25))
|
||||
|
||||
#define PCIE20_PARF_DEBUG_CNT_IN_L0S (0xc10)
|
||||
#define PCIE20_PARF_DEBUG_CNT_IN_L1 (0xc0c)
|
||||
#define PCIE20_PARF_DEBUG_CNT_IN_L1SUB_L1 (0xc84)
|
||||
#define PCIE20_PARF_DEBUG_CNT_IN_L1SUB_L2 (0xc88)
|
||||
#define PCIE20_PARF_PM_STTS_1 (0x28)
|
||||
#define PCIE20_PARF_L1SS_SLEEP_MODE_HANDLER_STATUS (0x4D0)
|
||||
#define PCIE20_PARF_L1SS_SLEEP_MODE_HANDLER_CFG (0x4D4)
|
||||
#define PCIE20_PARF_CORE_ERRORS (0x3C0)
|
||||
#define PCIE20_LINK_DOWN_AXI_ECAM_BLOCK_STATUS (0x630)
|
||||
#define PCIE20_PARF_STATUS (0x230)
|
||||
|
||||
#define PCIE20_PARF_CLKREQ_OVERRIDE (0x2b0)
|
||||
#define PCIE20_PARF_CLKREQ_IN_VALUE (BIT(3))
|
||||
#define PCIE20_PARF_CLKREQ_IN_ENABLE (BIT(1))
|
||||
|
|
@ -156,6 +167,12 @@
|
|||
#define PCIE20_AER_ROOT_ERR_STATUS_REG (0x130)
|
||||
#define PCIE20_AER_ERR_SRC_ID_REG (0x134)
|
||||
|
||||
#define PCIE20_L1SUB_CONTROL1_REG (0x204)
|
||||
#define PCIE20_TX_P_FC_CREDIT_STATUS_OFF (0x730)
|
||||
#define PCIE20_TX_NP_FC_CREDIT_STATUS_OFF (0x734)
|
||||
#define PCIE20_TX_CPL_FC_CREDIT_STATUS_OFF (0x738)
|
||||
#define PCIE20_QUEUE_STATUS_OFF (0x73C)
|
||||
|
||||
#define RD (0)
|
||||
#define WR (1)
|
||||
#define MSM_PCIE_ERROR (-1)
|
||||
|
|
@ -1025,6 +1042,15 @@ struct msm_pcie_dev_t {
|
|||
bool panic_on_aer;
|
||||
struct aer_stats *aer_stats;
|
||||
void (*rumi_init)(struct msm_pcie_dev_t *pcie_dev);
|
||||
|
||||
u32 phy_debug_reg_len;
|
||||
u32 *phy_debug_reg;
|
||||
|
||||
u32 parf_debug_reg_len;
|
||||
u32 *parf_debug_reg;
|
||||
|
||||
u32 dbi_debug_reg_len;
|
||||
u32 *dbi_debug_reg;
|
||||
};
|
||||
|
||||
struct msm_root_dev_t {
|
||||
|
|
@ -1179,6 +1205,12 @@ static const struct msm_pcie_irq_info_t msm_pcie_irq_info[MSM_PCIE_MAX_IRQ] = {
|
|||
{"int_global_int", 0}
|
||||
};
|
||||
|
||||
enum msm_pcie_reg_dump_type_t {
|
||||
MSM_PCIE_DUMP_PARF_REG = 0x0,
|
||||
MSM_PCIE_DUMP_DBI_REG,
|
||||
MSM_PCIE_DUMP_PHY_REG,
|
||||
};
|
||||
|
||||
static int msm_pcie_drv_send_rpmsg(struct msm_pcie_dev_t *pcie_dev,
|
||||
struct msm_pcie_drv_msg *msg);
|
||||
static void msm_pcie_config_sid(struct msm_pcie_dev_t *dev);
|
||||
|
|
@ -1198,6 +1230,115 @@ static void msm_pcie_config_link_pm(struct msm_pcie_dev_t *dev, bool enable);
|
|||
static int msm_pcie_set_link_width(struct msm_pcie_dev_t *pcie_dev,
|
||||
u16 target_link_width);
|
||||
|
||||
static u32 msm_pcie_reg_copy(struct msm_pcie_dev_t *dev,
|
||||
u8 *buf, u32 size, u8 reg_len,
|
||||
enum msm_pcie_reg_dump_type_t type)
|
||||
{
|
||||
u32 ret = 0, val, i;
|
||||
u32 *seq = NULL;
|
||||
u32 seq_len = 0;
|
||||
void __iomem *base;
|
||||
|
||||
PCIE_DUMP(dev, "RC%d buf=0x%x size=%u, reg_len=%u\n",
|
||||
dev->rc_idx, buf, size, reg_len);
|
||||
if (type == MSM_PCIE_DUMP_PARF_REG) {
|
||||
seq = dev->parf_debug_reg;
|
||||
seq_len = dev->parf_debug_reg_len;
|
||||
base = dev->parf;
|
||||
} else if (type == MSM_PCIE_DUMP_DBI_REG) {
|
||||
seq = dev->dbi_debug_reg;
|
||||
seq_len = dev->dbi_debug_reg_len;
|
||||
base = dev->dm_core;
|
||||
} else if (type == MSM_PCIE_DUMP_PHY_REG) {
|
||||
seq = dev->phy_debug_reg;
|
||||
seq_len = dev->phy_debug_reg_len;
|
||||
base = dev->phy;
|
||||
} else {
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (seq) {
|
||||
i = seq_len;
|
||||
while (i && (ret + reg_len <= size)) {
|
||||
PCIE_DUMP(dev, "RC%d *seq:%u\n",
|
||||
dev->rc_idx, *seq);
|
||||
val = readl_relaxed(base + *seq);
|
||||
memcpy(buf, &val, reg_len);
|
||||
i--;
|
||||
buf += reg_len;
|
||||
ret += reg_len;
|
||||
seq++;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int msm_pcie_reg_dump(struct pci_dev *pci_dev, u8 *buff, u32 len)
|
||||
{
|
||||
struct pci_dev *root_pci_dev;
|
||||
struct msm_pcie_dev_t *pcie_dev;
|
||||
u32 offset = 0;
|
||||
|
||||
if (!pci_dev)
|
||||
return -EINVAL;
|
||||
|
||||
root_pci_dev = pcie_find_root_port(pci_dev);
|
||||
if (!root_pci_dev)
|
||||
return -ENODEV;
|
||||
|
||||
pcie_dev = PCIE_BUS_PRIV_DATA(root_pci_dev->bus);
|
||||
|
||||
if (!pcie_dev) {
|
||||
pr_err("PCIe: did not find RC for pci endpoint device.\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
PCIE_DUMP(pcie_dev, "RC%d hang event dump buff=0x%x len=%u\n",
|
||||
pcie_dev->rc_idx, buff, len);
|
||||
|
||||
if (pcie_dev->link_status == MSM_PCIE_LINK_DOWN) {
|
||||
pr_err("PCIe: the link is in down state\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
if (pcie_dev->suspending) {
|
||||
pr_err("PCIe: the device is in suspend state\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
offset = msm_pcie_reg_copy(pcie_dev, buff, len,
|
||||
4, MSM_PCIE_DUMP_PARF_REG);
|
||||
|
||||
buff += offset;
|
||||
len -= offset;
|
||||
|
||||
/* check PHY status before dumping DBI registers */
|
||||
if (!(readl_relaxed(pcie_dev->phy + pcie_dev->phy_status_offset) &
|
||||
BIT(pcie_dev->phy_status_bit))) {
|
||||
|
||||
PCIE_DUMP(pcie_dev, "RC%d Dump DBI registers\n",
|
||||
pcie_dev->rc_idx);
|
||||
offset = msm_pcie_reg_copy(pcie_dev, buff, len,
|
||||
4, MSM_PCIE_DUMP_DBI_REG);
|
||||
} else {
|
||||
/* PHY status bit is set to 1 so dump 0's in dbi buffer space */
|
||||
PCIE_DUMP(pcie_dev, "RC%d PHY is off, skip DBI\n",
|
||||
pcie_dev->rc_idx);
|
||||
memset(buff, 0, pcie_dev->dbi_debug_reg_len * 4);
|
||||
offset = pcie_dev->dbi_debug_reg_len * 4;
|
||||
}
|
||||
|
||||
buff += offset;
|
||||
len -= offset;
|
||||
msm_pcie_reg_copy(pcie_dev, buff, len,
|
||||
1, MSM_PCIE_DUMP_PHY_REG);
|
||||
|
||||
PCIE_DUMP(pcie_dev, "RC%d hang event Exit\n", pcie_dev->rc_idx);
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(msm_pcie_reg_dump);
|
||||
|
||||
static void msm_pcie_write_reg(void __iomem *base, u32 offset, u32 value)
|
||||
{
|
||||
writel_relaxed(value, base + offset);
|
||||
|
|
@ -3975,6 +4116,123 @@ static int msm_pcie_get_phy(struct msm_pcie_dev_t *pcie_dev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int msm_pcie_get_phy_status_reg(struct msm_pcie_dev_t *pcie_dev)
|
||||
{
|
||||
int ret, size = 0;
|
||||
struct platform_device *pdev = pcie_dev->pdev;
|
||||
|
||||
PCIE_DBG(pcie_dev,
|
||||
"PCIe: RC%d: Enter\n",
|
||||
pcie_dev->rc_idx);
|
||||
of_get_property(pdev->dev.of_node, "qcom,phy-debug-reg", &size);
|
||||
if (!size) {
|
||||
PCIE_DBG(pcie_dev,
|
||||
"PCIe: RC%d: phy debug registers not present in DT\n",
|
||||
pcie_dev->rc_idx);
|
||||
pcie_dev->phy_debug_reg = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
pcie_dev->phy_debug_reg = kmalloc(size, GFP_KERNEL);
|
||||
if (!pcie_dev->phy_debug_reg)
|
||||
return -ENOMEM;
|
||||
|
||||
pcie_dev->phy_debug_reg_len = size / sizeof(*pcie_dev->phy_debug_reg);
|
||||
|
||||
ret = of_property_read_u32_array(pdev->dev.of_node,
|
||||
"qcom,phy-debug-reg",
|
||||
(unsigned int *)pcie_dev->phy_debug_reg,
|
||||
size / sizeof(*pcie_dev->phy_debug_reg));
|
||||
if (ret) {
|
||||
kfree(pcie_dev->phy_debug_reg);
|
||||
pcie_dev->phy_debug_reg = NULL;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
PCIE_DBG(pcie_dev,
|
||||
"PCIe: RC%d: no of phy dbg regs:%u size:%u\n",
|
||||
pcie_dev->rc_idx, size/sizeof(u32), size);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int msm_pcie_get_parf_status_reg(struct msm_pcie_dev_t *pcie_dev)
|
||||
{
|
||||
int ret, size = 0;
|
||||
struct platform_device *pdev = pcie_dev->pdev;
|
||||
|
||||
PCIE_DBG(pcie_dev,
|
||||
"PCIe: RC%d: Enter\n", pcie_dev->rc_idx);
|
||||
|
||||
of_get_property(pdev->dev.of_node, "qcom,parf-debug-reg", &size);
|
||||
if (!size) {
|
||||
PCIE_DBG(pcie_dev,
|
||||
"PCIe: RC%d: parf debug registers not present in DT\n",
|
||||
pcie_dev->rc_idx);
|
||||
pcie_dev->parf_debug_reg = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
pcie_dev->parf_debug_reg = kmalloc(size, GFP_KERNEL);
|
||||
if (!pcie_dev->parf_debug_reg)
|
||||
return -ENOMEM;
|
||||
|
||||
pcie_dev->parf_debug_reg_len = size / sizeof(u32);
|
||||
|
||||
ret = of_property_read_u32_array(pdev->dev.of_node,
|
||||
"qcom,parf-debug-reg",
|
||||
(unsigned int *)pcie_dev->parf_debug_reg,
|
||||
size / sizeof(u32));
|
||||
if (ret) {
|
||||
kfree(pcie_dev->parf_debug_reg);
|
||||
pcie_dev->parf_debug_reg = NULL;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
PCIE_DBG(pcie_dev,
|
||||
"PCIe: RC%d: no of parf dbg regs:%u size:%u\n",
|
||||
pcie_dev->rc_idx, size/sizeof(u32), size);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int msm_pcie_get_dbi_status_reg(struct msm_pcie_dev_t *pcie_dev)
|
||||
{
|
||||
int ret, size = 0;
|
||||
struct platform_device *pdev = pcie_dev->pdev;
|
||||
|
||||
PCIE_DBG(pcie_dev,
|
||||
"PCIe: RC%d: Enter\n",
|
||||
pcie_dev->rc_idx);
|
||||
of_get_property(pdev->dev.of_node, "qcom,dbi-debug-reg", &size);
|
||||
if (!size) {
|
||||
PCIE_DBG(pcie_dev,
|
||||
"PCIe: RC%d: dbi debug registers not present in DT\n",
|
||||
pcie_dev->rc_idx);
|
||||
pcie_dev->dbi_debug_reg = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
pcie_dev->dbi_debug_reg = kmalloc(size, GFP_KERNEL);
|
||||
if (!pcie_dev->dbi_debug_reg)
|
||||
return -ENOMEM;
|
||||
|
||||
pcie_dev->dbi_debug_reg_len = size / sizeof(u32);
|
||||
|
||||
ret = of_property_read_u32_array(pdev->dev.of_node,
|
||||
"qcom,dbi-debug-reg",
|
||||
(unsigned int *)pcie_dev->dbi_debug_reg,
|
||||
size / sizeof(u32));
|
||||
if (ret) {
|
||||
kfree(pcie_dev->dbi_debug_reg);
|
||||
pcie_dev->dbi_debug_reg = NULL;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
PCIE_DBG(pcie_dev,
|
||||
"PCIe: RC%d: no of dbi dbg regs:%u size:%u\n",
|
||||
pcie_dev->rc_idx, size/sizeof(u32), size);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int msm_pcie_get_iommu_map(struct msm_pcie_dev_t *pcie_dev)
|
||||
{
|
||||
/* iommu map structure */
|
||||
|
|
@ -4201,6 +4459,18 @@ static int msm_pcie_get_resources(struct msm_pcie_dev_t *dev,
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = msm_pcie_get_parf_status_reg(dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = msm_pcie_get_dbi_status_reg(dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = msm_pcie_get_phy_status_reg(dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
PCIE_DBG(dev, "RC%d: exit\n", dev->rc_idx);
|
||||
|
||||
return 0;
|
||||
|
|
@ -4208,6 +4478,7 @@ static int msm_pcie_get_resources(struct msm_pcie_dev_t *dev,
|
|||
|
||||
static void msm_pcie_release_resources(struct msm_pcie_dev_t *dev)
|
||||
{
|
||||
|
||||
dev->parf = NULL;
|
||||
dev->elbi = NULL;
|
||||
dev->iatu = NULL;
|
||||
|
|
@ -4215,6 +4486,13 @@ static void msm_pcie_release_resources(struct msm_pcie_dev_t *dev)
|
|||
dev->conf = NULL;
|
||||
dev->tcsr = NULL;
|
||||
dev->rumi = NULL;
|
||||
kfree(dev->parf_debug_reg);
|
||||
kfree(dev->dbi_debug_reg);
|
||||
kfree(dev->phy_debug_reg);
|
||||
dev->parf_debug_reg = NULL;
|
||||
dev->dbi_debug_reg = NULL;
|
||||
dev->phy_debug_reg = NULL;
|
||||
|
||||
}
|
||||
|
||||
static void msm_pcie_scale_link_bandwidth(struct msm_pcie_dev_t *pcie_dev,
|
||||
|
|
|
|||
|
|
@ -204,6 +204,17 @@ int msm_pcie_enumerate(u32 rc_idx);
|
|||
int msm_pcie_debug_info(struct pci_dev *dev, u32 option, u32 base,
|
||||
u32 offset, u32 mask, u32 value);
|
||||
|
||||
/*
|
||||
* msm_pcie_reg_dump - dump pcie regsters for debug
|
||||
* @pci_dev: pci device structure
|
||||
* @buffer: destination buffer address
|
||||
* @len: length of buffer
|
||||
*
|
||||
* This functions dumps PCIE registers for debug. Sould be used when
|
||||
* link is already enabled
|
||||
*/
|
||||
int msm_pcie_reg_dump(struct pci_dev *pci_dev, u8 *buff, u32 len);
|
||||
|
||||
#else /* !CONFIG_PCI_MSM */
|
||||
static inline int msm_pcie_pm_control(enum msm_pcie_pm_opt pm_opt, u32 busnr,
|
||||
void *user, void *data, u32 options)
|
||||
|
|
@ -256,6 +267,11 @@ static inline int msm_pcie_debug_info(struct pci_dev *dev, u32 option, u32 base,
|
|||
{
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
static inline int msm_pcie_reg_dump(struct pci_dev *pci_dev, u8 *buff, u32 len)
|
||||
{
|
||||
return -ENODEV;
|
||||
}
|
||||
#endif /* CONFIG_PCI_MSM */
|
||||
|
||||
#endif /* __MSM_PCIE_H */
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user