5-sphinx.addnodesdocument)}( rawsourcechildren]( translations LanguagesNode)}(hhh](h pending_xref)}(hhh]docutils.nodesTextEnglish}parenthsba attributes}(ids]classes]names]dupnames]backrefs] refdomainstdreftypedoc reftarget/driver-api/io_orderingmodnameN classnameN refexplicitutagnamehhh ubh)}(hhh]hChinese (Traditional)}hh2sbah}(h]h ]h"]h$]h&] refdomainh)reftypeh+ reftarget*/translations/zh_TW/driver-api/io_orderingmodnameN classnameN refexplicituh1hhh ubh)}(hhh]hItalian}hhFsbah}(h]h ]h"]h$]h&] refdomainh)reftypeh+ reftarget*/translations/it_IT/driver-api/io_orderingmodnameN classnameN refexplicituh1hhh ubh)}(hhh]hJapanese}hhZsbah}(h]h ]h"]h$]h&] refdomainh)reftypeh+ reftarget*/translations/ja_JP/driver-api/io_orderingmodnameN classnameN refexplicituh1hhh ubh)}(hhh]hKorean}hhnsbah}(h]h ]h"]h$]h&] refdomainh)reftypeh+ reftarget*/translations/ko_KR/driver-api/io_orderingmodnameN classnameN refexplicituh1hhh ubh)}(hhh]hSpanish}hhsbah}(h]h ]h"]h$]h&] refdomainh)reftypeh+ reftarget*/translations/sp_SP/driver-api/io_orderingmodnameN classnameN refexplicituh1hhh ubeh}(h]h ]h"]h$]h&]current_languageChinese (Simplified)uh1h hh _documenthsourceNlineNubhcomment)}(h SPDX-License-Identifier: GPL-2.0h]h SPDX-License-Identifier: GPL-2.0}hhsbah}(h]h ]h"]h$]h&] xml:spacepreserveuh1hhhhhhW/var/lib/git/docbuild/linux/Documentation/translations/zh_CN/driver-api/io_ordering.rsthKubhnote)}(hX{此文件的目的是为让中文读者更容易阅读和理解,而不是作为一个分支。 因此, 如果您对此文件有任何意见或更新,请先尝试更新原始英文文件。 如果您发现本文档与原始文件有任何不同或者有翻译问题,请发建议或者补丁给 该文件的译者,或者请求中文文档维护者和审阅者的帮助。h]h paragraph)}(hX{此文件的目的是为让中文读者更容易阅读和理解,而不是作为一个分支。 因此, 如果您对此文件有任何意见或更新,请先尝试更新原始英文文件。 如果您发现本文档与原始文件有任何不同或者有翻译问题,请发建议或者补丁给 该文件的译者,或者请求中文文档维护者和审阅者的帮助。h]hX{此文件的目的是为让中文读者更容易阅读和理解,而不是作为一个分支。 因此, 如果您对此文件有任何意见或更新,请先尝试更新原始英文文件。 如果您发现本文档与原始文件有任何不同或者有翻译问题,请发建议或者补丁给 该文件的译者,或者请求中文文档维护者和审阅者的帮助。}(hhhhhNhNubah}(h]h ]h"]h$]h&]uh1hh5Documentation/translations/zh_CN/disclaimer-zh_CN.rsthKhhubah}(h]h ]h"]h$]h&]uh1hhhhhhhhNubh field_list)}(hhh](hfield)}(hhh](h field_name)}(hOriginalh]hOriginal}(hhhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhhhKubh field_body)}(h)Documentation/driver-api/io_ordering.rst h]h)}(h(Documentation/driver-api/io_ordering.rsth]h(Documentation/driver-api/io_ordering.rst}(hhhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhhubah}(h]h ]h"]h$]h&]uh1hhhubeh}(h]h ]h"]h$]h&]uh1hhhhKhhhhubh)}(hhh](h)}(h翻译h]h翻译}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhj hhhKubh)}(h\林永听 Lin Yongting 司延腾 Yanteng Si h]h)}(h[林永听 Lin Yongting 司延腾 Yanteng Si h](h林永听 Lin Yongting <}(hj hhhNhNubh reference)}(hlinyongting@gmail.comh]hlinyongting@gmail.com}(hj*hhhNhNubah}(h]h ]h"]h$]h&]refurimailto:linyongting@gmail.comuh1j(hj ubh> 司延腾 Yanteng Si <}(hj hhhNhNubj))}(hsiyanteng@loongson.cnh]hsiyanteng@loongson.cn}(hj>hhhNhNubah}(h]h ]h"]h$]h&]refurimailto:siyanteng@loongson.cnuh1j(hj ubh>}(hj hhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhK hjubah}(h]h ]h"]h$]h&]uh1hhj ubeh}(h]h ]h"]h$]h&]uh1hhhhKhhhhubh)}(hhh](h)}(h校译h]h校译}(hjghhhNhNubah}(h]h ]h"]h$]h&]uh1hhjdhhhKubh)}(hhh]h}(h]h ]h"]h$]h&]uh1hhjdubeh}(h]h ]h"]h$]h&]uh1hhhhK hhhhubeh}(h]h ]h"]h$]h&]uh1hhhhhhhhKubhsection)}(hhh](htitle)}(h'对内存映射地址的I/O写入排序h]h'对内存映射地址的I/O写入排序}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jhjhhhhhKubh)}(hXJ在某些平台上,所谓的内存映射I/O是弱顺序。在这些平台上,驱动开发者有责任 保证I/O内存映射地址的写操作按程序图意的顺序达到设备。通常读取一个“安全” 设备寄存器或桥寄存器,触发IO芯片清刷未处理的写操作到达设备后才处理读操作, 而达到保证目的。驱动程序通常在spinlock保护的临界区退出之前使用这种技术。 这也可以保证后面的写操作只在前面的写操作之后到达设备(这非常类似于内存 屏障操作,mb(),不过仅适用于I/O)。h]hXJ在某些平台上,所谓的内存映射I/O是弱顺序。在这些平台上,驱动开发者有责任 保证I/O内存映射地址的写操作按程序图意的顺序达到设备。通常读取一个“安全” 设备寄存器或桥寄存器,触发IO芯片清刷未处理的写操作到达设备后才处理读操作, 而达到保证目的。驱动程序通常在spinlock保护的临界区退出之前使用这种技术。 这也可以保证后面的写操作只在前面的写操作之后到达设备(这非常类似于内存 屏障操作,mb(),不过仅适用于I/O)。}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjhhubh)}(h,假设一个设备驱动程的具体例子::h]h+假设一个设备驱动程的具体例子:}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjhhubh literal_block)}(hXz ... CPU A: spin_lock_irqsave(&dev_lock, flags) CPU A: val = readl(my_status); CPU A: ... CPU A: writel(newval, ring_ptr); CPU A: spin_unlock_irqrestore(&dev_lock, flags) ... CPU B: spin_lock_irqsave(&dev_lock, flags) CPU B: val = readl(my_status); CPU B: ... CPU B: writel(newval2, ring_ptr); CPU B: spin_unlock_irqrestore(&dev_lock, flags) ...h]hXz ... CPU A: spin_lock_irqsave(&dev_lock, flags) CPU A: val = readl(my_status); CPU A: ... CPU A: writel(newval, ring_ptr); CPU A: spin_unlock_irqrestore(&dev_lock, flags) ... CPU B: spin_lock_irqsave(&dev_lock, flags) CPU B: val = readl(my_status); CPU B: ... CPU B: writel(newval2, ring_ptr); CPU B: spin_unlock_irqrestore(&dev_lock, flags) ...}hjsbah}(h]h ]h"]h$]h&]hhuh1jhhhKhjhhubh)}(h上述例子中,设备可能会先接收到newval2的值,然后接收到newval的值,问题就 发生了。不过很容易通过下面方法来修复::h]h上述例子中,设备可能会先接收到newval2的值,然后接收到newval的值,问题就 发生了。不过很容易通过下面方法来修复:}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhK)hjhhubj)}(hX ... CPU A: spin_lock_irqsave(&dev_lock, flags) CPU A: val = readl(my_status); CPU A: ... CPU A: writel(newval, ring_ptr); CPU A: (void)readl(safe_register); /* 配置寄存器?*/ CPU A: spin_unlock_irqrestore(&dev_lock, flags) ... CPU B: spin_lock_irqsave(&dev_lock, flags) CPU B: val = readl(my_status); CPU B: ... CPU B: writel(newval2, ring_ptr); CPU B: (void)readl(safe_register); /* 配置寄存器?*/ CPU B: spin_unlock_irqrestore(&dev_lock, flags)h]hX ... CPU A: spin_lock_irqsave(&dev_lock, flags) CPU A: val = readl(my_status); CPU A: ... CPU A: writel(newval, ring_ptr); CPU A: (void)readl(safe_register); /* 配置寄存器?*/ CPU A: spin_unlock_irqrestore(&dev_lock, flags) ... CPU B: spin_lock_irqsave(&dev_lock, flags) CPU B: val = readl(my_status); CPU B: ... CPU B: writel(newval2, ring_ptr); CPU B: (void)readl(safe_register); /* 配置寄存器?*/ CPU B: spin_unlock_irqrestore(&dev_lock, flags)}hjsbah}(h]h ]h"]h$]h&]hhuh1jhhhK,hjhhubh)}(h在解决方案中,读取safe_register寄存器,触发IO芯片清刷未处理的写操作, 再处理后面的读操作,防止引发数据不一致问题。h]h在解决方案中,读取safe_register寄存器,触发IO芯片清刷未处理的写操作, 再处理后面的读操作,防止引发数据不一致问题。}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhK;hjhhubeh}(h]i-oah ]h"]'对内存映射地址的i/o写入排序ah$]h&]uh1jhhhhhhhKubeh}(h]h ]h"]h$]h&]sourcehuh1hcurrent_sourceN current_lineNsettingsdocutils.frontendValues)}(jN generatorN datestampN source_linkN source_urlN toc_backlinksentryfootnote_backlinksK sectnum_xformKstrip_commentsNstrip_elements_with_classesN strip_classesN report_levelK halt_levelKexit_status_levelKdebugNwarning_streamN tracebackinput_encoding utf-8-siginput_encoding_error_handlerstrictoutput_encodingutf-8output_encoding_error_handlerj error_encodingutf-8error_encoding_error_handlerbackslashreplace language_codeenrecord_dependenciesNconfigN id_prefixhauto_id_prefixid dump_settingsNdump_internalsNdump_transformsNdump_pseudo_xmlNexpose_internalsNstrict_visitorN_disable_configN_sourceh _destinationN _config_files]7/var/lib/git/docbuild/linux/Documentation/docutils.confafile_insertion_enabled raw_enabledKline_length_limitM'pep_referencesN pep_base_urlhttps://peps.python.org/pep_file_url_templatepep-%04drfc_referencesN rfc_base_url&https://datatracker.ietf.org/doc/html/ tab_widthKtrim_footnote_reference_spacesyntax_highlightlong smart_quotessmartquotes_locales]character_level_inline_markupdoctitle_xform docinfo_xformKsectsubtitle_xform image_loadinglinkembed_stylesheetcloak_email_addressessection_self_linkenvNubreporterNindirect_targets]substitution_defs}substitution_names}refnames}refids}nameids}jjs nametypes}jsh}jjs footnote_refs} citation_refs} autofootnotes]autofootnote_refs]symbol_footnotes]symbol_footnote_refs] footnotes] citations]autofootnote_startKsymbol_footnote_startK id_counter collectionsCounter}Rparse_messages]transform_messages] transformerN include_log];Documentation/translations/zh_CN/driver-api/io_ordering.rst(NNNNta decorationNhhub.