Linux 内核稀疏 - 警告:转换为受限 __le64

问题描述 投票:0回答:1

构建 Linux 内核源代码的

/drivers/staging/vt6655
部分时:

make M=drivers/staging/vt6655 C=2

sparse
抱怨
drivers/staging/vt6655/card.c:302:45: warning: cast to restricted __le64

我的任务是为此创建一个补丁。

我熟悉:little endian、big endian、u64、le64_to_cpu、__force 等'....
但是,我找不到在不失去“代码完整性”的情况下修复此警告的解决方案。

这是包含有问题的转换的函数:

bool card_update_tsf(struct vnt_private *priv, unsigned char rx_rate, u64 qwBSSTimestamp)
{
    u64 local_tsf;
    u64 qwTSFOffset = 0;

    local_tsf = vt6655_get_current_tsf(priv);

    if (qwBSSTimestamp != local_tsf) {
        qwTSFOffset = CARDqGetTSFOffset(rx_rate, qwBSSTimestamp,
                        local_tsf);
        /* adjust TSF, HW's TSF add TSF Offset reg */
        qwTSFOffset =  (__force u64)le64_to_cpu(qwTSFOffset);
        iowrite32((u32)qwTSFOffset, priv->port_offset + MAC_REG_TSFOFST);
        iowrite32((u32)(qwTSFOffset >> 32), priv->port_offset + MAC_REG_TSFOFST + 4);
        vt6655_mac_reg_bits_on(priv->port_offset, MAC_REG_TFTCTL, TFTCTL_TSFSYNCEN);
    }
    return true;
}
c linux-kernel endianness
1个回答
0
投票

Sparse 是一个旨在通过静态分析发现 Linux 内核代码中潜在问题的工具。当 Sparse 警告“强制转换为受限制的

__le64
”时,通常表示特定于字节序的代码存在类型安全问题。

__le64
类型是为小端字节顺序的 64 位值定义的。当您执行到
__le64
的转换时,您应该确定该值采用该类型的正确字节顺序。该警告表明您正在将值转换为
__le64
,但未确保其采用小端格式,这可能会导致大端系统上的数据损坏。

有问题的线路是:

qwTSFOffset =  (__force u64)le64_to_cpu(qwTSFOffset);

这里,

le64_to_cpu()
已经将 64 位小端值转换为 CPU 的本机端格式。如果
__force u64
在此调用后要保持 CPU 的本机字节序格式,则转换为
qwTSFOffset
是不必要且不正确的,这似乎是这种情况,因为您在本机中使用
iowrite32()
将其写入 IO 内存字节序。

要修复警告而不丢失“代码完整性”,您应该删除

__force
强制转换。你的代码应该是:

qwTSFOffset = le64_to_cpu(qwTSFOffset);

这是更正后的函数:

bool card_update_tsf(struct vnt_private *priv, unsigned char rx_rate, u64 qwBSSTimestamp)
{
    u64 local_tsf;
    u64 qwTSFOffset = 0;

    local_tsf = vt6655_get_current_tsf(priv);

    if (qwBSSTimestamp != local_tsf) {
        qwTSFOffset = CARDqGetTSFOffset(rx_rate, qwBSSTimestamp, local_tsf);

        // Convert little-endian TSF offset to CPU's endianness
        qwTSFOffset = le64_to_cpu(qwTSFOffset);

        // Write lower 32-bits of the TSF offset
        iowrite32((u32)qwTSFOffset, priv->port_offset + MAC_REG_TSFOFST);
        // Write upper 32-bits of the TSF offset
        iowrite32((u32)(qwTSFOffset >> 32), priv->port_offset + MAC_REG_TSFOFST + 4);

        // Enable TSF sync
        vt6655_mac_reg_bits_on(priv->port_offset, MAC_REG_TFTCTL, TFTCTL_TSFSYNCEN);
    }
    return true;
}

此更改应该会删除稀疏警告。如果您打算将其作为补丁提交到 Linux 内核,请确保遵循内核的编码风格并根据内核的补丁提交流程进行提交。

© www.soinside.com 2019 - 2024. All rights reserved.