设备驱动的兼容性,例如cpu_to_le16函数

本文探讨了Linux 2.1内核的重要更新,包括改进的中断管理机制,位操作函数的变化,新增的转换函数以及内存重映射函数的更名。这些改动提升了系统的稳定性和性能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 中断管理

  在2.1的开发中,有些Linux内部被修改了。新核心提供了对内部锁的很好的管理;通过使用几个细粒度的锁,而不是全局的锁,竞争条件被避免了,这样也获得了更好的性能----特别是SMP配置下。更细的锁机制的一个结果是intr_count不再存在了。2.1.34抛弃了这个全局变量,而布尔函数in_interrupt可以取而代之(这个函数从2.1.30开始存在)。目前,in_interrupt是在头文件中声明的宏,这个头文件又包含在中。头文件sysdep-2.1.h用intr_count的名义定义了in_interrupt以获得对2.0的向后兼容性。

  注意虽然in_interrupt是个整数,intr_count却是个unsigned long,因此,如果你想打印这个值,并在2.0和2.1间可移植,你必须强制将这个值转换为一个显式的类型,并在调用printk时指定一个合适的格式。在2.1.37中中断管理又引入了一个不同:快和慢中断处理程序不再存在了。SA_INTERRUPT不被新版本的request_irq使用,但它在处理程序执行以前仍然控制着中断是否被打开。如果几个处理程序共享一个中断线,每个可以是个不同的“类型”。中断打开与否依赖于第一个被调用的处理程序。当中断处理程序存在时,下半部总是执行。

  位操作

  2.1.37稍微改变了在中定义的位操作的作用。现在函数set_bit及其相关者返回void,而新的类似test_and_set_bit的函数已被引入。新的函数集有如下原型:

  

void set_bit(int nr, volatile void * addr); 
void clear_bit(int nr, volatile void * addr); 
void change_bit(int nr, volatile void * addr); 

int test_and_set_bit(int nr, volatile void * addr); 
int test_and_clear_bit(int nr, volatile void * addr); 
int test_and_change_bit(int nr, volatile void * addr); 
int test_bit(nr, addr);

  如果你想获得与2.0的后向兼容性,你可以在你的模块中包含sysdep-2.1.h,并使用新的原型。

  转换函数

  版本2.1.10引入了一个新的转换函数,在中声明。这些函数可以用来访问多字节值,只要这个值已知是小印地安字节序或大印地安字节序。因为这些函数为写驱动程序代码提供了很好的快捷方式,头文件sysdep-2.1.h在较早的版本就已经定义了它们。2.1核心源码提供的本身实现比sysdep-2.1.h提供的可移植的实现要快,因为它可以利用体系相关的功能。

  新函数对应下面的原型,其中le表示小印地安字节序,be表示大印地安字节序。注意编译器并不强制严格的数据类型化,因为大多数函数都是预处理宏;下面给出的类型仅供参考。

  

__u16 cpu_to_le16(__u16 cpu_val); 
       __u32 cpu_to_le32(__u32 cpu_val); 
       __u16 cpu_to_be16(__u16 cpu_val); 
       __u32 cpu_to_be32(__u32 cpu_val); 
       __u16 le16_to_cpu(__u16 le_val); 
       __u32 le32_to_cpu(__u32 le_val); 
       __u16 be16_to_cpu(__u16 be_val); 
       __u32 be32_to_cpu(__u32 be_val);

  这些函数在处理二进制数据流时很有用(例如文件系统数据或存在接口板中的信息),这些函数在处理二进制数据流时很有用(例如文件系统数据或存在接口板中的信息),版本2.1.43又增加了两个新的转换函数集。这些集允许你用指针获取一个值,或是对参数指定的一个值进行就地转换。对应与16位小印地安字节序的函数又如下的原型;类似的函数对其它类型的整数也存在,导致一共16个函数。

  

__u16 cpu_to_le16p(__u16 *addr) 
       __u16 le16_to_cpup(__u16 *addr) 
       void cpu_to_le16s(__u16 *addr) 
       void le16_to_cpus(__u16 *addr)

  “p”函数类似与指针的复引用,但在需要时转换这个值;“s”函数可以在原地转换一个值的印地安字节序(例如,cpu_to_le16s(addr) 和addr=cpu_to_le16(*addr)完成的工作是一样的)。

  这些函数也在sysdep-2.1.h中定义了。为了避免双重解释的副作用,这个头文件用线入函数,而不是预处理宏。

  

vremap<b></b> 
vremap

  “把握内存”中“vmalloc和朋友们”一节描述的vremap函数在版本2.1中得到一个新名字。新函数ioremap只是名字变了,它与旧的remap取同样的参数。响应的释放函数是iounmap,它代替vfree来释放被重映射的地址。这个改变是为了明确这个函数的实际作用:将I/O空间重映射到核心空间的一个虚地址。头文件sysdep-2.1.h强化了这种新规则,当在2.0版本编译时,它#define了ioremap和iounmap到它们2.0的对应者。

