This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

[参考译文] Linux/66AK2H12:错误:在 RapidIO 枚举中

Guru**** 2609895 points


请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/processors-group/processors/f/processors-forum/582933/linux-66ak2h12-bug-in-rapidio-enumeration

器件型号:66AK2H12

工具/软件:Linux

函数 keyston_Rio maint_read 和 keyston_Rio maint_write
发出两个可能睡眠的调用:kzalloc

tbuf = kzalloc (align_len、GFP_NOFS | GFP_DMA);
如果(!tbuf)
return -ENOMEM;

和 mutex_lock

mutex_lock (&Krio_priv->LSU_lock_maint);

(内联函数 keyston_Rio maint_request 中的后者)。

这意味着必须使用 KeySton_Rio_maint_read 和 keyston_Rio_maint_write
不能从中断上下文调用、也不能在保持自旋锁时调用。

函数 RIO_MPORT_READ_CONFIG_32 (RIO-ACCESS.c)将锁定
RIO_CONFIG_LOCK、然后通过指针调用 keyston_RIO_maint_read
mport->ops->cread。 这是不安全的、可能会使内核死锁。

RapidIO 枚举机制结束调用
RIO_MPORT_READ_CONFIG_32、因此我们无法在不生成的情况下进行枚举
错误。

[29.486937] Rio:枚举主端口0、RIO0 mport
[29.493231]错误:从/home/MITLL/CH22073/ojm/keystoneii/processor-sdk-linux/kernel/locking/mutex.c:620的无效上下文调用的睡眠函数
[29.50649] in_at原 子():1、IRQs_disabled():128、pid:612、name:modprobe
[29.513398] 2个由 modprobe 保持的锁/612:
[29.517417]#0:(Rio_mport_list_lock){++.+}、位于:[ ] RIO_INIT_MPORTS+0x34/0x2a4
[29.525923]#1:(RIO_CONFIG_LOCK){…… },位于:[ ] RIO_MPORT_READ_CONFIG_32+0x40/0xa0
[29.534770] IRQ 事件戳:18684
[29.538179] Hardirqs 上次启用时间:(18683):[ ]_raW_spin_unlock_irqrestore+0x6c/0x74
[29.547093] Hardirqs last disabledat (18684):[ ]_raW_spin_lock_irqsave+0x1c/0x58
[29.555569]上次启用的软件地址为(16960):[ ]__do_softirq+0x234/0x2b0
[29.563346]最后禁用的软通道数(16937):[] ] IRQ_EXIT+0xd8/0x114
[29.570687]在以下位置禁用抢占:[<(null)>](null)
[29.576019]
[29.577513] CPU:0 PID:612 Comm:modprobe proged: G W 4.4.3.32-W1CMC-g1c11a44-mis脏#53
[29.586679]硬件名称:KeyStone
[29.590183][ ](展开回扫)从[ ](show_stack+0x10/0x14)
[29.597957][ ](show_stack)从[ ](dump_stack+0x98/0xc4)
[29.605208][ ](dump_stack)从[ ](mutex_lock_nested_0x30/0x4b4)
[29.613157][ ](mutex_lock_nested)从[ ](KeySton_Rio_maint_read+0x12c/0x400)
[29.622326][ ](KeySton_Rio_maint_read)、来自[ ](keyston_Rio_config_read+0x34/0x3c)
[29.631931][ ](keyston_Rio_config_read)、来自[ ](RIO_MPORT_READ_CONFIG_32+0x74/0xa0)
[29.641623][ ](RIO_MPORT_READ_CONFIG_32)、来自[ ](RIO_MPORT_CHK_DEV_ACCESS_0x44/0x74)
[29.651322][ ](RIO_mport_chk_dev_access)、来自[ ](RIO_ENUM_PEER +0x34/0x76c [RIO_SCAN])
[29.661111][ ](RIO_ENUM_PEER [RIO_SCAN])、从[ ](RIO_ENUM_MPORT+0x134/0x2b8 [RIO_SCAN])
[29.671071][ ](RIO_ENUM_Mport [RIO_SCAN])、从[ ](RIO_INIT_MPORTS+0x9C/0x2a4)
[29.680157][ ](RIO_INIT_Mports)、来自[ ](RIO_BASIC ATT+0x34/0x40 [RIO_SCAN])
[29.689332][ ](RIO_BASE_Attach [RIO_SCAN])、从[ ](do_One_initcall+bc/0x204)
[29.698590][ ](多个_initcall)、来自[ ](DO_INIT_MODULE+0x60/0x3a4)
[29.706713][ ](DO_INIT_MODULE)从[ ](load_module+0x1dc8/0x2370)
[29.714748][ ](LOAD_MODULE)从[ ](SYS_FINIT_MODULE+0x8c/0xc8)
[29.722609][ ](sys_finIT_module)从[ ](RET_FAST_SYSCALL+0x0/0x1c)

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    这个补丁似乎解决了这个问题:使用 GFP_Atomic 并将互斥量转换为一个自旋锁。

    diff -git a/drivers/RapidIO/devices/keyston_Rio。c b/drivers/RapidIO/devices/keyston_erio.c index 9288d2a.e165ff8 100644 -- a/drivers/RapidIO/devices/keyston_Rio ++ b/drivers/RapidIO/rio/devices/rio_keyston_port_ron_ron_712,7t rio_rio_t ron_t rio/keystell @@@@ t_rio/rio_ron_port_rio_ron_rio_r&t rio/rio/ridt7 u32 packet_type =((info & 0xFFFF)<< 16) | KeySton_Rio_packet_type_DBELL; - spin_lock (&Krio_priv->LSU_lock_maint); + mutex_lock (&Krio_priv->LSU_lock_maint); RES = keyston_Rio_LSU_start_transfer (Krio_priv->LSU_maint、 mport->index、 dest_id、 @@-725,7+725,77 @@ static int keyston_Rio dmBell_send (struct Rio mport * mport、 1、 Krio_priv); 如果(分辨率){ - spin_unlock (&Krio_priv->LSU_lock_maint); + mutex_unlock (&Krio_priv->LSU_lock_maint); DEV_ERR(Krio_priv->dev、"DIO:发送门铃错误%d\n"、res); 返回 res; } @@-746、7 +746、7 @@静态 int keyston_Rio_dBell_send (struct Rio_mport * mport、 nDelay (keyston_rio_timeout_nsec); } - spin_unlock (&Krio_priv->LSU_lock_maint); + mutex_unlock (&Krio_priv->LSU_lock_maint); DEV_INFO (Krio_priv->dev、"DIO:发送门铃完成%u\n"、count); 返回 res; @@-788,7+788,7 @@ static inline int keyston_Rio_maint_request() u32计数= 0; u32 type =((hopcount & 0xff)<< 8)|(packet_type & 0xff); - spin_lock (&Krio_priv->LSU_lock_maint); + mutex_lock (&Krio_priv->LSU_lock_maint); RES = keyston_Rio_LSU_start_transfer (Krio_priv->LSU_maint、 port_id、 @@-802,7+802,7 @@ static inline int keyston_Rio _maint_request ( 0、 Krio_priv); 如果(分辨率){ - spin_unlock (&Krio_priv->LSU_lock_maint); + mutex_unlock (&Krio_priv->LSU_lock_maint); DEV_ERR(Krio_priv->dev、"maintenance packet transfer error\n"); 返回 res; } @@-823、7 +823、7 @@静态内联 int keyston_Rio _maint_request ( nDelay (keyston_rio_timeout_nsec); } - spin_unlock (&Krio_priv->LSU_lock_maint); + mutex_unlock (&Krio_priv->LSU_lock_maint); 返回分辨率; } @@-843,15 +843,11 @@静态 int keyston_rio_maint_read (struct keyston_rio_data * Krio_priv, struct device *dev = Krio_priv->dev; size_t align_len = l1_cache_align (len); - tbuf = kzalloc (align_len、GFP_Atomic | GFP_DMA); + tbuf = kzalloc (align_len、GFP_kernel | GFP_DMA); 如果(!tbuf) return -ENOMEM; dma = dma_map_single (dev、tbuf、len、dma_far_device); - if (dma_mapping _error (dev、dma)){ - kfree (tbuf); - 返回-ENOMEM; -} RES = KeySton_Rio_maint_request (port_id、 destid、 @@-902,7 +898,7 @@ static int keyston_rio_maint_write (struct keyston_rio_data * krio_priv, struct device *dev = Krio_priv->dev; size_t align_len = l1_cache_align (len); - tbuf = kzalloc (align_len、GFP_Atomic | GFP_DMA); + tbuf = kzalloc (align_len、GFP_kernel | GFP_DMA); 如果(!tbuf) return -ENOMEM; @@-920、10 +916、6 @@ static int keyston_rio_maint_write (struct keyston_rio_data * Krio_priv、 } dma = dma_map_single (dev、tbuf、len、dma_to_device); - if (dma_mapping _error (dev、dma)){ - kfree (tbuf); - 返回-ENOMEM; -} RES = KeySton_Rio_maint_request (port_id、 destid、 @@-3305、7 +3297、7 @@静态 int keyston_Rio_probe (struct platform_device * pdev) Krio_priv->LSU_free = Krio_priv->LSU_start; Krio_priv->LSU_maint = keyston_rio_LSU_alloc (Krio_priv); - spin_lock_init (&Krio_priv->LSU_lock_maint); + mutex_init (&Krio_priv->LSU_lock_maint); spin_lock_init (&Krio_priv->port_chk_lock); diff --git a/drivers/RapidIO/devices/keystone_rio.h b/drivers/RapidIO/devices/keystone_rio.h index 556a5c2..d19efc8 100644 -- a/drivers/RapidIO/devices/keystone_rio.h ++ ridio/devices/+ 4、48t/ridt/rio/keystone_rio.h @@@@驱动程序4、48t/rio/rio/ridt/rio/rio/rio/key4、48t/rio/rio/ridt/ridt/rio/r u32. 校准; /*防止并发 LSU 主访问*/ - 自旋锁_t LSU_LOCK_maint; + 结构互斥量 LSU_LOCK_maint; U8. LSU_START; U8. LSU_END; U8. LSU_FREE;

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    抱歉,补丁程序上的-/+被反转。 我将互斥量转换为自旋锁并在 kzalloc 中提供 GFP_Atomic。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    您好、Charles、

    感谢您共享该补丁。

    此致、
    帕维尔