int ath10k_wmi_event_mgmt_rx(struct ath10k *ar, struct sk_buff *skb) { struct wmi_mgmt_rx_ev_arg arg = {}; struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); struct ieee80211_hdr *hdr; struct ieee80211_supported_band *sband; u32 rx_status; u32 channel; u32 phy_mode; u32 snr, rssi; u32 rate; u16 fc; int ret, i; ret = ath10k_wmi_pull_mgmt_rx(ar, skb, &arg); if (ret) { ath10k_warn(ar, "failed to parse mgmt rx event: %d\n", ret); dev_kfree_skb(skb); return ret; } channel = __le32_to_cpu(arg.channel); rx_status = __le32_to_cpu(arg.status); snr = __le32_to_cpu(arg.snr); phy_mode = __le32_to_cpu(arg.phy_mode); rate = __le32_to_cpu(arg.rate); memset(status, 0, sizeof(*status)); ath10k_dbg(ar, ATH10K_DBG_MGMT, "event mgmt rx status %08x\n", rx_status); if ((test_bit(ATH10K_CAC_RUNNING, &ar->dev_flags)) || (rx_status & (WMI_RX_STATUS_ERR_DECRYPT | WMI_RX_STATUS_ERR_KEY_CACHE_MISS | WMI_RX_STATUS_ERR_CRC))) { dev_kfree_skb(skb); return 0; } if (rx_status & WMI_RX_STATUS_ERR_MIC) status->flag |= RX_FLAG_MMIC_ERROR; if (rx_status & WMI_RX_STATUS_EXT_INFO) { status->mactime = __le64_to_cpu(arg.ext_info.rx_mac_timestamp); status->flag |= RX_FLAG_MACTIME_END; } /* Hardware can Rx CCK rates on 5GHz. In that case phy_mode is set to * MODE_11B. This means phy_mode is not a reliable source for the band * of mgmt rx. */ if (channel >= 1 && channel <= 14) { status->band = NL80211_BAND_2GHZ; } else if (channel >= 36 && channel <= ATH10K_MAX_5G_CHAN) { status->band = NL80211_BAND_5GHZ; } else { /* Shouldn't happen unless list of advertised channels to * mac80211 has been changed. */ WARN_ON_ONCE(1); dev_kfree_skb(skb); return 0; } if (phy_mode == MODE_11B && status->band == NL80211_BAND_5GHZ) ath10k_dbg(ar, ATH10K_DBG_MGMT, "wmi mgmt rx 11b (CCK) on 5GHz\n"); sband = &ar->mac.sbands[status->band]; status->freq = ieee80211_channel_to_frequency(channel, status->band); status->signal = snr + ATH10K_DEFAULT_NOISE_FLOOR; BUILD_BUG_ON(ARRAY_SIZE(status->chain_signal) != ARRAY_SIZE(arg.rssi)); for (i = 0; i < ARRAY_SIZE(status->chain_signal); i++) { status->chains &= ~BIT(i); rssi = __le32_to_cpu(arg.rssi[i]); ath10k_dbg(ar, ATH10K_DBG_MGMT, "mgmt rssi[%d]:%d\n", i, arg.rssi[i]); if (rssi != ATH10K_INVALID_RSSI && rssi != 0) { status->chain_signal[i] = ATH10K_DEFAULT_NOISE_FLOOR + rssi; status->chains |= BIT(i); } } status->rate_idx = ath10k_mac_bitrate_to_idx(sband, rate / 100); hdr = (struct ieee80211_hdr *)skb->data; fc = le16_to_cpu(hdr->frame_control); /* Firmware is guaranteed to report all essential management frames via * WMI while it can deliver some extra via HTT. Since there can be * duplicates split the reporting wrt monitor/sniffing. */ status->flag |= RX_FLAG_SKIP_MONITOR; ath10k_wmi_handle_wep_reauth(ar, skb, status); if (ath10k_wmi_rx_is_decrypted(ar, hdr)) { status->flag |= RX_FLAG_DECRYPTED; if (!ieee80211_is_action(hdr->frame_control) && !ieee80211_is_deauth(hdr->frame_control) && !ieee80211_is_disassoc(hdr->frame_control)) { status->flag |= RX_FLAG_IV_STRIPPED | RX_FLAG_MMIC_STRIPPED; hdr->frame_control = __cpu_to_le16(fc & ~IEEE80211_FCTL_PROTECTED); } } if (ieee80211_is_beacon(hdr->frame_control)) ath10k_mac_handle_beacon(ar, skb); if (ieee80211_is_beacon(hdr->frame_control) || ieee80211_is_probe_resp(hdr->frame_control)) status->boottime_ns = ktime_get_boottime_ns(); ath10k_dbg(ar, ATH10K_DBG_MGMT, "event mgmt rx skb %pK len %d ftype %02x stype %02x\n", skb, skb->len, fc & IEEE80211_FCTL_FTYPE, fc & IEEE80211_FCTL_STYPE); ath10k_dbg(ar, ATH10K_DBG_MGMT, "event mgmt rx freq %d band %d snr %d, rate_idx %d\n", status->freq, status->band, status->signal, status->rate_idx); ieee80211_rx_ni(ar->hw, skb); return 0; }这个函数在做什么
04-09
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值