[
  {
    "path": ".dockerignore",
    "content": "# Generated files\n**/__pycache__\ntags\n/.cache/\n.idea/\nenv\nvenv/\n.venv/\n**/*.py[cod]\n\n**/*.db\n**/repo\n**/data\n\n.git\n.gitignore\n.gitattributes\n\n# Editor and other backup files\n**/*.swp\n**/*~\n**/~*\n"
  },
  {
    "path": ".editorconfig",
    "content": "# see https://editorconfig.org for the format of this file\nroot = true\n\n[*]\nend_of_line = LF\nindent_style = space\nindent_size = 4\n"
  },
  {
    "path": ".gitignore",
    "content": "# Generated files\n__pycache__\ntags\n/.cache/\n.idea/\nenv/\nvenv/\n/data/\n\n# Web-specific\nhttp/images\nhttp/*.html\nhttp/favicon.ico\nhttp/robots.txt\n\n# Editor and other backup files\n*.swp\n*~\n~*\n.envrc\n"
  },
  {
    "path": ".mailmap",
    "content": "Christopher White <cxwembedded@gmail.com>\nChristopher White <cxwembedded@gmail.com> <cwhite@d3engineering.com>\nMichael Opdenacker <michael.opdenacker@bootlin.com> <michael@bootlin.com>\nMichael Opdenacker <michael.opdenacker@bootlin.com> <michael@free-electrons.com>\nMichael Opdenacker <michael.opdenacker@bootlin.com> <michael.opdenacker@free-electrons.com>\nMikaël Bouillot <mikael.bouillot@bootlin.com> <jxaojeib@corbac.com>\nMikaël Bouillot <mikael.bouillot@bootlin.com> <mikael.bouillot@free-electrons.com>\n"
  },
  {
    "path": ".travis.yml",
    "content": "# .travis.yml for Elixir, https://github.com/bootlin/elixir\nlanguage: python\n\nos:\n  - linux\n\ndist:\n  - jammy\n\npython:\n  - \"3.10\"\n\nbefore_install:\n  - sudo apt-get -y install libdb-dev python3-pytest libjansson4 universal-ctags\n  - pip install jinja2 pygments bsddb3 falcon\n\nscript:\n  - prove -v\n"
  },
  {
    "path": "CHANGELOG.adoc",
    "content": "= Elixir Changelog\n\n== 2024-08 - WSGI update\n\n* Migrated Elixir from a CGI-based architecture to a WSGI-based architecture. This should improve performance.\n* Python files were moved from `./http` to `./elixir`.\n* Made autocomplete use a prefix search that's native for the database. This should massively improve autocomplete performance.\n\nChanges to configuration of most HTTP servers will be required.\nSome HTTP servers may not support WSGI natively and may require a separate WSGI server to proxy to\n(for example, lighthttpd and nginx do not support WSGI, but you can proxy requests to uWSGI).\nWe also recommend using Python virtual environments to manage dependencies.\nCheck \"Manual Installation\" section of README for details.\n\n== 2025-03 - Query refactor\n\nThe query tool was extracted to utils/query.py. Example call: `python3 -m utils.query file v6.8 /README'.\nVersion and cmd (file/ident) parameters changed order, to allow for commands that do not take version as a parameter.\n\n"
  },
  {
    "path": "COPYING",
    "content": "                    GNU AFFERO GENERAL PUBLIC LICENSE\n                       Version 3, 19 November 2007\n\n Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>\n Everyone is permitted to copy and distribute verbatim copies\n of this license document, but changing it is not allowed.\n\n                            Preamble\n\n  The GNU Affero General Public License is a free, copyleft license for\nsoftware and other kinds of works, specifically designed to ensure\ncooperation with the community in the case of network server software.\n\n  The licenses for most software and other practical works are designed\nto take away your freedom to share and change the works.  By contrast,\nour General Public Licenses are intended to guarantee your freedom to\nshare and change all versions of a program--to make sure it remains free\nsoftware for all its users.\n\n  When we speak of free software, we are referring to freedom, not\nprice.  Our General Public Licenses are designed to make sure that you\nhave the freedom to distribute copies of free software (and charge for\nthem if you wish), that you receive source code or can get it if you\nwant it, that you can change the software or use pieces of it in new\nfree programs, and that you know you can do these things.\n\n  Developers that use our General Public Licenses protect your rights\nwith two steps: (1) assert copyright on the software, and (2) offer\nyou this License which gives you legal permission to copy, distribute\nand/or modify the software.\n\n  A secondary benefit of defending all users' freedom is that\nimprovements made in alternate versions of the program, if they\nreceive widespread use, become available for other developers to\nincorporate.  Many developers of free software are heartened and\nencouraged by the resulting cooperation.  However, in the case of\nsoftware used on network servers, this result may fail to come about.\nThe GNU General Public License permits making a modified version and\nletting the public access it on a server without ever releasing its\nsource code to the public.\n\n  The GNU Affero General Public License is designed specifically to\nensure that, in such cases, the modified source code becomes available\nto the community.  It requires the operator of a network server to\nprovide the source code of the modified version running there to the\nusers of that server.  Therefore, public use of a modified version, on\na publicly accessible server, gives the public access to the source\ncode of the modified version.\n\n  An older license, called the Affero General Public License and\npublished by Affero, was designed to accomplish similar goals.  This is\na different license, not a version of the Affero GPL, but Affero has\nreleased a new version of the Affero GPL which permits relicensing under\nthis license.\n\n  The precise terms and conditions for copying, distribution and\nmodification follow.\n\n                       TERMS AND CONDITIONS\n\n  0. Definitions.\n\n  \"This License\" refers to version 3 of the GNU Affero General Public License.\n\n  \"Copyright\" also means copyright-like laws that apply to other kinds of\nworks, such as semiconductor masks.\n\n  \"The Program\" refers to any copyrightable work licensed under this\nLicense.  Each licensee is addressed as \"you\".  \"Licensees\" and\n\"recipients\" may be individuals or organizations.\n\n  To \"modify\" a work means to copy from or adapt all or part of the work\nin a fashion requiring copyright permission, other than the making of an\nexact copy.  The resulting work is called a \"modified version\" of the\nearlier work or a work \"based on\" the earlier work.\n\n  A \"covered work\" means either the unmodified Program or a work based\non the Program.\n\n  To \"propagate\" a work means to do anything with it that, without\npermission, would make you directly or secondarily liable for\ninfringement under applicable copyright law, except executing it on a\ncomputer or modifying a private copy.  Propagation includes copying,\ndistribution (with or without modification), making available to the\npublic, and in some countries other activities as well.\n\n  To \"convey\" a work means any kind of propagation that enables other\nparties to make or receive copies.  Mere interaction with a user through\na computer network, with no transfer of a copy, is not conveying.\n\n  An interactive user interface displays \"Appropriate Legal Notices\"\nto the extent that it includes a convenient and prominently visible\nfeature that (1) displays an appropriate copyright notice, and (2)\ntells the user that there is no warranty for the work (except to the\nextent that warranties are provided), that licensees may convey the\nwork under this License, and how to view a copy of this License.  If\nthe interface presents a list of user commands or options, such as a\nmenu, a prominent item in the list meets this criterion.\n\n  1. Source Code.\n\n  The \"source code\" for a work means the preferred form of the work\nfor making modifications to it.  \"Object code\" means any non-source\nform of a work.\n\n  A \"Standard Interface\" means an interface that either is an official\nstandard defined by a recognized standards body, or, in the case of\ninterfaces specified for a particular programming language, one that\nis widely used among developers working in that language.\n\n  The \"System Libraries\" of an executable work include anything, other\nthan the work as a whole, that (a) is included in the normal form of\npackaging a Major Component, but which is not part of that Major\nComponent, and (b) serves only to enable use of the work with that\nMajor Component, or to implement a Standard Interface for which an\nimplementation is available to the public in source code form.  A\n\"Major Component\", in this context, means a major essential component\n(kernel, window system, and so on) of the specific operating system\n(if any) on which the executable work runs, or a compiler used to\nproduce the work, or an object code interpreter used to run it.\n\n  The \"Corresponding Source\" for a work in object code form means all\nthe source code needed to generate, install, and (for an executable\nwork) run the object code and to modify the work, including scripts to\ncontrol those activities.  However, it does not include the work's\nSystem Libraries, or general-purpose tools or generally available free\nprograms which are used unmodified in performing those activities but\nwhich are not part of the work.  For example, Corresponding Source\nincludes interface definition files associated with source files for\nthe work, and the source code for shared libraries and dynamically\nlinked subprograms that the work is specifically designed to require,\nsuch as by intimate data communication or control flow between those\nsubprograms and other parts of the work.\n\n  The Corresponding Source need not include anything that users\ncan regenerate automatically from other parts of the Corresponding\nSource.\n\n  The Corresponding Source for a work in source code form is that\nsame work.\n\n  2. Basic Permissions.\n\n  All rights granted under this License are granted for the term of\ncopyright on the Program, and are irrevocable provided the stated\nconditions are met.  This License explicitly affirms your unlimited\npermission to run the unmodified Program.  The output from running a\ncovered work is covered by this License only if the output, given its\ncontent, constitutes a covered work.  This License acknowledges your\nrights of fair use or other equivalent, as provided by copyright law.\n\n  You may make, run and propagate covered works that you do not\nconvey, without conditions so long as your license otherwise remains\nin force.  You may convey covered works to others for the sole purpose\nof having them make modifications exclusively for you, or provide you\nwith facilities for running those works, provided that you comply with\nthe terms of this License in conveying all material for which you do\nnot control copyright.  Those thus making or running the covered works\nfor you must do so exclusively on your behalf, under your direction\nand control, on terms that prohibit them from making any copies of\nyour copyrighted material outside their relationship with you.\n\n  Conveying under any other circumstances is permitted solely under\nthe conditions stated below.  Sublicensing is not allowed; section 10\nmakes it unnecessary.\n\n  3. Protecting Users' Legal Rights From Anti-Circumvention Law.\n\n  No covered work shall be deemed part of an effective technological\nmeasure under any applicable law fulfilling obligations under article\n11 of the WIPO copyright treaty adopted on 20 December 1996, or\nsimilar laws prohibiting or restricting circumvention of such\nmeasures.\n\n  When you convey a covered work, you waive any legal power to forbid\ncircumvention of technological measures to the extent such circumvention\nis effected by exercising rights under this License with respect to\nthe covered work, and you disclaim any intention to limit operation or\nmodification of the work as a means of enforcing, against the work's\nusers, your or third parties' legal rights to forbid circumvention of\ntechnological measures.\n\n  4. Conveying Verbatim Copies.\n\n  You may convey verbatim copies of the Program's source code as you\nreceive it, in any medium, provided that you conspicuously and\nappropriately publish on each copy an appropriate copyright notice;\nkeep intact all notices stating that this License and any\nnon-permissive terms added in accord with section 7 apply to the code;\nkeep intact all notices of the absence of any warranty; and give all\nrecipients a copy of this License along with the Program.\n\n  You may charge any price or no price for each copy that you convey,\nand you may offer support or warranty protection for a fee.\n\n  5. Conveying Modified Source Versions.\n\n  You may convey a work based on the Program, or the modifications to\nproduce it from the Program, in the form of source code under the\nterms of section 4, provided that you also meet all of these conditions:\n\n    a) The work must carry prominent notices stating that you modified\n    it, and giving a relevant date.\n\n    b) The work must carry prominent notices stating that it is\n    released under this License and any conditions added under section\n    7.  This requirement modifies the requirement in section 4 to\n    \"keep intact all notices\".\n\n    c) You must license the entire work, as a whole, under this\n    License to anyone who comes into possession of a copy.  This\n    License will therefore apply, along with any applicable section 7\n    additional terms, to the whole of the work, and all its parts,\n    regardless of how they are packaged.  This License gives no\n    permission to license the work in any other way, but it does not\n    invalidate such permission if you have separately received it.\n\n    d) If the work has interactive user interfaces, each must display\n    Appropriate Legal Notices; however, if the Program has interactive\n    interfaces that do not display Appropriate Legal Notices, your\n    work need not make them do so.\n\n  A compilation of a covered work with other separate and independent\nworks, which are not by their nature extensions of the covered work,\nand which are not combined with it such as to form a larger program,\nin or on a volume of a storage or distribution medium, is called an\n\"aggregate\" if the compilation and its resulting copyright are not\nused to limit the access or legal rights of the compilation's users\nbeyond what the individual works permit.  Inclusion of a covered work\nin an aggregate does not cause this License to apply to the other\nparts of the aggregate.\n\n  6. Conveying Non-Source Forms.\n\n  You may convey a covered work in object code form under the terms\nof sections 4 and 5, provided that you also convey the\nmachine-readable Corresponding Source under the terms of this License,\nin one of these ways:\n\n    a) Convey the object code in, or embodied in, a physical product\n    (including a physical distribution medium), accompanied by the\n    Corresponding Source fixed on a durable physical medium\n    customarily used for software interchange.\n\n    b) Convey the object code in, or embodied in, a physical product\n    (including a physical distribution medium), accompanied by a\n    written offer, valid for at least three years and valid for as\n    long as you offer spare parts or customer support for that product\n    model, to give anyone who possesses the object code either (1) a\n    copy of the Corresponding Source for all the software in the\n    product that is covered by this License, on a durable physical\n    medium customarily used for software interchange, for a price no\n    more than your reasonable cost of physically performing this\n    conveying of source, or (2) access to copy the\n    Corresponding Source from a network server at no charge.\n\n    c) Convey individual copies of the object code with a copy of the\n    written offer to provide the Corresponding Source.  This\n    alternative is allowed only occasionally and noncommercially, and\n    only if you received the object code with such an offer, in accord\n    with subsection 6b.\n\n    d) Convey the object code by offering access from a designated\n    place (gratis or for a charge), and offer equivalent access to the\n    Corresponding Source in the same way through the same place at no\n    further charge.  You need not require recipients to copy the\n    Corresponding Source along with the object code.  If the place to\n    copy the object code is a network server, the Corresponding Source\n    may be on a different server (operated by you or a third party)\n    that supports equivalent copying facilities, provided you maintain\n    clear directions next to the object code saying where to find the\n    Corresponding Source.  Regardless of what server hosts the\n    Corresponding Source, you remain obligated to ensure that it is\n    available for as long as needed to satisfy these requirements.\n\n    e) Convey the object code using peer-to-peer transmission, provided\n    you inform other peers where the object code and Corresponding\n    Source of the work are being offered to the general public at no\n    charge under subsection 6d.\n\n  A separable portion of the object code, whose source code is excluded\nfrom the Corresponding Source as a System Library, need not be\nincluded in conveying the object code work.\n\n  A \"User Product\" is either (1) a \"consumer product\", which means any\ntangible personal property which is normally used for personal, family,\nor household purposes, or (2) anything designed or sold for incorporation\ninto a dwelling.  In determining whether a product is a consumer product,\ndoubtful cases shall be resolved in favor of coverage.  For a particular\nproduct received by a particular user, \"normally used\" refers to a\ntypical or common use of that class of product, regardless of the status\nof the particular user or of the way in which the particular user\nactually uses, or expects or is expected to use, the product.  A product\nis a consumer product regardless of whether the product has substantial\ncommercial, industrial or non-consumer uses, unless such uses represent\nthe only significant mode of use of the product.\n\n  \"Installation Information\" for a User Product means any methods,\nprocedures, authorization keys, or other information required to install\nand execute modified versions of a covered work in that User Product from\na modified version of its Corresponding Source.  The information must\nsuffice to ensure that the continued functioning of the modified object\ncode is in no case prevented or interfered with solely because\nmodification has been made.\n\n  If you convey an object code work under this section in, or with, or\nspecifically for use in, a User Product, and the conveying occurs as\npart of a transaction in which the right of possession and use of the\nUser Product is transferred to the recipient in perpetuity or for a\nfixed term (regardless of how the transaction is characterized), the\nCorresponding Source conveyed under this section must be accompanied\nby the Installation Information.  But this requirement does not apply\nif neither you nor any third party retains the ability to install\nmodified object code on the User Product (for example, the work has\nbeen installed in ROM).\n\n  The requirement to provide Installation Information does not include a\nrequirement to continue to provide support service, warranty, or updates\nfor a work that has been modified or installed by the recipient, or for\nthe User Product in which it has been modified or installed.  Access to a\nnetwork may be denied when the modification itself materially and\nadversely affects the operation of the network or violates the rules and\nprotocols for communication across the network.\n\n  Corresponding Source conveyed, and Installation Information provided,\nin accord with this section must be in a format that is publicly\ndocumented (and with an implementation available to the public in\nsource code form), and must require no special password or key for\nunpacking, reading or copying.\n\n  7. Additional Terms.\n\n  \"Additional permissions\" are terms that supplement the terms of this\nLicense by making exceptions from one or more of its conditions.\nAdditional permissions that are applicable to the entire Program shall\nbe treated as though they were included in this License, to the extent\nthat they are valid under applicable law.  If additional permissions\napply only to part of the Program, that part may be used separately\nunder those permissions, but the entire Program remains governed by\nthis License without regard to the additional permissions.\n\n  When you convey a copy of a covered work, you may at your option\nremove any additional permissions from that copy, or from any part of\nit.  (Additional permissions may be written to require their own\nremoval in certain cases when you modify the work.)  You may place\nadditional permissions on material, added by you to a covered work,\nfor which you have or can give appropriate copyright permission.\n\n  Notwithstanding any other provision of this License, for material you\nadd to a covered work, you may (if authorized by the copyright holders of\nthat material) supplement the terms of this License with terms:\n\n    a) Disclaiming warranty or limiting liability differently from the\n    terms of sections 15 and 16 of this License; or\n\n    b) Requiring preservation of specified reasonable legal notices or\n    author attributions in that material or in the Appropriate Legal\n    Notices displayed by works containing it; or\n\n    c) Prohibiting misrepresentation of the origin of that material, or\n    requiring that modified versions of such material be marked in\n    reasonable ways as different from the original version; or\n\n    d) Limiting the use for publicity purposes of names of licensors or\n    authors of the material; or\n\n    e) Declining to grant rights under trademark law for use of some\n    trade names, trademarks, or service marks; or\n\n    f) Requiring indemnification of licensors and authors of that\n    material by anyone who conveys the material (or modified versions of\n    it) with contractual assumptions of liability to the recipient, for\n    any liability that these contractual assumptions directly impose on\n    those licensors and authors.\n\n  All other non-permissive additional terms are considered \"further\nrestrictions\" within the meaning of section 10.  If the Program as you\nreceived it, or any part of it, contains a notice stating that it is\ngoverned by this License along with a term that is a further\nrestriction, you may remove that term.  If a license document contains\na further restriction but permits relicensing or conveying under this\nLicense, you may add to a covered work material governed by the terms\nof that license document, provided that the further restriction does\nnot survive such relicensing or conveying.\n\n  If you add terms to a covered work in accord with this section, you\nmust place, in the relevant source files, a statement of the\nadditional terms that apply to those files, or a notice indicating\nwhere to find the applicable terms.\n\n  Additional terms, permissive or non-permissive, may be stated in the\nform of a separately written license, or stated as exceptions;\nthe above requirements apply either way.\n\n  8. Termination.\n\n  You may not propagate or modify a covered work except as expressly\nprovided under this License.  Any attempt otherwise to propagate or\nmodify it is void, and will automatically terminate your rights under\nthis License (including any patent licenses granted under the third\nparagraph of section 11).\n\n  However, if you cease all violation of this License, then your\nlicense from a particular copyright holder is reinstated (a)\nprovisionally, unless and until the copyright holder explicitly and\nfinally terminates your license, and (b) permanently, if the copyright\nholder fails to notify you of the violation by some reasonable means\nprior to 60 days after the cessation.\n\n  Moreover, your license from a particular copyright holder is\nreinstated permanently if the copyright holder notifies you of the\nviolation by some reasonable means, this is the first time you have\nreceived notice of violation of this License (for any work) from that\ncopyright holder, and you cure the violation prior to 30 days after\nyour receipt of the notice.\n\n  Termination of your rights under this section does not terminate the\nlicenses of parties who have received copies or rights from you under\nthis License.  If your rights have been terminated and not permanently\nreinstated, you do not qualify to receive new licenses for the same\nmaterial under section 10.\n\n  9. Acceptance Not Required for Having Copies.\n\n  You are not required to accept this License in order to receive or\nrun a copy of the Program.  Ancillary propagation of a covered work\noccurring solely as a consequence of using peer-to-peer transmission\nto receive a copy likewise does not require acceptance.  However,\nnothing other than this License grants you permission to propagate or\nmodify any covered work.  These actions infringe copyright if you do\nnot accept this License.  Therefore, by modifying or propagating a\ncovered work, you indicate your acceptance of this License to do so.\n\n  10. Automatic Licensing of Downstream Recipients.\n\n  Each time you convey a covered work, the recipient automatically\nreceives a license from the original licensors, to run, modify and\npropagate that work, subject to this License.  You are not responsible\nfor enforcing compliance by third parties with this License.\n\n  An \"entity transaction\" is a transaction transferring control of an\norganization, or substantially all assets of one, or subdividing an\norganization, or merging organizations.  If propagation of a covered\nwork results from an entity transaction, each party to that\ntransaction who receives a copy of the work also receives whatever\nlicenses to the work the party's predecessor in interest had or could\ngive under the previous paragraph, plus a right to possession of the\nCorresponding Source of the work from the predecessor in interest, if\nthe predecessor has it or can get it with reasonable efforts.\n\n  You may not impose any further restrictions on the exercise of the\nrights granted or affirmed under this License.  For example, you may\nnot impose a license fee, royalty, or other charge for exercise of\nrights granted under this License, and you may not initiate litigation\n(including a cross-claim or counterclaim in a lawsuit) alleging that\nany patent claim is infringed by making, using, selling, offering for\nsale, or importing the Program or any portion of it.\n\n  11. Patents.\n\n  A \"contributor\" is a copyright holder who authorizes use under this\nLicense of the Program or a work on which the Program is based.  The\nwork thus licensed is called the contributor's \"contributor version\".\n\n  A contributor's \"essential patent claims\" are all patent claims\nowned or controlled by the contributor, whether already acquired or\nhereafter acquired, that would be infringed by some manner, permitted\nby this License, of making, using, or selling its contributor version,\nbut do not include claims that would be infringed only as a\nconsequence of further modification of the contributor version.  For\npurposes of this definition, \"control\" includes the right to grant\npatent sublicenses in a manner consistent with the requirements of\nthis License.\n\n  Each contributor grants you a non-exclusive, worldwide, royalty-free\npatent license under the contributor's essential patent claims, to\nmake, use, sell, offer for sale, import and otherwise run, modify and\npropagate the contents of its contributor version.\n\n  In the following three paragraphs, a \"patent license\" is any express\nagreement or commitment, however denominated, not to enforce a patent\n(such as an express permission to practice a patent or covenant not to\nsue for patent infringement).  To \"grant\" such a patent license to a\nparty means to make such an agreement or commitment not to enforce a\npatent against the party.\n\n  If you convey a covered work, knowingly relying on a patent license,\nand the Corresponding Source of the work is not available for anyone\nto copy, free of charge and under the terms of this License, through a\npublicly available network server or other readily accessible means,\nthen you must either (1) cause the Corresponding Source to be so\navailable, or (2) arrange to deprive yourself of the benefit of the\npatent license for this particular work, or (3) arrange, in a manner\nconsistent with the requirements of this License, to extend the patent\nlicense to downstream recipients.  \"Knowingly relying\" means you have\nactual knowledge that, but for the patent license, your conveying the\ncovered work in a country, or your recipient's use of the covered work\nin a country, would infringe one or more identifiable patents in that\ncountry that you have reason to believe are valid.\n\n  If, pursuant to or in connection with a single transaction or\narrangement, you convey, or propagate by procuring conveyance of, a\ncovered work, and grant a patent license to some of the parties\nreceiving the covered work authorizing them to use, propagate, modify\nor convey a specific copy of the covered work, then the patent license\nyou grant is automatically extended to all recipients of the covered\nwork and works based on it.\n\n  A patent license is \"discriminatory\" if it does not include within\nthe scope of its coverage, prohibits the exercise of, or is\nconditioned on the non-exercise of one or more of the rights that are\nspecifically granted under this License.  You may not convey a covered\nwork if you are a party to an arrangement with a third party that is\nin the business of distributing software, under which you make payment\nto the third party based on the extent of your activity of conveying\nthe work, and under which the third party grants, to any of the\nparties who would receive the covered work from you, a discriminatory\npatent license (a) in connection with copies of the covered work\nconveyed by you (or copies made from those copies), or (b) primarily\nfor and in connection with specific products or compilations that\ncontain the covered work, unless you entered into that arrangement,\nor that patent license was granted, prior to 28 March 2007.\n\n  Nothing in this License shall be construed as excluding or limiting\nany implied license or other defenses to infringement that may\notherwise be available to you under applicable patent law.\n\n  12. No Surrender of Others' Freedom.\n\n  If conditions are imposed on you (whether by court order, agreement or\notherwise) that contradict the conditions of this License, they do not\nexcuse you from the conditions of this License.  If you cannot convey a\ncovered work so as to satisfy simultaneously your obligations under this\nLicense and any other pertinent obligations, then as a consequence you may\nnot convey it at all.  For example, if you agree to terms that obligate you\nto collect a royalty for further conveying from those to whom you convey\nthe Program, the only way you could satisfy both those terms and this\nLicense would be to refrain entirely from conveying the Program.\n\n  13. Remote Network Interaction; Use with the GNU General Public License.\n\n  Notwithstanding any other provision of this License, if you modify the\nProgram, your modified version must prominently offer all users\ninteracting with it remotely through a computer network (if your version\nsupports such interaction) an opportunity to receive the Corresponding\nSource of your version by providing access to the Corresponding Source\nfrom a network server at no charge, through some standard or customary\nmeans of facilitating copying of software.  This Corresponding Source\nshall include the Corresponding Source for any work covered by version 3\nof the GNU General Public License that is incorporated pursuant to the\nfollowing paragraph.\n\n  Notwithstanding any other provision of this License, you have\npermission to link or combine any covered work with a work licensed\nunder version 3 of the GNU General Public License into a single\ncombined work, and to convey the resulting work.  The terms of this\nLicense will continue to apply to the part which is the covered work,\nbut the work with which it is combined will remain governed by version\n3 of the GNU General Public License.\n\n  14. Revised Versions of this License.\n\n  The Free Software Foundation may publish revised and/or new versions of\nthe GNU Affero General Public License from time to time.  Such new versions\nwill be similar in spirit to the present version, but may differ in detail to\naddress new problems or concerns.\n\n  Each version is given a distinguishing version number.  If the\nProgram specifies that a certain numbered version of the GNU Affero General\nPublic License \"or any later version\" applies to it, you have the\noption of following the terms and conditions either of that numbered\nversion or of any later version published by the Free Software\nFoundation.  If the Program does not specify a version number of the\nGNU Affero General Public License, you may choose any version ever published\nby the Free Software Foundation.\n\n  If the Program specifies that a proxy can decide which future\nversions of the GNU Affero General Public License can be used, that proxy's\npublic statement of acceptance of a version permanently authorizes you\nto choose that version for the Program.\n\n  Later license versions may give you additional or different\npermissions.  However, no additional obligations are imposed on any\nauthor or copyright holder as a result of your choosing to follow a\nlater version.\n\n  15. Disclaimer of Warranty.\n\n  THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY\nAPPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT\nHOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM \"AS IS\" WITHOUT WARRANTY\nOF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,\nTHE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\nPURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM\nIS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF\nALL NECESSARY SERVICING, REPAIR OR CORRECTION.\n\n  16. Limitation of Liability.\n\n  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING\nWILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS\nTHE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY\nGENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE\nUSE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF\nDATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD\nPARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),\nEVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF\nSUCH DAMAGES.\n\n  17. Interpretation of Sections 15 and 16.\n\n  If the disclaimer of warranty and limitation of liability provided\nabove cannot be given local legal effect according to their terms,\nreviewing courts shall apply local law that most closely approximates\nan absolute waiver of all civil liability in connection with the\nProgram, unless a warranty or assumption of liability accompanies a\ncopy of the Program in return for a fee.\n\n                     END OF TERMS AND CONDITIONS\n\n            How to Apply These Terms to Your New Programs\n\n  If you develop a new program, and you want it to be of the greatest\npossible use to the public, the best way to achieve this is to make it\nfree software which everyone can redistribute and change under these terms.\n\n  To do so, attach the following notices to the program.  It is safest\nto attach them to the start of each source file to most effectively\nstate the exclusion of warranty; and each file should have at least\nthe \"copyright\" line and a pointer to where the full notice is found.\n\n    <one line to give the program's name and a brief idea of what it does.>\n    Copyright (C) <year>  <name of author>\n\n    This program is free software: you can redistribute it and/or modify\n    it under the terms of the GNU Affero General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU Affero General Public License for more details.\n\n    You should have received a copy of the GNU Affero General Public License\n    along with this program.  If not, see <http://www.gnu.org/licenses/>.\n\nAlso add information on how to contact you by electronic and paper mail.\n\n  If your software can interact with users remotely through a computer\nnetwork, you should also make sure that it provides a way for users to\nget its source.  For example, if your program is a web application, its\ninterface could display a \"Source\" link that leads users to an archive\nof the code.  There are many ways you could offer source, and different\nsolutions will be better for different programs; see section 13 for the\nspecific requirements.\n\n  You should also get your employer (if you work as a programmer) or school,\nif any, to sign a \"copyright disclaimer\" for the program, if necessary.\nFor more information on this, and how to apply and follow the GNU AGPL, see\n<http://www.gnu.org/licenses/>.\n"
  },
  {
    "path": "README.adoc",
    "content": "= The Elixir Cross Referencer\n:doctype: book\n:pp: {plus}{plus}\n:toc:\n:toc-placement!:\n\nElixir is a source code cross-referencer inspired by\nhttps://en.wikipedia.org/wiki/LXR_Cross_Referencer[LXR]. It's written\nin Python and its main purpose is to index every release of a C or C{pp}\nproject (like the Linux kernel) while keeping a minimal footprint.\n\nIt uses Git as a source-code file store and Berkeley DB for cross-reference\ndata. Internally, it indexes Git _blobs_ rather than trees of files to avoid\nduplicating work and data. It has a straightforward data structure\n(reminiscent of older LXR releases) to keep queries simple and fast.\n\nYou can see it in action on https://elixir.bootlin.com/\n\nlink:CHANGELOG.adoc[Changelog]\n\ntoc::[]\n\n= Requirements\n\n* Python >= 3.8\n* Git >= 1.9\n* The Jinja2 and Pygments (>= 2.7) Python libraries\n* Berkeley DB (and its Python binding)\n* Universal Ctags\n* Perl (for non-greedy regexes and automated testing)\n* Falcon and `mod_wsgi` (for the REST API)\n\n= Architecture\n\nThe shell script (`script.sh`) is the lower layer and provides commands\nto interact with Git and other Unix utilities. The Python commands use\nthe shell script's services to provide access to the annotated source\ncode and identifier lists (`query.py`) or to create and update the\ndatabases (`update.py`). Finally, the web interface (`web.py`) and\nuses the query interface to generate HTML pages and to answer REST\nqueries, respectively.\n\nWhen installing the system, you should test each layer manually and make\nsure it works correctly before moving on to the next one.\n\n= Manual Installation\n\n== Install Dependencies\n\n____\nFor Debian\n____\n\n----\nsudo apt install python3-pip python3-venv libdb-dev python3-dev build-essential universal-ctags perl git apache2 libapache2-mod-wsgi-py3 libjansson4\n----\n\n== Download Elixir Project\n\n----\ngit clone https://github.com/bootlin/elixir.git /usr/local/elixir/\n----\n\n== Create a virtualenv for Elixir\n\n----\npython -m venv /usr/local/elixir/venv\n. /usr/local/elixir/venv/bin/activate\npip install -r /usr/local/elixir/requirements.txt\n----\n\n== Create directories for project data\n\n----\nmkdir -p /path/elixir-data/linux/repo\nmkdir -p /path/elixir-data/linux/data\n----\n\n== Set environment variables\n\nTwo environment variables are used to tell Elixir where to find the project's\nlocal git repository and its databases:\n\n* `LXR_REPO_DIR` (the git repository directory for your project)\n* `LXR_DATA_DIR` (the database directory for your project)\n\nNow open `/etc/profile` and append the following content.\n\n----\nexport LXR_REPO_DIR=/path/elixir-data/linux/repo\nexport LXR_DATA_DIR=/path/elixir-data/linux/data\n----\n\nAnd then run `source /etc/profile`.\n\n== Clone Kernel source code\n\nFirst clone the master tree released by Linus Torvalds:\n\n----\ncd /path/elixir-data/linux\ngit clone --bare https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git repo\n----\n\nThen, you should also declare a `stable` remote branch corresponding to the `stable` tree, to get all release updates:\n\n----\ncd repo\ngit remote add stable git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git\ngit fetch stable\n----\n\nThen, you can also declare an `history` remote branch corresponding to the old Linux versions not present in the other repos, to get all the old version still available:\n\n----\ncd repo\ngit remote add history https://github.com/bootlin/linux-history.git\ngit fetch history --tags\n----\n\nFeel free to add more remote branches in this way, as Elixir will consider tags from all remote branches.\n\n== First Test\n\n----\ncd /usr/local/elixir/\n./script.sh list-tags\n----\n\n== Create Database\n\n----\n. ./venv/bin/activate\n./update.py <number of threads>\n----\n\n____\nGenerating the full database can take a long time: it takes about 15 hours on a Xeon E3-1245 v5 to index 1800 tags in the Linux kernel. For that reason, you may want to tweak the script (for example, by limiting the number of tags with a \"head\") in order to test the update and query commands. You can even create a new Git repository and just create one tag instead of using the official kernel repository which is very large.\n____\n\n== Second Test\n\nVerify that the queries work:\n\n $ python3 -m utils.query ident v4.10 raw_spin_unlock_irq C\n $ python3 -m utils.query file v4.10 /kernel/sched/clock.c\n\nNOTE: `v4.10` can be replaced with any other tag.\nNOTE: Don't forget to activate the virtual environment!\n\n== Configure httpd\n\nThe CGI interface (`web.py`) is meant to be called from your web\nserver. Since it includes support for indexing multiple projects,\nit expects a different variable (`LXR_PROJ_DIR`) which points to a\ndirectory with a specific structure:\n\n* `<LXR_PROJ_DIR>`\n ** `<project 1>`\n  *** `data`\n  *** `repo`\n ** `<project 2>`\n  *** `data`\n  *** `repo`\n ** `<project 3>`\n  *** `data`\n  *** `repo`\n\nIt will then generate the other two variables upon calling the query\ncommand.\n\nNow replace `/etc/apache2/sites-enabled/000-default.conf` with `docker/000-default.conf`.\nNote: If using httpd (RedHat/Centos) instead of apache2 (Ubuntu/Debian),\nthe default config file to edit is `/etc/httpd/conf.d/elixir.conf`.\n\nFinally, start the httpd server.\n\n----\nsystemctl restart apache2\n----\n\n\n== Configure SELinux policy\n\nWhen running systemd with SELinux enabled, httpd server can only visit limited directories.\nIf your /path/elixir-data/ is not one of these allowed directories, you will be responded with 500 status code.\n\nTo allow httpd server to visit /path/elixir-data/, run following codes:\n----\nchcon -R -t httpd_sys_rw_content_t /path/elixir-data/\n----\n\nTo check if it takes effect, run the following codes:\n----\nls -Z /path/elixir-data/\n----\n\nIn case you want to check SELinux log related with httpd, run the following codes:\n----\naudit2why -a | grep httpd | less\n----\n\n== Configure systemd log directory\n\nBy default, the error log of elixir will be put in /tmp/elixir-errors.\nHowever, systemd enables PrivateTmp by default.\nAnd, the final error directory will be like /tmp/systemd-private-xxxxx-httpd.service-xxxx/tmp/elixir-errors.\nIf you want to disable it, configure httpd.service with the following attribute:\n----\nPrivateTmp=false\n----\n\n== Configuration for other servers\n\nOther HTTP servers (like nginx or lighthttpd) may not support WSGI and may require a separate WSGI server, like uWSGI.\n\nInformation about how to configure uWSGI with Lighthttpd can be found here:\nhttps://redmine.lighttpd.net/projects/lighttpd/wiki/HowToPythonWSGI#Python-WSGI-apps-via-uwsgi-SCGI-FastCGI-or-HTTP-using-the-uWSGI-server\n\nPull requests with example uWSGI configuration for Elixir are welcome.\n\n= REST API usage\n\nAfter configuring httpd, you can test the API usage:\n\n== ident query\n\nSend a get request to `/api/ident/<Project>/<Ident>?version=<version>&family=<family>`.\nFor example:\n\n curl http://127.0.0.1/api/ident/barebox/cdev?version=latest&family=C\n\nThe response body is of the following structure:\n\n----\n{\n    \"definitions\":\n        [{\"path\": \"commands/loadb.c\", \"line\": 71, \"type\": \"variable\"}, ...],\n    \"references\":\n        [{\"path\": \"arch/arm/boards/cm-fx6/board.c\", \"line\": \"64,64,71,72,75\", \"type\": null}, ...]\n}\n----\n\n= Maintenance and enhancements\n\n== Using a cache to improve performance\n\nAt Bootlin, we're using the https://varnish-cache.org/[Varnish http cache]\nas a front-end to reduce the load on the server running the Elixir code.\n\n .-------------.           .---------------.           .-----------------------.\n | Http client | --------> | Varnish cache | --------> | Apache running Elixir |\n '-------------'           '---------------'           '-----------------------'\n\n== Keeping Elixir databases up to date\n\nTo keep your Elixir databases up to date and index new versions that are released,\nwe're proposing to use a script like `index /srv/elixir-data --all` which is called\nthrough a daily cron job.\n\nYou can set `$ELIXIR_THREADS` if you want to change the number of threads used by\nupdate.py for indexing (by default the number of CPUs on your system).\n\n= Building Docker images\n\nDockerfiles are provided in the `docker/` directory.\nTo build the image, run the following commands:\n\n # git clone https://github.com/bootlin/elixir.git ./elixir\n # docker build -t elixir --build-arg ELIXIR_VERSION=`git rev-parse --short HEAD` -f ./elixir/docker/Dockerfile ./elixir\n\nELIXIR_VER build argument is optional. Since .git directory is not copied into Docker image by default,\nthe option is used to pass a version string to Elixir.\n\nYou can then run the image using `docker run`.\nHere we mount a host directory as Elixir data:\n\n # mkdir ./elixir-data\n # docker run -v ./elixir-data/:/srv/elixir-data -d --name elixir-container elixir\n\nThe Docker image does not contain any repositories.\nTo index a repository, you can use the `index-repository` script.\nFor example, to add the https://musl.libc.org/[musl] repository, run:\n\n # docker exec -it elixir-container index /srv/elixir-data musl\n\nOr, to run indexing in a separate container:\n\n # docker run -v ./elixir-data/:/srv/elixir-data \\\n    --entrypoint index elixir /srv/elixir-data musl\n\nYou can also use `index /srv/elixir-data --all` to start indexing all officially supported repositories.\n\nAfter indexing is done, Elixir should be available under the following URL on your host:\nhttp://172.17.0.2/musl/latest/source\n\nIf 172.17.0.2 does not answer, you can check the IP address of the container by running:\n\n # docker inspect elixir-container | grep IPAddress\n\n== Automatic repository updates\n\nThe Docker image does not automatically update repositories by itself.\nYou can, for example, start `index /srv/elixir-data --all` in the container (or in a separate container, with Elixir data volume/directory mounted)\nfrom cron on the host to periodically update repositories.\n\n== Using Docker image as a development server\n\nYou can easily use the Docker image as a development server by following the steps above, but mounting Elixir source directory from the host\ninto `/usr/local/elixir/` in the container when running `docker run elixir`.\n\nChanges in the code made on the host should be automatically reflected in the container.\nYou can use `apache2ctl` to restart Apache.\nError logs are available in `/var/log/apache2/error.log` within the container.\n\n= Hardware requirements\n\nPerformance requirements depend mostly on the amount of traffic that you get\non your Elixir service. However, a fast server also helps for the initial\nindexing of the projects.\n\nSSD storage is strongly recommended because of the frequent access to\ngit repositories.\n\nAt Bootlin, here are a few details about the server we're using:\n\n* As of July 2019, our Elixir service consumes 17 GB of data (supporting all projects),\nor for the Linux kernel alone (version 5.2 being the latest), 12 GB for indexing data,\nand 2 GB for the git repository.\n* We're using an LXD instance with 8 GB of RAM on a cloud server with 8 CPU cores\nrunning at 3.1 GHz.\n\n= Contributing to Elixir\n\n== Supporting a new project\n\nElixir has a very simple modular architecture that allows to support\nnew source code projects by just adding a new file to the Elixir sources.\n\nElixir's assumptions:\n\n* Project sources have to be available in a git repository\n* All project releases are associated to a given git tag. Elixir\nonly considers such tags.\n\nFirst make an installation of Elixir by following the above instructions.\nSee the `projects` subdirectory for projects that are already supported.\n\nOnce Elixir works for at least one project, it's time to clone the git\nrepository for the project you want to support:\n\n cd /srv/git\n git clone --bare https://github.com/zephyrproject-rtos/zephyr\n\nAfter doing this, you may also reference and fetch remote branches for this project,\nfor example corresponding to the `stable` tree for the Linux kernel (see the\ninstructions for Linux earlier in this document).\n\nNow, in your `LXR_PROJ_DIR` directory, create a new directory for the\nnew project:\n\n cd $LXR_PROJ_DIR\n mkdir -p zephyr/data\n ln -s /srv/git/zephyr.git repo\n export LXR_DATA_DIR=$LXR_PROJ_DIR/data\n export LXR_REPO_DIR=$LXR_PROJ_DIR/repo\n\nNow, go back to the Elixir sources and test that tags are correctly\nextracted:\n\n ./script.sh list-tags\n\nDepending on how you want to show the available versions on the Elixir pages,\nyou may have to apply substitutions to each tag string, for example to add\na `v` prefix if missing, for consistency with how other project versions are\nshown. You may also decide to ignore specific tags. All this can be done\nby redefining the default `list_tags()` function in a new `projects/<projectname>.sh`\nfile. Here's an example (`projects/zephyr.sh` file):\n\n list_tags()\n {\n     echo \"$tags\" |\n     grep -v '^zephyr-v'\n }\n\nNote that `<project_name>` *must* match the name of the directory that\nyou created under `LXR_PROJ_DIR`.\n\nThe next step is to make sure that versions are classified as you wish\nin the version menu. This classification work is done through the\n`list_tags_h()` function which generates the output of the `./scripts.sh list-tags -h`\ncommand. Here's what you get for the Linux project:\n\n v4 v4.16 v4.16\n v4 v4.16 v4.16-rc7\n v4 v4.16 v4.16-rc6\n v4 v4.16 v4.16-rc5\n v4 v4.16 v4.16-rc4\n v4 v4.16 v4.16-rc3\n v4 v4.16 v4.16-rc2\n v4 v4.16 v4.16-rc1\n ...\n\nThe first column is the top level menu entry for versions.\nThe second one is the next level menu entry, and\nthe third one is the actual version that can be selected by the menu.\nNote that this third entry must correspond to the exact\nname of the tag in git.\n\nIf the default behavior is not what you want, you will have\nto customize the `list_tags_h` function.\n\nYou should also make sure that Elixir properly identifies\nthe most recent versions:\n\n ./script.sh get-latest-tags | head\n\nIf needed, customize the `get_latest_tags()` function.\n\nIf you want to enable support for `compatible` properties in Devicetree files,\nadd `dts_comp_support=1` at the beginning of `projects/<projectname>.sh`.\n\nYou are now ready to generate Elixir's database for your\nnew project:\n\n ./update.py <number of threads>\n\nYou can then check that Elixir works through your http server.\n\n== Coding style\n\nIf you wish to contribute to Elixir's Python code, please\nfollow the https://www.python.org/dev/peps/pep-0008/[official coding style for Python].\n\n== How to send patches\n\nThe best way to share your contributions with us is to https://github.com/bootlin/elixir/pulls[file a pull\nrequest on GitHub].\n\n= Automated testing\n\nElixir includes a simple test suite in `t/`.  To run it,\nfrom the top-level Elixir directory, run:\n\n prove\n\nThe test suite uses code extracted from Linux v5.4 in `t/tree`.\n\n== Licensing of code in `t/tree`\n\nThe copied code is licensed as described in the https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/plain/COPYING[COPYING] file included with\nLinux.  All the files copied carry SPDX license identifiers of `GPL-2.0+` or\n`GPL-2.0-or-later`.  Per https://www.gnu.org/licenses/gpl-faq.en.html#AllCompatibility[GNU's compatibility table], GPL 2.0+ code can be used\nunder GPLv3 provided the combination is under GPLv3.  Moreover, https://www.gnu.org/licenses/license-list.en.html#AGPLv3.0[GNU's overview\nof AGPLv3] indicates that its terms \"effectively consist of the terms of GPLv3\"\nplus the network-use paragraph.  Therefore, the developers have a good-faith\nbelief that licensing these files under AGPLv3 is authorized.  (See also https://github.com/Freemius/wordpress-sdk/issues/166#issuecomment-310561976[this\nissue comment] for another example of a similar situation.)\n\n= License\n\nElixir is copyright (c) 2017--2020 its contributors.  It is licensed AGPLv3.\nSee the `COPYING` file included with Elixir for details.\n"
  },
  {
    "path": "docker/000-default.conf",
    "content": "<Directory /usr/local/elixir/>\n    AllowOverride None\n    Require all denied\n    <FilesMatch \"wsgi.py\">\n        Require all granted\n    </FilesMatch>\n</Directory>\n<Directory /usr/local/elixir/static/>\n    AllowOverride None\n    Require all granted\n</Directory>\n<VirtualHost *:80>\n    ServerName MY_LOCAL_IP\n    DocumentRoot /usr/local/elixir/\n\n    SetEnv LXR_PROJ_DIR /srv/elixir-data/\n    # restart-interval is 12 hours\n    WSGIDaemonProcess Elixir processes=16 threads=1 \\\n        display-name=%{GROUP} restart-interval=43200 \\\n        home=/usr/local/elixir/ python-home=/usr/local/elixir/venv/\n    WSGIApplicationGroup %{GLOBAL}\n\n    WSGIProcessGroup Elixir\n    WSGIScriptAliasMatch \"^/(?!static/)\" /usr/local/elixir/wsgi.py/$1\n\n    AllowEncodedSlashes On\n    RewriteEngine on\n    RewriteRule \"^/$\" \"/linux/latest/source\" [R]\n    RewriteRule \"^/robots.txt$\" \"/static/robots.txt\" [L]\n    RewriteRule \"^/favicon.ico$\" \"/static/img/favicon.ico\" [L]\n</VirtualHost>\n"
  },
  {
    "path": "docker/Dockerfile",
    "content": "FROM debian:bookworm AS build\n\nRUN \\\n  apt-get update && \\\n  apt-get --no-install-recommends -y install \\\n    git build-essential pkg-config autoconf automake \\\n    python3 python3-pip python3-dev python3-docutils \\\n    libdb-dev \\\n    libseccomp-dev libjansson-dev libyaml-dev libxml2-dev\n\nWORKDIR /build-berkeleydb/\n\n# NOTE wheel version MUST be sycnhronized with requirements.txt\nRUN pip wheel berkeleydb==18.1.10\n\nWORKDIR /build-ctags/\n\nRUN git clone --branch v6.1.0 --depth 1 https://github.com/universal-ctags/ctags.git\nWORKDIR ctags\nRUN ./autogen.sh && ./configure && make -j $(nproc)\n\nFROM debian:bookworm\n\nRUN \\\n  apt-get update && \\\n  apt-get --no-install-recommends -y install \\\n    python3 \\\n    python3-pip \\\n    python3-venv \\\n    libdb5.3 \\\n    perl \\\n    git \\\n    apache2 \\\n    libapache2-mod-wsgi-py3 \\\n    libjansson4 \\\n    libyaml-0-2 \\\n    wget\n\nCOPY ./requirements.txt /usr/local/elixir/\n\nWORKDIR /usr/local/elixir/\n\nCOPY --from=build /build-berkeleydb/berkeleydb-*.whl /tmp/build/\n\nRUN python3 -m venv venv && \\\n    . ./venv/bin/activate && \\\n    pip install /tmp/build/berkeleydb-*.whl && \\\n    pip install -r requirements.txt\n\nCOPY --from=build /build-ctags/ctags/ctags /usr/bin/ctags\n\nRUN mkdir -p /srv/elixir-data/\n\nCOPY ./docker/000-default.conf /etc/apache2/sites-available/000-default.conf\nCOPY ./docker/gitconfig /etc/gitconfig\n\nRUN a2enmod rewrite\n\nEXPOSE 80\n\nARG ELIXIR_VERSION\n\nENV ELIXIR_VERSION=$ELIXIR_VERSION \\\n    ELIXIR_ROOT=/srv/elixir-data \\\n    PATH=\"/usr/local/elixir/utils:/usr/local/elixir/venv/bin:$PATH\" \\\n    PYTHONUNBUFFERED=1\n\nCOPY . /usr/local/elixir/\n\nENTRYPOINT [\"/usr/sbin/apache2ctl\", \"-D\", \"FOREGROUND\"]\n"
  },
  {
    "path": "docker/gitconfig",
    "content": "[safe]\n    directory = *\n"
  },
  {
    "path": "elixir/__init__.py",
    "content": ""
  },
  {
    "path": "elixir/api.py",
    "content": "#!/usr/bin/env python3\n\n#  This file is part of Elixir, a source code cross-referencer.\n#\n#  Copyright (C) 2019--2020 Carmeli Tamir and contributors.\n#\n#  Elixir is free software: you can redistribute it and/or modify\n#  it under the terms of the GNU Affero General Public License as published by\n#  the Free Software Foundation, either version 3 of the License, or\n#  (at your option) any later version.\n#\n#  Elixir is distributed in the hope that it will be useful,\n#  but WITHOUT ANY WARRANTY; without even the implied warranty of\n#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n#  GNU Affero General Public License for more details.\n#\n#  You should have received a copy of the GNU Affero General Public License\n#  along with Elixir.  If not, see <http://www.gnu.org/licenses/>.\n\nimport json\nimport os\n\nimport falcon\nfrom urllib import parse\nimport sys\n\nfrom .query import get_query\nfrom .lib import validFamily\nfrom .web_utils import validate_version\n\nclass ApiIdentGetterResource:\n    def on_get(self, req, resp, project, ident):\n        version = validate_version(req.get_param('version'))\n        if version is None:\n            raise falcon.HTTPInvalidParam('', 'version')\n\n        family = req.get_param('family')\n        if not validFamily(family):\n            family = 'C'\n\n        query = get_query(req.context.config.project_dir, project)\n        if not query:\n            resp.status = falcon.HTTP_NOT_FOUND\n            return\n\n        if version in ('latest', 'latest-rc'):\n            rc = version == 'latest-rc'\n            version = query.get_latest_tag(rc=rc)\n\n        symbol_definitions, symbol_references, symbol_doccomments, _ = query.search_ident(version, ident, family)\n\n        resp.status = falcon.HTTP_200\n        resp.content_type = falcon.MEDIA_JSON\n        resp.media = {\n            'definitions': [sym.__dict__ for sym in symbol_definitions],\n            'references': [sym.__dict__ for sym in symbol_references],\n            'documentations': [sym.__dict__ for sym in symbol_doccomments]\n        }\n\n        query.close()\n\n"
  },
  {
    "path": "elixir/autocomplete.py",
    "content": "#!/usr/bin/env python3\n#  This file is part of Elixir, a source code cross-referencer.\n#\n#  Copyright (C) 2017--2020 Maxime Chretien <maxime.chretien@bootlin.com>\n#                           and contributors.\n#\n#  Elixir is free software: you can redistribute it and/or modify\n#  it under the terms of the GNU Affero General Public License as published by\n#  the Free Software Foundation, either version 3 of the License, or\n#  (at your option) any later version.\n#\n#  Elixir is distributed in the hope that it will be useful,\n#  but WITHOUT ANY WARRANTY; without even the implied warranty of\n#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n#  GNU Affero General Public License for more details.\n#\n#  You should have received a copy of the GNU Affero General Public License\n#  along with Elixir.  If not, see <http://www.gnu.org/licenses/>.\n\nimport sys\nimport os\nimport json\nfrom urllib import parse\nfrom berkeleydb.db import DB_SET_RANGE\nimport falcon\n\nfrom .lib import autoBytes, validFamily\nfrom .query import get_query\nfrom .web_utils import validate_project, validate_ident\n\nclass AutocompleteResource:\n    def on_get(self, req, resp):\n        ident_prefix = req.get_param('q')\n        family = req.get_param('f')\n        project = req.get_param('p')\n\n        ident_prefix = validate_ident(ident_prefix)\n        if ident_prefix is None:\n            raise falcon.HTTPInvalidParam('', 'ident')\n\n        project = validate_project(project)\n        if project is None:\n            raise falcon.HTTPInvalidParam('', 'project')\n\n        if not validFamily(family):\n            family = 'C'\n\n        query = get_query(req.context.config.project_dir, project)\n        if not query:\n            resp.status = falcon.HTTP_NOT_FOUND\n            return\n\n        if family == 'B':\n            # DTS identifiers are stored quoted\n            process = lambda x: parse.unquote(x)\n            db = query.db.comps\n        else:\n            process = lambda x: x\n            db = query.db.defs\n\n        response = []\n\n        i = 0\n        cur = db.db.cursor()\n        query_bytes = autoBytes(parse.quote(ident_prefix))\n        # Find \"the smallest key greater than or equal to the specified key\"\n        # https://docs.oracle.com/cd/E17276_01/html/api_reference/C/dbcget.html\n        # In practice this should mean \"the key that starts with provided prefix\"\n        # See docs about the default comparison function for B-Tree databases:\n        # https://docs.oracle.com/cd/E17276_01/html/api_reference/C/dbset_bt_compare.html\n        key, _ = cur.get(query_bytes, DB_SET_RANGE)\n        while i <= 10:\n            if key.startswith(query_bytes):\n                # If found key starts with the prefix, add to response\n                # and move to the next key\n                i += 1\n                response.append(process(key.decode(\"utf-8\")))\n                key, _ = cur.next()\n            else:\n                # If found key does not start with the prefix, stop\n                break\n\n        resp.status = falcon.HTTP_200\n        resp.content_type = falcon.MEDIA_JSON\n        resp.media = response\n\n        query.close()\n\n"
  },
  {
    "path": "elixir/data.py",
    "content": "#!/usr/bin/env python3\n\n#  This file is part of Elixir, a source code cross-referencer.\n#\n#  Copyright (C) 2017--2020 Mikaël Bouillot <mikael.bouillot@bootlin.com>\n#  and contributors\n#\n#  Elixir is free software: you can redistribute it and/or modify\n#  it under the terms of the GNU Affero General Public License as published by\n#  the Free Software Foundation, either version 3 of the License, or\n#  (at your option) any later version.\n#\n#  Elixir is distributed in the hope that it will be useful,\n#  but WITHOUT ANY WARRANTY; without even the implied warranty of\n#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n#  GNU Affero General Public License for more details.\n#\n#  You should have received a copy of the GNU Affero General Public License\n#  along with Elixir.  If not, see <http://www.gnu.org/licenses/>.\n\nimport berkeleydb\nimport re\nfrom . import lib\nimport os\nimport os.path\nimport errno\n\ndeflist_regex = re.compile(b'(\\d*)(\\w)(\\d*)(\\w),?')\ndeflist_macro_regex = re.compile('\\dM\\d+(\\w)')\n\n##################################################################################\n\ndefTypeR = {\n    'c': 'config',\n    'd': 'define',\n    'e': 'enum',\n    'E': 'enumerator',\n    'f': 'function',\n    'l': 'label',\n    'M': 'macro',\n    'm': 'member',\n    'p': 'prototype',\n    's': 'struct',\n    't': 'typedef',\n    'u': 'union',\n    'v': 'variable',\n    'x': 'externvar'}\n\ndefTypeD = {v: k for k, v in defTypeR.items()}\n\n##################################################################################\n\nmaxId = 999999999\n\nclass DefList:\n    '''Stores associations between a blob ID, a type (e.g., \"function\"),\n        a line number and a file family.\n        Also stores in which families the ident exists for faster tests.'''\n    def __init__(self, data=b'#'):\n        self.data, self.families = data.split(b'#')\n\n    def iter(self, dummy=False):\n        # Get all element in a list of sublists and sort them\n        entries = deflist_regex.findall(self.data)\n        entries.sort(key=lambda x:int(x[0]))\n        for id, type, line, family in entries:\n            id = int(id)\n            type = defTypeR [type.decode()]\n            line = int(line)\n            family = family.decode()\n            yield id, type, line, family\n        if dummy:\n            yield maxId, None, None, None\n\n    def append(self, id, type, line, family):\n        if type not in defTypeD:\n            return\n        p = str(id) + defTypeD[type] + str(line) + family\n        if self.data != b'':\n            p = ',' + p\n        self.data += p.encode()\n        self.add_family(family)\n\n    def pack(self):\n        return self.data + b'#' + self.families\n\n    def add_family(self, family):\n        family = family.encode()\n        if not family in self.families.split(b','):\n            if self.families != b'':\n                family = b',' + family\n            self.families += family\n\n    def get_families(self):\n        return self.families.decode().split(',')\n\n    def get_macros(self):\n        return deflist_macro_regex.findall(self.data.decode()) or ''\n\nclass PathList:\n    '''Stores associations between a blob ID and a file path.\n        Inserted by update.py sorted by blob ID.'''\n    def __init__(self, data=b''):\n        self.data = data\n\n    def iter(self, dummy=False):\n        for p in self.data.split(b'\\n')[:-1]:\n            id, path = p.split(b' ',maxsplit=1)\n            id = int(id)\n            path = path.decode()\n            yield id, path\n        if dummy:\n            yield maxId, None\n\n    def append(self, id, path):\n        p = str(id).encode() + b' ' + path + b'\\n'\n        self.data += p\n\n    def pack(self):\n        return self.data\n\nclass RefList:\n    '''Stores a mapping from blob ID to list of lines\n        and the corresponding family.'''\n    def __init__(self, data=b''):\n        self.data = data\n\n    def iter(self, dummy=False):\n        # Split all elements in a list of sublists and sort them\n        entries = [x.split(b':') for x in self.data.split(b'\\n')[:-1]]\n        entries.sort(key=lambda x:int(x[0]))\n        for b, c, d in entries:\n            b = int(b.decode())\n            c = c.decode()\n            d = d.decode()\n            yield b, c, d\n        if dummy:\n            yield maxId, None, None\n\n    def append(self, id, lines, family):\n        p = str(id) + ':' + lines + ':' + family + '\\n'\n        self.data += p.encode()\n\n    def pack(self):\n        return self.data\n\nclass BsdDB:\n    def __init__(self, filename, readonly, contentType, shared=False):\n        self.filename = filename\n        self.db = berkeleydb.db.DB()\n        flags = berkeleydb.db.DB_THREAD if shared else 0\n\n        if readonly:\n            flags |= berkeleydb.db.DB_RDONLY\n            self.db.open(filename, flags=flags)\n        else:\n            flags |= berkeleydb.db.DB_CREATE\n            self.db.open(filename, flags=flags, mode=0o644, dbtype=berkeleydb.db.DB_BTREE)\n        self.ctype = contentType\n\n    def exists(self, key):\n        key = lib.autoBytes(key)\n        return self.db.exists(key)\n\n    def get(self, key):\n        key = lib.autoBytes(key)\n        p = self.db.get(key)\n        return self.ctype(p) if p is not None else None\n\n    def get_keys(self):\n        return self.db.keys()\n\n    def put(self, key, val, sync=False):\n        key = lib.autoBytes(key)\n        val = lib.autoBytes(val)\n        if type(val) is not bytes:\n            val = val.pack()\n        self.db.put(key, val)\n        if sync:\n            self.db.sync()\n\n    def close(self):\n        self.db.close()\n\n    def __len__(self):\n        return self.db.stat()[\"nkeys\"]\n\nclass DB:\n    def __init__(self, dir, readonly=True, dtscomp=False, shared=False):\n        if os.path.isdir(dir):\n            self.dir = dir\n        else:\n            raise FileNotFoundError(errno.ENOENT, os.strerror(errno.ENOENT), dir)\n\n        ro = readonly\n\n        self.vars = BsdDB(dir + '/variables.db', ro, lambda x: int(x.decode()), shared=shared)\n            # Key-value store of basic information\n        self.blob = BsdDB(dir + '/blobs.db', ro, lambda x: int(x.decode()), shared=shared)\n            # Map hash to sequential integer serial number\n        self.hash = BsdDB(dir + '/hashes.db', ro, lambda x: x, shared=shared)\n            # Map serial number back to hash\n        self.file = BsdDB(dir + '/filenames.db', ro, lambda x: x.decode(), shared=shared)\n            # Map serial number to filename\n        self.vers = BsdDB(dir + '/versions.db', ro, PathList, shared=shared)\n        self.defs = BsdDB(dir + '/definitions.db', ro, DefList, shared=shared)\n        self.defs_cache = {}\n        NOOP = lambda x: x\n        self.defs_cache['C'] = BsdDB(dir + '/definitions-cache-C.db', ro, NOOP, shared=shared)\n        self.defs_cache['K'] = BsdDB(dir + '/definitions-cache-K.db', ro, NOOP, shared=shared)\n        self.defs_cache['D'] = BsdDB(dir + '/definitions-cache-D.db', ro, NOOP, shared=shared)\n        self.defs_cache['M'] = BsdDB(dir + '/definitions-cache-M.db', ro, NOOP, shared=shared)\n        assert sorted(self.defs_cache.keys()) == sorted(lib.CACHED_DEFINITIONS_FAMILIES)\n        self.refs = BsdDB(dir + '/references.db', ro, RefList, shared=shared)\n        self.docs = BsdDB(dir + '/doccomments.db', ro, RefList, shared=shared)\n        self.dtscomp = dtscomp\n        if dtscomp:\n            self.comps = BsdDB(dir + '/compatibledts.db', ro, RefList, shared=shared)\n            self.comps_docs = BsdDB(dir + '/compatibledts_docs.db', ro, RefList, shared=shared)\n            # Use a RefList in case there are multiple doc comments for an identifier\n\n    def close(self):\n        self.vars.close()\n        self.blob.close()\n        self.hash.close()\n        self.file.close()\n        self.vers.close()\n        self.defs.close()\n        self.defs_cache['C'].close()\n        self.defs_cache['K'].close()\n        self.defs_cache['D'].close()\n        self.defs_cache['M'].close()\n        self.refs.close()\n        self.docs.close()\n        if self.dtscomp:\n            self.comps.close()\n            self.comps_docs.close()\n\n"
  },
  {
    "path": "elixir/filters/__init__.py",
    "content": "from typing import List\n\nfrom .utils import Filter, FilterContext\nfrom .projects import project_filters, default_filters\n\n# Returns a list of applicable filters for project_name under provided filter context\ndef get_filters(ctx: FilterContext, project_name: str) -> List[Filter]:\n    filter_classes = project_filters.get(project_name, default_filters)\n    filters = []\n\n    for filter_cls in filter_classes:\n        if type(filter_cls) == tuple and len(filter_cls) == 2:\n            cls, kwargs = filter_cls\n            filters.append(cls(**kwargs))\n        elif type(filter_cls) == type:\n            filters.append(filter_cls())\n        else:\n            raise ValueError(f\"Invalid filter: {filter_cls}, \" \\\n                    \"should be either a two element tuple or a type. \" \\\n                    \"Make sure project_filters in project.py is valid.\")\n\n    return [f for f in filters if f.check_if_applies(ctx)]\n\n"
  },
  {
    "path": "elixir/filters/configin.py",
    "content": "import re\nfrom .utils import Filter, FilterContext, decode_number, encode_number, filename_without_ext_matches\n\n# Filters for Config.in includes\n# source \"path/file\"\n# Example: uclibc-ng/v1.0.47/source/extra/Configs/Config.in#L176\nclass ConfigInFilter(Filter):\n    def __init__(self, *args, **kwargs):\n        super().__init__(*args, **kwargs)\n        self.configin = []\n\n    def check_if_applies(self, ctx) -> bool:\n        return super().check_if_applies(ctx) and \\\n                filename_without_ext_matches(ctx.filepath, {'Config'})\n\n    def transform_raw_code(self, ctx, code: str) -> str:\n        def keep_configin(m):\n            self.configin.append(m.group(4))\n            return f'{ m.group(1) }{ m.group(2) }{ m.group(3) }\"__KEEPCONFIGIN__{ encode_number(len(self.configin)) }\"'\n\n        return re.sub('^(\\s*)(source)(\\s*)\\\"(.*)\\\"', keep_configin, code, flags=re.MULTILINE)\n\n    def untransform_formatted_code(self, ctx: FilterContext, html: str) -> str:\n        def replace_configin(m):\n            w = self.configin[decode_number(m.group(1)) - 1]\n            return f'<a href=\"{ ctx.get_absolute_source_url(w) }\">{ w }</a>'\n\n        return re.sub('__KEEPCONFIGIN__([A-J]+)', replace_configin, html, flags=re.MULTILINE)\n\n"
  },
  {
    "path": "elixir/filters/cppinc.py",
    "content": "import re\nfrom .utils import Filter, FilterContext, encode_number, decode_number, extension_matches\n\n# Filters for cpp includes like these:\n# #include \"file\"\n# Example: musl/v1.2.5/source/src/dirent/dirfd.c#L2\n# #include \"__dirent.h\"\nclass CppIncFilter(Filter):\n    def __init__(self, *args, **kwargs):\n        super().__init__(*args, **kwargs)\n        self.cppinc = []\n\n    def check_if_applies(self, ctx) -> bool:\n        return super().check_if_applies(ctx) and \\\n                extension_matches(ctx.filepath, {'dts', 'dtsi', 'c', 'cc', 'cpp', 'c++', 'cxx', 'h', 's'})\n\n    def transform_raw_code(self, ctx, code: str) -> str:\n        def keep_cppinc(m):\n            self.cppinc.append(m.group(3))\n            return f'{ m.group(1) }#include{ m.group(2) }\"__KEEPCPPINC__{ encode_number(len(self.cppinc)) }\"'\n\n        return re.sub('^(\\s*)#include(\\s*)\\\"(.*?)\\\"', keep_cppinc, code, flags=re.MULTILINE)\n\n    def untransform_formatted_code(self, ctx: FilterContext, html: str) -> str:\n        def replace_cppinc(m):\n            w = self.cppinc[decode_number(m.group(1)) - 1]\n            url = ctx.get_relative_source_url(w)\n            return f'<a href=\"{ url }\">{ w }</a>'\n\n        return re.sub('__KEEPCPPINC__([A-J]+)', replace_cppinc, html, flags=re.MULTILINE)\n\n"
  },
  {
    "path": "elixir/filters/cpppathinc.py",
    "content": "import re\nfrom typing import List\nfrom .utils import Filter, FilterContext, encode_number, decode_number, extension_matches\n\n# Filters for cpp includes like these:\n# #include <file>\n\n# Such filters work typically for standalone projects (like kernels and bootloaders)\n# If we make references to other projects, we could\n# end up with links to headers which are outside the project\n# Example: u-boot/v2023.10/source/env/embedded.c#L16\n# prefix_path: a list of paths, will be used to replace the prefix path during the\n# untransform_formatted_code step\nclass CppPathIncFilter(Filter):\n    def __init__(self, prefix_path: List[str] = [\"include\"], *args, **kwargs):\n        self.prefix_path = prefix_path\n        super().__init__(*args, **kwargs)\n        self.cpppathinc = []\n\n    def check_if_applies(self, ctx) -> bool:\n        return super().check_if_applies(ctx) and \\\n                extension_matches(ctx.filepath, {'dts', 'dtsi', 'c', 'cc', 'cpp', 'c++', 'cxx', 'h', 's'})\n\n    def transform_raw_code(self, ctx, code: str) -> str:\n        def keep_cpppathinc(m):\n            m1 = m.group(1)\n            m2 = m.group(2)\n            inc = m.group(3)\n            if re.match('^asm/.*', inc):\n                # Keep the original string in case the path contains \"asm/\"\n                # Because there are then multiple include possibilites, one per architecture\n                return m.group(0)\n            else:\n                self.cpppathinc.append(inc)\n                return f'{ m1 }#include{ m2 }<__KEEPCPPPATHINC__{ encode_number(len(self.cpppathinc)) }>'\n\n        return re.sub('^(\\s*)#include(\\s*)<(.*?)>', keep_cpppathinc, code, flags=re.MULTILINE)\n\n    def untransform_formatted_code(self, ctx: FilterContext, html: str) -> str:\n        def replace_cpppathinc(m):\n            w = self.cpppathinc[decode_number(m.group(1)) - 1]\n            for p in self.prefix_path:\n                path = f\"/{p}/{w}\"\n                if ctx.query.file_exists(ctx.tag, path):\n                    return f'<a href=\"{ ctx.get_absolute_source_url(path) }\">{ w }</a>'\n            return w\n\n        return re.sub('__KEEPCPPPATHINC__([A-J]+)', replace_cpppathinc, html, flags=re.MULTILINE)\n\n"
  },
  {
    "path": "elixir/filters/defconfig.py",
    "content": "import re\nfrom .utils import Filter, FilterContext, encode_number, decode_number, extension_matches\n\n# Filter for kconfig identifier in defconfigs\n# Replaces defconfig identifiers with links to definitions/references\n# `CONFIG_OPTION=y`\n# Example: u-boot/v2023.10/source/configs/A13-OLinuXino_defconfig#L1\nclass DefConfigIdentsFilter(Filter):\n    def __init__(self, *args, **kwargs):\n        super().__init__(*args, **kwargs)\n        self.defconfigidents = []\n\n    def check_if_applies(self, ctx) -> bool:\n        return super().check_if_applies(ctx) and \\\n                ctx.filepath.endswith('defconfig')\n\n    def transform_raw_code(self, ctx, code: str) -> str:\n        def keep_defconfigidents(m):\n            self.defconfigidents.append(m.group(1))\n            return '__KEEPDEFCONFIGIDENTS__' + encode_number(len(self.defconfigidents))\n\n        return re.sub('(CONFIG_[\\w]+)', keep_defconfigidents, code, flags=re.MULTILINE)\n\n    def untransform_formatted_code(self, ctx: FilterContext, html: str) -> str:\n        def replace_defconfigidents(m):\n            i = self.defconfigidents[decode_number(m.group(1)) - 1]\n            return f'<a class=\"ident\" href=\"{ ctx.get_ident_url(i, \"K\") }\">{ i }</a>'\n\n        return re.sub('__KEEPDEFCONFIGIDENTS__([A-J]+)', replace_defconfigidents, html, flags=re.MULTILINE)\n\n"
  },
  {
    "path": "elixir/filters/dtscompcode.py",
    "content": "import re\nfrom .utils import Filter, FilterContext, encode_number, decode_number, extension_matches\n\n# Filter for DT compatible strings in code (C family) files\n# Finds assigments to properties and variables named 'compatible' and recognized by\n# Query.get_tokenized_file()\n# .compatible = \"device\"\n# Example: u-boot/v2023.10/source/drivers/phy/nop-phy.c#L84\nclass DtsCompCodeFilter(Filter):\n    def __init__(self, *args, **kwargs):\n        super().__init__(*args, **kwargs)\n        self.dtscompC = []\n\n    def check_if_applies(self, ctx) -> bool:\n        return super().check_if_applies(ctx) and \\\n            ctx.query.dts_comp_support and \\\n            extension_matches(ctx.filepath, {'c', 'cc', 'cpp', 'c++', 'cxx', 'h', 's'})\n\n    def transform_raw_code(self, ctx, code: str) -> str:\n        # quit early if source file does not contain any strings that could be an assignment to a 'compatible' property\n        # this is much faster than the match-and-replace regex, especially for big files\n        compatible_search = re.search('\\.(\\033\\[31m)?compatible(\\033\\[0m)?\\s*=', code, flags=re.MULTILINE)\n        if compatible_search is None:\n            return code\n\n        def keep_dtscompC(m):\n            self.dtscompC.append(m.group(4))\n            return f'{ m.group(1) }\"__KEEPDTSCOMPC__{ encode_number(len(self.dtscompC)) }\"'\n\n        return re.sub('(\\s*{*\\s*\\.(\\033\\[31m)?compatible(\\033\\[0m)?\\s*=\\s*)\\\"(.+?)\\\"',\n                      keep_dtscompC, code, flags=re.MULTILINE)\n\n    def untransform_formatted_code(self, ctx: FilterContext, html: str) -> str:\n        def replace_dtscompC(m):\n            i = self.dtscompC[decode_number(m.group(1)) - 1]\n            return f'<a class=\"ident\" href=\"{ ctx.get_ident_url(i, \"B\") }\">{ i }</a>'\n\n        return re.sub('__KEEPDTSCOMPC__([A-J]+)', replace_dtscompC, html, flags=re.MULTILINE)\n\n"
  },
  {
    "path": "elixir/filters/dtscompdocs.py",
    "content": "import re\nfrom urllib.parse import quote\nfrom .utils import Filter, FilterContext, encode_number, decode_number\n\n# Filter for DT compatible strings in documentation (B family) files\n# syscon\n# Example: linux/v6.9.4/source/Documentation/devicetree/bindings/thermal/brcm,avs-ro-thermal.yaml#L17\n# Note that this also finds strings in comments, descriptions and other potentially unrelated properties\nclass DtsCompDocsFilter(Filter):\n    def __init__(self, *args, **kwargs):\n        super().__init__(*args, **kwargs)\n        self.dtscompB = []\n\n    def check_if_applies(self, ctx) -> bool:\n        return super().check_if_applies(ctx) and \\\n            ctx.query.dts_comp_support and \\\n            ctx.filepath.startswith('/Documentation/devicetree/bindings')\n\n    def transform_raw_code(self, ctx, code: str) -> str:\n        def keep_dtscompB(m):\n            text = m.group(1)\n\n            if ctx.query.dts_comp_exists(quote(text)):\n                self.dtscompB.append(text)\n                return f'__KEEPDTSCOMPB__{ encode_number(len(self.dtscompB)) }'\n            else:\n                return m.group(0)\n\n        return re.sub('([\\w-]+,?[\\w-]+)', keep_dtscompB, code, flags=re.MULTILINE)\n\n    def untransform_formatted_code(self, ctx: FilterContext, html: str) -> str:\n        def replace_dtscompB(m):\n            i = self.dtscompB[decode_number(m.group(1)) - 1]\n\n            return f'<a class=\"ident\" href=\"{ ctx.get_ident_url(i, \"B\") }\">{ i }</a>'\n\n        return re.sub('__KEEPDTSCOMPB__([A-J]+)', replace_dtscompB, html, flags=re.MULTILINE)\n\n"
  },
  {
    "path": "elixir/filters/dtscompdts.py",
    "content": "import re\nfrom .utils import Filter, FilterContext, encode_number, decode_number, extension_matches\n\n# Filter for DT compatible strings in DTS (D family) files\n# compatible = \"device\"\n# Example: u-boot/v2023.10/source/arch/arm/dts/ac5-98dx35xx-rd.dts#L37\nclass DtsCompDtsFilter(Filter):\n    def __init__(self, *args, **kwargs):\n        super().__init__(*args, **kwargs)\n        self.dtscompD = []\n\n    def check_if_applies(self, ctx) -> bool:\n        return super().check_if_applies(ctx) and \\\n            ctx.query.dts_comp_support and \\\n            extension_matches(ctx.filepath, {'dts', 'dtsi'})\n\n    def transform_raw_code(self, ctx, code: str) -> str:\n        def sub_func(m):\n            match = m.group(0)\n            strings = re.findall(\"\\\"(.+?)\\\"\", m.group(1))\n\n            for string in strings:\n                self.dtscompD.append(string)\n                match = match.replace(string, '__KEEPDTSCOMPD__' + encode_number(len(self.dtscompD)))\n\n            return match\n\n        return re.sub('\\s*compatible(.*?)$', sub_func, code, flags=re.MULTILINE)\n\n    def untransform_formatted_code(self, ctx: FilterContext, html: str) -> str:\n        def replace_dtscompD(m):\n            i = self.dtscompD[decode_number(m.group(1)) - 1]\n\n            return f'<a class=\"ident\" href=\"{ ctx.get_ident_url(i, \"B\") }\">{ i }</a>'\n\n        return re.sub('__KEEPDTSCOMPD__([A-J]+)', replace_dtscompD, html, flags=re.MULTILINE)\n\n"
  },
  {
    "path": "elixir/filters/dtsi.py",
    "content": "import re\nfrom .utils import Filter, FilterContext, encode_number, decode_number, extension_matches\n\n# Filters for dts includes as follows:\n# Replaces include directives in dts/dtsi files with links to source\n# /include/ \"file\"\n# Example: u-boot/v2023.10/source/arch/powerpc/dts/t1023si-post.dtsi#L12\nclass DtsiFilter(Filter):\n    def __init__(self, *args, **kwargs):\n        super().__init__(*args, **kwargs)\n        self.dtsi = []\n\n    def check_if_applies(self, ctx) -> bool:\n        return super().check_if_applies(ctx) and \\\n                extension_matches(ctx.filepath, {'dts', 'dtsi'})\n\n    def transform_raw_code(self, ctx, code: str) -> str:\n        def keep_dtsi(m):\n            self.dtsi.append(m.group(3))\n            return f'{ m.group(1) }/include/{ m.group(2) }\"__KEEPDTSI__{ encode_number(len(self.dtsi)) }\"'\n\n        return re.sub('^(\\s*)/include/(\\s*)\\\"(.*?)\\\"', keep_dtsi, code, flags=re.MULTILINE)\n\n    def untransform_formatted_code(self, ctx: FilterContext, html: str) -> str:\n        def replace_dtsi(m):\n            w = self.dtsi[decode_number(m.group(1)) - 1]\n            return f'<a href=\"{ ctx.get_relative_source_url(w) }\">{ w }</a>'\n\n        return re.sub('__KEEPDTSI__([A-J]+)', replace_dtsi, html, flags=re.MULTILINE)\n\n"
  },
  {
    "path": "elixir/filters/ident.py",
    "content": "import re\nfrom .utils import Filter, FilterContext, encode_number, decode_number\n\n# Filter for identifier links\n# Replaces identifiers marked by Query.get_tokenized_file() with links to ident page.\n# If Query.get_tokenized_file() detects that a file belongs to a family that can contain\n# indexed identifiers, it processes the file by adding unprintable markers\n# ('\\033[31m' + token + b'\\033[0m') to tokens that have an entry in the definitions\n# database. This filter replaces these marked tokens with links to their ident pages,\n# unless the token starts with CONFIG_ - these tokens are handled by the Kconfig filter.\nclass IdentFilter(Filter):\n    def __init__(self, *args, **kwargs):\n        super().__init__(*args, **kwargs)\n        self.idents = []\n\n    def transform_raw_code(self, ctx, code: str) -> str:\n        def sub_func(m):\n            self.idents.append(m.group(1))\n            return '__KEEPIDENTS__' + encode_number(len(self.idents))\n\n        return re.sub('\\033\\[31m(?!CONFIG_)(.*?)\\033\\[0m', sub_func, code, flags=re.MULTILINE)\n\n    def untransform_formatted_code(self, ctx: FilterContext, html: str) -> str:\n        def sub_func(m):\n            i = self.idents[decode_number(m.group(2)) - 1]\n            link = f'<a class=\"ident\" href=\"{ ctx.get_ident_url(i) }\">{ i }</a>'\n            return str(m.group(1) or '') + link\n\n        return re.sub('__(<.+?>)?KEEPIDENTS__([A-J]+)', sub_func, html, flags=re.MULTILINE)\n\n"
  },
  {
    "path": "elixir/filters/kconfig.py",
    "content": "import re\nfrom .utils import Filter, FilterContext, encode_number, decode_number, filename_without_ext_matches\n\n# Filters for Kconfig includes\n# Replaces KConfig includes (source keyword) with links to included files\n# `source \"path/file\"`\n# Example: u-boot/v2023.10/source/Kconfig#L10\nclass KconfigFilter(Filter):\n    def __init__(self, *args, **kwargs):\n        super().__init__(*args, **kwargs)\n        self.kconfig = []\n\n    def check_if_applies(self, ctx) -> bool:\n        return super().check_if_applies(ctx) and \\\n                filename_without_ext_matches(ctx.filepath, {'Kconfig'})\n\n    def transform_raw_code(self, ctx, code: str) -> str:\n        def keep_kconfig(m):\n            self.kconfig.append(m.group(4))\n            return f'{ m.group(1) }{ m.group(2) }{ m.group(3) }\"__KEEPKCONFIG__{ encode_number(len(self.kconfig)) }\"'\n\n        return re.sub('^(\\s*)(source)(\\s*)\\\"([\\w/_\\.-]+)\\\"', keep_kconfig, code, flags=re.MULTILINE)\n\n    def untransform_formatted_code(self, ctx: FilterContext, html: str) -> str:\n        def replace_kconfig(m):\n            w = self.kconfig[decode_number(m.group(1)) - 1]\n            return f'<a href=\"{ ctx.get_absolute_source_url(w) }\">{ w }</a>'\n\n        return re.sub('__KEEPKCONFIG__([A-J]+)', replace_kconfig, html, flags=re.MULTILINE)\n\n"
  },
  {
    "path": "elixir/filters/kconfigidents.py",
    "content": "import re\nfrom .utils import Filter, FilterContext, encode_number, decode_number\n\n# Filter for kconfig identifier links\n# Replaces KConfig identifiers with links to definitions and references\n# `config OPTION`\n# Example: u-boot/v2023.10/source/Kconfig#L17\n# Note: Prepends identifier with CONFIG_\nclass KconfigIdentsFilter(Filter):\n    def __init__(self, *args, **kwargs):\n        super().__init__(*args, **kwargs)\n        self.kconfigidents = []\n\n    def transform_raw_code(self, ctx, code: str) -> str:\n      def keep_kconfigidents(m):\n          self.kconfigidents.append(m.group(1))\n          return f'__KEEPKCONFIGIDENTS__{ encode_number(len(self.kconfigidents)) }'\n\n      return re.sub('\\033\\[31m(?=CONFIG_)(.*?)\\033\\[0m', keep_kconfigidents, code, flags=re.MULTILINE)\n\n    def untransform_formatted_code(self, ctx: FilterContext, html: str) -> str:\n        def replace_kconfigidents(m):\n            i = self.kconfigidents[decode_number(m.group(2)) - 1]\n\n            n = i\n            #Remove the CONFIG_ when we are in a Kconfig file\n            if ctx.family == 'K':\n                n = n[7:]\n\n            return f'{ m.group(1) or \"\" }<a class=\"ident\" href=\"{ ctx.get_ident_url(i, \"K\") }\">{ n }</a>'\n\n        return re.sub('__(<.+?>)?KEEPKCONFIGIDENTS__([A-J]+)', replace_kconfigidents, html, flags=re.MULTILINE)\n\n"
  },
  {
    "path": "elixir/filters/makefiledir.py",
    "content": "from os.path import dirname\nimport re\nfrom .utils import Filter, FilterContext, decode_number, encode_number, filename_without_ext_matches\n\n# Filters for Makefile directory includes as follows:\n# obj-$(VALUE) += dir/\n# Example: u-boot/v2023.10/source/Makefile#L867\nclass MakefileDirFilter(Filter):\n    def __init__(self, *args, **kwargs):\n        super().__init__(*args, **kwargs)\n        self.makefiledir = []\n\n    def check_if_applies(self, ctx) -> bool:\n        return super().check_if_applies(ctx) and \\\n                filename_without_ext_matches(ctx.filepath, {'Makefile'})\n\n    def transform_raw_code(self, ctx, code: str) -> str:\n        def keep_makefiledir(m):\n            filedir = dirname(ctx.filepath)\n\n            if filedir != '/':\n                filedir += '/'\n\n            if ctx.query.file_exists(ctx.tag, filedir + m.group(1) + '/Makefile'):\n                self.makefiledir.append(m.group(1))\n                return f'__KEEPMAKEFILEDIR__{ encode_number(len(self.makefiledir)) }/{ m.group(2) }'\n            else:\n                return m.group(0)\n\n        return re.sub('(?<=\\s)([-\\w/]+)/(\\s+|$)', keep_makefiledir, code, flags=re.MULTILINE)\n\n    def untransform_formatted_code(self, ctx: FilterContext, html: str) -> str:\n        def replace_makefiledir(m):\n            w = self.makefiledir[decode_number(m.group(1)) - 1]\n            filedir = dirname(ctx.filepath)\n\n            if filedir != '/':\n                filedir += '/'\n\n            fpath = f'{ filedir }{ w }/Makefile'\n\n            return f'<a href=\"{ ctx.get_absolute_source_url(fpath) }\">{ w }/</a>'\n\n        return re.sub('__KEEPMAKEFILEDIR__([A-J]+)/', replace_makefiledir, html, flags=re.MULTILINE)\n\n"
  },
  {
    "path": "elixir/filters/makefiledtb.py",
    "content": "from os.path import dirname\nimport re\nfrom .utils import Filter, FilterContext, decode_number, encode_number, filename_without_ext_matches\n\n# Filters for Makefile file includes like these:\n# dtb-y += file.dtb\n# Example: u-boot/v2023.10/source/Makefile#L992\nclass MakefileDtbFilter(Filter):\n    def __init__(self, *args, **kwargs):\n        super().__init__(*args, **kwargs)\n        self.makefiledtb = []\n\n    def check_if_applies(self, ctx) -> bool:\n        return super().check_if_applies(ctx) and \\\n                filename_without_ext_matches(ctx.filepath, {'Makefile'})\n\n    def transform_raw_code(self, ctx, code: str) -> str:\n        def keep_makefiledtb(m):\n            self.makefiledtb.append(m.group(1))\n            return f'__KEEPMAKEFILEDTB__{ encode_number(len(self.makefiledtb)) }.dtb'\n\n        return re.sub('(?<=\\s)([-\\w/+\\.]+)\\.dtb', keep_makefiledtb, code, flags=re.MULTILINE)\n\n    def untransform_formatted_code(self, ctx: FilterContext, html: str) -> str:\n        def replace_makefiledtb(m):\n            w = self.makefiledtb[decode_number(m.group(1)) - 1]\n            filedir = dirname(ctx.filepath)\n\n            if filedir != '/':\n                filedir += '/'\n\n            npath = f'{ filedir }{ w }.dts'\n            return f'<a href=\"{ ctx.get_absolute_source_url(npath) }\">{ w }.dtb</a>'\n\n        return re.sub('__KEEPMAKEFILEDTB__([A-J]+)\\.dtb', replace_makefiledtb, html, flags=re.MULTILINE)\n\n"
  },
  {
    "path": "elixir/filters/makefilefile.py",
    "content": "from os.path import dirname\nimport re\nfrom .utils import Filter, FilterContext, decode_number, encode_number, filename_without_ext_matches\n\n# Filters for files listed in Makefiles\n# path/file\n# Example: u-boot/v2023.10/source/Makefile#L1509\nclass MakefileFileFilter(Filter):\n    def __init__(self, *args, **kwargs):\n        super().__init__(*args, **kwargs)\n        self.makefilefile = []\n\n    def check_if_applies(self, ctx) -> bool:\n        return super().check_if_applies(ctx) and \\\n                filename_without_ext_matches(ctx.filepath, {'Makefile'})\n\n    def transform_raw_code(self, ctx, code: str) -> str:\n        def keep_makefilefile(m):\n            filedir = dirname(ctx.filepath)\n\n            if filedir != '/':\n                filedir += '/'\n\n            if ctx.query.file_exists(ctx.tag, filedir + m.group(1)):\n                self.makefilefile.append(m.group(1))\n                return f'__KEEPMAKEFILEFILE__{ encode_number(len(self.makefilefile)) }{ m.group(2) }'\n            else:\n                return m.group(0)\n\n        return re.sub('(?:(?<=\\s|=)|(?<=-I))(?!/)([-\\w/]+/[-\\w\\.]+)(\\s+|\\)|$)', keep_makefilefile, code, flags=re.MULTILINE)\n\n    def untransform_formatted_code(self, ctx: FilterContext, html: str) -> str:\n        def replace_makefilefile(m):\n            w = self.makefilefile[decode_number(m.group(1)) - 1]\n            filedir = dirname(ctx.filepath)\n\n            if filedir != '/':\n                filedir += '/'\n\n            npath = filedir + w\n            return f'<a href=\"{ ctx.get_absolute_source_url(npath) }\">{ w }</a>'\n\n        return re.sub('__KEEPMAKEFILEFILE__([A-J]+)', replace_makefilefile, html, flags=re.MULTILINE)\n\n"
  },
  {
    "path": "elixir/filters/makefileo.py",
    "content": "from os.path import dirname\nimport re\nfrom .utils import Filter, FilterContext, decode_number, encode_number, filename_without_ext_matches\n\n# Filters for Makefile file includes like these:\n# file.o\n# Example: u-boot/v2023.10/source/Makefile#L1767\nclass MakefileOFilter(Filter):\n    def __init__(self, *args, **kwargs):\n        super().__init__(*args, **kwargs)\n        self.makefileo = []\n\n    def check_if_applies(self, ctx) -> bool:\n        return super().check_if_applies(ctx) and \\\n                filename_without_ext_matches(ctx.filepath, {'Makefile'})\n\n    def transform_raw_code(self, ctx, code: str) -> str:\n        def keep_makefileo(m):\n            self.makefileo.append(m.group(1))\n            return f'__KEEPMAKEFILEO__{ encode_number(len(self.makefileo)) }.o'\n\n        return re.sub('(?<=\\s)([-\\w/]+)\\.o(?!\\w)(?! :?=)', keep_makefileo, code, flags=re.MULTILINE)\n\n    def untransform_formatted_code(self, ctx: FilterContext, html: str) -> str:\n        def replace_makefileo(m):\n            w = self.makefileo[decode_number(m.group(1)) - 1]\n\n            filedir = dirname(ctx.filepath)\n            if filedir != '/':\n                filedir += '/'\n\n            npath = f'{ filedir }{ w }.c'\n            return f'<a href=\"{ ctx.get_absolute_source_url(npath) }\">{ w }.o</a>'\n\n        return re.sub('__KEEPMAKEFILEO__([A-J]+)\\.o', replace_makefileo, html, flags=re.MULTILINE)\n\n"
  },
  {
    "path": "elixir/filters/makefilesrctree.py",
    "content": "import re\nfrom .utils import Filter, FilterContext, decode_number, encode_number, filename_without_ext_matches\n\n# Filters for files listed in Makefiles using $(srctree)\n# $(srctree)/Makefile\n# Example: u-boot/v2023.10/source/Makefile#L1983\nclass MakefileSrcTreeFilter(Filter):\n    def __init__(self, *args, **kwargs):\n        super().__init__(*args, **kwargs)\n        self.makefilesrctree = []\n\n    def check_if_applies(self, ctx) -> bool:\n        return super().check_if_applies(ctx) and \\\n            filename_without_ext_matches(ctx.filepath, {'Makefile'})\n\n    def transform_raw_code(self, ctx, code: str) -> str:\n        def keep_makefilesrctree(m):\n            if ctx.query.file_exists(ctx.tag, '/' + m.group(1)):\n                self.makefilesrctree.append(m.group(1))\n                return f'__KEEPMAKEFILESRCTREE__{ encode_number(len(self.makefilesrctree)) }{ m.group(2) }'\n            else:\n                return m.group(0)\n\n        return re.sub('(?:(?<=\\s|=)|(?<=-I))(?!/)\\$\\(srctree\\)/((?:[-\\w/]+/)?[-\\w\\.]+)(\\s+|\\)|$)',\n                      keep_makefilesrctree, code, flags=re.MULTILINE)\n\n    def untransform_formatted_code(self, ctx: FilterContext, html: str) -> str:\n        def replace_makefilesrctree(m):\n            w = self.makefilesrctree[decode_number(m.group(1)) - 1]\n            url = ctx.get_absolute_source_url(w)\n            return f'<a href=\"{ url }\">$(srctree)/{ w }</a>'\n\n        return re.sub('__KEEPMAKEFILESRCTREE__([A-J]+)', replace_makefilesrctree, html, flags=re.MULTILINE)\n\n"
  },
  {
    "path": "elixir/filters/makefilesubdir.py",
    "content": "from os.path import dirname\nimport re\nfrom .utils import Filter, FilterContext, decode_number, encode_number, filename_without_ext_matches\n\n# Filters for Makefile directory includes as follows:\n# subdir-y += dir\n# Example: u-boot/v2023.10/source/examples/Makefile#L9\nclass MakefileSubdirFilter(Filter):\n    def __init__(self, *args, **kwargs):\n        super().__init__(*args, **kwargs)\n        self.makefilesubdir = []\n\n    def check_if_applies(self, ctx) -> bool:\n        return super().check_if_applies(ctx) and \\\n            filename_without_ext_matches(ctx.filepath, {'Makefile'})\n\n    def transform_raw_code(self, ctx, code: str) -> str:\n        def keep_makefilesubdir(m):\n            self.makefilesubdir.append(m.group(5))\n            n = encode_number(len(self.makefilesubdir))\n            return f'{ m.group(1) }{ m.group(2) }{ m.group(3) }{ m.group(4) }__KEEPMAKESUBDIR__{ n }{ m.group(6) }'\n\n        return re.sub('(subdir-y)(\\s+)(\\+=|:=)(\\s+)([-\\w]+)(\\s*|$)', keep_makefilesubdir, code, flags=re.MULTILINE)\n\n    def untransform_formatted_code(self, ctx: FilterContext, html: str) -> str:\n        def replace_makefilesubdir(m):\n            w = self.makefilesubdir[decode_number(m.group(1)) - 1]\n            filedir = dirname(ctx.filepath)\n\n            if filedir != '/':\n                filedir += '/'\n\n            npath = f'{ filedir }{ w }/Makefile'\n            return f'<a href=\"{ ctx.get_absolute_source_url(npath) }\">{ w }</a>'\n\n        return re.sub('__KEEPMAKESUBDIR__([A-J]+)', replace_makefilesubdir, html, flags=re.MULTILINE)\n\n"
  },
  {
    "path": "elixir/filters/projects.py",
    "content": "from .ident import IdentFilter\n\nfrom .cppinc import CppIncFilter\nfrom .cpppathinc import CppPathIncFilter\n\nfrom .defconfig import DefConfigIdentsFilter\nfrom .configin import ConfigInFilter\n\nfrom .kconfig import KconfigFilter\nfrom .kconfigidents import KconfigIdentsFilter\n\nfrom .dtsi import DtsiFilter\nfrom .dtscompdocs import DtsCompDocsFilter\nfrom .dtscompcode import DtsCompCodeFilter\nfrom .dtscompdts import DtsCompDtsFilter\n\nfrom .makefileo import MakefileOFilter\nfrom .makefiledtb import MakefileDtbFilter\nfrom .makefiledir import MakefileDirFilter\nfrom .makefilesubdir import MakefileSubdirFilter\nfrom .makefilefile import MakefileFileFilter\nfrom .makefilesrctree import MakefileSrcTreeFilter\nfrom .makefilesubdir import MakefileSubdirFilter\n\n\n# List of filters applied to all projects\ndefault_filters = [\n    DtsCompCodeFilter,\n    DtsCompDtsFilter,\n    DtsCompDocsFilter,\n    IdentFilter,\n    CppIncFilter,\n]\n\n# List of filters for Kconfig files\ncommon_kconfig_filters = [\n    KconfigFilter,\n    KconfigIdentsFilter,\n    DefConfigIdentsFilter,\n]\n\n# List of filters for Makefiles\ncommon_makefile_filters = [\n    MakefileOFilter,\n    MakefileDtbFilter,\n    MakefileDirFilter,\n    MakefileFileFilter,\n    MakefileSubdirFilter,\n    MakefileSrcTreeFilter,\n]\n\n# Dictionary of custom per-projects filters.\n# Projects not present in this dictionary only use default_filters.\n# Use `*` to unpack filter lists defined above,\n# you can pass additional options to filters by putting a Filter\n# class and a dictionary with options in a tuple, like this:\n# (FilterCls, {\"option\": True}).\n# Check filter files and utils.py for information about available options\nproject_filters = {\n    'amazon-freertos': [\n        *default_filters,\n        MakefileSubdirFilter,\n    ],\n    'arm-trusted-firmware': [\n        *default_filters,\n        CppPathIncFilter,\n    ],\n    'barebox': [\n        *default_filters,\n        DtsiFilter,\n        *common_kconfig_filters,\n        CppPathIncFilter,\n        *common_makefile_filters,\n    ],\n    'coreboot': [\n        *default_filters,\n        DtsiFilter,\n        *common_kconfig_filters,\n        *common_makefile_filters,\n    ],\n    'iproute2': [\n        *default_filters,\n        *common_makefile_filters,\n    ],\n    'linux': [\n        *default_filters,\n        DtsiFilter,\n        *common_kconfig_filters,\n        *common_makefile_filters,\n        # include/uapi contains includes to user headers under #ifndef __KERNEL__\n        # Our solution is to ignore all includes in such paths\n        (CppPathIncFilter, {\"path_exceptions\": {'^/include/uapi/.*'}}),\n    ],\n    'opensbi': [\n        *default_filters,\n        *common_kconfig_filters,\n    ],\n    'qemu': [\n        *default_filters,\n        *common_kconfig_filters,\n    ],\n    'u-boot': [\n        *default_filters,\n        DtsiFilter,\n        *common_kconfig_filters,\n        CppPathIncFilter,\n        *common_makefile_filters,\n    ],\n    'uclibc-ng': [\n        *default_filters,\n        ConfigInFilter,\n    ],\n    'vpp': [\n        *default_filters,\n        (CppPathIncFilter, {\"prefix_path\": ['src', 'src/plugins', 'src/vpp-api', 'src/vpp-api/vapi']}),\n        MakefileFileFilter,\n    ],\n    'zephyr': [\n        *default_filters,\n        DtsiFilter,\n        *common_kconfig_filters,\n        CppPathIncFilter,\n    ],\n}\n\n"
  },
  {
    "path": "elixir/filters/utils.py",
    "content": "import re\nimport os\nfrom dataclasses import dataclass\nfrom typing import Callable, List\nfrom ..query import Query\n\n# Context data used by Filters\n# tag: browsed version, unqoted\n# family: family of file\n# path: path of file\n# get_ident_url: function that returns URL to identifier passed as argument\n# get_absolute_source_url: function that returns a URL to file with absolute path passed as an argument\n# get_relative_source_url: function that returns a URL to file in directory of current file\n@dataclass\nclass FilterContext:\n    query: Query\n    tag: str\n    family: str\n    filepath: str\n    get_ident_url: Callable[[str], str]\n    get_absolute_source_url: Callable[[str], str]\n    get_relative_source_url: Callable[[str], str]\n\n# Filter interface/base class\n# Filters are used to add extra information, like links, to code formatted into HTML by Pygments.\n# Filters consist of two parts: the first part runs on unformatted code, transforming it\n# to mark interesting identifiers, for example keywords. How the identifiers are marked is\n# up to the filter, but it's important to be careful to not break formatting.\n# The second part runs on HTML, replacing markings left by the first part with HTML code.\n# path_exceptions: list of regexes, disables filter if path of the filtered file matches a regex from the list\nclass Filter:\n    def __init__(self, path_exceptions: List[str] = []):\n        self.path_exceptions = path_exceptions\n\n    # Return True if filter can be applied to file with path\n    def check_if_applies(self, ctx: FilterContext) -> bool:\n        for p in self.path_exceptions:\n            if re.match(p, ctx.filepath):\n                return False\n\n        return True\n\n    # Add information required by filter by transforming raw source code.\n    # Known identifiers are marked by '\\033[31m' and '\\033[0m'. Note that these marked\n    # identifiers are usually handled by IdentFilter or KconfigIdentsFilter.\n    def transform_raw_code(self, ctx: FilterContext, code: str) -> str:\n        return code\n\n    # Replace information left by `transform_raw_code` with target HTML\n    # html: HTML output from code formatter\n    def untransform_formatted_code(self, ctx: FilterContext, html: str) -> str:\n        return html\n\n\n# Returns true if filename from filepath, with removed extension, is in the\n# allowed_filenames_without_ext iterable\ndef filename_without_ext_matches(filepath: str, allowed_filenames_without_ext) -> bool:\n    filename = os.path.basename(filepath)\n    filename_without_ext, _ = os.path.splitext(filename)\n    return filename_without_ext in allowed_filenames_without_ext\n\n# Returns true if extension of filename from filepath is in the\n# allowed_extensions iterable\ndef extension_matches(filepath: str, allowed_extensions) -> bool:\n    _, file_ext_dot = os.path.splitext(filepath)\n    file_ext = file_ext_dot[1:].lower()\n    return file_ext in allowed_extensions\n\n\n# Encodes an integer into a string of characters (A-J)\n# encode_number(10239) = 'BACDJ'\ndef encode_number(number):\n    result = ''\n\n    while number != 0:\n        number, rem = divmod(number, 10)\n        rem = chr(ord('A') + rem)\n        result = rem + result\n\n    return result\n\n# Decodes a string of characters returned by encode_number into an integer\n# decode_number('BACDJ') = 10239\ndef decode_number(string):\n    result = ''\n\n    while string != '':\n        string, char = string[:-1], string[-1]\n        char = str(ord(char) - ord('A'))\n        result = char + result\n\n    return int(result)\n\n"
  },
  {
    "path": "elixir/lib.py",
    "content": "#!/usr/bin/env python3\n\n#  This file is part of Elixir, a source code cross-referencer.\n#\n#  Copyright (C) 2017  Mikaël Bouillot\n#  <mikael.bouillot@bootlin.com>\n#\n#  Elixir is free software: you can redistribute it and/or modify\n#  it under the terms of the GNU Affero General Public License as published by\n#  the Free Software Foundation, either version 3 of the License, or\n#  (at your option) any later version.\n#\n#  Elixir is distributed in the hope that it will be useful,\n#  but WITHOUT ANY WARRANTY; without even the implied warranty of\n#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n#  GNU Affero General Public License for more details.\n#\n#  You should have received a copy of the GNU Affero General Public License\n#  along with Elixir.  If not, see <http://www.gnu.org/licenses/>.\n\nimport sys\nimport logging\nimport subprocess, os\n\nlogger = logging.getLogger(__name__)\n\nCURRENT_DIR = os.path.abspath(os.path.dirname(os.path.abspath(__file__)) + '/../')\n\ndef script(*args, env=None):\n    args = (os.path.join(CURRENT_DIR, 'script.sh'),) + args\n    # subprocess.run was introduced in Python 3.5\n    # fall back to subprocess.check_output if it's not available\n    if hasattr(subprocess, 'run'):\n        p = subprocess.run(args, stdout=subprocess.PIPE, env=env)\n        p = p.stdout\n    else:\n        p = subprocess.check_output(args)\n    return p\n\ndef run_cmd(*args, env=None):\n    p = subprocess.run(args, stdout=subprocess.PIPE, stderr=subprocess.PIPE, env=env)\n    if len(p.stderr) != 0:\n        logger.error('command %s printed to stderr: \\n%s', str(args), p.stderr.decode('utf-8'))\n    return p.stdout, p.returncode\n\n# Invoke ./script.sh with the given arguments\n# Returns the list of output lines\n\ndef scriptLines(*args, env=None):\n    p = script(*args, env=env)\n    p = p.split(b'\\n')\n    del p[-1]\n    return p\n\ndef unescape(bstr):\n    subs = (\n        ('\\1','\\n'),\n    )\n    for a,b in subs:\n        a = a.encode()\n        b = b.encode()\n        bstr = bstr.replace(a, b)\n    return bstr\n\ndef decode(byte_object):\n    # decode('ascii') fails on special chars\n    # FIXME: major hack until we handle everything as bytestrings\n    try:\n        return byte_object.decode('utf-8')\n    except UnicodeDecodeError:\n        return byte_object.decode('iso-8859-1')\n\n# List of tokens which we don't want to consider as identifiers\n# Typically for very frequent variable names and things redefined by #define\n# TODO: allow to have per project blacklists\n\nblacklist = (\n    b'NULL',\n    b'__',\n    b'adapter',\n    b'addr',\n    b'arg',\n    b'attr',\n    b'base',\n    b'bp',\n    b'buf',\n    b'buffer',\n    b'c',\n    b'card',\n    b'char',\n    b'chip',\n    b'cmd',\n    b'codec',\n    b'const',\n    b'count',\n    b'cpu',\n    b'ctx',\n    b'data',\n    b'default',\n    b'define',\n    b'desc',\n    b'dev',\n    b'driver',\n    b'else',\n    b'end',\n    b'endif',\n    b'entry',\n    b'err',\n    b'error',\n    b'event',\n    b'extern',\n    b'failed',\n    b'flags',\n    b'h',\n    b'host',\n    b'hw',\n    b'i',\n    b'id',\n    b'idx',\n    b'if',\n    b'index',\n    b'info',\n    b'inline',\n    b'int',\n    b'irq',\n    b'j',\n    b'len',\n    b'length',\n    b'list',\n    b'lock',\n    b'long',\n    b'mask',\n    b'mode',\n    b'msg',\n    b'n',\n    b'name',\n    b'net',\n    b'next',\n    b'offset',\n    b'ops',\n    b'out',\n    b'p',\n    b'pdev',\n    b'port',\n    b'priv',\n    b'ptr',\n    b'q',\n    b'r',\n    b'rc',\n    b'rdev',\n    b'reg',\n    b'regs',\n    b'req',\n    b'res',\n    b'result',\n    b'ret',\n    b'return',\n    b'retval',\n    b'root',\n    b's',\n    b'sb',\n    b'size',\n    b'sizeof',\n    b'sk',\n    b'skb',\n    b'spec',\n    b'start',\n    b'state',\n    b'static',\n    b'status',\n    b'struct',\n    b't',\n    b'tmp',\n    b'tp',\n    b'type',\n    b'val',\n    b'value',\n    b'vcpu',\n    b'x'\n)\n\ndef isIdent(bstr):\n    if (len(bstr) < 2 or\n        bstr in blacklist or\n        bstr.startswith(b'~')):\n        return False\n    else:\n        return True\n\ndef autoBytes(arg):\n    if type(arg) is str:\n        arg = arg.encode()\n    elif type(arg) is int:\n        arg = str(arg).encode()\n    return arg\n\ndef getDataDir():\n    try:\n        return os.environ['LXR_DATA_DIR']\n    except KeyError:\n        print(sys.argv[0] + ': LXR_DATA_DIR needs to be set')\n        exit(1)\n\ndef getRepoDir():\n    try:\n        return os.environ['LXR_REPO_DIR']\n    except KeyError:\n        print(sys.argv[0] + ': LXR_REPO_DIR needs to be set')\n        exit(1)\n\ndef currentProject():\n    return os.path.basename(os.path.dirname(getDataDir()))\n\n# List all families supported by Elixir\nfamilies = ['A', 'B', 'C', 'D', 'K', 'M']\n\n# Those families have databases that cache the content of definitions.db.\n# This allows faster lookup.\nCACHED_DEFINITIONS_FAMILIES = ['C', 'K', 'D', 'M']\n\ndef validFamily(family):\n    return family in families\n\ndef getFileFamily(filename):\n    name, ext = os.path.splitext(filename)\n    name, ext = name.lower(), ext.lower()\n\n    if ext in ['.c', '.cc', '.cpp', '.c++', '.cxx', '.h', '.s'] :\n        return 'C' # C file family and ASM\n    elif ext in ['.dts', '.dtsi'] :\n        return 'D' # Devicetree files\n    elif name[:7] == 'kconfig' and ext != '.rst':\n        # Some files are named like Kconfig-nommu so we only check the first 7 letters\n        # We also exclude documentation files that can be named kconfig\n        return 'K' # Kconfig files\n    elif name[:8] == 'makefile' and ext != '.rst' or ext == '.mk':\n        return 'M' # Makefiles\n    else :\n        return None\n\n# 1 char values are file families\n# 2 chars values with a M are macros families\ncompatibility_list = {\n    'C' : ['C', 'K'],\n    'K' : ['K'],\n    'D' : ['D', 'CM'],\n    'M' : ['K']\n}\n\n# Check if families are compatible\n# First argument can be a list of different families\n# Second argument is the key for choosing the right array in the compatibility list\ndef compatibleFamily(file_family, requested_family):\n    return any(item in file_family for item in compatibility_list[requested_family])\n\n# Check if a macro is compatible with the requested family\n# First argument can be a list of different families\n# Second argument is the key for choosing the right array in the compatibility list\ndef compatibleMacro(macro_family, requested_family):\n    result = False\n    for item in macro_family:\n        item += 'M'\n        result = result or item in compatibility_list[requested_family]\n    return result\n"
  },
  {
    "path": "elixir/query.py",
    "content": "#!/usr/bin/env python3\n\n#  This file is part of Elixir, a source code cross-referencer.\n#\n#  Copyright (C) 2017--2020 Mikaël Bouillot <mikael.bouillot@bootlin.com>\n#  and contributors\n#\n#  Elixir is free software: you can redistribute it and/or modify\n#  it under the terms of the GNU Affero General Public License as published by\n#  the Free Software Foundation, either version 3 of the License, or\n#  (at your option) any later version.\n#\n#  Elixir is distributed in the hope that it will be useful,\n#  but WITHOUT ANY WARRANTY; without even the implied warranty of\n#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n#  GNU Affero General Public License for more details.\n#\n#  You should have received a copy of the GNU Affero General Public License\n#  along with Elixir.  If not, see <http://www.gnu.org/licenses/>.\n\nfrom .lib import script, scriptLines, decode\nfrom . import lib\nfrom . import data\nimport os\nfrom collections import OrderedDict\nfrom urllib import parse\n\nfrom io import BytesIO\n\nclass SymbolInstance(object):\n    def __init__(self, path, line, type=None):\n        self.path = path\n        self.line = line\n        self.type = type\n\n    def __repr__(self):\n        type_repr = \"\"\n        if self.type:\n            type_repr = f\" , type: {self.type}\"\n\n        return f\"Symbol in path: {self.path}, line: {self.line}\" + type_repr\n\n    def __str__(self):\n        return self.__repr__()\n\n# Returns a Query class instance or None if project data directory does not exist\n# basedir: absolute path to parent directory of all project data directories, ex. \"/srv/elixir-data/\"\n# project: name of the project, directory in basedir, ex. \"linux\"\ndef get_query(basedir, project):\n    datadir = basedir + '/' + project + '/data'\n    repodir = basedir + '/' + project + '/repo'\n\n    if not os.path.exists(datadir) or not os.path.exists(repodir):\n        return None\n\n    return Query(datadir, repodir)\n\nclass Query:\n    def __init__(self, data_dir, repo_dir):\n        self.repo_dir = repo_dir\n        self.data_dir = data_dir\n        self.dts_comp_support = int(self.script('dts-comp'))\n        self.db = data.DB(data_dir, readonly=True, dtscomp=self.dts_comp_support)\n        self.file_cache = {}\n\n    def script(self, *args):\n        return script(*args, env=self.getEnv())\n\n    def scriptLines(self, *args):\n        return scriptLines(*args, env=self.getEnv())\n\n    def getEnv(self):\n        return {\n            **os.environ,\n            \"LXR_REPO_DIR\": self.repo_dir,\n            \"LXR_DATA_DIR\": self.data_dir,\n        }\n\n    def close(self):\n        self.db.close()\n\n    # Check if a dts compatible string exists\n    def dts_comp_exists(self, ident):\n        if self.dts_comp_support:\n            return self.db.comps.exists(ident)\n        else:\n            return False\n\n    # Returns True if file exists\n    def file_exists(self, version, path):\n        if version not in self.file_cache:\n            version_cache = set()\n            last_dir = None\n            for _, path in self.db.vers.get(version).iter():\n                dirname, filename = os.path.split(path)\n                if dirname != last_dir:\n                    last_dir = dirname\n                    version_cache.add(dirname)\n                version_cache.add(path)\n\n            self.file_cache[version] = version_cache\n\n        return path.strip('/') in self.file_cache[version]\n\n    # Returns the contents of the specified file\n    # Tokens are marked for further processing\n    # Example: v3.1-rc10 /Makefile\n    def get_tokenized_file(self, version, path):\n        filename = os.path.basename(path)\n        family = lib.getFileFamily(filename)\n\n        if family != None:\n            assert family in lib.CACHED_DEFINITIONS_FAMILIES, f\"family {family} must have its definitions cached\"\n\n            buffer = BytesIO()\n            tokens = self.scriptLines('tokenize-file', version, path, family)\n            even = True\n\n            prefix = b''\n            if family == 'K':\n                prefix = b'CONFIG_'\n\n            for tok in tokens:\n                even = not even\n                tok2 = prefix + tok\n                if even and self.db.defs_cache[family].exists(tok2):\n                    tok = b'\\033[31m' + tok2 + b'\\033[0m'\n                else:\n                    tok = lib.unescape(tok)\n                buffer.write(tok)\n            return decode(buffer.getvalue())\n        else:\n            return decode(self.script('get-file', version, path))\n\n    # Returns the contents (trees or blobs) of the specified directory\n    # Example: v3.1-rc10 /arch\n    def get_dir_contents(self, version, path):\n        entries_str =  decode(self.script('get-dir', version, path))\n        return entries_str.split(\"\\n\")[:-1]\n\n    # Returns indexed versions, as a tree of OrderedDict.\n    # It has a depth of 3, for example: v3 v3.1 v3.1-rc10.\n    def get_versions(self):\n        versions = OrderedDict()\n\n        for line in self.scriptLines('list-tags', '-h'):\n            taginfo = decode(line).split(' ')\n            num = len(taginfo)\n            topmenu, submenu = 'FIXME', 'FIXME'\n\n            if num == 1:\n                tag, = taginfo\n            elif num == 2:\n                submenu, tag = taginfo\n            elif num == 3:\n                topmenu, submenu, tag = taginfo\n            else:\n                raise Exception(\"unexpected number of fields in taginfo\")\n\n            if self.db.vers.exists(tag):\n                if topmenu not in versions:\n                    versions[topmenu] = OrderedDict()\n                if submenu not in versions[topmenu]:\n                    versions[topmenu][submenu] = []\n                versions[topmenu][submenu].append(tag)\n\n        return versions\n\n    # Returns the type (blob or tree) associated to\n    # the given path. Example:\n    # > ./query.py type v3.1-rc10 /Makefile\n    # blob\n    # > ./query.py type v3.1-rc10 /arch\n    # tree\n    def get_file_type(self, version, path):\n        return decode(self.script('get-type', version, path)).strip()\n\n    # Returns identifier search results\n    def search_ident(self, version, ident, family):\n        # DT bindings compatible strings are handled differently\n        if family == 'B':\n            return self.get_idents_comps(version, ident)\n        else:\n            return self.get_idents_defs(version, ident, family)\n\n    # Returns the latest tag that is included in the database.\n    # This excludes release candidates if `rc` is False.\n    def get_latest_tag(self, rc):\n        if rc:\n            sorted_tags = reversed(self.scriptLines('list-tags'))\n        else:\n            sorted_tags = self.scriptLines('get-latest-tags')\n\n        for tag in sorted_tags:\n            if self.db.vers.exists(tag):\n                return tag.decode()\n\n        # return the oldest tag, even if it does not exist in the database\n        return sorted_tags[-1].decode()\n\n    def get_file_raw(self, version, path):\n        return decode(self.script('get-file', version, path))\n\n    def get_idents_comps(self, version, ident):\n\n        # DT bindings compatible strings are handled differently\n        # They are defined in C files\n        # Used in DT files\n        # Documented in documentation files\n        symbol_c = []\n        symbol_dts = []\n        symbol_docs = []\n\n        # DT compatible strings are quoted in the database\n        ident = parse.quote(ident)\n\n        if not self.dts_comp_support or not self.db.comps.exists(ident):\n            return symbol_c, symbol_dts, symbol_docs, False\n\n        files_this_version = self.db.vers.get(version).iter()\n        comps = self.db.comps.get(ident).iter(dummy=True)\n\n        if self.db.comps_docs.exists(ident):\n            comps_docs = self.db.comps_docs.get(ident).iter(dummy=True)\n        else:\n            comps_docs = data.RefList().iter(dummy=True)\n\n        comps_idx, comps_lines, comps_family = next(comps)\n        comps_docs_idx, comps_docs_lines, comps_docs_family = next(comps_docs)\n        compsCBuf = [] # C/CPP/ASM files\n        compsDBuf = [] # DT files\n        compsBBuf = [] # DT bindings docs files\n\n        for file_idx, file_path in files_this_version:\n            while comps_idx < file_idx:\n                comps_idx, comps_lines, comps_family = next(comps)\n\n            while comps_docs_idx < file_idx:\n                comps_docs_idx, comps_docs_lines, comps_docs_family = next(comps_docs)\n\n            if comps_idx == file_idx:\n                if comps_family == 'C':\n                    compsCBuf.append((file_path, comps_lines))\n                elif comps_family == 'D':\n                    compsDBuf.append((file_path, comps_lines))\n\n            if comps_docs_idx == file_idx:\n                compsBBuf.append((file_path, comps_docs_lines))\n\n        for path, cline in sorted(compsCBuf):\n            symbol_c.append(SymbolInstance(path, cline, 'compatible'))\n\n        for path, dlines in sorted(compsDBuf):\n            symbol_dts.append(SymbolInstance(path, dlines))\n\n        for path, blines in sorted(compsBBuf):\n            symbol_docs.append(SymbolInstance(path, blines))\n\n        return symbol_c, symbol_dts, symbol_docs, True\n\n    def get_idents_defs(self, version, ident, family):\n\n        symbol_definitions = []\n        symbol_references = []\n        symbol_doccomments = []\n\n        if not self.db.defs.exists(ident):\n            return symbol_definitions, symbol_references, symbol_doccomments, False\n\n        if not self.db.vers.exists(version):\n            return symbol_definitions, symbol_references, symbol_doccomments, True\n\n        files_this_version = self.db.vers.get(version).iter()\n        this_ident = self.db.defs.get(ident)\n        defs_this_ident = this_ident.iter(dummy=True)\n        macros_this_ident = this_ident.get_macros()\n        # FIXME: see why we can have a discrepancy between defs_this_ident and refs\n        if self.db.refs.exists(ident):\n            refs = self.db.refs.get(ident).iter(dummy=True)\n        else:\n            refs = data.RefList().iter(dummy=True)\n\n        if self.db.docs.exists(ident):\n            docs = self.db.docs.get(ident).iter(dummy=True)\n        else:\n            docs = data.RefList().iter(dummy=True)\n\n        # vers, defs, refs, and docs are all populated by update.py in order of\n        # idx, and there is a one-to-one mapping between blob hashes and idx\n        # values.  Therefore, we can sequentially step through the defs, refs,\n        # and docs for each file in a version.\n\n        def_idx, def_type, def_line, def_family = next(defs_this_ident)\n        ref_idx, ref_lines, ref_family = next(refs)\n        doc_idx, doc_line, doc_family = next(docs)\n\n        dBuf = []\n        rBuf = []\n        docBuf = []\n\n        for file_idx, file_path in files_this_version:\n            # Advance defs, refs, and docs to the current file\n            while def_idx < file_idx:\n                def_idx, def_type, def_line, def_family = next(defs_this_ident)\n            while ref_idx < file_idx:\n                ref_idx, ref_lines, ref_family = next(refs)\n            while doc_idx < file_idx:\n                doc_idx, doc_line, doc_family = next(docs)\n\n            # Copy information about this identifier into dBuf, rBuf, and docBuf.\n            while def_idx == file_idx:\n                if (def_family == family or family == 'A'\n                    or lib.compatibleMacro(macros_this_ident, family)):\n                    dBuf.append((file_path, def_type, def_line))\n                def_idx, def_type, def_line, def_family = next(defs_this_ident)\n\n            if ref_idx == file_idx:\n                if lib.compatibleFamily(family, ref_family) or family == 'A':\n                    rBuf.append((file_path, ref_lines))\n\n            if doc_idx == file_idx: # TODO should this be a `while`?\n                docBuf.append((file_path, doc_line))\n\n        # Sort dBuf by path name before sorting by type in the loop\n        dBuf.sort()\n\n        for path, type, dline in sorted(dBuf, key=lambda d: d[1], reverse=True):\n            symbol_definitions.append(SymbolInstance(path, dline, type))\n\n        for path, rlines in sorted(rBuf):\n            symbol_references.append(SymbolInstance(path, rlines))\n\n        for path, docline in sorted(docBuf):\n            symbol_doccomments.append(SymbolInstance(path, docline))\n\n        return symbol_definitions, symbol_references, symbol_doccomments, True\n\n"
  },
  {
    "path": "elixir/web.py",
    "content": "#!/usr/bin/env python3\n\n#  This file is part of Elixir, a source code cross-referencer.\n#\n#  Copyright (C) 2017--2020 Mikaël Bouillot <mikael.bouillot@bootlin.com>\n#  and contributors.\n#\n#  Elixir is free software: you can redistribute it and/or modify\n#  it under the terms of the GNU Affero General Public License as published by\n#  the Free Software Foundation, either version 3 of the License, or\n#  (at your option) any later version.\n#\n#  Elixir is distributed in the hope that it will be useful,\n#  but WITHOUT ANY WARRANTY; without even the implied warranty of\n#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n#  GNU Affero General Public License for more details.\n#\n#  You should have received a copy of the GNU Affero General Public License\n#  along with Elixir.  If not, see <http://www.gnu.org/licenses/>.\n\nimport logging\nimport os\nimport sys\nimport re\nimport threading\nimport time\nimport datetime\nfrom collections import OrderedDict, namedtuple\nfrom re import search, sub\nfrom typing import Any, Callable, NamedTuple, Tuple\nfrom urllib import parse\nimport falcon\nimport jinja2\n\nfrom .lib import validFamily, getFileFamily\nfrom .query import Query, SymbolInstance\nfrom .filters import get_filters\nfrom .filters.utils import FilterContext\nfrom .autocomplete import AutocompleteResource\nfrom .api import ApiIdentGetterResource\nfrom .query import get_query\nfrom .web_utils import ProjectConverter, IdentConverter, validate_version, validate_project, validate_ident, \\\n        get_elixir_version_string, get_elixir_repo_url, RequestContext, Config\n\nVERSION_CACHE_DURATION_SECONDS = 2 * 60  # 2 minutes\nADD_ISSUE_LINK = \"https://github.com/bootlin/elixir/issues/new\"\nELIXIR_VERSION_STRING = get_elixir_version_string()\nELIXIR_REPO_LINK = get_elixir_repo_url(ELIXIR_VERSION_STRING)\n\nDEFAULT_PROJECT = 'linux'\n\n# Error with extra information about browsed project,\n# to be used in project/version URLs\nclass ElixirProjectError(falcon.errors.HTTPError):\n    def __init__(self, title, description, project=None, version=None, query=None,\n                 status=falcon.HTTP_BAD_REQUEST, extra_template_args={}, **kwargs):\n        self.project = project\n        self.version = version\n        self.query = query\n        self.extra_template_args = extra_template_args\n        super().__init__(status, title=title, description=description, **kwargs)\n\n# Generate a summary of error details for a bug report\ndef generate_error_details(req, resp, title, details):\n    return f\"Request date: {datetime.datetime.now()}\\n\" + \\\n           f\"Path: {req.path}\\n\" + \\\n           f\"Query string: {req.query_string}\\n\" + \\\n           f\"Method: {req.method}\\n\" + \\\n           f\"Status code: {resp.status}\\n\" + \\\n           f\"Error title: {title}\\n\" + \\\n           f\"Error details: {details}\\n\"\n\ndef get_github_issue_url(details: str):\n    body = (\"TODO: add information on how you reached the error here and \" +\n            \"validate the details below.\\n\\n\" +\n            \"---\\n\\n\" +\n            details)\n\n    return ADD_ISSUE_LINK + \"?body=\" + parse.quote(body)\n\n\n# Generate an error page from ElixirProjectError\ndef get_project_error_page(req, resp, exception: ElixirProjectError):\n    report_error_details = generate_error_details(req, resp, exception.title, exception.description)\n\n    template_ctx = {\n        'projects': get_projects(req.context.config.project_dir),\n        'topbar_families': TOPBAR_FAMILIES,\n        'current_version_path': (None, None, None),\n        'current_family': 'A',\n        'source_base_url': '/',\n        'elixir_version_string': req.context.config.version_string,\n        'elixir_repo_url': req.context.config.repo_url,\n\n        'referer': req.referer if req.referer != req.uri else None,\n        'bug_report_url': get_github_issue_url(report_error_details),\n        'home_page_url': '/',\n        'report_error_details': report_error_details,\n\n        'error_title': exception.title,\n    }\n\n    if exception.project is not None and exception.query is not None:\n        # Add details about current project\n        query = exception.query\n        project = exception.project\n        version = exception.version\n\n        versions_raw = get_versions_cached(query, req.context, project)\n        get_url_with_new_version = lambda v: stringify_source_path(project, v, '/')\n        versions, current_version_path = get_versions(versions_raw, get_url_with_new_version, version)\n\n        if current_version_path[2] is None:\n            # If details about current version are not available, make base links\n            # point to latest.\n            # current_tag is not set to latest to avoid latest being highlighted in the sidebar\n            version = query.get_latest_tag()\n\n        template_ctx = {\n            **template_ctx,\n\n            'current_project': project,\n            'current_tag': version,\n            'versions': versions,\n            'current_version_path': current_version_path,\n\n            'home_page_url': get_source_base_url(project, version),\n            'source_base_url': get_source_base_url(project, version),\n            'ident_base_url': get_ident_base_url(project, version),\n        }\n\n    if exception.description is not None:\n        template_ctx['error_details'] = exception.description\n\n    template_ctx = {\n        **template_ctx,\n        **exception.extra_template_args,\n    }\n\n    template = req.context.jinja_env.get_template('error.html')\n    result = template.render(template_ctx)\n\n    if exception.query is not None:\n        exception.query.close()\n\n    return result\n\n# Generate an error page from falcon exceptions\ndef get_error_page(req, resp, exception: ElixirProjectError):\n    report_error_details = generate_error_details(req, resp, exception.title, exception.description)\n\n    template_ctx = {\n        'projects': get_projects(req.context.config.project_dir),\n        'topbar_families': TOPBAR_FAMILIES,\n        'current_version_path': (None, None, None),\n        'current_family': 'A',\n        'source_base_url': '/',\n\n        'referer': req.referer,\n        'bug_report_url': ADD_ISSUE_LINK + parse.quote(report_error_details),\n        'report_error_details': report_error_details,\n\n        'error_title': exception.title,\n    }\n\n    if exception.description is not None:\n        template_ctx['error_details'] = exception.description\n\n    template = req.context.jinja_env.get_template('error.html')\n    return template.render(template_ctx)\n\n# Validates project and version, returns project, version and query.\n# To be used in project/version URLs\ndef validate_project_and_version(ctx, project, version):\n    project = validate_project(parse.unquote(project))\n    if project is None:\n        raise ElixirProjectError('Error', 'Invalid project name')\n\n    query = get_query(ctx.config.project_dir, project)\n    if not query:\n        raise ElixirProjectError('Error', 'Unknown project', status=falcon.HTTP_NOT_FOUND)\n\n    version = validate_version(parse.unquote(version))\n    if version is None:\n        raise ElixirProjectError('Error', 'Invalid version', project=project, query=query)\n\n    return project, version, query\n\n\n# Returns base url of source pages\n# project and version are assumed to be unquoted\ndef get_source_base_url(project: str, version: str) -> str:\n    return f'/{ parse.quote(project, safe=\"\") }/{ parse.quote(version, safe=\"\") }/source'\n\n# Converts ParsedSourcePath to a string with corresponding URL path\ndef stringify_source_path(project: str, version: str, path: str) -> str:\n    if not path.startswith('/'):\n        path = '/' + path\n    path = f'{ get_source_base_url(project, version) }{ path }'\n    return path.rstrip('/')\n\n# Handles the '/' URL\nclass IndexResource:\n    def on_get(self, req, resp):\n        ctx = req.context\n        project = DEFAULT_PROJECT\n\n        query = get_query(ctx.config.project_dir, project)\n        if not query:\n            raise ElixirProjectError('Error', f'Unknown default project: {project}',\n                                     status=falcon.HTTP_INTERNAL_SERVER_ERROR)\n\n        version = query.get_latest_tag()\n        resp.status = falcon.HTTP_FOUND\n        resp.location = stringify_source_path(project, version, '/')\n        return\n\n# Handles source URLs\n# Path parameters are asssumed to be unquoted by converters\nclass SourceResource:\n    def on_get(self, req, resp, project: str, version: str, path: str):\n        project, version, query = validate_project_and_version(req.context, project, version)\n\n        if not path.startswith('/') and len(path) != 0:\n            path = f'/{ path }'\n\n        if path.endswith('/'):\n            resp.status = falcon.HTTP_MOVED_PERMANENTLY\n            resp.location = stringify_source_path(project, version, path)\n            return\n\n        # Check if path contains only allowed characters\n        if not search('^[A-Za-z0-9_/.,+-]*$', path):\n            raise ElixirProjectError('Error', 'Path contains characters that are not allowed',\n                              project=project, version=version, query=query)\n\n        if version in ('latest', 'latest-rc'):\n            rc = version == 'latest-rc'\n            version = query.get_latest_tag(rc=rc)\n            resp.status = falcon.HTTP_FOUND\n            resp.location = stringify_source_path(project, version, path)\n            return\n\n        raw_param = req.get_param('raw')\n        if raw_param is not None and raw_param.strip() != '0':\n            generate_raw_source(resp, query, project, version, path)\n        else:\n            resp.content_type = falcon.MEDIA_HTML\n            resp.status, resp.text = generate_source_page(req.context, query, project, version, path)\n\n        query.close()\n\n# Handles source URLs without a path, ex. '/u-boot/v2023.10/source'.\n# Note lack of trailing slash\nclass SourceWithoutPathResource(SourceResource):\n    def on_get(self, req, resp, project: str, version: str):\n        return super().on_get(req, resp, project, version, '')\n\n\n# Returns base url of ident pages\n# project and version assumed unquoted\ndef get_ident_base_url(project: str, version: str, family: str|None = None) -> str:\n    project = parse.quote(project, safe=\"\")\n    version = parse.quote(version, safe=\"\")\n    if family is not None:\n        return f'/{ project }/{ version }/{ parse.quote(family, safe=\"\") }/ident'\n    else:\n        return f'/{ project }/{ version }/ident'\n\n# Converts ParsedIdentPath to a string with corresponding URL path\ndef stringify_ident_path(project, version, family, ident) -> str:\n    path = f'{ get_ident_base_url(project, version, family) }/{ parse.quote(ident, safe=\"\") }'\n    return path.rstrip('/')\n\n# Handles redirect from ident with form (POST/GET with query parameters)\n# to default ident URL format\nclass IdentPostRedirectResource:\n    def on_get(self, req, resp, project: str, version: str, family: str|None = None, _ident: str|None = None):\n        get_ident = req.get_param('i', required=False)\n        get_family = req.get_param('f', required=False)\n        if get_ident is None:\n            project, version, _ = validate_project_and_version(req.context, project, version)\n            resp.status = falcon.HTTP_FOUND\n            resp.location = stringify_source_path(project, version, \"\")\n        else:\n            return self.handle(req, resp, project, version, get_ident, get_family)\n\n    def on_post(self, req, resp, project: str, version: str, family: str|None = None, _ident: str|None = None):\n        form = req.get_media()\n        post_ident = form.get('i')\n        post_family = form.get('f')\n        return self.handle(req, resp, project, version, post_ident, post_family)\n\n    def handle(self, req, resp, project: str, version: str, ident: str, family: str):\n        project, version, query = validate_project_and_version(req.context, project, version)\n\n        if not validFamily(family):\n            family = 'C'\n\n        if not ident:\n            raise ElixirProjectError('Error', 'Invalid identifier',\n                              project=project, version=version, query=query,\n                              extra_template_args={\n                                  'searched_ident': parse.unquote(ident),\n                                  'current_family': family,\n                              })\n\n        ident = ident.strip()\n        resp.status = falcon.HTTP_MOVED_PERMANENTLY\n        resp.location = stringify_ident_path(project, version, family, ident)\n\n        query.close()\n\n# Handles ident URLs when family is specified in the URL, both POST and GET\n# See IdentPostRedirectResource for behavior on POST\n# Path parameters are asssumed to be unquoted by converters\nclass IdentResource(IdentPostRedirectResource):\n    def on_get(self, req, resp, project: str, version: str, family: str, ident: str):\n        project, version, query = validate_project_and_version(req.context, project, version)\n\n        family = parse.unquote(family)\n        if not validFamily(family):\n            family = 'C'\n\n        ident = parse.unquote(ident)\n        validated_ident = validate_ident(ident)\n        if validated_ident is None:\n            raise ElixirProjectError('Error', 'Invalid identifier',\n                              project=project, version=version, query=query,\n                              extra_template_args={\n                                  'searched_ident': ident,\n                                  'current_family': family,\n                              })\n\n        ident = validated_ident\n\n        if version in ('latest', 'latest-rc'):\n            rc = version == 'latest-rc'\n            version = query.get_latest_tag(rc=rc)\n            resp.status = falcon.HTTP_FOUND\n            resp.location = stringify_ident_path(project, version, family, ident)\n            return\n\n        resp.content_type = falcon.MEDIA_HTML\n        resp.status, resp.text = generate_ident_page(req.context, query, project, version, family, ident)\n\n        query.close()\n\n# Handles ident URLs when family is not specified in the URL\n# Also handles POST requests for ident URLs without family - IdentPostRedirectResource is\n# inherited from IdentResource\nclass IdentWithoutFamilyResource(IdentResource):\n    def on_get(self, req, resp, project: str, version: str, ident: str):\n        super().on_get(req, resp, project, version, 'C', ident)\n\n# Handles /{project}/{version} URL, without path\nclass IncompleteURLRedirectResource:\n    def on_get(self, req, resp, project: str, version: str = \"latest\"):\n        ctx = req.context\n\n        query = get_query(ctx.config.project_dir, project)\n        if not query:\n            raise ElixirProjectError('Error', f'Unknown default project: {project}',\n                                     status=falcon.HTTP_INTERNAL_SERVER_ERROR)\n\n        if version in ('latest', 'latest-rc') or len(version) == 0:\n            rc = version == 'latest-rc'\n            version = query.get_latest_tag(rc=rc)\n\n        resp.status = falcon.HTTP_FOUND\n        resp.location = stringify_source_path(project, version, '/')\n\n# Handles /{project}/{version}/... URLs with unknown \"command\"\nclass UnknownPathResource:\n    def on_get(self, req, resp, project: str, version: str, family: str = \"\", subcmd: str = \"\", path: str = \"\"):\n        project, version, query = validate_project_and_version(req.context, project, version)\n\n        raise ElixirProjectError('Error', 'Invalid path',\n                          project=project, version=version, query=query,\n                          extra_template_args={\n                              'current_family': 'A',\n                          })\n\n\n# File families available in the dropdown next to search input in the topbar\nTOPBAR_FAMILIES = {\n    'A': 'All symbols',\n    'C': 'C/CPP/ASM',\n    'K': 'Kconfig',\n    'D': 'Devicetree',\n    'B': 'DT compatible',\n}\n\n# Returns a list of names of top-level directories in basedir\ndef get_directories(basedir: str) -> list[str]:\n    directories = []\n    for filename in os.listdir(basedir):\n        filepath = os.path.join(basedir, filename)\n        if os.path.isdir(filepath):\n            directories.append(filename)\n    return sorted(directories)\n\n# Tuple of project name and URL to root of that project\n# Used to render project list\nProjectEntry = namedtuple('ProjectEntry', 'name, url')\n\n# Returns a list of ProjectEntry tuples of projects stored in directory basedir\ndef get_projects(basedir: str) -> list[ProjectEntry]:\n    return [ProjectEntry(p, f\"/{p}/latest/source\") for p in get_directories(basedir)]\n\n# Tuple of version name and URL to chosen resource with that version\n# Used to render version list in the sidebar\nVersionEntry = namedtuple('VersionEntry', 'version, url')\n\n# Takes result of Query.get_versions() and prepares it for the sidebar template.\n#  Returns an OrderedDict with version information and optionally a triple with\n#  (major, minor, version) of current_version. The triple is useful, because sometimes\n#  the major or minor of a version (in this context) is a custom string (ex. FIXME).\n# versions: OrderedDict with major parts of versions as keys, values are OrderedDicts\n#   with minor version parts as keys and complete version strings as values\n# get_url: function that takes a version string and returns the URL\n#   for that version. Meaning of the URL can depend on the context\n# current_version: string with currently browsed version\ndef get_versions(versions: OrderedDict[str, OrderedDict[str, str]],\n                 get_url: Callable[[str], str],\n                 current_version: str) -> Tuple[dict[str, dict[str, list[VersionEntry]]], Tuple[str|None, str|None, str|None]]:\n\n    result = OrderedDict()\n    current_version_path = (None, None, None)\n    for major, minor_verions in versions.items():\n        for minor, patch_versions in minor_verions.items():\n            for v in patch_versions:\n                if major not in result:\n                    result[major] = OrderedDict()\n                if minor not in result[major]:\n                    result[major][minor] = []\n                result[major][minor].append(VersionEntry(v, get_url(v)))\n                if v == current_version:\n                    current_version_path = (major, minor, v)\n\n    return result, current_version_path\n\n# Caches get_versions result in a context object\ndef get_versions_cached(q, ctx, project):\n    with ctx.versions_cache_lock:\n        if project not in ctx.versions_cache:\n            ctx.versions_cache[project] = (time.time(), q.get_versions())\n            cached_versions = ctx.versions_cache[project]\n        else:\n            cached_versions = ctx.versions_cache[project]\n            if time.time()-cached_versions[0] > VERSION_CACHE_DURATION_SECONDS:\n                ctx.versions_cache[project] = (time.time(), q.get_versions())\n                cached_versions = ctx.versions_cache[project]\n\n        return cached_versions[1]\n\n# Retruns template context used by the layout template\n# get_url_with_new_version: see get_url parameter of get_versions\n# project: name of the project\n# version: version of the project\ndef get_layout_template_context(q: Query, ctx: RequestContext, get_url_with_new_version: Callable[[str], str],\n                                project: str, version: str) -> dict[str, Any]:\n    versions_raw = get_versions_cached(q, ctx, project)\n    versions, current_version_path = get_versions(versions_raw, get_url_with_new_version, version)\n\n    return {\n        'projects': get_projects(ctx.config.project_dir),\n        'versions': versions,\n        'current_version_path': current_version_path,\n        'topbar_families': TOPBAR_FAMILIES,\n        'elixir_version_string': ctx.config.version_string,\n        'elixir_repo_url': ctx.config.repo_url,\n\n        'source_base_url': get_source_base_url(project, version),\n        'ident_base_url': get_ident_base_url(project, version),\n        'current_project': project,\n        'current_tag': parse.unquote(version),\n        'current_family': 'A',\n    }\n\n# Generate raw source response\ndef generate_raw_source(resp, query, project, version, path):\n    type = query.get_file_type(version, path)\n    if type != 'blob':\n        raise ElixirProjectError('File not found', 'This file does not exist.',\n                                 query=query, project=project, version=version)\n    else:\n        code = query.get_file_raw(version, path)\n        resp.content_type = 'application/octet-stream'\n        resp.text = code\n        resp.downloadable_as = path.split('/')[-1]\n        # Cache for 24 hours\n        resp.cache_control = ('max-age=86400',)\n        # Sandbox result just in case\n        resp.headers['Content-Security-Policy'] = \"sandbox; default-src 'none'\"\n\n# Guesses file format based on filename, returns code formatted as HTML\ndef format_code(filename: str, code: str) -> str:\n    import pygments\n    import pygments.lexers\n    import pygments.formatters\n    from pygments.lexers.asm import GasLexer\n    from pygments.lexers.r import SLexer\n\n    try:\n        lexer = pygments.lexers.guess_lexer_for_filename(filename, code)\n        if filename.endswith('.S') and isinstance(lexer, SLexer):\n            lexer = GasLexer()\n    except pygments.util.ClassNotFound:\n        lexer = pygments.lexers.get_lexer_by_name('text')\n\n    lexer.stripnl = False\n    formatter = pygments.formatters.HtmlFormatter(\n        # Adds line numbers column to output\n        linenos=True,\n        # Wraps line numbers in link (a) tags\n        anchorlinenos=True,\n        # Wraps each line in a span tag with id='codeline-{line_number}'\n        linespans='codeline',\n    )\n    return pygments.highlight(code, lexer, formatter)\n\n# Generate formatted HTML of a file, apply filters (for ex. to add identifier links)\n# q: Query object\n# project: name of the requested project\n# version: requested version of the project\n# path: path to the file in the repository\ndef generate_source(q: Query, project: str, version: str, path: str) -> str:\n    code = q.get_tokenized_file(version, path)\n\n    _, fname = os.path.split(path)\n    _, extension = os.path.splitext(fname)\n    extension = extension[1:].lower()\n    family = getFileFamily(fname)\n\n    source_base_url = get_source_base_url(project, version)\n\n    def get_ident_url(ident, ident_family=None):\n        if ident_family is None:\n            ident_family = family\n        return stringify_ident_path(project, version, ident_family, ident)\n\n    filter_ctx = FilterContext(\n        q,\n        version,\n        family,\n        path,\n        get_ident_url,\n        lambda path: f'{ source_base_url }{ \"/\" if not path.startswith(\"/\") else \"\" }{ path }',\n        lambda rel_path: f'{ source_base_url }{ os.path.dirname(path) }/{ rel_path }',\n    )\n\n    filters = get_filters(filter_ctx, project)\n\n    # Apply filters\n    for f in filters:\n        code = f.transform_raw_code(filter_ctx, code)\n\n    html_code_block = format_code(fname, code)\n\n    # Replace line numbers by links to the corresponding line in the current file\n    html_code_block = sub('href=\"#codeline-(\\d+)', 'name=\"L\\\\1\" id=\"L\\\\1\" href=\"#L\\\\1', html_code_block)\n\n    for f in filters:\n        html_code_block = f.untransform_formatted_code(filter_ctx, html_code_block)\n\n    return html_code_block\n\n# Represents a file entry in git tree\n# type : either tree (directory), blob (file) or symlink\n# name: filename of the file\n# path: path of the file, path to the target in case of symlinks\n# url: absolute URL of the file\n# size: int, file size in bytes, None for directories and symlinks\nDirectoryEntry = namedtuple('DirectoryEntry', 'type, name, path, url, size')\n\n# Returns a list of DirectoryEntry objects with information about files in a directory\n# base_url: file URLs will be created by appending file path to this URL. It shouldn't end with a slash\n# tag: requested repository tag\n# path: path to the directory in the repository\ndef get_directory_entries(q: Query, base_url, tag: str, path: str) -> list[DirectoryEntry]:\n    dir_entries = []\n    lines = q.get_dir_contents(tag, path)\n\n    for l in lines:\n        type, name, size, perm = l.split(' ')\n        file_path = f\"{ path }/{ name }\"\n\n        if type == 'tree':\n            dir_entries.append(DirectoryEntry('tree', name, file_path, f\"{ base_url }{ file_path }\", None))\n        elif type == 'blob':\n            # 120000 permission means it's a symlink\n            if perm == '120000':\n                dir_path = path if path.endswith('/') else path + '/'\n                link_contents = q.get_file_raw(tag, file_path)\n                link_target_path = os.path.abspath(dir_path + link_contents)\n\n                dir_entries.append(DirectoryEntry('symlink', name, link_target_path, f\"{ base_url }{ link_target_path }\", size))\n            else:\n                dir_entries.append(DirectoryEntry('blob', name, file_path, f\"{ base_url }{ file_path }\", size))\n\n    return dir_entries\n\n# Generates response (status code and optionally HTML) of the `source` route\ndef generate_source_page(ctx: RequestContext, q: Query,\n                         project: str, version: str, path: str) -> tuple[int, str]:\n\n    status = falcon.HTTP_OK\n    source_base_url = get_source_base_url(project, version)\n\n    type = q.get_file_type(version, path)\n\n    # Generate breadcrumbs\n    path_split = path.split('/')[1:]\n    path_temp = ''\n    breadcrumb_urls = []\n    for p in path_split:\n        path_temp += '/'+p\n        breadcrumb_urls.append((p, f'{ source_base_url }{ path_temp }'))\n\n    if type == 'tree':\n        back_path = os.path.dirname(path[:-1])\n        if back_path == '/':\n            back_path = ''\n\n        template_ctx = {\n            'dir_entries': get_directory_entries(q, source_base_url, version, path),\n            'back_url': f'{ source_base_url }{ back_path }' if path != '' else None,\n        }\n        template = ctx.jinja_env.get_template('tree.html')\n    elif type == 'blob':\n        template_ctx = {\n            'code': generate_source(q, project, version, path),\n            'path': path,\n        }\n        template = ctx.jinja_env.get_template('source.html')\n    else:\n        raise ElixirProjectError('File not found', 'This file does not exist.',\n                                 status=falcon.HTTP_NOT_FOUND,\n                                 query=q, project=project, version=version,\n                                 extra_template_args={'breadcrumb_urls': breadcrumb_urls})\n\n    # Create titles like this:\n    # root path: \"Linux source code (v5.5.6) - Bootlin\"\n    # first level path: \"arch - Linux source code (v5.5.6) - Bootlin\"\n    # deeper paths: \"Makefile - arch/um/Makefile - Linux source code (v5.5.6) - Bootlin\"\n    if path == '':\n        title_path = ''\n    elif len(path_split) == 1:\n        title_path = f'{ path_split[0] } - '\n    else:\n        title_path = f'{ path_split[-1] } - { \"/\".join(path_split) } - '\n\n    get_url_with_new_version = lambda v: stringify_source_path(project, v, path)\n\n    # Create template context\n    data = {\n        **get_layout_template_context(q, ctx, get_url_with_new_version, project, version),\n\n        'title_path': title_path,\n        'path': path,\n        'breadcrumb_urls': breadcrumb_urls,\n\n        **template_ctx,\n    }\n\n    return (status, template.render(data))\n\n# Represents line in a file with URL to that line\nLineWithURL = namedtuple('LineWithURL', 'lineno, url')\n\n# Represents a symbol occurrence to be rendered by ident template\n# type : type of the symbol\n# path: path of the file that contains the symbol\n# line: list of LineWithURL\nSymbolEntry = namedtuple('SymbolEntry', 'type, path, lines')\n\n# Converts SymbolInstance into SymbolEntry\n# path of SymbolInstance will be appended to base_url\ndef symbol_instance_to_entry(base_url: str, symbol: SymbolInstance) -> SymbolEntry:\n    # TODO this should be a responsibility of Query\n    if type(symbol.line) is str:\n        line_numbers = symbol.line.split(',')\n    else:\n        line_numbers = [symbol.line]\n\n    lines = [\n        LineWithURL(l, f'{ base_url }/{ symbol.path }#L{ l }')\n        for l in line_numbers\n    ]\n\n    return SymbolEntry(symbol.type, symbol.path, lines)\n\n# Generates response (status code and optionally HTML) of the `ident` route\n# basedir: path to data directory, ex: \"/srv/elixir-data\"\ndef generate_ident_page(ctx: RequestContext, q: Query,\n                        project: str, version: str, family: str, ident: str) -> tuple[int, str]:\n\n    status = falcon.HTTP_OK\n    source_base_url = get_source_base_url(project, version)\n    symbol_definitions, symbol_references, symbol_doccomments, symbol_exists = q.search_ident(\n            version, ident, family)\n    symbol_sections = []\n\n    if len(symbol_definitions) or len(symbol_references):\n        if len(symbol_doccomments):\n            symbol_sections.append({\n                'title': 'Documented',\n                'symbols': {'_unknown': [symbol_instance_to_entry(source_base_url, sym) for sym in symbol_doccomments]},\n            })\n\n        if len(symbol_definitions):\n            defs_by_type = OrderedDict({})\n\n            # TODO this should be a responsibility of Query\n            for sym in symbol_definitions:\n                if sym.type not in defs_by_type:\n                    defs_by_type[sym.type] = [symbol_instance_to_entry(source_base_url, sym)]\n                else:\n                    defs_by_type[sym.type].append(symbol_instance_to_entry(source_base_url, sym))\n\n            symbol_sections.append({\n                'title': 'Defined',\n                'symbols': defs_by_type,\n            })\n        else:\n            symbol_sections.append({\n                'message': 'No definitions found in the database',\n            })\n\n        if len(symbol_references):\n            symbol_sections.append({\n                'title': 'Referenced',\n                'symbols': {'_unknown': [symbol_instance_to_entry(source_base_url, sym) for sym in symbol_references]},\n            })\n        else:\n            symbol_sections.append({\n                'message': 'No references found in the database',\n            })\n\n    elif ident != '':\n        status = falcon.HTTP_NOT_FOUND\n\n    get_url_with_new_version = lambda v: stringify_ident_path(project, v, family, ident)\n\n    data = {\n        **get_layout_template_context(q, ctx, get_url_with_new_version, project, version),\n\n        'searched_ident': ident,\n        'current_family': family,\n\n        'symbol_sections': symbol_sections,\n\n        'symbol_exists': symbol_exists,\n    }\n\n    template = ctx.jinja_env.get_template('ident.html')\n    return (status, template.render(data))\n\n\ndef get_jinja_env():\n    script_dir = os.path.dirname(os.path.realpath(__file__))\n    templates_dir = os.path.join(script_dir, '../templates/')\n    loader = jinja2.FileSystemLoader(templates_dir)\n    return jinja2.Environment(loader=loader)\n\n# see https://falcon.readthedocs.io/en/v3.1.2/user/recipes/raw-url-path.html\n# Replaces the default, unquoted URL with a quoted version\n# NOTE: this is non-standard and it's not guaranteed to work on all WSGI servers\nclass RawPathComponent:\n    def process_request(self, req, _):\n        raw_uri = req.env.get('RAW_URI') or req.env.get('REQUEST_URI')\n        if raw_uri:\n            req.path, _, _ = raw_uri.partition('?')\n\n# Adds request context to all requests\nclass RequestContextMiddleware:\n    def __init__(self, jinja_env):\n        self.jinja_env = jinja_env\n        self.versions_cache = {}\n        self.versions_cache_lock = threading.Lock()\n\n    def process_request(self, req, _resp):\n        req.context = RequestContext(\n            Config(req.env['LXR_PROJ_DIR'], ELIXIR_VERSION_STRING, ELIXIR_REPO_LINK),\n            self.jinja_env,\n            logging.getLogger(__name__),\n            self.versions_cache,\n            self.versions_cache_lock,\n        )\n\n# Serialies caught exceptions to JSON or HTML\n# See https://falcon.readthedocs.io/en/stable/api/app.html#falcon.App.set_error_serializer\ndef error_serializer(req, resp, exception):\n    preferred = req.client_prefers((falcon.MEDIA_HTML, falcon.MEDIA_JSON))\n\n    if preferred is not None:\n        if preferred == falcon.MEDIA_JSON:\n            resp.data = exception.to_json()\n            resp.content_type = falcon.MEDIA_JSON\n        elif preferred == falcon.MEDIA_HTML:\n            if isinstance(exception, ElixirProjectError):\n                resp.text = get_project_error_page(req, resp, exception)\n            else:\n                resp.text = get_error_page(req, resp, exception)\n            resp.content_type = falcon.MEDIA_HTML\n\n    resp.append_header('Vary', 'Accept')\n\n# Builds and returns the Falcon application\ndef get_application():\n    app = falcon.App(middleware=[\n        RawPathComponent(),\n        RequestContextMiddleware(get_jinja_env()),\n    ])\n\n    app.router_options.converters['project'] = ProjectConverter\n    app.router_options.converters['ident'] = IdentConverter\n\n    app.set_error_serializer(error_serializer)\n\n    app.add_route('/', IndexResource())\n    app.add_route('/{project}/{version}/source/{path:path}', SourceResource())\n    app.add_route('/{project}/{version}/source', SourceWithoutPathResource())\n    app.add_route('/{project}/{version}/ident', IdentPostRedirectResource())\n    app.add_route('/{project}/{version}/ident/{ident}', IdentWithoutFamilyResource())\n    app.add_route('/{project}/{version}/{family}/ident/{ident}', IdentResource())\n\n    app.add_route('/acp', AutocompleteResource())\n    app.add_route('/api/ident/{project:project}/{ident:ident}', ApiIdentGetterResource())\n\n    app.add_route('/{project}', IncompleteURLRedirectResource())\n    app.add_route('/{project}/{version}', IncompleteURLRedirectResource())\n    app.add_route('/{project}/{version}/', IncompleteURLRedirectResource())\n    app.add_route('/{project}/{version}/{family}', UnknownPathResource())\n    app.add_route('/{project}/{version}/{family}/{subcmd}', UnknownPathResource())\n    app.add_route('/{project}/{version}/{family}/{subcmd}/{path:path}', UnknownPathResource())\n\n    return app\n\napplication = get_application()\n\n"
  },
  {
    "path": "elixir/web_utils.py",
    "content": "import os\nimport re\nimport logging\nimport threading\nfrom urllib import parse\nfrom typing import Any, Dict, NamedTuple\nimport falcon\nimport jinja2\n\nfrom .lib import validFamily, run_cmd\n\nELIXIR_DIR = os.path.normpath(os.path.dirname(__file__) + \"/../\")\nELIXIR_REPO_LINK = 'https://github.com/bootlin/elixir/'\n\ndef get_elixir_version_string():\n    version = os.environ.get('ELIXIR_VERSION')\n    if version is not None and len(version) != 0:\n        return version\n\n    try:\n        # try to get Elixir version from git\n        result, return_code = run_cmd('git',\n            '-C', ELIXIR_DIR,\n            '-c', f'safe.directory={ ELIXIR_DIR }',\n            'rev-parse', '--short', 'HEAD'\n        )\n\n        if return_code == 0:\n            return result.decode('utf-8')\n\n    except Exception:\n        logging.exception(\"failed to get elixir commit hash\")\n\n    return ''\n\ndef get_elixir_repo_url(version):\n    if re.match('^[0-9a-f]{5,12}$', version) or version.startswith('v'):\n        return ELIXIR_REPO_LINK + f'tree/{ version }'\n    else:\n        return ELIXIR_REPO_LINK\n\n# Elixir config, currently contains only path to directory with projects\nclass Config(NamedTuple):\n    project_dir: str\n    version_string: str\n    repo_url: str\n\n# Basic information about handled request - current Elixir configuration, configured Jinja environment\n# and logger\nclass RequestContext(NamedTuple):\n    config: Config\n    jinja_env: jinja2.Environment\n    logger: logging.Logger\n    versions_cache: Dict[str, str]\n    versions_cache_lock: threading.Lock\n\ndef validate_project(project: str) -> str|None:\n    if project is not None and re.match(r'^[a-zA-Z0-9_.,:/-]+$', project):\n        return project.strip()\n\n# Validates and unquotes project parameter\nclass ProjectConverter(falcon.routing.BaseConverter):\n    def convert(self, value: str) -> str:\n        value = parse.unquote(value)\n        project = validate_project(value)\n        if project is None:\n            raise falcon.HTTPBadRequest('Error', 'Invalid project name')\n        return project\n\ndef validate_version(version) -> str|None:\n    if version is not None and re.match(r'^[a-zA-Z0-9_.,:/-]+$', version):\n        return version.strip()\n\ndef validate_ident(ident: str) -> str|None:\n    if ident is not None and re.match(r'^[A-Za-z0-9_,.+?#-]+$', ident):\n        return ident.strip()\n\n# Validates and unquotes identifier parameter\nclass IdentConverter(falcon.routing.BaseConverter):\n    def convert(self, value: str) -> str|None:\n        value = parse.unquote(value)\n        return validate_ident(value)\n\n"
  },
  {
    "path": "find-file-doc-comments.pl",
    "content": "#!/usr/bin/env perl\n# find-file-doc-comments.pl: Find the doc comments for a file.\n# Usage: find-file-doc-comments.pl <C source file name>\n\n#  This file is part of Elixir, a source code cross-referencer.\n#\n#  By Christopher White <cwhite@d3engineering.com>\n#  Copyright (c) 2019--2020 D3 Engineering, LLC.\n#\n#  Elixir is free software: you can redistribute it and/or modify\n#  it under the terms of the GNU Affero General Public License as published by\n#  the Free Software Foundation, either version 3 of the License, or\n#  (at your option) any later version.\n#\n#  Elixir is distributed in the hope that it will be useful,\n#  but WITHOUT ANY WARRANTY; without even the implied warranty of\n#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n#  GNU Affero General Public License for more details.\n#\n#  You should have received a copy of the GNU Affero General Public License\n#  along with Elixir.  If not, see <http://www.gnu.org/licenses/>.\n\nuse 5.010001;\nuse strict;\nuse warnings;\nuse autodie;\n\nmy $VERBOSE = $ENV{V};\n\nexit main(@ARGV);\n\nsub main {\n    die \"Need a filename\" unless @_;\n    my $filename = shift;\n    die \"Could not read $filename\" unless -r $filename;\n    say \"Processing file $filename\" if $VERBOSE;\n\n    # Fatalize all warnings, and log which file triggered the warning.\n    local $SIG{__WARN__} = sub {\n        die \"While processing $filename: $_[0]\\n\";\n    };\n\n    # Do `script.sh parse-defs` on the file\n    my @ctags = qx{ ctags -x --c-kinds=+p-m --language-force=C \"$filename\" |\n            grep -av \"^operator \" |\n            awk '{print \\$1\" \"\\$2\" \"\\$3}' };\n    die \"Could not get ctags: $!\" if $!;\n    say \"No ctags results\" if $VERBOSE && !@ctags;\n    return 0 unless @ctags;\n\n    # Make a list of [name, type, line] arrays\n    my @ctags_parsed = map { [split] } @ctags;\n\n    # Flip it around to index functions and types by line.  Don't index anything\n    # by name, since there can be multiple names with different types/lines (#186).\n    my %definition_lines;\n    my %definition_types;\n    for my $tag (@ctags_parsed) {\n        $definition_lines{$tag->[2]} = $tag->[0];\n        $definition_types{$tag->[2]} = $tag->[1] // '<none>';\n    }\n\n    if($VERBOSE) {\n        for my $tag (sort { $a->[2] <=> $b->[2] } @ctags_parsed) {\n            say $tag->[2], ': ', $tag->[0], ' is a(n) ', $tag->[1];\n        }\n    }\n\n    # Read the source file\n    open my $fh, '<', $filename;\n    my @source_lines = (undef, <$fh>);\n        # undef => indices in @source_lines match ctags's 1-based linenos\n    close $fh;\n\n    # Work backwards through the file and look for doc comments\n    my %doc_comments;\n\n    my $doc_comment_opener = qr{^\\h*\\/\\*\\*(?:\\h|$)};    # Start of doc comment\n    my $comment_leader = qr{\\h+\\*\\h+(?:(?:struct|enum|union|typedef)\\h+)?};\n\n    for(my $lineno = $#source_lines ; $lineno >= 1 ; --$lineno) {\n        next unless exists $definition_lines{$lineno};\n        my $definition_name = $definition_lines{$lineno};\n        my $definition_type = $definition_types{$lineno};\n        say \"\\nChecking $definition_type $definition_name @ $lineno\" if $VERBOSE;\n\n        # Comment header: be liberal in what we accept.  For example, do not\n        # check the type of the definition/declaration against the type in\n        # the comment header.  I don't think this will be a problem.\n        my $this_doc_comment_header =\n            qr{^$comment_leader\\Q$definition_name\\E(?:\\h|\\(|:|$)};\n        say \"  Regex is -$this_doc_comment_header-\" if $VERBOSE;\n\n        # Make sure we get back past the first line of multiline definitions\n        if($definition_type eq 'macro') {\n            --$lineno while $lineno && $source_lines[$lineno] !~ /^\\h*#\\h*define/;\n        } elsif($definition_type eq 'function') {\n            # Try to handle the case of \"int\\nfoo()\"\n            if($source_lines[$lineno] =~ /^\\h*\\Q$definition_name\\E\\b/) {\n                --$lineno while $lineno && $source_lines[$lineno] =~ /^[a-z_]/i;\n            }\n        }\n\n        # Assume cflags gave us the first line of the definition, or we got\n        # back to it manually.  Move to the first line that might be a doc comment.\n        --$lineno;\n\n        # If we ran off the beginning of the file, there's no doc comment.\n        next if $lineno <= 0;\n\n        # TODO make sure we're not still in the definition.\n        # E.g., memblock.h:for_each_mem_range().  The defintion is reported\n        # on the second line of the #define, not the first line.\n\n        say \"  Starting search for docs at line $lineno\" if $VERBOSE;\n\n        # Find the last line that could be a doc-comment header\n        # for this function.\n        while($lineno && $source_lines[$lineno] =~\n            qr{\n                    ^\\h*$               # Empty line\n                |   ^\\h+\\*\\/            # End of comment\n                |   ^\\h+\\*(?:\\h|$)      # Continuation of comment\n                |   $this_doc_comment_header\n            }x) {\n            if($VERBOSE) {\n                my $line = $source_lines[$lineno];\n                chomp $line;\n                say \"  skipped $lineno '$line'\";\n            }\n            --$lineno;\n        }\n        ++$lineno;  # Check the last line that matched,\n                    # because we may have just skipped past $this_doc_comment_header\n\n        # Is it actually a header for this function?\n        say \"  Checking line $lineno for header\" if $VERBOSE;\n        next unless $source_lines[$lineno] =~ $this_doc_comment_header;\n\n        # We have found a header.  Confirm it's a doc comment.\n        --$lineno;\n        next unless $lineno > 0 && $source_lines[$lineno] =~ $doc_comment_opener;\n        say \"  * Match\" if $VERBOSE;\n\n        # We have found a doc comment for this function!  Record it.\n        push @{$doc_comments{$definition_name}}, $lineno;\n    } # foreach line in reverse order\n\n    # Report the doc comments for each function\n    for my $definition_name (keys %doc_comments) {\n        my $comment_lines = $doc_comments{$definition_name};\n        say \"$definition_name $_\" foreach @$comment_lines;\n    }\n\n    return 0;\n} #main\n"
  },
  {
    "path": "find_compatible_dts.py",
    "content": "#!/usr/bin/env python3\n\n#  This file is part of Elixir, a source code cross-referencer.\n#\n#  Copyright (C) 2017--2020  Maxime Chretien <maxime.chretien@bootlin.com>\n#                            and contributors\n#\n#  Elixir is free software: you can redistribute it and/or modify\n#  it under the terms of the GNU Affero General Public License as published by\n#  the Free Software Foundation, either version 3 of the License, or\n#  (at your option) any later version.\n#\n#  Elixir is distributed in the hope that it will be useful,\n#  but WITHOUT ANY WARRANTY; without even the implied warranty of\n#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n#  GNU Affero General Public License for more details.\n#\n#  You should have received a copy of the GNU Affero General Public License\n#  along with Elixir.  If not, see <http://www.gnu.org/licenses/>.\n\nimport re\nfrom urllib import parse\nfrom elixir.lib import decode\n\nclass FindCompatibleDTS:\n    def __init__(self):\n        # Compile regexes\n        self.regex_c = re.compile(\"\\s*{*\\s*\\.compatible\\s*=\\s*\\\"(.+?)\\\"\")\n        self.regex_dts1 = re.compile(\"\\s*compatible\")\n        self.regex_dts2 = re.compile(\"\\\"(.+?)\\\"\")\n        self.regex_bindings = re.compile(\"([\\w-]+,?[\\w-]+)\")\n\n    def parse_c(self, content):\n        return self.regex_c.findall(content)\n\n    def parse_dts(self, content):\n        ret = []\n        if self.regex_dts1.match(content) != None:\n            ret = self.regex_dts2.findall(content)\n        return ret\n\n    def parse_bindings(self, content):\n        # There are a lot of wrong results\n        # but we don't apply that to a lot of files\n        # so it should be fine\n        return self.regex_bindings.findall(content)\n\n    def run(self, file_lines, family):\n        ident_list = []\n\n        # Iterate though lines and search for idents\n        for num, line in enumerate(file_lines, 1):\n            line = decode(line)\n            if family == 'C':\n                ret = self.parse_c(line)\n            elif family == 'D':\n                ret = self.parse_dts(line)\n            elif family == 'B':\n                ret = self.parse_bindings(line)\n\n            for i in range(len(ret)):\n                ident_list.append(str(parse.quote(ret[i])) + ' ' + str(num))\n\n        return ident_list\n\n"
  },
  {
    "path": "projects/amazon-freertos.sh",
    "content": "# Elixir definitions for Amazon FreeRTOS\n\nlist_tags_h()\n{\n\n    echo \"$tags\" |\n    grep -v '^v' |\n    tac |\n    sed -r 's/^([0-9][0-9][0-9][0-9])([0-9][0-9])(.*)$/\\1 \\1\\2 \\1\\2\\3/'\n\n    echo \"$tags\" |\n    grep '^v' |\n    tac |\n    sed -r 's/^(v[0-9]*)\\.([0-9]*)(.*)$/\\1 \\1.\\2 \\1.\\2\\3/'\n}\n\nget_latest_tags()\n{\n    git tag | grep '^20' | sort -Vr\n}\n"
  },
  {
    "path": "projects/arm-trusted-firmware.sh",
    "content": "# Elixir definitions for Arm Trusted Firmware\n# https://github.com/ARM-software/arm-trusted-firmware\n\n# Enable DT bindings compatible strings support\ndts_comp_support=1\n\nlist_tags_h()\n{\n    echo \"$tags\" |\n    grep -v 'for-v0\\.4' |\n    tac |\n    sed -r 's/^(v[0-9]*)\\.([0-9]*)(.*)$/\\1 \\1.\\2 \\1.\\2\\3/'\n\n    echo \"$tags\" |\n    grep 'for-v0\\.4' |\n    tac |\n    sed -r 's/^/custom for-v0.4 /'\n}\n"
  },
  {
    "path": "projects/barebox.sh",
    "content": "# Elixir definitions for Barebox\n\n# Enable DT bindings compatible strings support\ndts_comp_support=1\n\nlist_tags_h()\n{\n    echo \"$tags\" |\n    grep '^v20' |\n    tac |\n    sed -r 's/^(v20..)\\.([0-9][0-9])\\.(.*)$/\\1 \\1.\\2 \\1.\\2.\\3/'\n\n    echo \"$tags\" |\n    grep '^v2\\.0' |\n    tac |\n    sed -r 's/^(v2\\.0)(.*)$/old \\1 \\1\\2/'\n\n    echo \"$tags\" |\n    grep '^freescale' |\n    tac |\n    sed -r 's/^(freescale)(.*)$/old \\1 \\1\\2/'\n}\n"
  },
  {
    "path": "projects/bluez.sh",
    "content": "# Elixir definitions for BlueZ\nlist_tags()\n{\n    echo \"$tags\" |\n    grep '^[0-9]'\n}\n\nlist_tags_h()\n{\n    echo \"$tags\" |\n    grep '^[0-9]' |\n    sort -rV |\n    sed -E 's/^([0-9]*)\\.([0-9]*)$/v\\1 v\\1.\\2 \\1.\\2/'\n}\n\nget_latest_tags()\n{\n    git tag | grep '^[0-9]\\.' | sort -Vr\n}\n"
  },
  {
    "path": "projects/busybox.sh",
    "content": "# Elixir definitions for BusyBox\n\nversion_dir()\n{\n    tr '_.' '._';\n}\n\nversion_rev()\n{\n    tr '._' '_.';\n}\n\nlist_tags_h()\n{\n    echo \"$tags\" |\n    tac |\n    sed -r 's/^([0-9]*)\\.([0-9]*)(.*)$/v\\1 \\1.\\2 \\1.\\2\\3/'\n}\n\n"
  },
  {
    "path": "projects/coreboot.sh",
    "content": "# Elixir definitions for Coreboot\n\nlist_tags_h()\n{\n    echo \"$tags\" |\n    tac |\n    sed -r 's/^([0-9]*)\\.([0-9]*)(.*)$/v\\1 v\\1.\\2 \\1.\\2\\3/'\n}\n"
  },
  {
    "path": "projects/dpdk.sh",
    "content": "# Elixir definitions for DPDK\n\nlist_tags_h()\n{\n    echo \"$tags\" |\n    grep -vE '^v1\\.|^v2\\.' |\n    tac |\n    sed -r 's/^v([0-9]*)\\.([0-9]*)(.*)$/v\\1 v\\1.\\2 v\\1.\\2\\3/'\n\n    echo \"$tags\" |\n    grep -E '^v1\\.|^v2\\.' |\n    tac |\n    sed -r 's/^v(1|2)\\.([0-9])(.*)$/old v\\1.\\2 v\\1.\\2\\3/'\n}\n"
  },
  {
    "path": "projects/freebsd.sh",
    "content": "# FreeBSD\n\nversion_dir()\n{\n    grep \"^release/[0-9]*\\.[0-9]*\\.[0-9]*$\" |\n    sed -e 's,^release/,v,' |\n    sed -e 's,\\.0$,,';\n}\n\nversion_rev()\n{\n    grep \"^v\" |\n    sed -e 's,v[0-9]*\\.[0-9]*$,&\\.0,' |\n    sed -e 's,^v,release/,';\n}\n"
  },
  {
    "path": "projects/glibc.sh",
    "content": "# Elixir definitions for glibc\n\nlist_tags()\n{\n    echo \"$tags\" |\n    grep -v 'cvs'\n}\n\nlist_tags_h()\n{\n    echo \"$tags\" |\n    grep \"glibc\" |\n    grep -v \"fedora\" |\n    grep -v \"cvs\" |\n    tac |\n    sed -r 's/^glibc-([0-9]*)(\\.[0-9]*)(.*)$/v\\1 v\\1\\2 glibc-\\1\\2\\3/'\n\n    echo \"$tags\" |\n    grep -v \"cvs\" |\n    grep \"fedora\" |\n    tac |\n    sed -r 's/^fedora\\/glibc-([0-9]*)(\\.[0-9]*)(.*)$/fedora v\\1\\2 fedora\\/glibc-\\1\\2\\3/'\n}\n"
  },
  {
    "path": "projects/grub.sh",
    "content": "# Elixir definitions for Grub\n\nlist_tags_h()\n{\n    echo \"$tags\" |\n    tac |\n    sed -r 's/^(grub-)?([0-9]+).([0-9]+)([A-Za-z0-9\\.-]*)$/\\2 \\2.\\3 \\1\\2.\\3\\4/'\n}\n"
  },
  {
    "path": "projects/iproute2.sh",
    "content": ""
  },
  {
    "path": "projects/linux.sh",
    "content": "# Elixir definitions for Linux\n\n# Enable DT bindings compatible strings support\ndts_comp_support=1\n\nget_tags()\n{\n    git tag |\n    version_dir |\n    sed -r 's/^(pre|lia64-|)(v?[0-9\\.]*)(pre|-[^pf].*?|)(alpha|-[pf].*?|)([0-9]*)(.*?)$/\\2#\\3@\\4@\\5@\\60@\\1.0/' |\n    sort -V |\n    sed -r 's/^(.*?)#(.*?)@(.*?)@(.*?)@(.*?)0@(.*?)\\.0$/\\6\\1\\2\\3\\4\\5/'\n}\n\nlist_tags_h()\n{\n    echo \"$tags\" |\n    tac |\n    sed -r 's/^(pre|lia64-|)(v?)([0-9]*)\\.([0-9]*)(.*)$/v\\3 v\\3.\\4 \\1\\2\\3.\\4\\5/'\n}\n"
  },
  {
    "path": "projects/llvm.sh",
    "content": "# Elixir definitions for LLVM\n\nlist_tags()\n{\n    echo \"$tags\" |\n    tac |\n    grep ^llvmorg-[0-9]*[\\.][0-9]*\n}\n\nlist_tags_h()\n{\n    echo \"$tags\" |\n    grep ^llvmorg |\n    grep -v init |\n    tac |\n    sed -r 's/^llvmorg-([0-9]*)\\.([0-9]*)(.*)$/v\\1 v\\1.\\2 llvmorg-\\1.\\2\\3/'\n}\n\nget_latest_tags()\n{\n    git tag | grep 'llvmorg' | grep -v init | sort -Vr\n}\n"
  },
  {
    "path": "projects/mesa.sh",
    "content": "# Elixir definitions for Mesa\n\nlist_tags()\n{\n    echo \"$tags\" |\n    tac |\n    grep ^mesa-[0-9]*[\\.][0-9]*\n}\n\nlist_tags_h()\n{\n    echo \"$tags\" |\n    grep ^mesa-[0-9]*[\\.][0-9]* |\n    tac |\n    sed -r 's/^mesa-([0-9]*)(\\.[0-9]*)(.*)$/v\\1 v\\1\\2 mesa-\\1\\2\\3/'\n}\n\nget_latest_tags()\n{\n    git tag | version_dir | grep ^mesa-[0-9]*[\\.][0-9]* | grep -v '\\-rc' | sort -Vr\n}\n"
  },
  {
    "path": "projects/musl.sh",
    "content": "# Elixir definitions for Musl\n# Using the default ones so far!\n"
  },
  {
    "path": "projects/ofono.sh",
    "content": "# Elixir definitions for Ofono\n\nlist_tags_h()\n{\n    echo \"$tags\" |\n    tac |\n    sed -r 's/^([0-9]*)\\.([0-9]*)(.*)$/v\\1 v\\1.\\2 \\1.\\2\\3/'\n}\n"
  },
  {
    "path": "projects/op-tee.sh",
    "content": "# Elixir definitions for OP-TEE Trusted OS\n\nlist_tags_h()\n{\n    echo \"$tags\" |\n    grep '^[0-9]\\.' |\n    tac |\n    sed -r 's/^([0-9]*)\\.([0-9]*)(.*)$/v\\1 \\1.\\2 \\1.\\2\\3/'\n}\n\nlist_tags()\n{\n    echo \"$tags\" |\n    grep '^[0-9]\\.'\n}\n\nget_latest_tags()\n{\n    git tag | grep '^[0-9]\\.' | grep -v '\\-rc' | sort -Vr\n}\n"
  },
  {
    "path": "projects/opensbi.sh",
    "content": ""
  },
  {
    "path": "projects/qemu.sh",
    "content": "# Elixir definitions for QEMU\n\nlist_tags_h()\n{\n    echo \"$tags\" |\n    grep -E \"^v[0-9].*\" |\n    tac |\n    sed -r 's/^(v[0-9])\\.([0-9]*)(.*)$/\\1 \\1.\\2 \\1.\\2\\3/'\n\n    echo \"$tags\" |\n    grep \"release\" |\n    tac |\n    sed -r 's/^(release)_([0-9_]*)$/old \\1 \\1_\\2/'\n\n    echo \"old initial initial\"\n}\n"
  },
  {
    "path": "projects/toybox.sh",
    "content": "# Elixir definitions for Toybox\n\nlist_tags_h()\n{\n    echo \"$tags\" |\n    tac |\n    sed -r 's/^([0-9]*)\\.([0-9]*)(.*)$/\\1 \\1.\\2 \\1.\\2\\3/'\n}"
  },
  {
    "path": "projects/u-boot.sh",
    "content": "# Elixir definitions for U-Boot\n\n# Enable DT bindings compatible strings support\ndts_comp_support=1\n\nlist_tags_h()\n{\n    echo \"$tags\" |\n    grep '^v20' |\n    tac |\n    sed -r 's/^(v20..)\\.([0-9][0-9])(.*)$/\\1 \\1.\\2 \\1.\\2\\3/'\n\n    echo \"$tags\" |\n    grep -E '^(v1|U)' |\n    tac |\n    sed -r 's/^/old by-version /'\n\n    echo \"$tags\" |\n    grep -E '^(LABEL|DENX)' |\n    tac |\n    sed -r 's/^/old by-date /'\n}\n"
  },
  {
    "path": "projects/uclibc-ng.sh",
    "content": "# Elixir definitions for uclibc-ng\n# Using the default ones so far\n"
  },
  {
    "path": "projects/xen.sh",
    "content": "# Xen hypervisor\n\nversion_dir()\n{\n    grep \"^RELEASE\" |\n    sed -e 's/^RELEASE-/v/';\n}\n\nversion_rev()\n{\n    grep \"^v\" |\n    sed -e 's/^v/RELEASE-/';\n}\n"
  },
  {
    "path": "projects/zephyr.sh",
    "content": "# Elixir definitions for Zephyr\n\n# Enable DT bindings compatible strings support\ndts_comp_support=1\n\nlist_tags()\n{\n    echo \"$tags\" |\n    grep -v '^zephyr-v'\n}\n\nlist_tags_h()\n{\n    echo \"$tags\" |\n    grep -v '^zephyr-v' |\n    tac |\n    sed -r 's/^(v[0-9]*)\\.([0-9]*)(.*)$/\\1 \\1.\\2 \\1.\\2\\3/'\n}\n\nget_latest_tags()\n{\n    git tag | grep -v '^zephyr-v' | version_dir | grep -v '\\-rc' | sort -Vr\n}\n"
  },
  {
    "path": "requirements.txt",
    "content": "Jinja2~=3.1.5\nPygments~=2.18.0\nFalcon~=4.0.2\npytest==7.2.1\n\n# NOTE binary wheels of berkeleydb are not distributed - on Debian this may\n# require installing build-essentials, python3-dev and libdb-dev\n# NOTE keep in sync with wheel version in the Dockerfile\nberkeleydb==18.1.10\n"
  },
  {
    "path": "samples/projects/linuxtest.sh",
    "content": "# Elixir definitions for Linux testing (only one tag)\n# Copy this file to the \"projects\" directory\n\nlist_tags()\n{\n    echo \"v5.6.1\"\n}\n\nlist_tags_h()\n{\n    echo \"v5 v5.6 v5.6.1\"\n}\n\nget_latest_tags()\n{\n    echo \"v5.6.1\"\n}\n"
  },
  {
    "path": "script.sh",
    "content": "#!/bin/sh\n\n#  This file is part of Elixir, a source code cross-referencer.\n#\n#  Copyright (C) 2017--2020  Mikaël Bouillot\n#  <mikael.bouillot@bootlin.com> and contributors\n#  Portions copyright (c) 2019 D3 Engineering, LLC\n#\n#  Elixir is free software: you can redistribute it and/or modify\n#  it under the terms of the GNU Affero General Public License as published by\n#  the Free Software Foundation, either version 3 of the License, or\n#  (at your option) any later version.\n#\n#  Elixir is distributed in the hope that it will be useful,\n#  but WITHOUT ANY WARRANTY; without even the implied warranty of\n#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n#  GNU Affero General Public License for more details.\n#\n#  You should have received a copy of the GNU Affero General Public License\n#  along with Elixir.  If not, see <http://www.gnu.org/licenses/>.\n\nif [ ! -d \"$LXR_REPO_DIR\" ]; then\n    echo \"$0: Can't find repository\"\n    exit 1\nfi\n\n# Get our path so we can find peer find-file-doc-comments.pl later\ncur_dir=`pwd`\nscript_path=`realpath \"$0\"`\ncd `dirname \"$script_path\"`\nscript_dir=`pwd`\ncd \"$cur_dir\"\ndts_comp_support=0 # DT bindings compatible strings support (disable by default)\n\nversion_dir()\n{\n    cat;\n}\n\nversion_rev()\n{\n    cat;\n}\n\nget_tags()\n{\n    git tag |\n    version_dir |\n    sed 's/$/.0/' |\n    sort -V |\n    sed 's/\\.0$//'\n}\n\nlist_tags()\n{\n    echo \"$tags\"\n}\n\nlist_tags_h()\n{\n    echo \"$tags\" |\n    tac |\n    sed -r 's/^(v[0-9]*)\\.([0-9]*)(.*)$/\\1 \\1.\\2 \\1.\\2\\3/'\n}\n\nget_latest_tags()\n{\n    git tag | version_dir | grep -v '\\-rc' | sort -Vr\n}\n\nget_type()\n{\n    v=`echo $opt1 | version_rev`\n    git cat-file -t \"$v:`denormalize $opt2`\" 2>/dev/null\n}\n\nget_blob()\n{\n    git cat-file blob $opt1\n}\n\nget_file()\n{\n    v=`echo $opt1 | version_rev`\n    git cat-file blob \"$v:`denormalize $opt2`\" 2>/dev/null\n}\n\nget_dir()\n{\n        v=`echo $opt1 | version_rev`\n        git ls-tree -l \"$v:`denormalize $opt2`\" 2>/dev/null |\n        awk '{print $2\" \"$5\" \"$4\" \"$1}' |\n        grep -v ' \\.' |\n        sort -t ' ' -k 1,1r -k 2,2\n}\n\ntokenize_file()\n{\n    if [ \"$opt1\" = -b ]; then\n        ref=$opt2\n    else\n        v=`echo $opt1 | version_rev`\n        ref=\"$v:`denormalize $opt2`\"\n    fi\n\n    if [ $opt3 = \"D\" ]; then #Don't cut around '-' in devicetrees\n        regex='s%((/\\*.*?\\*/|//.*?\\001|[^'\"'\"']\"(\\\\.|.)*?\"|# *include *<.*?>|[^\\w-])+)([\\w-]+)?%\\1\\n\\4\\n%g'\n    else\n        regex='s%((/\\*.*?\\*/|//.*?\\001|[^'\"'\"']\"(\\\\.|.)*?\"|# *include *<.*?>|\\W)+)(\\w+)?%\\1\\n\\4\\n%g'\n    fi\n\n    git cat-file blob $ref 2>/dev/null |\n    tr '\\n' '\\1' |\n    perl -pe \"$regex\" |\n    head -n -1\n}\n\nlist_blobs()\n{\n    v=`echo $opt2 | version_rev`\n\n    if [ \"$opt1\" = '-p' ]; then\n        # \"path\" option: return blob hash and full path\n        format='\\1 \\2'\n    elif [ \"$opt1\" = '-f' ]; then\n        # \"file\" option: return blob hash and file name (without its path)\n        format='\\1 \\4'\n    else\n        # default option: return only blob hash\n        format='\\1'\n        v=`echo $opt1 | version_rev`\n    fi\n\n    git ls-tree -r \"$v\" |\n    sed -r \"s/^\\S* blob (\\S*)\\t(([^/]*\\/)*(.*))$/$format/; /^\\S* commit .*$/d\"\n}\n\nuntokenize()\n{\n    tr -d '\\n' |\n    sed 's/>/\\*\\//g' |\n    sed 's/</\\/\\*/g' |\n    tr '\\1\\2\\3' '\\n<>'\n}\n\nparse_defs()\n{\n    case $opt3 in\n    \"C\")\n        parse_defs_C\n        ;;\n    \"K\")\n        parse_defs_K\n        ;;\n    \"D\")\n        parse_defs_D\n        ;;\n    esac\n}\n\nparse_defs_C()\n{\n    tmp=`mktemp -d`\n    full_path=$tmp/$opt2\n    git cat-file blob \"$opt1\" > \"$full_path\"\n\n    # Use ctags to parse most of the defs\n    ctags -x --kinds-c=+p+x --extras='-{anonymous}' \"$full_path\" |\n    grep -avE -e \"^operator \" -e \"^CONFIG_\" |\n    awk '{print $1\" \"$2\" \"$3}'\n\n    # Parse function macros, e.g., in .S files\n    perl -ne '/^\\s*ENTRY\\((\\w+)\\)/ and print \"$1 function $.\\n\"' \"$full_path\"\n    perl -ne '/^SYSCALL_DEFINE[0-9]\\(\\s*(\\w+)\\W/ and print \"sys_$1 function $.\\n\"' \"$full_path\"\n\n    rm \"$full_path\"\n    rmdir $tmp\n}\n\nparse_defs_K()\n{\n    tmp=`mktemp -d`\n    full_path=$tmp/$opt2\n    git cat-file blob \"$opt1\" > \"$full_path\"\n    ctags -x --language-force=kconfig --kinds-kconfig=c --extras-kconfig=-{configPrefixed} \"$full_path\" |\n    awk '{print \"CONFIG_\"$1\" \"$2\" \"$3}'\n    rm \"$full_path\"\n    rmdir $tmp\n}\n\nparse_defs_D()\n{\n    tmp=`mktemp -d`\n    full_path=$tmp/$opt2\n    git cat-file blob \"$opt1\" > \"$full_path\"\n    ctags -x --language-force=dts \"$full_path\" |\n    awk '{print $1\" \"$2\" \"$3}'\n    rm \"$full_path\"\n    rmdir $tmp\n}\n\nparse_docs()\n{\n    tmpfile=`mktemp`\n\n    git cat-file blob \"$opt1\" > \"$tmpfile\"\n    \"$script_dir/find-file-doc-comments.pl\" \"$tmpfile\" || exit \"$?\"\n\n    rm -rf \"$tmpfile\"\n}\n\ndts_comp()\n{\n    echo $dts_comp_support\n}\n\nproject=$(basename `dirname $LXR_REPO_DIR`)\n\nplugin=$script_dir/projects/$project.sh\nif [ -f \"$plugin\" ] ; then\n    . $plugin\nfi\n\ncd \"$LXR_REPO_DIR\"\n\ntest $# -gt 0 || set help\n\ncmd=$1\nopt1=$2\nopt2=$3\nopt3=$4\nshift\n\ndenormalize()\n{\n    echo $1 | cut -c 2-\n}\n\ncase $cmd in\n    list-tags)\n        tags=`get_tags`\n\n        if [ \"$opt1\" = '-h' ]; then\n            list_tags_h\n        else\n            list_tags\n        fi\n        ;;\n\n    get-latest-tags)\n        get_latest_tags\n        ;;\n\n    get-type)\n        get_type\n        ;;\n\n    get-blob)\n        get_blob\n        ;;\n\n    get-file)\n        get_file\n        ;;\n\n    get-dir)\n        get_dir\n        ;;\n\n    list-blobs)\n        list_blobs\n        ;;\n\n    tokenize-file)\n        tokenize_file\n        ;;\n\n    untokenize)\n        untokenize\n        ;;\n\n    parse-defs)\n        parse_defs\n        ;;\n\n    parse-docs)\n        parse_docs\n        ;;\n\n    dts-comp)\n        dts_comp\n        ;;\n\n    help)\n        echo \"Usage: $0 subcommand [args]...\"\n        exit 1\n        ;;\n\n    *)\n        echo \"$0: Unknown subcommand: $cmd\"\n        exit 1\nesac\n"
  },
  {
    "path": "static/autocomplete.js",
    "content": "/*\n * @license MIT\n *\n * Autocomplete.js v2.7.1\n * Developed by Baptiste Donaux\n * http://autocomplete-js.com\n *\n * (c) 2017, Baptiste Donaux\n *\n * Built with Browserify and modified by\n * Maxime Chretien <maxime.chretien@bootlin.com>\n * for the needs of Elixir Cross Referencer\n * https://github.com/bootlin/elixir\n *\n */\n\nvar currentScript = document.currentScript;\n\n(function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c=\"function\"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error(\"Cannot find module '\"+i+\"'\");throw a.code=\"MODULE_NOT_FOUND\",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u=\"function\"==typeof require&&require,i=0;i<t.length;i++)o(t[i]);return o}return r})()({1:[function(require,module,exports){\nvar AutoComplete = require('autocomplete-js');\n\nAutoComplete({\n    Url: \"/acp\",\n    Limit: 10,\n    MinChars: 4,\n    Delay: 500,\n    SelectCallback: _ => document.getElementById(\"search-form\").requestSubmit(),\n}, \"#search-input\");\n\n},{\"autocomplete-js\":2}],2:[function(require,module,exports){\n(function (global){\n(function(f){if(typeof exports===\"object\"&&typeof module!==\"undefined\"){module.exports=f()}else if(typeof define===\"function\"&&define.amd){define([],f)}else{var g;if(typeof window!==\"undefined\"){g=window}else if(typeof global!==\"undefined\"){g=global}else if(typeof self!==\"undefined\"){g=self}else{g=this}g.AutoComplete = f()}})(function(){var define,module,exports;return (function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c=\"function\"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error(\"Cannot find module '\"+i+\"'\");throw a.code=\"MODULE_NOT_FOUND\",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u=\"function\"==typeof require&&require,i=0;i<t.length;i++)o(t[i]);return o}return r})()({1:[function(require,module,exports){\n\"use strict\";\nvar ConditionOperator;\n(function (ConditionOperator) {\n    ConditionOperator[ConditionOperator[\"AND\"] = 0] = \"AND\";\n    ConditionOperator[ConditionOperator[\"OR\"] = 1] = \"OR\";\n})(ConditionOperator || (ConditionOperator = {}));\nvar EventType;\n(function (EventType) {\n    EventType[EventType[\"KEYDOWN\"] = 0] = \"KEYDOWN\";\n    EventType[EventType[\"KEYUP\"] = 1] = \"KEYUP\";\n})(EventType || (EventType = {}));\n/**\n * Core\n *\n * @class\n * @author Baptiste Donaux <baptiste.donaux@gmail.com> @baptistedonaux\n */\nvar AutoComplete = /** @class */ (function () {\n    // Constructor\n    function AutoComplete(params, selector) {\n        if (params === void 0) { params = {}; }\n        if (selector === void 0) { selector = \"[data-autocomplete]\"; }\n        if (Array.isArray(selector)) {\n            selector.forEach(function (s) {\n                new AutoComplete(params, s);\n            });\n        }\n        else if (typeof selector == \"string\") {\n            var elements = document.querySelectorAll(selector);\n            Array.prototype.forEach.call(elements, function (input) {\n                new AutoComplete(params, input);\n            });\n        }\n        else {\n            var specificParams = AutoComplete.merge(AutoComplete.defaults, params, {\n                DOMResults: document.createElement(\"div\")\n            });\n            AutoComplete.prototype.create(specificParams, selector);\n            return specificParams;\n        }\n    }\n    AutoComplete.prototype.create = function (params, element) {\n        params.Input = element;\n        if (params.Input.nodeName.match(/^INPUT$/i) && (params.Input.hasAttribute(\"type\") === false || params.Input.getAttribute(\"type\").match(/^TEXT|SEARCH$/i))) {\n            params.Input.setAttribute(\"autocomplete\", \"off\");\n            params._Position(params);\n            params.Input.parentNode.appendChild(params.DOMResults);\n            params.$Listeners = {\n                blur: params._Blur.bind(params),\n                destroy: AutoComplete.prototype.destroy.bind(null, params),\n                focus: params._Focus.bind(params),\n                keyup: AutoComplete.prototype.event.bind(null, params, EventType.KEYUP),\n                keydown: AutoComplete.prototype.event.bind(null, params, EventType.KEYDOWN),\n                position: params._Position.bind(params)\n            };\n            for (var event in params.$Listeners) {\n                params.Input.addEventListener(event, params.$Listeners[event]);\n            }\n        }\n\n        // Init cache for all families\n        var e = document.getElementsByName(\"f\")[0];\n        for (var i = 0; i < e.options.length; i++) {\n            var family = encodeURIComponent(e.options[i].value);\n            params.$Cache[family] = {};\n        }\n    };\n    AutoComplete.prototype.getEventsByType = function (params, type) {\n        var mappings = {};\n        for (var key in params.KeyboardMappings) {\n            var event = EventType.KEYUP;\n            if (params.KeyboardMappings[key].Event !== undefined) {\n                event = params.KeyboardMappings[key].Event;\n            }\n            if (event == type) {\n                mappings[key] = params.KeyboardMappings[key];\n            }\n        }\n        return mappings;\n    };\n    AutoComplete.prototype.event = function (params, type, event) {\n        var eventIdentifier = function (condition) {\n            if ((match === true && mapping.Operator == ConditionOperator.AND) || (match === false && mapping.Operator == ConditionOperator.OR)) {\n                condition = AutoComplete.merge({\n                    Not: false\n                }, condition);\n                if (condition.hasOwnProperty(\"Is\")) {\n                    if (condition.Is == event.keyCode) {\n                        match = !condition.Not;\n                    }\n                    else {\n                        match = condition.Not;\n                    }\n                }\n                else if (condition.hasOwnProperty(\"From\") && condition.hasOwnProperty(\"To\")) {\n                    if (event.keyCode >= condition.From && event.keyCode <= condition.To) {\n                        match = !condition.Not;\n                    }\n                    else {\n                        match = condition.Not;\n                    }\n                }\n            }\n        };\n        for (var name in AutoComplete.prototype.getEventsByType(params, type)) {\n            var mapping = AutoComplete.merge({\n                Operator: ConditionOperator.AND\n            }, params.KeyboardMappings[name]), match = ConditionOperator.AND == mapping.Operator;\n            mapping.Conditions.forEach(eventIdentifier);\n            if (match === true) {\n                mapping.Callback.call(params, event);\n            }\n        }\n    };\n    AutoComplete.prototype.makeRequest = function (params, callback, callbackErr) {\n        var propertyHttpHeaders = Object.getOwnPropertyNames(params.HttpHeaders), request = new XMLHttpRequest(), method = params._HttpMethod(), url = params._Url(), queryParams = params._Pre(), queryParamsStringify = encodeURIComponent(params._QueryArg()) + \"=\" + encodeURIComponent(queryParams);\n        if (method.match(/^GET$/i)) {\n            if (url.indexOf(\"?\") !== -1) {\n                url += \"&\" + queryParamsStringify;\n            }\n            else {\n                url += \"?\" + queryParamsStringify;\n            }\n        }\n\n        // Send select family to display only relevant elements\n        var e = document.getElementsByName(\"f\")[0];\n        var family = encodeURIComponent(e.options[e.selectedIndex].value);\n        url += \"&f=\" + encodeURIComponent(family);\n\n        // Send project name\n        url += \"&p=\" + encodeURIComponent(currentScript.getAttribute('project'));\n\n        request.open(method, url, true);\n        for (var i = propertyHttpHeaders.length - 1; i >= 0; i--) {\n            request.setRequestHeader(propertyHttpHeaders[i], params.HttpHeaders[propertyHttpHeaders[i]]);\n        }\n        request.onreadystatechange = function () {\n            if (request.readyState == 4 && request.status == 200) {\n                var e = document.getElementsByName(\"f\")[0];\n                var family = encodeURIComponent(e.options[e.selectedIndex].value);\n                params.$Cache[family][queryParams] = request.response;\n                callback(request.response);\n            }\n            else if (request.status >= 400) {\n                callbackErr();\n            }\n        };\n        return request;\n    };\n    AutoComplete.prototype.ajax = function (params, request, timeout) {\n        if (timeout === void 0) { timeout = true; }\n        if (params.$AjaxTimer) {\n            window.clearTimeout(params.$AjaxTimer);\n        }\n        if (timeout === true) {\n            params.$AjaxTimer = window.setTimeout(AutoComplete.prototype.ajax.bind(null, params, request, false), params.Delay);\n        }\n        else {\n            if (params.Request) {\n                params.Request.abort();\n            }\n            params.Request = request;\n            params.Request.send(params._QueryArg() + \"=\" + params._Pre());\n        }\n    };\n    AutoComplete.prototype.cache = function (params, callback, callbackErr) {\n        var e = document.getElementsByName(\"f\")[0];\n        var family = encodeURIComponent(e.options[e.selectedIndex].value);\n\n        var response = params._Cache(family, params._Pre());\n        if (response === undefined) {\n            var request = AutoComplete.prototype.makeRequest(params, callback, callbackErr);\n            AutoComplete.prototype.ajax(params, request);\n        }\n        else {\n            callback(response);\n        }\n    };\n    AutoComplete.prototype.destroy = function (params) {\n        for (var event in params.$Listeners) {\n            params.Input.removeEventListener(event, params.$Listeners[event]);\n        }\n        params.DOMResults.parentNode.removeChild(params.DOMResults);\n    };\n    AutoComplete.merge = function () {\n        var merge = {}, tmp;\n        for (var i = 0; i < arguments.length; i++) {\n            for (tmp in arguments[i]) {\n                merge[tmp] = arguments[i][tmp];\n            }\n        }\n        return merge;\n    };\n    AutoComplete.defaults = {\n        Delay: 150,\n        EmptyMessage: \"No result here\",\n        Highlight: {\n            getRegex: function (value) {\n                return new RegExp(value, \"ig\");\n            },\n            transform: function (value) {\n                return \"<strong>\" + value + \"</strong>\";\n            }\n        },\n        HttpHeaders: {\n            \"Content-type\": \"application/x-www-form-urlencoded\"\n        },\n        Limit: 0,\n        MinChars: 0,\n        HttpMethod: \"GET\",\n        QueryArg: \"q\",\n        Url: null,\n        SelectCallback: null,\n        KeyboardMappings: {\n            \"Enter\": {\n                Conditions: [{\n                        Is: 13,\n                        Not: false\n                    }],\n                Callback: function (event) {\n                    if (this.DOMResults.getAttribute(\"class\").indexOf(\"open\") != -1) {\n                        var liActive = this.DOMResults.querySelector(\"li.active\");\n                        if (liActive !== null) {\n                            event.preventDefault();\n                            this._Select(liActive);\n                            this.DOMResults.setAttribute(\"class\", \"autocomplete\");\n                        }\n                    }\n                },\n                Operator: ConditionOperator.AND,\n                Event: EventType.KEYDOWN\n            },\n            \"KeyUpAndDown_down\": {\n                Conditions: [{\n                        Is: 38,\n                        Not: false\n                    },\n                    {\n                        Is: 40,\n                        Not: false\n                    }],\n                Callback: function (event) {\n                    event.preventDefault();\n                },\n                Operator: ConditionOperator.OR,\n                Event: EventType.KEYDOWN\n            },\n            \"KeyUpAndDown_up\": {\n                Conditions: [{\n                        Is: 38,\n                        Not: false\n                    },\n                    {\n                        Is: 40,\n                        Not: false\n                    }],\n                Callback: function (event) {\n                    event.preventDefault();\n                    var first = this.DOMResults.querySelector(\"li:first-child:not(.locked)\"), last = this.DOMResults.querySelector(\"li:last-child:not(.locked)\"), active = this.DOMResults.querySelector(\"li.active\");\n                    if (active) {\n                        var currentIndex = Array.prototype.indexOf.call(active.parentNode.children, active), position = currentIndex + (event.keyCode - 39), lisCount = this.DOMResults.getElementsByTagName(\"li\").length;\n                        if (position < 0 || position >= lisCount) {\n                            active.classList.remove(\"active\");\n                            active = null;\n                        }\n                        if (active) {\n                            active.classList.remove(\"active\");\n                            active.parentElement.children.item(position).classList.add(\"active\");\n                        }\n                    }\n                    else if (last && event.keyCode == 38) {\n                        last.classList.add(\"active\");\n                    }\n                    else if (first) {\n                        first.classList.add(\"active\");\n                    }\n                },\n                Operator: ConditionOperator.OR,\n                Event: EventType.KEYUP\n            },\n            \"AlphaNum\": {\n                Conditions: [{\n                        Is: 13,\n                        Not: true\n                    }, {\n                        From: 35,\n                        To: 40,\n                        Not: true\n                    }],\n                Callback: function () {\n                    var oldValue = this.Input.getAttribute(\"data-autocomplete-old-value\"), currentValue = this._Pre();\n                    if (currentValue !== \"\" && currentValue.length >= this._MinChars()) {\n                        if (!oldValue || currentValue != oldValue) {\n                            this.DOMResults.setAttribute(\"class\", \"autocomplete open\");\n                        }\n                        AutoComplete.prototype.cache(this, function (response) {\n                            this._Render(this._Post(response));\n                            this._Open();\n                        }.bind(this), this._Error);\n                    }\n                    else {\n                        this._Close();\n                    }\n                },\n                Operator: ConditionOperator.AND,\n                Event: EventType.KEYUP\n            }\n        },\n        DOMResults: null,\n        Request: null,\n        Input: null,\n        /**\n         * Return the message when no result returns\n         */\n        _EmptyMessage: function () {\n            var emptyMessage = \"\";\n            if (this.Input.hasAttribute(\"data-autocomplete-empty-message\")) {\n                emptyMessage = this.Input.getAttribute(\"data-autocomplete-empty-message\");\n            }\n            else if (this.EmptyMessage !== false) {\n                emptyMessage = this.EmptyMessage;\n            }\n            else {\n                emptyMessage = \"\";\n            }\n            return emptyMessage;\n        },\n        /**\n         * Returns the maximum number of results\n         */\n        _Limit: function () {\n            var limit = this.Input.getAttribute(\"data-autocomplete-limit\");\n            if (isNaN(limit) || limit === null) {\n                return this.Limit;\n            }\n            return parseInt(limit, 10);\n        },\n        /**\n         * Returns the minimum number of characters entered before firing ajax\n         */\n        _MinChars: function () {\n            var minchars = this.Input.getAttribute(\"data-autocomplete-minchars\");\n            if (isNaN(minchars) || minchars === null) {\n                return this.MinChars;\n            }\n            return parseInt(minchars, 10);\n        },\n        /**\n         * Apply transformation on labels response\n         */\n        _Highlight: function (label) {\n            return label.replace(this.Highlight.getRegex(this._Pre()), this.Highlight.transform);\n        },\n        /**\n         * Returns the HHTP method to use\n         */\n        _HttpMethod: function () {\n            if (this.Input.hasAttribute(\"data-autocomplete-method\")) {\n                return this.Input.getAttribute(\"data-autocomplete-method\");\n            }\n            return this.HttpMethod;\n        },\n        /**\n         * Returns the query param to use\n         */\n        _QueryArg: function () {\n            if (this.Input.hasAttribute(\"data-autocomplete-param-name\")) {\n                return this.Input.getAttribute(\"data-autocomplete-param-name\");\n            }\n            return this.QueryArg;\n        },\n        /**\n         * Returns the URL to use for AJAX request\n         */\n        _Url: function () {\n            if (this.Input.hasAttribute(\"data-autocomplete\")) {\n                return this.Input.getAttribute(\"data-autocomplete\");\n            }\n            return this.Url;\n        },\n        /**\n         * Manage the close\n         */\n        _Blur: function (now) {\n            if (now === void 0) { now = false; }\n            if (now) {\n                this._Close();\n            }\n            else {\n                var params = this;\n                setTimeout(function () {\n                    params._Blur(true);\n                }, 150);\n            }\n        },\n        /**\n         * Manage the cache\n         */\n        _Cache: function (family, value) {\n            return this.$Cache[family][value];\n        },\n        /**\n         * Manage the open\n         */\n        _Focus: function () {\n            var oldValue = this.Input.getAttribute(\"data-autocomplete-old-value\");\n            if ((!oldValue || this.Input.value != oldValue) && this._MinChars() <= this.Input.value.length) {\n                this.DOMResults.setAttribute(\"class\", \"autocomplete open\");\n            }\n        },\n        /**\n         * Bind all results item if one result is opened\n         */\n        _Open: function () {\n            var params = this;\n            Array.prototype.forEach.call(this.DOMResults.getElementsByTagName(\"li\"), function (li) {\n                if (li.getAttribute(\"class\") != \"locked\") {\n                    li.onclick = function () {\n                        params._Select(li);\n                    };\n                }\n            });\n        },\n        _Close: function () {\n            this.DOMResults.setAttribute(\"class\", \"autocomplete\");\n        },\n        /**\n         * Position the results HTML element\n         */\n        _Position: function () {\n            this.DOMResults.setAttribute(\"class\", \"autocomplete\");\n            this.DOMResults.setAttribute(\"style\", \"top:\" + (this.Input.offsetTop + this.Input.offsetHeight) + \"px;left:\" + this.Input.offsetLeft + \"px;width:\" + this.Input.clientWidth + \"px;\");\n        },\n        /**\n         * Execute the render of results DOM element\n         */\n        _Render: function (response) {\n            var ul;\n            if (typeof response == \"string\") {\n                ul = this._RenderRaw(response);\n            }\n            else {\n                ul = this._RenderResponseItems(response);\n            }\n            if (this.DOMResults.hasChildNodes()) {\n                this.DOMResults.removeChild(this.DOMResults.childNodes[0]);\n            }\n            this.DOMResults.appendChild(ul);\n        },\n        /**\n         * ResponseItems[] rendering\n         */\n        _RenderResponseItems: function (response) {\n            var ul = document.createElement(\"ul\"), li = document.createElement(\"li\"), limit = this._Limit();\n            // Order\n            if (limit < 0) {\n                response = response.reverse();\n            }\n            else if (limit === 0) {\n                limit = response.length;\n            }\n            for (var item = 0; item < Math.min(Math.abs(limit), response.length); item++) {\n                li.innerHTML = response[item].Label;\n                li.setAttribute(\"data-autocomplete-value\", response[item].Value);\n                ul.appendChild(li);\n                li = document.createElement(\"li\");\n            }\n            return ul;\n        },\n        /**\n         * string response rendering (RAW HTML)\n         */\n        _RenderRaw: function (response) {\n            var ul = document.createElement(\"ul\"), li = document.createElement(\"li\");\n            if (response.length > 0) {\n                this.DOMResults.innerHTML = response;\n            }\n            else {\n                var emptyMessage = this._EmptyMessage();\n                if (emptyMessage !== \"\") {\n                    li.innerHTML = emptyMessage;\n                    li.setAttribute(\"class\", \"locked\");\n                    ul.appendChild(li);\n                }\n            }\n            return ul;\n        },\n        /**\n         * Deal with request response\n         */\n        _Post: function (response) {\n            try {\n                var returnResponse = [];\n                //JSON return\n                var json = JSON.parse(response);\n                if (Object.keys(json).length === 0) {\n                    return \"\";\n                }\n                if (Array.isArray(json)) {\n                    for (var i = 0; i < Object.keys(json).length; i++) {\n                        returnResponse[returnResponse.length] = { \"Value\": json[i], \"Label\": this._Highlight(json[i]) };\n                    }\n                }\n                else {\n                    for (var value in json) {\n                        returnResponse.push({\n                            \"Value\": value,\n                            \"Label\": this._Highlight(json[value])\n                        });\n                    }\n                }\n                return returnResponse;\n            }\n            catch (event) {\n                //HTML return\n                return response;\n            }\n        },\n        /**\n         * Return the autocomplete value to send (before request)\n         */\n        _Pre: function () {\n            return this.Input.value;\n        },\n        /**\n         * Choice one result item\n         */\n        _Select: function (item) {\n            if (item.hasAttribute(\"data-autocomplete-value\")) {\n                this.Input.value = item.getAttribute(\"data-autocomplete-value\");\n            }\n            else {\n                this.Input.value = item.innerHTML;\n            }\n            this.Input.setAttribute(\"data-autocomplete-old-value\", this.Input.value);\n            if (this.SelectCallback) {\n                this.SelectCallback();\n            }\n        },\n        /**\n         * Handle HTTP error on the request\n         */\n        _Error: function () {\n        },\n        $AjaxTimer: null,\n        $Cache: {},\n        $Listeners: {}\n    };\n    return AutoComplete;\n}());\nmodule.exports = AutoComplete;\n\n},{}]},{},[1])(1)\n});\n\n}).call(this,typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {})\n},{}]},{},[1]);\n"
  },
  {
    "path": "static/dynamic-references.js",
    "content": "\"use strict\";\n\nfunction identUrl(project, ident, version, family) {\n  return `/api/ident/${project}/${ident}?version=${version}&family=${family}`;\n}\n\n/*\n  \"definitions\": [\n    {\n      \"path\": \"arch/x86_64/kstat.h\",\n      \"line\": 1,\n      \"type\": \"struct\"\n    }\n  ],\n  \"references\": [\n    {\n      \"path\": \"src/stat/fstatat.c\",\n      \"line\": \"78,142\",\n      \"type\": null\n    }\n  ],\n  \"documentations\": [\n    {\n      \"path\": \"Documentation/devicetree/bindings/arm/arm,cci-400.yaml\",\n      \"line\": \"15,17,18\",\n      \"type\": null\n    }\n  ]\n*/\n\nfunction generateSymbolDefinitionsHTML(symbolDefinitions, project, version) {\n  let result = \"\";\n  let typesCount = {};\n  let previous_type = \"\";\n\n  if(symbolDefinitions.length == 0) {\n    return '<h2>No definitions found in the database</h2>';\n  }\n\n  for(let symbolDefinition of symbolDefinitions) {\n    if (symbolDefinition.type in typesCount) {\n      typesCount[symbolDefinition.type] += 1;\n    } else {\n      typesCount[symbolDefinition.type] = 1;\n    }\n  }\n\n  for (let sd of symbolDefinitions) {\n    if (sd.type != previous_type) {\n      if (previous_type != '') {\n        result += '</ul>';\n      }\n      result += '<h2>Defined in ' + typesCount[sd.type].toString() + ' files as a ' + sd.type + ':</h2>';\n      result += '<ul>';\n      previous_type = sd.type;\n    }\n    let ln = sd.line.toString().split(',');\n    if (ln.length == 1) {\n      let n = ln[0];\n      result += `<li><a href=\"/${project}/${version}/source/${sd.path}#L${n}\"><strong>${sd.path}</strong>, line ${n} <em>(as a ${sd.type})</em></a>`;\n    } else {\n      if (symbolDefinitions.length > 100) {\n        let n = ln.length;\n        result += `<li><a href=\"/${project}/${version}/source/${sd.path}#L${ln[0]}\"><strong>${sd.path}</strong>, <em>${n} times</em> <em>(as a ${sd.type})</em></a>`;\n      } else {\n        result += `<li><a href=\"/${project}/${version}/source/${sd.path}#L${ln[0]}\"><strong>${sd.path}</strong> <em>(as a ${sd.type})</em></a>`;\n        result += '<ul>';\n        for(let n of ln) {\n          result += `<li><a href=\"/${project}/${version}/source/${sd.path}#L${n}\">line ${n}</a></li>`;\n        }\n        result += '</ul>';\n      }\n    }\n  }\n  result += '</ul>';\n\n  return result;\n}\n\nfunction generateSymbolReferencesHTML(symbolReferences, project, version) {\n  let result = \"\";\n\n  if(symbolReferences.length == 0) {\n    return '<h2>No references found in the database</h2>';\n  }\n\n  result += '<h2>Referenced in ' + symbolReferences.length.toString() + ' files:</h2>';\n  result += '<ul>';\n  for (let sr of symbolReferences) {\n    let ln = sr.line.split(',');\n    if (ln.length == 1) {\n      let n = ln[0];\n      result += `<li><a href=\"/${project}/${version}/source/${sr.path}#L${n}\"><strong>${sr.path}</strong>, line ${n}</a>`;\n    } else {\n      if(symbolReferences.length > 100) {\n        let n = ln.length;\n        result += `<li><a href=\"/${project}/${version}/source/${sr.path}#L${ln[0]}\"><strong>${sr.path}</strong>, <em>${n} times</em></a>`;\n      } else {\n        result += `<li><a href=\"/${project}/${version}/source/${sr.path}#L${ln[0]}\"><strong>${sr.path}</strong></a>`;\n        result += '<ul>'\n        for(let n of ln) {\n          result += `<li><a href=\"/${project}/${version}/source/${sr.path}#L${n}\">line ${n}</a>`\n        }\n        result += '</ul>'\n      }\n    }\n  }\n  result += '</ul>'\n  return result;\n}\n\nfunction generateDocCommentsHTML(symbolDocComments, project, version) {\n  let result = \"\";\n  if (symbolDocComments.length == 0) {\n    return result;\n  }\n  result += '<h2>Documented in ' + symbolDocComments.length.toString() + ' files:</h2>';\n  result += '<ul>';\n  for(let sd of symbolDocComments) {\n    let ln = sd.line.split(',');\n    if(ln.length == 1) {\n      let n = ln[0];\n      result += `<li><a href=\"/${project}/${version}/source/${sd.path}#L${n}\"><strong>${sd.path}</strong>, line ${n}</a>`;\n    } else {\n      if(symbolDocComments.length > 100) {\n        let n = ln.length;\n        result += `<li><a href=\"/${project}/${version}/source/${sd.path}#L${ln[0]}\"><strong>${sd.path}</strong>, <em>${n} times</em></a>`;\n      } else {\n        result += `<li><a href=\"/${project}/${version}/source/${sd.path}#L${ln[0]}\"><strong>${sd.path}</strong></a>`;\n        result += '<ul>';\n        for(let n of ln) {\n          result += `<li><a href=\"/${project}/${version}/source/${sd.path}#L${n}\">line ${n}</a>`;\n        }\n        result += '</ul>';\n      }\n    }\n  }\n  result += '</ul>';\n  return result;\n}\n\nfunction generateReferencesHTML(data, project, version) {\n  let symbolDefinitions = data[\"definitions\"];\n  let symbolReferences = data[\"references\"];\n  let symbolDocumentations = data[\"documentations\"];\n  return '<div class=\"lxrident\">' +\n    generateDocCommentsHTML(symbolDocumentations, project, version) +\n    generateSymbolDefinitionsHTML(symbolDefinitions, project, version) +\n    generateSymbolReferencesHTML(symbolReferences, project, version) +\n    '</div>';\n}\n\nfunction showPopup(referencePopup, target) {\n  let targetRect = target.getBoundingClientRect();\n  let x = target.offsetLeft;\n  let y = target.offsetTop + targetRect.height;\n\n  referencePopup.style.visibility = \"visible\";\n  referencePopup.style.display = \"block\";\n  referencePopup.style.left = `${x}px`;\n  referencePopup.style.top = `${y}px`;\n  referencePopup.scrollTop = 0;\n  referencePopup.scrollLeft = 0;\n\n  let referenceRect = referencePopup.getBoundingClientRect();\n\n  if((referenceRect.top + referenceRect.height) > window.innerHeight) {\n    referencePopup.style.top = `${target.offsetTop - referenceRect.height}px`;\n  }\n\n  if((referenceRect.left + referenceRect.width) > window.innerWidth) {\n    x -= ((referenceRect.left + referenceRect.width) - window.innerWidth);\n    referencePopup.style.left = `${x}px`;\n  }\n}\n\nfunction hidePopup(referencePopup) {\n  referencePopup.style.visibility = \"hidden\";\n  referencePopup.style.display = \"none\";\n}\n\ndocument.addEventListener(\"DOMContentLoaded\", _ => {\n  let referencePopup = document.getElementById(\"reference-popup\");\n  let loadingPopup = document.getElementById(\"loading-popup\");\n  var loadingTimer;\n  var popupId = 0;\n  var abortController;\n\n  document.body.querySelectorAll(\".ident\").forEach(el => {\n    el.addEventListener(\"click\", async ev => {\n      if (ev.ctrlKey || ev.metaKey || ev.shiftKey) {\n        return;\n      }\n      ev.preventDefault();\n\n      let splitPath = ev.target.pathname.split(\"/\");\n      let [_, project, version, family, _i, ident] = splitPath;\n\n      let currentPopupId = ++popupId;\n\n      if(abortController !== undefined)\n        abortController.abort();\n      abortController = new AbortController();\n\n      hidePopup(loadingPopup);\n      clearTimeout(loadingTimer);\n      loadingTimer = setTimeout(() => {\n        showPopup(loadingPopup, ev.target);\n      }, 200);\n\n      function cancelLoadingPopup() {\n        if (currentPopupId == popupId) {\n          hidePopup(loadingPopup);\n          clearTimeout(loadingTimer);\n        }\n      }\n\n      try {\n        let result = await fetch(identUrl(project, ident, version, family),\n          { signal: abortController.signal })\n          .then(r => r.json());\n\n        if(currentPopupId == popupId) {\n          referencePopup.innerHTML = generateReferencesHTML(result, project, version);\n          showPopup(referencePopup, ev.target);\n        }\n      } catch(e) {\n        if(e.name !== \"AbortError\") {\n          cancelLoadingPopup();\n          throw e;\n        }\n      }\n\n      cancelLoadingPopup();\n    });\n  });\n\n  referencePopup.addEventListener(\"click\", ev => ev.stopPropagation());\n\n  document.body.addEventListener(\"click\", _ => hidePopup(referencePopup));\n\n  document.body.addEventListener(\"keydown\", ev => {\n    if (ev.key === \"Escape\") {\n      hidePopup(referencePopup);\n    }\n  });\n});\n"
  },
  {
    "path": "static/fonts/ubuntu/LICENCE-FAQ.txt",
    "content": "                        Ubuntu Font Family Licensing FAQ\n\n  Stylistic Foundations\n\n   The Ubuntu Font Family is the first time that a libre typeface has been\n   designed professionally and explicitly with the intent of developing a\n   public and long-term community-based development process.\n\n   When developing an open project, it is generally necessary to have firm\n   foundations: a font needs to maintain harmony within itself even across\n   many type designers and writing systems. For the [1]Ubuntu Font Family,\n   the process has been guided with the type foundry Dalton Maag setting\n   the project up with firm stylistic foundation covering several\n   left-to-right scripts: Latin, Greek and Cyrillic; and right-to-left\n   scripts: Arabic and Hebrew (due in 2011).\n\n   With this starting point the community will, under the supervision of\n   [2]Canonical and [3]Dalton Maag, be able to build on the existing font\n   sources to expand their character coverage. Ultimately everybody will\n   be able to use the Ubuntu Font Family in their own written languages\n   across the whole of Unicode (and this will take some time!).\n\n  Licensing\n\n   The licence chosen by any free software project is one of the\n   foundational decisions that sets out how derivatives and contributions\n   can occur, and in turn what kind of community will form around the\n   project.\n\n   Using a licence that is compatible with other popular licences is a\n   powerful constraint because of the [4]network effects: the freedom to\n   share improvements between projects allows free software to reach\n   high-quality over time. Licence-proliferation leads to many\n   incompatible licences, undermining the network effect, the freedom to\n   share and ultimately making the libre movement that Ubuntu is a part of\n   less effective. For all kinds of software, writing a new licence is not\n   to be taken lightly and is a choice that needs to be thoroughly\n   justified if this path is taken.\n\n   Today it is not clear to Canonical what the best licence for a font\n   project like the Ubuntu Font Family is: one that starts life designed\n   by professionals and continues with the full range of community\n   development, from highly commercial work in new directions to curious\n   beginners' experimental contributions. The fast and steady pace of the\n   Ubuntu release cycle means that an interim libre licence has been\n   necessary to enable the consideration of the font family as part of\n   Ubuntu 10.10 operating system release.\n\n   Before taking any decision on licensing, Canonical as sponsor and\n   backer of the project has reviewed the many existing licenses used for\n   libre/open fonts and engaged the stewards of the most popular licenses\n   in detailed discussions. The current interim licence is the first step\n   in progressing the state-of-the-art in licensing for libre/open font\n   development.\n\n   The public discussion must now involve everyone in the (comparatively\n   new) area of the libre/open font community; including font users,\n   software freedom advocates, open source supporters and existing libre\n   font developers. Most importantly, the minds and wishes of professional\n   type designers considering entering the free software business\n   community must be taken on board.\n\n   Conversations and discussion has taken place, privately, with\n   individuals from the following groups (generally speaking personally on\n   behalf of themselves, rather than their affiliations):\n     * [5]SIL International\n     * [6]Open Font Library\n     * [7]Software Freedom Law Center\n     * [8]Google Font API\n\n    Document embedding\n\n   One issue highlighted early on in the survey of existing font licences\n   is that of document embedding. Almost all font licences, both free and\n   unfree, permit embedding a font into a document to a certain degree.\n   Embedding a font with other works that make up a document creates a\n   \"combined work\" and copyleft would normally require the whole document\n   to be distributed under the terms of the font licence. As beautiful as\n   the font might be, such a licence makes a font too restrictive for\n   useful general purpose digital publishing.\n\n   The situation is not entirely unique to fonts and is encountered also\n   with tools such as GNU Bison: a vanilla GNU GPL licence would require\n   anything generated with Bison to be made available under the terms of\n   the GPL as well. To avoid this, Bison is [9]published with an\n   additional permission to the GPL which allows the output of Bison to be\n   made available under any licence.\n\n   The conflict between licensing of fonts and licensing of documents, is\n   addressed in two popular libre font licences, the SIL OFL and GNU GPL:\n     * [10]SIL Open Font Licence: When OFL fonts are embedded in a\n       document, the OFL's terms do not apply to that document. (See\n       [11]OFL-FAQ for details.\n     * [12]GPL Font Exception: The situation is resolved by granting an\n       additional permission to allow documents to not be covered by the\n       GPL. (The exception is being reviewed).\n\n   The Ubuntu Font Family must also resolve this conflict, ensuring that\n   if the font is embedded and then extracted it is once again clearly\n   under the terms of its libre licence.\n\n    Long-term licensing\n\n   Those individuals involved, especially from Ubuntu and Canonical, are\n   interested in finding a long-term libre licence that finds broad favour\n   across the whole libre/open font community. The deliberation during the\n   past months has been on how to licence the Ubuntu Font Family in the\n   short-term, while knowingly encouraging everyone to pursue a long-term\n   goal.\n     * [13]Copyright assignment will be required so that the Ubuntu Font\n       Family's licensing can be progressively expanded to one (or more)\n       licences, as best practice continues to evolve within the\n       libre/open font community.\n     * Canonical will support and fund legal work on libre font licensing.\n       It is recognised that the cost and time commitments required are\n       likely to be significant. We invite other capable parties to join\n       in supporting this activity.\n\n   The GPL version 3 (GPLv3) will be used for Ubuntu Font Family build\n   scripts and the CC-BY-SA for associated documentation and non-font\n   content: all items which do not end up embedded in general works and\n   documents.\n\nUbuntu Font Licence\n\n   For the short-term only, the initial licence is the [14]Ubuntu Font\n   License (UFL). This is loosely inspired from the work on the SIL\n   OFL 1.1, and seeks to clarify the issues that arose during discussions\n   and legal review, from the perspective of the backers, Canonical Ltd.\n   Those already using established licensing models such as the GPL, OFL\n   or Creative Commons licensing should have no worries about continuing\n   to use them. The Ubuntu Font Licence (UFL) and the SIL Open Font\n   Licence (SIL OFL) are not identical and should not be confused with\n   each other. Please read the terms precisely. The UFL is only intended\n   as an interim license, and the overriding aim is to support the\n   creation of a more suitable and generic libre font licence. As soon as\n   such a licence is developed, the Ubuntu Font Family will migrate to\n   it—made possible by copyright assignment in the interium. Between the\n   OFL 1.1, and the UFL 1.0, the following changes are made to produce the\n   Ubuntu Font Licence:\n     * Clarification:\n\n    1. Document embedding (see [15]embedding section above).\n    2. Apply at point of distribution, instead of receipt\n    3. Author vs. copyright holder disambiguation (type designers are\n       authors, with the copyright holder normally being the funder)\n    4. Define \"Propagate\" (for internationalisation, similar to the GPLv3)\n    5. Define \"Substantially Changed\"\n    6. Trademarks are explicitly not transferred\n    7. Refine renaming requirement\n\n     Streamlining:\n    8. Remove \"not to be sold separately\" clause\n    9. Remove \"Reserved Font Name(s)\" declaration\n\n   A visual demonstration of how these points were implemented can be\n   found in the accompanying coloured diff between SIL OFL 1.1 and the\n   Ubuntu Font Licence 1.0: [16]ofl-1.1-ufl-1.0.diff.html\n\nReferences\n\n   1. http://font.ubuntu.com/\n   2. http://www.canonical.com/\n   3. http://www.daltonmaag.com/\n   4. http://en.wikipedia.org/wiki/Network_effect\n   5. http://scripts.sil.org/\n   6. http://openfontlibrary.org/\n   7. http://www.softwarefreedom.org/\n   8. http://code.google.com/webfonts\n   9. http://www.gnu.org/licenses/gpl-faq.html#CanIUseGPLToolsForNF\n  10. http://scripts.sil.org/OFL_web\n  11. http://scripts.sil.org/OFL-FAQ_web\n  12. http://www.gnu.org/licenses/gpl-faq.html#FontException\n  13. https://launchpad.net/~uff-contributors\n  14. http://font.ubuntu.com/ufl/ubuntu-font-licence-1.0.txt\n  15. http://font.ubuntu.com/ufl/FAQ.html#embedding\n  16. http://font.ubuntu.com/ufl/ofl-1.1-ufl-1.0.diff.html\n"
  },
  {
    "path": "static/fonts/ubuntu/LICENCE.txt",
    "content": "-------------------------------\nUBUNTU FONT LICENCE Version 1.0\n-------------------------------\n\nPREAMBLE\nThis licence allows the licensed fonts to be used, studied, modified and\nredistributed freely. The fonts, including any derivative works, can be\nbundled, embedded, and redistributed provided the terms of this licence\nare met. The fonts and derivatives, however, cannot be released under\nany other licence. The requirement for fonts to remain under this\nlicence does not require any document created using the fonts or their\nderivatives to be published under this licence, as long as the primary\npurpose of the document is not to be a vehicle for the distribution of\nthe fonts.\n\nDEFINITIONS\n\"Font Software\" refers to the set of files released by the Copyright\nHolder(s) under this licence and clearly marked as such. This may\ninclude source files, build scripts and documentation.\n\n\"Original Version\" refers to the collection of Font Software components\nas received under this licence.\n\n\"Modified Version\" refers to any derivative made by adding to, deleting,\nor substituting -- in part or in whole -- any of the components of the\nOriginal Version, by changing formats or by porting the Font Software to\na new environment.\n\n\"Copyright Holder(s)\" refers to all individuals and companies who have a\ncopyright ownership of the Font Software.\n\n\"Substantially Changed\" refers to Modified Versions which can be easily\nidentified as dissimilar to the Font Software by users of the Font\nSoftware comparing the Original Version with the Modified Version.\n\nTo \"Propagate\" a work means to do anything with it that, without\npermission, would make you directly or secondarily liable for\ninfringement under applicable copyright law, except executing it on a\ncomputer or modifying a private copy. Propagation includes copying,\ndistribution (with or without modification and with or without charging\na redistribution fee), making available to the public, and in some\ncountries other activities as well.\n\nPERMISSION & CONDITIONS\nThis licence does not grant any rights under trademark law and all such\nrights are reserved.\n\nPermission is hereby granted, free of charge, to any person obtaining a\ncopy of the Font Software, to propagate the Font Software, subject to\nthe below conditions:\n\n1) Each copy of the Font Software must contain the above copyright\nnotice and this licence. These can be included either as stand-alone\ntext files, human-readable headers or in the appropriate machine-\nreadable metadata fields within text or binary files as long as those\nfields can be easily viewed by the user.\n\n2) The font name complies with the following:\n(a) The Original Version must retain its name, unmodified.\n(b) Modified Versions which are Substantially Changed must be renamed to\navoid use of the name of the Original Version or similar names entirely.\n(c) Modified Versions which are not Substantially Changed must be\nrenamed to both (i) retain the name of the Original Version and (ii) add\nadditional naming elements to distinguish the Modified Version from the\nOriginal Version. The name of such Modified Versions must be the name of\nthe Original Version, with \"derivative X\" where X represents the name of\nthe new work, appended to that name.\n\n3) The name(s) of the Copyright Holder(s) and any contributor to the\nFont Software shall not be used to promote, endorse or advertise any\nModified Version, except (i) as required by this licence, (ii) to\nacknowledge the contribution(s) of the Copyright Holder(s) or (iii) with\ntheir explicit written permission.\n\n4) The Font Software, modified or unmodified, in part or in whole, must\nbe distributed entirely under this licence, and must not be distributed\nunder any other licence. The requirement for fonts to remain under this\nlicence does not affect any document created using the Font Software,\nexcept any version of the Font Software extracted from a document\ncreated using the Font Software may only be distributed under this\nlicence.\n\nTERMINATION\nThis licence becomes null and void if any of the above conditions are\nnot met.\n\nDISCLAIMER\nTHE FONT SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF\nCOPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE\nCOPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,\nINCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL\nDAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\nFROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM OTHER\nDEALINGS IN THE FONT SOFTWARE.\n"
  },
  {
    "path": "static/fonts/ubuntu/copyright.txt",
    "content": "Copyright 2010,2011 Canonical Ltd.\n\nThis Font Software is licensed under the Ubuntu Font Licence, Version\n1.0.  https://launchpad.net/ubuntu-font-licence\n\n"
  },
  {
    "path": "static/messages.json",
    "content": "[\n    {\n        \"title\": \"Embedded Linux training (on-line)\",\n        \"body\": \"Apr 13-23, 2026\",\n        \"action\": \"Register\",\n        \"link\": \"https://shop.bootlin.com/en/event/189\"\n    },\n    {\n        \"title\": \"Embedded Linux training (on-line)\",\n        \"body\": \"Nov 2-12, 2026\",\n        \"action\": \"Register\",\n        \"link\": \"https://shop.bootlin.com/en/event/188\"\n    },\n    {\n        \"title\": \"Linux kernel drivers training (on-line)\",\n        \"body\": \"Apr 13-23, 2026\",\n        \"action\": \"Register\",\n        \"link\": \"https://shop.bootlin.com/en/event/183\"\n    },\n    {\n        \"title\": \"Yocto / OpenEmbedded training (on-line)\",\n        \"body\": \"Apr 20-23, 2026\",\n        \"action\": \"Register\",\n        \"link\": \"https://shop.bootlin.com/en/event/186\"\n    },\n    {\n        \"title\": \"Linux debugging, profiling, tracing and performance analysis training\",\n        \"body\": \"Apr 20-23, 2026\",\n        \"action\": \"Register\",\n        \"link\": \"https://shop.bootlin.com/en/event/185\"\n    },\n    {\n        \"title\": \"Buildroot System Development training\",\n        \"body\": \"Dec 7-11, 2026\",\n        \"action\": \"Register\",\n        \"link\": \"https://shop.bootlin.com/en/event/170\"\n    },\n    {\n        \"title\": \"Embedded Linux Networking training\",\n        \"body\": \"Apr 13-17, 2026\",\n        \"action\": \"Register\",\n        \"link\": \"https://shop.bootlin.com/en/event/181\"\n    },\n    {\n        \"title\": \"Embedded Linux Audio training\",\n        \"body\": \"Sep 21-25, 2026\",\n        \"action\": \"Register\",\n        \"link\": \"https://shop.bootlin.com/en/event/190\"\n    },\n    {\n        \"title\": \"Linux BSP development engineering services\",\n        \"body\": \"Need help to port Linux and bootloaders to your hardware?\",\n        \"link\": \"https://bootlin.com/engineering/linux-board-support-package/\"\n    },\n    {\n        \"title\": \"Open-source upstreaming\",\n        \"body\": \"Need help get the support for your hardware in upstream Linux?\",\n        \"link\": \"https://bootlin.com/engineering/upstreaming/\"\n    },\n    {\n        \"title\": \"Linux BSP upgrade and security maintenance\",\n        \"body\": \"Need help to get security updates for your Linux BSP?\",\n        \"link\": \"https://bootlin.com/engineering/linux-board-support-package/\"\n    },\n    {\n        \"title\": \"Yocto distribution development and maintenance\",\n        \"body\": \"Need a Yocto distribution for your embedded project?\",\n        \"link\": \"https://bootlin.com/engineering/linux-board-support-package/\"\n    },\n    {\n        \"title\": \"Buildroot integration, development and maintenance\",\n        \"body\": \"Need a Buildroot system for your embedded project?\",\n        \"link\": \"https://bootlin.com/engineering/linux-board-support-package/\"\n    },\n    {\n        \"title\": \"Zephyr development and porting\",\n        \"body\": \"Building a Zephyr-based project?\",\n        \"link\": \"https://bootlin.com/engineering/zephyr/\"\n    }\n]\n"
  },
  {
    "path": "static/robots.txt",
    "content": "User-Agent: *\nAllow: /\nCrawl-Delay: 2\n"
  },
  {
    "path": "static/script.js",
    "content": "\"use strict\";\n\n/* Tags menu filter */\n\n// Get a dictionary of tag name -> tag link from HTML\nfunction getTags() {\n  const tags = {};\n  const list = document.querySelectorAll('.versions a');\n  for (const el of list) {\n    tags[el.innerText.trim()] = el.href;\n  }\n  return tags;\n}\n\n// Generate tag search results based on input\n// filter: current filter input text\n// tags: dictionary of tag name -> tag link\nfunction generateResults(filter, tags) {\n  const searchResults = document.createDocumentFragment();\n  const filterRegex = new RegExp(filter, 'i');\n\n  for (let key in tags) {\n    if (tags.hasOwnProperty(key)) {\n      let tagFound = false;\n      const tagHighlight = key.replace(filterRegex, result => {\n        if (result) tagFound = true;\n        return '<strong>' + result + '</strong>';\n      })\n\n      if (tagFound) {\n        const tagLink = document.createElement('a');\n        tagLink.href = tags[key];\n        tagLink.innerHTML = tagHighlight;\n        searchResults.appendChild(tagLink);\n      }\n    }\n  }\n\n  return searchResults;\n}\n\n// Setup tags filter input\nfunction setupVersionsFilter() {\n  const input = document.querySelector('.filter-input');\n  const results = document.querySelector('.filter-results');\n  const versions = document.querySelector('.versions');\n  const tags = getTags();\n\n  input.addEventListener('input', e => {\n    if (e.target.value === '') {\n      versions.classList.remove('hide');\n      results.innerHTML = '';\n    } else {\n      versions.classList.add('hide');\n      results.innerHTML = '';\n      results.appendChild(generateResults(e.target.value, tags));\n    }\n  });\n}\n\n// Setup expanding/collapsing versions tree on click\nfunction setupVersionsTree() {\n  const versions = document.querySelector('.versions');\n  versions.addEventListener('click', e => {\n    if (e.target && e.target.nodeName == 'SPAN') {\n      e.target.classList.toggle('active')\n    }\n  });\n}\n\nfunction isWidescreen() {\n  return getComputedStyle(document.documentElement).getPropertyValue('--is-widescreen') === 'true';\n}\n\n// Toggles sidebar visibility, handles widescreen and mobile layouts\nfunction toggleMenu() {\n  const isWidescreen = getComputedStyle(document.documentElement).getPropertyValue('--is-widescreen') === 'true';\n  if(isWidescreen) {\n    const hasShowMenu = document.documentElement.classList.contains('show-menu');\n    window.localStorage.setItem('show-sidebar', !hasShowMenu);\n    document.documentElement.classList.toggle('show-menu');\n  } else {\n    document.documentElement.classList.toggle('show-menu-mobile');\n  }\n}\n\n// Setup sidebar hamburger menu button, close button and mobile sidebar backdrop events\nfunction setupSidebarSwitch() {\n  const tag = document.querySelector('.version em');\n  const openMenu = document.querySelector('.open-menu');\n  const sidebar = document.querySelector('.sidebar');\n\n  // toggle on hamburger menu click\n  openMenu.addEventListener('click', e => {\n    e.preventDefault();\n    toggleMenu();\n  });\n\n  // toggle on footer tag icon click\n  tag.addEventListener('click', e => {\n    e.preventDefault();\n    toggleMenu();\n  });\n\n  // close on close-menu/backdrop click\n  sidebar.addEventListener('click', e => {\n    if (e.target === sidebar && isWidescreen()) {\n      document.documentElement.classList.remove('show-menu');\n      window.localStorage.setItem('show-sidebar', false);\n    } else if (e.target === sidebar || e.target.classList.contains('close-menu')) {\n      document.documentElement.classList.remove('show-menu-mobile');\n    }\n  });\n}\n\n// Parse and validate line identifier in format L${number}\nfunction parseLineId(lineId) {\n  if (lineId[0] != \"L\") {\n    return;\n  }\n\n  let lineIdNum = parseInt(lineId.substring(1));\n  console.assert(!isNaN(lineIdNum), \"Invalid line id\");\n\n  let lineElement = document.getElementById(lineId);\n  if (lineElement === null || lineElement.tagName !== \"A\") {\n    return;\n  }\n\n  return lineIdNum;\n}\n\n// Parse and validate line range anchor in format #L${lineRangeStart}-L${lineRangeEnd}\nfunction parseLineRangeAnchor(hashStr) {\n  const hash = hashStr.substring(1).split(\"-\");\n  if (hash.length < 1 || hash.length > 2) {\n    return;\n  }\n\n  let firstLine = parseLineId(hash[0]);\n  let lastLine = hash.length === 2 ? parseLineId(hash[1]) : firstLine;\n\n  if (firstLine === undefined || lastLine === undefined) {\n    return;\n  }\n\n  // Swap line numbers to support \"#L2-L1\" format. Postel's law.\n  if (firstLine > lastLine) {\n    const lineTmp = lastLine;\n    lastLine = firstLine;\n    firstLine = lineTmp;\n  }\n\n  return [firstLine, lastLine];\n}\n\n// Highlights line number elements from firstLine to lastLine\nfunction highlightFromTo(firstLine, lastLine) {\n  const firstLineElement = document.getElementById(`L${ firstLine }`);\n  const lastLineElement = document.getElementById(`L${ lastLine }`);\n\n  const firstCodeLine = document.getElementById(`codeline-${ firstLine }`);\n  const lastCodeLine = document.getElementById(`codeline-${ lastLine }`);\n\n  addClassToRangeOfElements(firstLineElement.parentNode, lastLineElement.parentNode, \"line-highlight\");\n  addClassToRangeOfElements(firstCodeLine, lastCodeLine, \"line-highlight\");\n}\n\nfunction clearRangeHighlight() {\n  const highlightElements = Array.from(document.getElementsByClassName(\"line-highlight\"));\n  for (let el of highlightElements) {\n    el.classList.remove(\"line-highlight\");\n  }\n}\n\nfunction addClassToRangeOfElements(first, last, class_name) {\n  let element = first;\n  const elementAfterLast = last !== null ? last.nextElementSibling : null;\n  while (element !== null && element != elementAfterLast) {\n    element.classList.add(class_name);\n    element = element.nextElementSibling;\n  }\n}\n\n// Sets up listeners on element that contains line numbers to handle\n// shift-clicks for range highlighting\nfunction setupLineRangeHandlers() {\n  // Check if page contains the element with line numbers\n  // If not, then likely script is not executed in context of the source page\n  const linenodiv = document.querySelector(\".linenodiv\");\n  if (linenodiv === null) {\n    return;\n  }\n\n  let rangeStartLine, rangeEndLine;\n\n  const parseFromHash = () => {\n    const highlightedRange = parseLineRangeAnchor(window.location.hash);\n    // Set range start/end to elements from hash\n    if (highlightedRange !== undefined) {\n      rangeStartLine = highlightedRange[0];\n      rangeEndLine = highlightedRange[1];\n      highlightFromTo(rangeStartLine, rangeEndLine);\n      document.getElementById(`L${rangeStartLine}`).scrollIntoView();\n    } else if (location.hash !== \"\" && location.hash[1] === \"L\") {\n      rangeStartLine = parseLineId(location.hash.substring(1));\n    }\n  }\n\n  window.addEventListener(\"hashchange\", _ => {\n    clearRangeHighlight();\n    parseFromHash();\n  });\n\n  parseFromHash();\n\n  linenodiv.addEventListener(\"click\", ev => {\n    if (ev.ctrlKey || ev.metaKey) {\n      return;\n    }\n    ev.preventDefault();\n\n    // Handler is set on the element that contains all line numbers, check if the\n    // event is directed at an actual line number element\n    const el = ev.target;\n    if (typeof(el.id) !== \"string\" || el.id[0] !== \"L\" || el.tagName !== \"A\") {\n      return;\n    }\n\n    clearRangeHighlight();\n\n    if (rangeStartLine === undefined || !ev.shiftKey) {\n      rangeStartLine = parseLineId(el.id);\n      rangeEndLine = undefined;\n      highlightFromTo(rangeStartLine, rangeStartLine);\n      window.location.hash = el.id;\n    } else if (ev.shiftKey) {\n      if (rangeEndLine === undefined) {\n        rangeEndLine = parseLineId(el.id);\n      }\n\n      const newLine = parseLineId(el.id);\n      console.assert(newLine !== undefined, \"parseLineId for clicked line is undefined\");\n\n      // Swap range elements if range end that was previously undefined is now\n      // before range start\n      if (rangeStartLine > rangeEndLine) {\n        const lineTmp = rangeStartLine;\n        rangeStartLine = rangeEndLine;\n        rangeEndLine = lineTmp;\n      }\n\n      if (newLine < rangeStartLine) {\n        // Expand if element above range\n        rangeStartLine = newLine;\n      } else if (newLine > rangeEndLine) {\n        // Expand if element below range\n        rangeEndLine = newLine;\n      } else {\n        // Shrink moving the edge that's closest to the selection.\n        // Move end if center was selected.\n        const distanceFromStart = Math.abs(rangeStartLine-newLine);\n        const distanceFromEnd = Math.abs(rangeEndLine-newLine);\n        if (distanceFromStart < distanceFromEnd) {\n          rangeStartLine = newLine;\n        } else {\n          rangeEndLine = newLine;\n        }\n      }\n\n      highlightFromTo(rangeStartLine, rangeEndLine);\n      window.location.hash = `L${rangeStartLine}-L${rangeEndLine}`;\n    }\n  });\n}\n\n/* Other fixes */\n\n// prevent chrome from auto-scrolling to input elements\nfunction setupAutoscrollingPrevention() {\n  const wrapper = document.querySelector('.wrapper');\n  Array.prototype.forEach.call(document.querySelectorAll('input'), el => {\n    el.addEventListener('keydown', _ => {\n      const before = wrapper.scrollTop;\n      const reset = () => wrapper.scrollTop = before;\n      window.requestAnimationFrame(reset);\n      setTimeout(reset, 0);\n    });\n  });\n}\n\n// Scrolls the page after each anchor change to prevent selected line from\n// hiding under the topbar after a line number click.\nfunction setupAnchorOffsetHandler() {\n  const wrapper = document.querySelector('.wrapper');\n\n  const anchorChangeHandler = e => {\n    if (e && e.preventDefault) e.preventDefault();\n    if (location.hash.length !== 0) {\n      const el = document.querySelector(location.hash);\n      if (el) {\n        const offsetTop = el.offsetTop;\n        wrapper.scrollTop = offsetTop < 100 ? 200 : offsetTop + 100;\n      }\n    }\n  };\n\n  window.requestAnimationFrame(anchorChangeHandler);\n  window.addEventListener('hashchange', anchorChangeHandler);\n}\n\nfunction setupGoToTop() {\n  const wrapper = document.querySelector('.wrapper');\n  const goToTop = document.querySelector('.go-top');\n\n  goToTop.addEventListener('click', e => {\n    wrapper.scrollTop = 0;\n    wrapper.scrollLeft = 0;\n  });\n}\n\nfunction randomChoice(arr) {\n  return arr[Math.floor(Math.random() * arr.length)];\n}\n\nfunction updateBannerContents(msg) {\n  const banner = document.querySelector('.message-banner');\n\n  banner.querySelector('.title').innerText = msg.title;\n  banner.querySelector('.subtitle').innerHTML = msg.body.replace('\\n', '<br/>');\n  document.querySelector('.message-link').href = msg.link;\n\n  const actionElement = banner.querySelector('.action');\n    const actionInner = actionElement.querySelector('.action-inner');\n  if (msg.action) {\n    actionInner.innerText = msg.action;\n    actionElement.classList.add(\"action-visible\");\n  } else {\n    actionElement.classList.remove(\"action-visible\");\n  }\n}\n\nfunction updateMessageBanner() {\n  fetch('/static/messages.json')\n    .then(r => r.json())\n    .then(messages => {\n      // TODO compatibility with old messages format, remove after ~march 2025\n      const pickedMsg = randomChoice(messages);\n      const msg = pickedMsg.desktop ? pickedMsg.desktop : pickedMsg;\n\n      updateBannerContents(msg);\n    });\n}\n\nfunction cycleBanner(delay=500) {\n  fetch('/static/messages.json')\n    .then(r => r.json())\n    .then(messages => {\n      cycleBannerWithData(messages, delay);\n    });\n}\n\nfunction sleep(duration) {\n  return new Promise(resolve => setTimeout(resolve, duration));\n}\n\nasync function cycleBannerWithData(data, delay=500) {\n  for (const msg of data) {\n    updateBannerContents(msg);\n    await sleep(delay);\n  }\n  console.log(\"cycle finished\");\n}\n\ndocument.addEventListener('DOMContentLoaded', _ => {\n  updateMessageBanner();\n\n  setupVersionsFilter();\n  setupVersionsTree();\n  setupSidebarSwitch();\n\n  setupLineRangeHandlers();\n\n  setupAutoscrollingPrevention();\n  setupAnchorOffsetHandler();\n  setupGoToTop();\n\n  document.getElementById('clear-search').addEventListener('click',\n    _ => document.getElementById('search-input').value = ''\n  );\n});\n"
  },
  {
    "path": "static/style.css",
    "content": "@charset \"UTF-8\";\n\n/*! normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css */\n html{line-height:1.15;-webkit-text-size-adjust:100%}body{margin:0}main{display:block}h1{font-size:2em;margin:.67em 0}hr{box-sizing:content-box;height:0;overflow:visible}pre{font-family:monospace,monospace;font-size:1em}a{background-color:#fff0}abbr[title]{border-bottom:none;text-decoration:underline;text-decoration:underline dotted}b,strong{font-weight:bolder}code,kbd,samp{font-family:monospace,monospace;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}img{border-style:none}button,input,optgroup,select,textarea{font-family:inherit;font-size:100%;line-height:1.15;margin:0}button,input{overflow:visible}button,select{text-transform:none}button,[type=\"button\"],[type=\"reset\"],[type=\"submit\"]{-webkit-appearance:button}button::-moz-focus-inner,[type=\"button\"]::-moz-focus-inner,[type=\"reset\"]::-moz-focus-inner,[type=\"submit\"]::-moz-focus-inner{border-style:none;padding:0}button:-moz-focusring,[type=\"button\"]:-moz-focusring,[type=\"reset\"]:-moz-focusring,[type=\"submit\"]:-moz-focusring{outline:1px dotted ButtonText}fieldset{padding:.35em .75em .625em}legend{box-sizing:border-box;color:inherit;display:table;max-width:100%;padding:0;white-space:normal}progress{vertical-align:baseline}textarea{overflow:auto}[type=\"checkbox\"],[type=\"radio\"]{box-sizing:border-box;padding:0}[type=\"number\"]::-webkit-inner-spin-button,[type=\"number\"]::-webkit-outer-spin-button{height:auto}[type=\"search\"]{-webkit-appearance:textfield;outline-offset:-2px}[type=\"search\"]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}details{display:block}summary{display:list-item}template{display:none}[hidden]{display:none}\n\n\n/* commons */\n\nhtml {\n  -webkit-box-sizing: border-box;\n          box-sizing: border-box;\n  font-size: 16px;\n  line-height: 1.2;\n}\n*, *:before, *:after {\n  -webkit-box-sizing: inherit;\n          box-sizing: inherit;\n}\n\n*::-webkit-scrollbar {\n  width: 9px;\n  height: 9px;\n}\n\n.sidebar nav::-webkit-scrollbar-corner {\n  background: #222;\n}\n.sidebar nav::-webkit-scrollbar-track {\n  background: #222;\n}\n.sidebar nav::-webkit-scrollbar-thumb {\n  background: #666;\n}\n\nbody::-webkit-scrollbar-corner {\n  background: #666;\n}\nbody::-webkit-scrollbar-track {\n  background: #666;\n}\nbody::-webkit-scrollbar-thumb {\n  background: #ccc;\n}\n\n.wrapper::-webkit-scrollbar-corner {\n  background: #666;\n}\n.wrapper::-webkit-scrollbar-track {\n  background: #666;\n}\n.wrapper::-webkit-scrollbar-thumb {\n  background: #ccc;\n}\n\nbody {\n  background: #fff;\n  font-family: 'Ubuntu', sans-serif;\n}\n\npre {\n  font-family: 'Ubuntu Mono', monospace;\n  font-size: 0.9em;\n  line-height: 1.2;\n  padding: 0;\n  color: #787878;\n}\n\ntable {\n  border-collapse: collapse;\n}\ntable td {\n  padding: 0;\n  height: 100%;\n}\n\na {\n  color: #000;\n  text-decoration: none;\n}\na::before,\nbutton::before {\n  -webkit-transition: color 0.2s, background-color 0.2s;\n  transition: color 0.2s, background-color 0.2s;\n}\ninput {\n  -webkit-transition: background-color 0.2s;\n  transition: background-color 0.2s;\n}\n\na:focus {\n  outline: 1px;\n  outline-style: dotted;\n  outline-offset: -1px;\n}\n\nh2 {\n  color: #aaa;\n  font-weight: 100;\n  margin-top: 0;\n  margin-bottom: 1rem;\n}\n\n.link {\n  color: #6d7dd2;\n  text-decoration: underline;\n}\n\n\n/* oocss */\n\n.hide {\n  display: none;\n}\n\n.screenreader {\n  font-size: 0;\n}\n\n\n/* IE 9 */\n\n.browserupgrade {\n  position: absolute;\n  top: 0em;\n  left: 0;\n  right: 0;\n  width: auto;\n  height: auto;\n  padding: 1em;\n  margin: 0;\n  z-index: 10;\n  background-color: #440a0a;\n  color: #fff;\n  font-size: 0.7em;\n  text-align: center;\n}\n.browserupgrade a {\n  color: #fff;\n  text-decoration: underline;\n}\n\n\n\n\n/* sub-header */\n\n.sub-header {\n  height: 2.7em;\n  margin-top: -2.7em;\n  text-align: center;\n}\n.select-projects {\n  padding: 0.5rem 0.6rem;\n  border: 0 none;\n  color: #fff;\n  font-family: 'Ubuntu Mono', monospace;\n  font-weight: 700;\n  font-style: italic;\n  font-size: 1.6em;\n  padding-right: 1.5em;\n\n  /* custom select design */\n  -webkit-appearance: none;\n  -moz-appearance: none;\n  appearance: none;\n  background-color: transparent;\n  background-image: url(\"data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='100' height='100' fill='%23b4bde7'><polygon points='0,0 100,0 50,50'/></svg>\");\n  background-repeat: no-repeat;\n  background-position: bottom 0.45em right 0.3em;\n  background-size: 9%;\n\n  opacity: 0.7;\n}\n.select-projects:-moz-focusring {\n  color: #fff;\n  color: rgba(255,255,255,0);\n  text-shadow: 0 0 0 #fff;\n  outline: 1px;\n  outline-style: dotted;\n  outline-offset: -1px;\n}\n.select-projects:focus {\n  outline: 1px;\n  outline-style: dotted;\n  outline-offset: -1px;\n  outline-color: #fff;\n}\n.select-projects:hover,\n.select-projects:focus {\n  opacity: 1;\n}\n.select-projects option {\n  color: #000;\n}\n\n\n/* topbar */\n\n.topbar {\n  background: #c0c0c0;\n  z-index: 20;\n}\n\n.breadcrumb {\n  display: inline-block;\n  color: #888;\n  padding: 0.9rem 1.3rem;\n  font-size: 0.8em;\n}\n.breadcrumb a {\n  color: #555;\n  padding: 0.35em;\n}\n.breadcrumb a:hover {\n  color: #000;\n}\n.project {\n  font-weight: 700;\n}\n\n\n/* filter / search  */\n\n.filter,\n.search {\n  position: relative;\n}\n.search input {\n  height: 100%;\n}\n.filter input,\n.search input {\n  font-family: 'Ubuntu Mono', monospace;\n  font-size: 0.9em;\n  width: 100%;\n  border: 0 none;\n  padding: 0.45em;\n  margin: 0;\n}\n.filter input:focus,\n.search input:focus {\n  outline: 0 none;\n}\n.filter button {\n  position: absolute;\n  right: 0;\n  bottom: 0;\n  border: 0 none;\n  font-size: 1.7em;\n  height: 1.5em;\n  background: transparent;\n  color: #999;\n  cursor: pointer;\n}\n.search button {\n  border: 0 none;\n  font-size: 1.7em;\n  height: 1.5em;\n  background: transparent;\n  color: #555;\n  cursor: pointer;\n  width: 50px;\n}\n\n.search {\n  position: relative;\n  padding: 0.5em;\n  padding-top: 0;\n}\n.search form {\n  display: flex;\n  flex-direction: row;\n}\n.search button:focus,\n.search button:hover {\n  color: #000;\n  outline: 0 none;\n}\n.search input {\n  color: #000;\n  background: #ddd;\n  padding-right: 3em;\n  min-width: 0;\n  flex: 3.5;\n}\n.search input:focus {\n  background: #eee;\n}\n.search select {\n  -moz-appearance: none;\n  -webkit-appearance: none;\n  appearance: none;\n\n  font-family: 'Ubuntu Mono', monospace;\n  font-size: 0.9em;\n  text-align: center;\n  text-align-last: center;\n  min-height: 32px;\n\n  padding: 7px;\n  padding-right: 20px;\n  text-decoration: none;\n\n  background-color: #aaa;\n  background-image: url(\"/static/img/arrow-dropdown-16.svg\");\n  background-position: right 2px center;\n  background-repeat: no-repeat;\n\n  opacity: 0.9;\n  border: 0 none;\n  margin: 0;\n  min-width: 0;\n  flex: 1;\n}\n.search select:-moz-focusring { /* Remove unwanted firefox borders */\n  color: #000;\n  color: rgba(0,0,0,0);\n  text-shadow: 0 0 0 #000;\n  outline: 1px;\n  outline-style: dotted;\n  outline-offset: -1px;\n}\n.search select:focus {\n  outline: 1px;\n  outline-style: dotted;\n  outline-offset: -1px;\n  outline-color: #000;\n}\n.search select:hover,\n.search select:focus {\n  opacity: 1;\n}\n.search option { /* Firefox ignores that on linux but the default color is close */\n  background-color: #ccc;\n}\n.search .search-controls {\n  flex: 3;\n  display: flex;\n  flex-direction: row;\n  align-items: center;\n}\n\n.filter {\n  padding: 0.5em;\n  background: #222;\n}\n.filter input {\n  color: #fff;\n  background: #333;\n}\n.filter input:focus {\n  background: #444;\n}\n.filter button {\n  pointer-events: none; /* filter button is for decoration only */\n  color: #666;\n  font-size: 1.3em;\n  height: 2em;\n  right: 0.15em;\n}\n\n\n/* footer */\n\n.footer {\n  height: 25px;\n  padding: 0.3rem 2.5rem;\n  padding-left: 1.5rem;\n  font-size: 0.8em;\n  background: #aaa;\n  color: #555;\n}\n.footer a {\n  font-style: normal;\n  padding-left: 0.3em;\n}\n.version a {\n  color: #444;\n  font-weight: 700;\n}\n.version em {\n  margin-left: 0.3em;\n}\n.version em::before {\n  margin-right: 0.3em;\n  opacity: 0.5;\n}\n.go-top,\n.poweredby {\n  float: right;\n}\n.poweredby {\n  font-style: italic;\n  float: right;\n}\n.go-top {\n  margin-left: 1rem;\n  line-height: 0;\n  position: absolute;\n  top: 0;\n  right: 0;\n}\n.go-top:focus {\n  outline: 0 none;\n}\n.go-top::before {\n  color: #ccc;\n  font-size: 1.4rem;\n  background: #888;\n  display: inline-block;\n  text-align: center;\n  width: 2rem;\n  height: 1.4rem;\n  top: 0.1rem;\n  position: relative;\n  -webkit-box-shadow: 0 0 0 1px #888;\n          box-shadow: 0 0 0 1px #888;\n}\n.go-top:focus::before,\n.go-top:hover::before {\n  color: #fff;\n  background: #666;\n  -webkit-box-shadow: 0 0 0 1px #666;\n          box-shadow: 0 0 0 1px #666;\n}\n\n#file-download-link {\n  margin-left: 1rem;\n}\n\n/* sidebar */\n\n.sidebar {\n  height: auto;\n  z-index: 10;\n}\n.sidebar nav {\n  background: #111;\n  color: #fff;\n}\n.sidebar nav a {\n  color: #fff;\n}\n.sidebar nav a:hover,\n.sidebar nav a:hover strong{\n  color: #6d7dd2;\n}\n.sidebar nav {\n  font-size: 0.9em;\n  padding: 1rem;\n}\n.sidebar nav ul {\n  list-style: none;\n  margin: 0;\n}\n.sidebar nav li.active a {\n  color: #eee;\n  color: #6d7dd2;\n  font-weight: 700;\n}\n.sidebar nav ul {\n  padding: 0;\n}\n\n/* reference popup */\n\n#reference-popup-wrapper {\n  position: absolute;\n  display: inline-block;\n}\n\n#reference-popup {\n  position: absolute;\n  visibility: hidden;\n  display: none;\n  border: 2px solid black;\n  background: white;\n  padding: 5px;\n  z-index: 10;\n  overflow-y: scroll;\n  min-height: 25vh;\n  min-width: 40vw;\n  max-height: 50vh;\n  max-width: 75vw;\n\n  @media only screen and (max-width: 1000px) {\n    min-width: 100vw;\n  }\n}\n\n#reference-popup::-webkit-scrollbar-corner {\n  background: #666;\n}\n\n#reference-popup::-webkit-scrollbar-track {\n  background: #666;\n}\n\n#reference-popup::-webkit-scrollbar-thumb {\n  background: #ccc;\n}\n\n#loading-popup {\n  position: absolute;\n  visibility: hidden;\n  border: 2px solid black;\n  background: white;\n  color: gray;\n  padding: 5px;\n  z-index: 10;\n}\n\n/* if javascript on/off */\n\n.js .sidebar {\n  display: -webkit-box;\n  display: -ms-flexbox;\n  display: flex;\n  -webkit-box-orient: vertical;\n  -webkit-box-direction: normal;\n      -ms-flex-direction: column;\n          flex-direction: column;\n}\n.js .sidebar nav {\n  will-change: transform;\n  overflow-y: auto;\n  -webkit-box-flex: 1;\n      -ms-flex: 1;\n          flex: 1;\n}\n\n.js .sidebar li li::before {\n  color: #444;\n  font-family: 'Ubuntu Mono', monospace;\n  font-size: 1.29em;\n  line-height: 1;\n}\n.js .sidebar li li::before {\n  content: '├╴';\n}\n.js .sidebar li li:last-of-type::before {\n  content: '└╴';\n}\n.js .sidebar li li li::before {\n  content: '│\\00a0├╴';\n}\n.js .sidebar li li li:last-of-type::before {\n  content: '│\\00a0└╴';\n}\n.js .sidebar li li:last-of-type li::before {\n  content: '\\00a0\\00a0├╴';\n}\n.js .sidebar li li:last-of-type li:last-of-type::before {\n  content: '\\00a0\\00a0└╴';\n}\n\n.js .sidebar .versions > li > span{\n  margin-left: 0.5em;\n}\n.js .sidebar .versions {\n  margin-left: -0.4em;\n}\n.js .sidebar li {\n  display: block;\n  line-height: 1.5;\n}\n.js .sidebar .versions li span,\n.js .sidebar .versions li a {\n  font-size: 0.9em;\n  vertical-align: 0.12em;\n}\n.js .sidebar li span {\n  color: #888;\n  cursor: pointer;\n}\n.js .sidebar li span:hover::before {\n  color: #fff;\n}\n.js .sidebar li span::before {\n  color: #444;\n  font-family: 'Ubuntu Mono', monospace;\n  font-size: 1.3em;\n  line-height: 1em;\n  content: '▸';\n  position: relative;\n  top: -0.05em;\n  left: -0.35em;\n  margin-right: -0.2em;\n}\n.js .sidebar li span.active::before {\n  content: '▾';\n}\n\n.js .sidebar .li-link {\n  display: -webkit-box;\n  display: -ms-flexbox;\n  display: flex;\n}\n.js .sidebar .li-link::before {\n  -webkit-box-flex: 0;\n      -ms-flex: 0;\n          flex: 0;\n}\n.js .sidebar .li-link a {\n  word-break: break-word;\n  -webkit-box-flex: 1;\n      -ms-flex: 1;\n          flex: 1;\n}\n\n/* tag menu tree closed */\n.js .sidebar nav ul ul {\n  display: none;\n}\n/* tag menu tree open */\n.js .sidebar li span.active + ul {\n  display: block;\n}\n\n.visible-if-js {\n  display: none;\n}\n\n.js .visible-if-js {\n  display: revert;\n}\n\n.no-js .sidebar:target {\n  left: 0;\n  height: 100vh;\n  overflow: auto;\n}\n.no-js .sidebar nav ul span {\n  display: none;\n}\n.no-js .versions {\n  margin-top: 1em;\n}\n\n.no-js .sub-header {\n  display: none;\n}\n.js .projects {\n  display: none;\n}\n\n.no-js .select-projects {\n  display: none;\n}\n\n.no-js .filter-input {\n  display: none;\n}\n\n.no-js .icon-filter {\n  display: none;\n}\n\n\n\n/* filter results */\n\n.filter-results a {\n  color: #fff;\n  display: block;\n  line-height: 1.2;\n}\n.filter-results a strong {\n  color: #ffa264;\n}\n\n\n/* error */\n\n.lxrerror {\n  padding: 1.5em;\n}\n\n#error-details {\n  margin-bottom: 1em;\n}\n\n#error-details-links * {\n  display: block;\n}\n\n#error-details-links button {\n  border: 0;\n  background-color: transparent;\n  padding: 0;\n  margin: 0;\n}\n\n#report-error-details-header {\n  color: gray;\n}\n\n/* ident */\n\n.lxrident {\n  padding: 1.5em;\n}\n.lxrident ul {\n  list-style: none;\n  padding: 0;\n  padding-bottom: 0em;\n}\n.lxrident a {\n  font-size: 0.8em;\n  line-height: 1.55;\n  color: #666;\n}\n.lxrident a:hover {\n  border-bottom: 1px dotted #999999;\n}\n.lxrident a strong {\n  font-size: 1.3em;\n  font-weight: 400;\n  color: #000;\n}\n.lxrident li li::before {\n  color: #444;\n}\n\n.lxrident > pre {\n  background-color: #edf0ff;\n  color: #5764a8;\n  padding: 1em;\n  margin-top: 0;\n  border-radius: 0.3em;\n}\n\n.lxrident li li::before {\n  font-family: 'Ubuntu Mono', monospace;\n  font-size: 1.1em;\n  content: '├╴';\n}\n.lxrident li li:last-of-type::before {\n  content: '└╴';\n}\n\n\n/* tree */\n\n.lxrtree table {\n  width: 100%;\n  max-width: 100%;\n  margin-top: 0.5em;\n  margin-bottom: 2em;\n}\n.lxrtree table td:first-child {\n  width: 1%;\n}\n.lxrtree table td a {\n  white-space: nowrap;\n  text-overflow: ellipsis;\n}\n.lxrtree {\n  padding: 1em 0;\n}\n.lxrtree td a {\n  display: block;\n  padding: 0.15em 1.5em;\n}\n.lxrtree tr:hover {\n  background: #ddd;\n}\n.tree-icon:before {\n  display: inline-block;\n  width: 1.5em;\n}\n.tree-icon.icon-tree:before {\n  color: #ffa264;\n}\n.tree-icon.icon-blob:before {\n  color: #a0a7ce;\n}\n.tree-icon.icon-back {\n  color: #000;\n  font-style: italic;\n  opacity: 0.5;\n}\n.tree-icon.icon-back:hover {\n  opacity: 1;\n}\n.size {\n  opacity: 0.6;\n  min-height: 1.5em; /* line_height + 2 * padding = 1.2em + 2 * 0.15em */\n  text-align: right;\n}\n\n\n/* source code */\n\n.lxrcode {\n  position: relative;\n}\n.lxrcode pre {\n  margin: 0;\n  padding-top: 1em;\n  padding-bottom: 4em;\n  min-height: 100%;\n}\n\n.lxrcode pre * {\n  vertical-align: top;\n}\n\n.lxrcode,\n.highlighttable,\n.linenodiv,\n.highlight {\n  height: 100%;\n}\n\nspan[id^='codeline-'] {\n  display: block;\n  padding-left: 1em;\n}\n\nspan[id^='codeline-'].line-highlight {\n  width: 100%;\n  height: 100%;\n  background: #f8edc3;\n}\n\n.linenodiv {\n  background: #e9e9e9;\n}\n\n.linenodiv pre a {\n  color: #999;\n  display: inline-block;\n  padding: 0 1em;\n  width: 100%;\n  scroll-margin: 15vh;\n  scroll-margin-top: 15vh;\n}\n.line-highlight {\n  background: #ccc;\n}\n.linenodiv pre a.line-highlight,\n.linenodiv pre span {\n  display: inline-block;\n}\n.linenodiv pre span.line-highlight > a,\n.linenodiv pre a:target {\n  color: #444;\n}\n.linenodiv pre a:target {\n  background: #ccc;\n  pointer-events: none;\n}\n.linenodiv pre a:focus,\n.linenodiv pre a:hover {\n  color: #000;\n}\n.linenodiv pre a:hover {\n  background: #ddd;\n}\n.linenodiv pre a:focus {\n  outline: 1px;\n  outline-style: dotted;\n  outline-offset: -1px;\n}\n\n.highlight .code a {\n  color: inherit;\n  font-weight: 700;\n  background: linear-gradient(to bottom, #0000 10%, #f4f6ff 10%, #f4f6ff 90%, #0000 90%);\n  border-radius: 0.2em;\n}\n.highlight .code a:hover {\n  border-bottom: 1px dotted #000;\n}\n\n.code > div {\n  height: 100%;\n}\n\n/* icons */\n\n@font-face {\n  font-family: \"lxr\";\n  src: url(\"/static/fonts/lxr.svg\") format(\"svg\"),\n       url(\"/static/fonts/lxr.ttf\") format(\"truetype\");\n  font-weight: normal;\n  font-style: normal;\n}\n\n[class^=\"icon-\"]:before,\n[class*=\" icon-\"]:before {\n  font-family: \"lxr\" !important;\n  font-style: normal !important;\n  font-weight: normal !important;\n  font-variant: normal !important;\n  text-transform: none !important;\n  speak: none;\n  line-height: 1;\n  -webkit-font-smoothing: antialiased;\n  -moz-osx-font-smoothing: grayscale;\n}\n\n.icon-blob:before {\n  content: \"\\62\";\n}\n.icon-tree:before {\n  content: \"\\64\";\n}\n.icon-back:before {\n  content: \"\\68\";\n}\n.icon-search:before {\n  content: \"\\6d\";\n}\n.icon-rss:before {\n  content: \"\\67\";\n}\n.icon-github:before {\n  content: \"\\61\";\n}\n.icon-facebook:before {\n  content: \"\\65\";\n}\n.icon-mastodon:before {\n  content: \"\\66\";\n}\n.icon-twitter:before {\n  content: \"\\69\";\n}\n.icon-linkedin:before {\n  content: \"\\6a\";\n}\n.icon-cross:before {\n  content: \"\\6c\";\n}\n.icon-filter:before {\n  content: \"\\6e\";\n}\n.icon-menu:before {\n  content: \"\\6f\";\n}\n.icon-up:before {\n  content: \"\\70\";\n}\n.icon-tag:before {\n  content: \"\\63\";\n}\n\n\n/* highlight */\n\n.highlight .code pre {\n  color: #000;\n  -moz-tab-size: 8;\n  -o-tab-size: 8;\n  tab-size: 8;\n\n  white-space: pre;\n  word-spacing: normal;\n  word-break: normal;\n  word-wrap: normal;\n\n  -webkit-hyphens: none;\n  -ms-hyphens: none;\n  hyphens: none;\n}\n\n.highlight .code .hll { background-color: #ffffcc }\n.highlight .code  { background: #ffffff }\n.highlight .code .c { color: slategray; font-style: italic; } /* Comment */\n.highlight .code .err { color: #FF0000; background-color: #FFAAAA } /* Error */\n.highlight .code .k { color: #008800 } /* Keyword */\n.highlight .code .o { color: #666 } /* Operator */\n.highlight .code .ch { color: #888888 } /* Comment.Hashbang */\n.highlight .code .cm { color: slategray; font-style: italic; } /* Comment.Multiline */\n.highlight .code .cp { color: #557799 } /* Comment.Preproc */\n.highlight .code .cpf { color: #888888 } /* Comment.PreprocFile */\n.highlight .code .c1 { color: slategray; font-style: italic; } /* Comment.Single */\n.highlight .code .cs { color: #cc0000 } /* Comment.Special */\n.highlight .code .gd { color: #A00000 } /* Generic.Deleted */\n.highlight .code .ge { font-style: italic } /* Generic.Emph */\n.highlight .code .gr { color: #FF0000 } /* Generic.Error */\n.highlight .code .gh { color: #000080 } /* Generic.Heading */\n.highlight .code .gi { color: #00A000 } /* Generic.Inserted */\n.highlight .code .go { color: #888888 } /* Generic.Output */\n.highlight .code .gp { color: #c65d09 } /* Generic.Prompt */\n.highlight .code .gs { font-weight: bold } /* Generic.Strong */\n.highlight .code .gu { color: #800080 } /* Generic.Subheading */\n.highlight .code .gt { color: #0044DD } /* Generic.Traceback */\n.highlight .code .kc { color: #008800 } /* Keyword.Constant */\n.highlight .code .kd { color: #008800 } /* Keyword.Declaration */\n.highlight .code .kn { color: #008800 } /* Keyword.Namespace */\n.highlight .code .kp { color: #003388 } /* Keyword.Pseudo */\n.highlight .code .kr { color: #008800 } /* Keyword.Reserved */\n.highlight .code .kt { color: #333399 } /* Keyword.Type */\n.highlight .code .m { color: #6600EE } /* Literal.Number */\n.highlight .code .s { color: #de7f00 } /* Literal.String */\n.highlight .code .na { color: #0000CC } /* Name.Attribute */\n.highlight .code .nb { color: #007020 } /* Name.Builtin */\n.highlight .code .nc { color: #BB0066 } /* Name.Class */\n.highlight .code .no { color: #003366 } /* Name.Constant */\n.highlight .code .nd { color: #555555 } /* Name.Decorator */\n.highlight .code .ni { color: #880000 } /* Name.Entity */\n.highlight .code .ne { color: #FF0000 } /* Name.Exception */\n.highlight .code .nf { color: #0066BB } /* Name.Function */\n.highlight .code .nl { color: #997700 } /* Name.Label */\n.highlight .code .nn { color: #0e84b5 } /* Name.Namespace */\n.highlight .code .nt { color: #007700 } /* Name.Tag */\n.highlight .code .nv { color: #996633 } /* Name.Variable */\n.highlight .code .ow { color: #000000 } /* Operator.Word */\n.highlight .code .p { color: #666 } /* Text.Punctuation */\n.highlight .code .w { color: #bbbbbb } /* Text.Whitespace */\n.highlight .code .mb { color: #6600EE } /* Literal.Number.Bin */\n.highlight .code .mf { color: #6600EE } /* Literal.Number.Float */\n.highlight .code .mh { color: #005588 } /* Literal.Number.Hex */\n.highlight .code .mi { color: #0000DD } /* Literal.Number.Integer */\n.highlight .code .mo { color: #4400EE } /* Literal.Number.Oct */\n.highlight .code .sa { color: #de7f00 } /* Literal.String.Affix */\n.highlight .code .sb { color: #de7f00 } /* Literal.String.Backtick */\n.highlight .code .sc { color: #de7f00 } /* Literal.String.Char */\n.highlight .code .dl { color: #de7f00 } /* Literal.String.Delimiter */\n.highlight .code .sd { color: #a29900 } /* Literal.String.Doc */\n.highlight .code .s2 { color: #de7f00 } /* Literal.String.Double */\n.highlight .code .se { color: #a29900 } /* Literal.String.Escape */\n.highlight .code .sh { color: #de7f00 } /* Literal.String.Heredoc */\n.highlight .code .si { color: #de7f00 } /* Literal.String.Interpol */\n.highlight .code .sx { color: #de7f00 } /* Literal.String.Other */\n.highlight .code .sr { color: #a29900 } /* Literal.String.Regex */\n.highlight .code .s1 { color: #de7f00 } /* Literal.String.Single */\n.highlight .code .ss { color: #a29900 } /* Literal.String.Symbol */\n.highlight .code .bp { color: #007020 } /* Name.Builtin.Pseudo */\n.highlight .code .fm { color: #0066BB } /* Name.Function.Magic */\n.highlight .code .vc { color: #336699 } /* Name.Variable.Class */\n.highlight .code .vg { color: #dd7700 } /* Name.Variable.Global */\n.highlight .code .vi { color: #3333BB } /* Name.Variable.Instance */\n.highlight .code .vm { color: #996633 } /* Name.Variable.Magic */\n.highlight .code .il { color: #0000DD } /* Literal.Number.Integer.Long */\n\n\n/* layout */\n\nmain {\n  min-height: calc(100vh - 45px - 25px);\n  display: -webkit-box;\n  display: -ms-flexbox;\n  display: flex;\n  position: relative;\n  width: max-content;\n}\n.js .wrapper {\n  position: absolute;\n  top: 0;\n  bottom: 0;\n  left: 0;\n  right: 0;\n  width: auto;\n  height: auto;\n  overflow-x: auto;\n  overflow-y: scroll;\n}\n.footer {\n  position: fixed;\n  bottom: 0;\n  left: 0;\n  right: 0;\n  z-index: 2;\n}\n\n\n/* responsive */\n\n.open-menu {\n  margin-right: 1.2rem;\n  margin-left: -0.5rem;\n}\n.open-menu::before {\n  font-size: 1.5rem;\n  line-height: 0;\n  vertical-align: -0.31rem;\n}\n\n.close-menu {\n  background: #222;\n  color: #fff;\n  position: absolute;\n  text-align: center;\n  padding-top: 0.5rem;\n  font-size: 1.7rem;\n  width: 2.8rem;\n  height: 2.8rem;\n}\n.close-menu {\n  margin-left: 0.3em;\n  margin-top: -0.3em;\n}\n\n.sidebar {\n  position: fixed;\n  z-index: 30;\n  top: 0;\n  bottom: 0;\n  left: -100%;\n  width: 100%;\n  height: auto;\n  background: rgba(3, 8, 35, 0);\n}\n.sidebar .filter,\n.sidebar nav {\n  width: 60%;\n  max-width: 330px;\n}\n\n/* tablet and above */\n@media screen and (min-width: 600px) {\n  .filter input,\n  .search input {\n    padding: 0.9rem 1rem;\n  }\n  .search,\n  .filter {\n    padding: 0;\n  }\n  .filter {\n    background: #222;\n  }\n  .close-menu {\n    margin-left: 0;\n    margin-top: 0;\n  }\n  .topbar {\n    display: -webkit-box;\n    display: -ms-flexbox;\n    display: flex;\n  }\n  .breadcrumb {\n    -webkit-box-flex: 1;\n        -ms-flex: 1;\n            flex: 1;\n  }\n  .search {\n    width: 40%;\n  }\n  .sub-header {\n    text-align: left;\n  }\n}\n\n/* tablet only */\n@media screen and (max-width: 1000px) {\n  .sidebar {\n    -webkit-transition: left 0.2s ease 0.2s, background 0.2s ease;\n    transition: left 0.2s ease 0.2s, background 0.2s ease;\n  }\n  .show-menu-mobile .sidebar {\n    position: fixed;\n    left: 0;\n    background: rgba(3, 8, 35, 0.5);\n  }\n}\n\n/* desktop */\n@media screen and (min-width: 1000px) {\n  :root {\n    --is-widescreen: true;\n  }\n  .close-menu {\n    display: none;\n  }\n  .sidebar {\n    position: absolute;\n    top: -45px;\n    bottom: -25px;\n    -webkit-box-ordinal-group: 1;\n        -ms-flex-order: 0;\n            order: 0;\n    width: 235px;\n    -webkit-box-flex: 0;\n        -ms-flex: 0 0 235px;\n            flex: 0 0 235px;\n  }\n  .sidebar .filter, .sidebar nav {\n    width: 100%;\n  }\n  .sidebar nav {\n    height: 100%;\n  }\n  .workspace {\n    -webkit-box-ordinal-group: 2;\n        -ms-flex-order: 1;\n            order: 1;\n    padding-left: 235px;\n  }\n  .show-menu .topbar, .no-js .topbar {\n    padding-left: 235px;\n  }\n  .show-menu .footer, .no-js .footer {\n    padding-left: calc(2.5rem + 235px);\n  }\n  .show-menu .sidebar {\n    position: -webkit-sticky;\n    position: sticky;\n    left: 0;\n  }\n  .linenos {\n    left: 235px;\n  }\n  .no-js .sidebar {\n    left: 0;\n    height: 100%;\n  }\n}\n\n/* if browser support position: sticky */\n@supports ((position: -webkit-sticky) or (position: sticky)) {\n  .js .header {\n    position: -webkit-sticky;\n    position: sticky;\n    left: 0;\n  }\n  .js .footer {\n    position: -webkit-sticky;\n    position: sticky;\n    right: unset;\n  }\n  .js .topbar {\n    position: -webkit-sticky;\n    position: sticky;\n    top: 0;\n    left: 0;\n    z-index: 2;\n  }\n  .js .sub-header {\n    position: -webkit-sticky;\n    position: sticky;\n    left: 0;\n  }\n  .js .linenos {\n    position: -webkit-sticky;\n    position: sticky;\n    left: 0;\n    z-index: 1;\n  }\n  .js main {\n    position: unset;\n  }\n\n  /* desktop */\n  @media screen and (min-width: 1000px) {\n    .show-menu .js .linenos {\n      left: 235px;\n    }\n    .js .workspace {\n      padding-left: unset;\n    }\n    .js .sidebar {\n      top: 0;\n      height: 100vh;\n      margin-top: -45px;\n      margin-bottom: -25px;\n\n      /* screen height minus potential horizontal scrollbar height */\n      height: calc(100vh - 18px);\n      /* little hack to hide potential scrollbar gap */\n      -webkit-box-shadow: 0 18px 0 0 #111;\n              box-shadow: 0 18px 0 0 #111;\n    }\n  }\n}\n\n/* === Banner =============================================================== */\n\n/* Message banner in desktop mode */\n@media screen and (min-width: 748px) {\n  .message-banner {\n    padding: 5px;\n    -webkit-box-shadow: -2px 0px 15px 1px rgba(0,0,0,0.69);\n    -moz-box-shadow: -2px 0px 15px 1px rgba(0,0,0,0.69);\n    box-shadow: -2px 0px 15px 1px rgba(0,0,0,0.69);\n    font-size: 14;\n    font-family: Arial;\n    font-weight: bold;\n    width: 215px;\n    height: 120px;\n    text-align: center;\n    border-radius: 20px;\n    background: rgba(255,255,255,1);\n    background: -moz-linear-gradient(top, rgba(255,255,255,1) 0%, rgba(246,246,246,1) 47%, rgba(237,237,237,1) 100%);\n    background: -webkit-gradient(left top, left bottom, color-stop(0%, rgba(255,255,255,1)), color-stop(47%, rgba(246,246,246,1)), color-stop(100%, rgba(237,237,237,1)));\n    background: -webkit-linear-gradient(top, rgba(255,255,255,1) 0%, rgba(246,246,246,1) 47%, rgba(237,237,237,1) 100%);\n    background: -o-linear-gradient(top, rgba(255,255,255,1) 0%, rgba(246,246,246,1) 47%, rgba(237,237,237,1) 100%);\n    background: -ms-linear-gradient(top, rgba(255,255,255,1) 0%, rgba(246,246,246,1) 47%, rgba(237,237,237,1) 100%);\n    background: linear-gradient(to bottom, rgba(255,255,255,1) 0%, rgba(246,246,246,1) 47%, rgba(237,237,237,1) 100%);\n    filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#ffffff', endColorstr='#ededed', GradientType=0 );\n  }\n  .message-banner p.title {\n    font-size: 14px;\n    margin: 0;\n  }\n  .message-banner .subtitle {\n    font-size: 12px;\n    position: relative;\n  }\n  .message-banner .container {\n    height: 100%;\n    display: flex;\n    flex-direction: column;\n    justify-content: space-evenly;\n  }\n  .message-banner .action {\n    font-size: 14px;\n    justify-content: center;\n    display: none;\n  }\n  .message-banner .action-inner {\n    border: 1px solid black;\n    border-radius: 5px;\n    padding: 2px 10px;\n  }\n  .message-banner .action-visible {\n    display: flex;\n  }\n}\n\n.icon-googleplus:before,\n.icon-mastodon:before {\n  position: relative;\n  left: 3px;\n}\n.select-projects {\n  background-position: bottom 0.15em right 0.3em;\n  width: 100%;\n}\n\n/* Message banner in mobile mode */\n@media screen and (max-width: 748px) {\n  .message-banner {\n    width: 100%;\n    padding: 3px;\n    text-align: center;\n    background: #757575;\n    color: #fff;\n    font-family: Arial;\n  }\n  .message-banner .title {\n    margin: 0;\n    font-weight: 900;\n    text-wrap: pretty;\n  }\n  .message-banner .subtitle {\n    padding-top: 2px;\n    margin: 0;\n    word-break: break-word;\n  }\n  .message-banner .action {\n    display: none;\n  }\n  .message-banner .action-visible {\n    display: none;\n  }\n  .message-link {\n    width: 100%;\n  }\n}\n\n/* === Fonts ================================================================ */\n\n/* ubuntu-regular - cyrillic_greek_latin_latin-ext_greek-ext_cyrillic-ext */\n@font-face {\n  font-family: 'Ubuntu';\n  font-style: normal;\n  font-weight: 400;\n  src: url('/static/fonts/ubuntu/ubuntu-v14-cyrillic_greek_latin_latin-ext_greek-ext_cyrillic-ext-regular.eot'); /* IE9 Compat Modes */\n  src: local('Ubuntu Regular'), local('Ubuntu-Regular'),\n       url('/static/fonts/ubuntu/ubuntu-v14-cyrillic_greek_latin_latin-ext_greek-ext_cyrillic-ext-regular.eot?#iefix') format('embedded-opentype'), /* IE6-IE8 */\n       url('/static/fonts/ubuntu/ubuntu-v14-cyrillic_greek_latin_latin-ext_greek-ext_cyrillic-ext-regular.woff2') format('woff2'), /* Super Modern Browsers */\n       url('/static/fonts/ubuntu/ubuntu-v14-cyrillic_greek_latin_latin-ext_greek-ext_cyrillic-ext-regular.woff') format('woff'), /* Modern Browsers */\n       url('/static/fonts/ubuntu/ubuntu-v14-cyrillic_greek_latin_latin-ext_greek-ext_cyrillic-ext-regular.ttf') format('truetype'), /* Safari, Android, iOS */\n       url('/static/fonts/ubuntu/ubuntu-v14-cyrillic_greek_latin_latin-ext_greek-ext_cyrillic-ext-regular.svg#Ubuntu') format('svg'); /* Legacy iOS */\n}\n/* ubuntu-italic - cyrillic_greek_latin_latin-ext_greek-ext_cyrillic-ext */\n@font-face {\n  font-family: 'Ubuntu';\n  font-style: italic;\n  font-weight: 400;\n  src: url('/static/fonts/ubuntu/ubuntu-v14-cyrillic_greek_latin_latin-ext_greek-ext_cyrillic-ext-italic.eot'); /* IE9 Compat Modes */\n  src: local('Ubuntu Italic'), local('Ubuntu-Italic'),\n       url('/static/fonts/ubuntu/ubuntu-v14-cyrillic_greek_latin_latin-ext_greek-ext_cyrillic-ext-italic.eot?#iefix') format('embedded-opentype'), /* IE6-IE8 */\n       url('/static/fonts/ubuntu/ubuntu-v14-cyrillic_greek_latin_latin-ext_greek-ext_cyrillic-ext-italic.woff2') format('woff2'), /* Super Modern Browsers */\n       url('/static/fonts/ubuntu/ubuntu-v14-cyrillic_greek_latin_latin-ext_greek-ext_cyrillic-ext-italic.woff') format('woff'), /* Modern Browsers */\n       url('/static/fonts/ubuntu/ubuntu-v14-cyrillic_greek_latin_latin-ext_greek-ext_cyrillic-ext-italic.ttf') format('truetype'), /* Safari, Android, iOS */\n       url('/static/fonts/ubuntu/ubuntu-v14-cyrillic_greek_latin_latin-ext_greek-ext_cyrillic-ext-italic.svg#Ubuntu') format('svg'); /* Legacy iOS */\n}\n/* ubuntu-700 - cyrillic_greek_latin_latin-ext_greek-ext_cyrillic-ext */\n@font-face {\n  font-family: 'Ubuntu';\n  font-style: normal;\n  font-weight: 700;\n  src: url('/static/fonts/ubuntu/ubuntu-v14-cyrillic_greek_latin_latin-ext_greek-ext_cyrillic-ext-700.eot'); /* IE9 Compat Modes */\n  src: local('Ubuntu Bold'), local('Ubuntu-Bold'),\n       url('/static/fonts/ubuntu/ubuntu-v14-cyrillic_greek_latin_latin-ext_greek-ext_cyrillic-ext-700.eot?#iefix') format('embedded-opentype'), /* IE6-IE8 */\n       url('/static/fonts/ubuntu/ubuntu-v14-cyrillic_greek_latin_latin-ext_greek-ext_cyrillic-ext-700.woff2') format('woff2'), /* Super Modern Browsers */\n       url('/static/fonts/ubuntu/ubuntu-v14-cyrillic_greek_latin_latin-ext_greek-ext_cyrillic-ext-700.woff') format('woff'), /* Modern Browsers */\n       url('/static/fonts/ubuntu/ubuntu-v14-cyrillic_greek_latin_latin-ext_greek-ext_cyrillic-ext-700.ttf') format('truetype'), /* Safari, Android, iOS */\n       url('/static/fonts/ubuntu/ubuntu-v14-cyrillic_greek_latin_latin-ext_greek-ext_cyrillic-ext-700.svg#Ubuntu') format('svg'); /* Legacy iOS */\n}\n\n/* === Header =============================================================== */\n\n.header {\n  min-height: 200px;\n  background: #6D7DD2;\n  background-image: url('/static/img/2penguins.svg');\n  background-repeat: no-repeat;\n  background-size: 300px;\n  background-position: bottom -82px right;\n}\n\n.header {\n  display: -webkit-box;\n  display: -ms-flexbox;\n  display: flex;\n  flex-direction: column;\n}\n.header h1 {\n  font-family: 'Ubuntu Mono', monospace;\n  font-style: italic;\n  text-align: center;\n  font-size: 3.2em;\n  word-spacing: -0.4em;\n  color: #fff;\n  margin-bottom: 0;\n  margin-top: 0;\n}\n.header h1 a {\n  color: #fff;\n}\n.header h2 {\n  font-family: 'Ubuntu Mono', monospace;\n  text-align: center;\n  font-size: 1em;\n  font-weight: 400;\n  margin-top: -0.5em;\n  color: #fff;\n  color: #ffa264;\n}\n.header em {\n  font-style: normal;\n  font-size: 0.9em;\n  line-height: 1;\n  text-align: center;\n  float: right;\n  padding: 0.5em 1em;\n  position: absolute;\n  bottom: 0;\n  left: 0;\n  right: 0;\n  color: rgba(255,255,255,.7);\n  background-color: rgba(255,255,255,.1);\n}\n.header em a {\n  color: rgba(255,255,255,.9);\n}\n.header nav {\n  text-align: center;\n  width: 100%;\n}\n.header nav ul {\n  list-style: none;\n}\n\n.header-main {\n  display: grid;\n  grid-template-columns: 235px 1fr 235px;\n}\n\n.banners {\n  display: flex;\n  justify-content: center;\n  align-items: center;\n  position: relative;\n}\n\n.under-topbar {\n  height: 48px;\n}\n\n.nav-links {\n  padding: 0.5em 1em;\n  margin: 0;\n  background-color: rgba(0,0,0,.5);\n  width: 100%;\n  font-size: 0.8em;\n  line-height: 1.7;\n}\n.nav-links li {\n  display: inline-block;\n  margin: 0 0.5em;\n}\n.nav-links a {\n  text-transform: uppercase;\n  color: #9da9ea;\n}\n.nav-links a:hover {\n  color: #fff;\n}\n\n.social-icons {\n  position: absolute;\n  top: 0.05rem;\n  right: 0.3rem;\n  padding: 0;\n  margin: 0;\n  display: inline-block;\n  line-height: 1.5rem; /* little hack for firefox vertical align */\n}\n.social-icons li {\n  display: inline-block;\n  font-size: 0;\n}\n.social-icons a::before {\n  font-size: 1.65rem;\n  color: #717fc5;\n}\n.social-icons a:focus::before,\n.social-icons a:hover::before {\n  color: #fff;\n}\n\n/* responsive */\n\n@media (max-width: 748px) {\n  .banners {\n    justify-content: flex-start;\n  }\n  .header .social-icons {\n    position: static;\n    background-color: rgba(0,0,0,.5);\n    width: 100%;\n  }\n  .social-icons a::before {\n    font-size: 1.5rem;\n    color: #9da9ea;\n  }\n  .header-main {\n    display: flex;\n    flex-direction: column;\n  }\n}\n\n@media (max-width: 520px) {\n  .header h1 {\n    font-size: 2.5em;\n    font-size: 8vw;\n  }\n  .header h2 {\n    font-size: 1em;\n    font-size: 3vw;\n  }\n}\n\n@media (max-width: 330px) {\n  .header h1 {\n    margin-top: 1.8em;\n  }\n}\n\n/* === Autocomplete ========================================================= */\n\n/*\n * @license MIT\n *\n * Autocomplete.js v2.7.1\n * Developed by Baptiste Donaux\n * http://autocomplete-js.com\n *\n * (c) 2017, Baptiste Donaux\n *\n * Modified by Maxime Chretien <maxime.chretien@bootlin.com>\n * for the needs of Elixir Cross Referencer\n * https://github.com/bootlin/elixir\n *\n */\n\ninput[data-autocomplete] {\n  border-color: #808080;\n  border-style: none none solid none;\n  border-width: 0px 0px 1px 0px;\n  margin: 0px;\n  padding: 5px;\n  width: 100%;\n}\n.autocomplete {\n  position: absolute;\n  transition: all 0.5s ease 0s;\n  max-height: 0;\n  overflow-y: hidden;\n  transition-duration: 0.3s;\n  transition-property: all;\n  transition-timing-function: cubic-bezier(0, 1, 0.5, 1);\n}\n.autocomplete:active,\n.autocomplete:focus,\n.autocomplete:hover {\n  background-color: #EEEEEE;\n  transition: all 0.5s ease 0s;\n}\n.autocomplete:empty {\n  display: none;\n}\n.autocomplete > ul {\n  list-style-type: none;\n  margin: 0;\n  padding: 0;\n}\n.autocomplete > ul > li {\n  cursor: pointer;\n  padding: 5px 0 5px 10px;\n  white-space: nowrap;\n}\n.autocomplete > ul > li.active,\n.autocomplete > ul > li:active,\n.autocomplete > ul > li:focus,\n.autocomplete > ul > li:hover {\n  background-color: #DDDDDD;\n  transition: all 0.5s ease 0s;\n}\n.autocomplete > ul > li.active a:active,\n.autocomplete > ul > li:active a:active,\n.autocomplete > ul > li:focus a:active,\n.autocomplete > ul > li:hover a:active,\n.autocomplete > ul > li.active a:focus,\n.autocomplete > ul > li:active a:focus,\n.autocomplete > ul > li:focus a:focus,\n.autocomplete > ul > li:hover a:focus,\n.autocomplete > ul > li.active a:hover,\n.autocomplete > ul > li:active a:hover,\n.autocomplete > ul > li:focus a:hover,\n.autocomplete > ul > li:hover a:hover {\n  text-decoration: none;\n}\n.autocomplete > ul > li.locked {\n  cursor: inherit;\n}\n.autocomplete.open {\n  display: block;\n  transition: all 0.5s ease 0s;\n  background-color: #EEEEEE;\n  max-height: 500px;\n  overflow-y: auto;\n  transition-duration: 0.3s;\n  transition-property: all;\n  transition-timing-function: cubic-bezier(0, 1, 0.5, 1);\n  z-index: 100;\n}\n.autocomplete.open:empty {\n  display: none;\n}\n"
  },
  {
    "path": "t/050-testhelpers.t",
    "content": "#!/usr/bin/env perl\n# t/50-testhelpers.t: test TestHelpers.pm\n#\n# Copyright (c) 2020 Christopher White, <cxwembedded@gmail.com>.\n# Copyright (c) 2020 D3 Engineering, LLC.\n#\n# Elixir is free software; you can redistribute it and/or modify\n# it under the terms of the GNU Affero General Public License as published by\n# the Free Software Foundation, either version 3 of the License, or\n# (at your option) any later version.\n#\n# Elixir is distributed in the hope that it will be useful,\n# but WITHOUT ANY WARRANTY; without even the implied warranty of\n# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n# GNU Affero General Public License for more details.\n# # You should have received a copy of the GNU Affero General Public License\n# along with Elixir.  If not, see <http://www.gnu.org/licenses/>.\n#\n# SPDX-License-Identifier: AGPL-3.0-or-later\n#\n# This file uses core Perl modules only.\n\nuse FindBin '$Bin';\nuse lib $Bin;\n\nuse Test::More;\n\nuse TestEnvironment;\nuse TestHelpers qw(:all);\n\n# === line_mark_string =======================================================\n\nour ($fn, $refln, $ln);\n\nsub level1 {\n    eval line_mark_string 1, '$fn = __FILE__; $ln = __LINE__';\n    ok !$@, 'level1 no errors';\n}\n\n$refln = __LINE__; level1;\nis $fn, __FILE__, 'level1 file';\ncmp_ok $ln, '==', $refln, 'level1 line';\n\nsub level2 {\n    level2_inner();\n}\n\nsub level2_inner {\n    eval line_mark_string 2, '$fn = __FILE__; $ln = __LINE__';\n    ok !$@, 'level2_inner no errors';\n}\n\n$refln = __LINE__; level2;\nis $fn, __FILE__, 'level2 file';\ncmp_ok $ln, '==', $refln, 'level2 line';\n\ndone_testing;\n"
  },
  {
    "path": "t/100-basic.t",
    "content": "#!/usr/bin/env perl\n# 100-basic.t: Test basic elixir functions against the files in tree/ .\n#\n# Copyright (c) 2020 D3 Engineering, LLC.\n# By Christopher White, <cwhite@d3engineering.com>.\n#\n# Elixir is free software; you can redistribute it and/or modify\n# it under the terms of the GNU Affero General Public License as published by\n# the Free Software Foundation, either version 3 of the License, or\n# (at your option) any later version.\n#\n# Elixir is distributed in the hope that it will be useful,\n# but WITHOUT ANY WARRANTY; without even the implied warranty of\n# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n# GNU Affero General Public License for more details.\n#\n# You should have received a copy of the GNU Affero General Public License\n# along with Elixir.  If not, see <http://www.gnu.org/licenses/>.\n#\n# SPDX-License-Identifier: AGPL-3.0-or-later\n#\n# This file uses core Perl modules only.\n\nuse autodie;    # note: still need to check system() calls manually\n\nuse FindBin '$Bin';\nuse lib $Bin;\n\nuse File::Spec;\n\nuse Test::More;\n\nuse TestEnvironment;\nuse TestHelpers;\n\n# ===========================================================================\n# Main\n\n# Set up\nmy $tree_src_dir = sibling_abs_path('tree');\n\nmy $tenv = TestEnvironment->new;\n\n# Check programs\nmy $script_sh = $tenv->script_sh;\nmy $update_py = $tenv->update_py;\nmy $query_py = $tenv->query_py;\n\nok_or_die( (-f $script_sh && -r _ && -x _), 'script.sh executable',\n    \"Could not find executable script.sh at $script_sh\");\nok_or_die( (-f $update_py && -r _ && -x _), 'update.py executable',\n    \"Could not find executable update.py at $update_py\");\nok_or_die( (-f $query_py && -r _ && -x _), 'query.py executable',\n    \"Could not find executable query.py at $query_py\");\n\n$tenv->build_repo($tree_src_dir);\n$tenv->update_env;  # Set LXR_REPO_DIR\n\ndiag $tenv->report;\n\n# Check for tags in `script.sh list-tags`, as a sanity check before\n# building the test DB\nmy @tags = `$script_sh list-tags`;\ndie(\"Could not list tags: $! ($?)\") if $?;\nok_or_die( @tags == 1, 'One tag present', \"Not one tag (@{[scalar @tags]})\");\nok_or_die( $tags[0] =~ /^v5.4$/, 'Found the correct tag', 'Not the tag we expected');\n\n$tenv->build_db;\n$tenv->update_env;  # Set LXR_DATA_DIR\nmy $db_dir = $tenv->lxr_data_dir;\n\nok_or_die( -d $db_dir, 'database dir exists',\n    \"Database dir $db_dir not present\");\n\n# Make sure the database has the files we expect\nok( (-r File::Spec->catfile($db_dir, $_)), \"$_ exists\" )\n    foreach qw(blobs.db definitions.db filenames.db hashes.db references.db\n                variables.db versions.db);\n\n# Spot-check some identifiers\n\nrun_produces_ok('ident query (nonexistent)',\n    [$query_py, qw(v5.4 ident SOME_NONEXISTENT_IDENTIFIER_XYZZY_PLUGH C)],\n    [qr{^Symbol Definitions:}, qr{^Symbol References:}, qr{^\\s*$}],\n    MUST_SUCCEED);\n\nrun_produces_ok('ident query (existent)',\n    [$query_py, qw(v5.4 ident i2c_acpi_notify C)],\n    [qr{^Symbol Definitions:}, qr{^Symbol References:},\n        { def => qr{drivers/i2c/i2c-core-acpi\\.c.+\\b402\\b.+\\bfunction\\b} },\n        { ref => qr{drivers/i2c/i2c-core-acpi\\.c.+\\b439} },\n    ],\n    MUST_SUCCEED);\n\nrun_produces_ok('ident query (existent, #131)',\n    [$query_py, qw(v5.4 ident class C)],\n    [qr{^Symbol Definitions:}, qr{^Symbol References:},\n        { def => qr{issue131\\.h.+\\b9\\b.+\\bstruct\\b} },\n        { ref => qr{issue131\\.h.+\\b13}  },\n    ],\n    MUST_SUCCEED);\n\nrun_produces_ok('ident query (existent, #150)',\n    [$query_py, qw(v5.4 ident memset C)],\n    [qr{^Symbol Definitions:}, qr{^Symbol References:},\n        { def => qr{issue150\\.S.+\\b7\\b.+\\bfunction\\b} },\n        { ref => qr{i2c-core-acpi\\.c.+\\b121\\b} }\n    ],\n    MUST_SUCCEED);\n\nrun_produces_ok('ident query (ENTRY that should not be detected, #150)',\n    [$query_py, qw(v5.4 ident), 'HYPERVISOR_##hypercall', 'C'],\n    [qr{^Symbol Definitions:}, qr{^Symbol References:},\n        { def => { not => qr{hypercall\\.S} } },\n    ],\n    MUST_SUCCEED);\n\nrun_produces_ok('ident query (ENTRY that should not be detected, #150)',\n    [$query_py, qw(v5.4 ident), '0xfffffffe', 'C'],\n    [qr{^Symbol Definitions:}, qr{^Symbol References:},\n        { def => { not => qr{bcm74xx_sprom\\.c} } },\n    ],\n    MUST_SUCCEED);\n\nrun_produces_ok('ident query (existent, #228)',\n    [$query_py, qw(v5.4 ident sys_init_module C)],\n    [qr{^Symbol Definitions:}, qr{^Symbol References:},\n        { def => qr{syscall_define\\.c.+\\b1\\b.+\\bfunction\\b} }\n    ],\n    MUST_SUCCEED);\n\n# Spot-check some files\n\nrun_produces_ok('file query (nonexistent)',\n    [$query_py, qw(v5.4 file /SOME_NONEXISTENT_FILENAME_XYZZY_PLUGH)],\n    [{not => qr{\\S}}]);\n\nrun_produces_ok('file query (existent), .h',\n    [$query_py, qw(v5.4 file /drivers/i2c/i2c-dev.c)],\n    [qr{\\S}],\n    MUST_SUCCEED);\n\nrun_produces_ok('file query (existent), .c',\n    [$query_py, qw(v5.4 file /drivers/i2c/i2c-dev.c)],\n    [qr{i2c-dev\\.c}, qr{\\bVogl\\b}],\n    MUST_SUCCEED);\n\nrun_produces_ok('file query (existent), .h',\n    [$query_py, qw(v5.4 file /drivers/i2c/i2c-core.h)],\n    [qr{i2c-core\\.h}, qr{\\bWe\\b}],\n    MUST_SUCCEED);\n\ndone_testing;\n"
  },
  {
    "path": "t/200-api.t",
    "content": "#!/usr/bin/env perl\n# 200-api.t: Test elixir's REST api against the files in tree/ .\n#\n# Copyright (c) 2020 Tamir Carmeli, <carmeli.tamir@gmail.com>.\n#\n# Elixir is free software; you can redistribute it and/or modify\n# it under the terms of the GNU Affero General Public License as published by\n# the Free Software Foundation, either version 3 of the License, or\n# (at your option) any later version.\n#\n# Elixir is distributed in the hope that it will be useful,\n# but WITHOUT ANY WARRANTY; without even the implied warranty of\n# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n# GNU Affero General Public License for more details.\n# # You should have received a copy of the GNU Affero General Public License\n# along with Elixir.  If not, see <http://www.gnu.org/licenses/>.\n#\n# SPDX-License-Identifier: AGPL-3.0-or-later\n#\n# This file uses core Perl modules only.\n\nuse FindBin '$Bin';\nuse lib $Bin;\n\nuse Test::More;\n\nuse TestEnvironment;\nuse TestHelpers;\n\nmy $tenv = TestEnvironment->new;\n$tenv->build_repo(sibling_abs_path('tree'))->build_db->update_env;\n\n# Test the api using pytest. Prints the test results\nrun_produces_ok('api pytest suite', [\"pytest\", \"-v\", \"t\"], [], MUST_SUCCEED, 1);\n\ndone_testing;\n"
  },
  {
    "path": "t/300-doc-comments.t",
    "content": "#!/usr/bin/env perl\n# 300-doc-comments.t: Test elixir doc-comment extraction against the files in tree/ .\n#\n# Copyright (c) 2020 Christopher White.\n# Copyright (c) 2020 D3 Engineering, LLC.\n# By Christopher White, <cwhite@d3engineering.com>.\n#\n# Elixir is free software; you can redistribute it and/or modify\n# it under the terms of the GNU Affero General Public License as published by\n# the Free Software Foundation, either version 3 of the License, or\n# (at your option) any later version.\n#\n# Elixir is distributed in the hope that it will be useful,\n# but WITHOUT ANY WARRANTY; without even the implied warranty of\n# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n# GNU Affero General Public License for more details.\n#\n# You should have received a copy of the GNU Affero General Public License\n# along with Elixir.  If not, see <http://www.gnu.org/licenses/>.\n#\n# SPDX-License-Identifier: AGPL-3.0-or-later\n#\n# This file uses core Perl modules only.\n\nuse autodie;    # note: still need to check system() calls manually\n\nuse FindBin '$Bin';\nuse lib $Bin;\n\nuse File::Spec;\nuse Test::More;\n\nuse TestEnvironment;\nuse TestHelpers;\n\n# ===========================================================================\n# Main\n\n# Set up\nmy $tenv = TestEnvironment->new;\n$tenv->build_repo(sibling_abs_path('tree'))->build_db->update_env;\n\nok_or_die( -d $tenv->lxr_data_dir, 'database dir exists',\n    \"Database dir @{[$tenv->lxr_data_dir]} not present\");\n\n# Spot-check some identifiers\n\nrun_produces_ok('doc-comment query (nonexistent)',\n    [$tenv->query_py, qw(v5.4 ident SOME_NONEXISTENT_IDENTIFIER_XYZZY_PLUGH C)],\n    [\n        qr{^Documented in:},\n        {doc => { not => qr{/} }},   # No file paths in the doc section\n    ],\n    MUST_SUCCEED);\n\nrun_produces_ok('doc-comment query (existent but not documented)',\n    [$tenv->query_py, qw(v5.4 ident gsb_buffer C)],   # in drivers/i2c/i2c-core-acpi.c\n    [\n        qr{^Documented in:},\n        {doc => { not => qr{/} }}\n    ],\n    MUST_SUCCEED);\n\nrun_produces_ok('ident query (existent, function, documented in C file)',\n    [$tenv->query_py, qw(v5.4 ident i2c_acpi_get_i2c_resource C)],\n    [\n        qr{^Documented in:},\n        {doc => qr{drivers/i2c/i2c-core-acpi\\.c.+\\b45\\b}},\n    ],\n    MUST_SUCCEED);\n\nrun_produces_ok('ident query (existent, function, documented in C file, #102)',\n    [$tenv->query_py, qw(v5.4 ident documented_function_XYZZY C)],\n    [\n        qr{^Documented in:},\n        {doc => qr{issue102\\.c.+\\b6\\b}},\n    ],\n    MUST_SUCCEED);\n\n# Non-functions\n\nrun_produces_ok('ident query (existent, enum, documented in H file)',\n    [$tenv->query_py, qw(v5.4 ident memblock_flags C)],\n    [\n        qr{^Documented in:},\n        {doc => qr{\\bmemblock\\.h.+\\b28\\b}},\n    ],\n    MUST_SUCCEED);\n\nrun_produces_ok('ident query (existent, enum, not documented)',\n    [$tenv->query_py, qw(v5.4 ident rseq_cpu_id_state C)],  # uapi/linux/rseq.h:16\n    [\n        qr{^Documented in:},\n        {doc => { not => qr{/} }}\n    ],\n    MUST_SUCCEED);\n\nrun_produces_ok('ident query (existent, struct, documented in H file)',\n    [$tenv->query_py, qw(v5.4 ident memblock_region C)],\n    [\n        qr{^Documented in:},\n        {doc => qr{\\bmemblock\\.h.+\\b42\\b}},\n    ],\n    MUST_SUCCEED);\n\nrun_produces_ok('ident query (existent, struct, not documented)',\n    [$tenv->query_py, qw(v5.4 ident epoll_event C)],    # eventpoll.h:77\n    [\n        qr{^Documented in:},\n        {doc => { not => qr{/} }}\n    ],\n    MUST_SUCCEED);\n\nrun_produces_ok('ident query (existent, macro, documented in H file)',\n    [$tenv->query_py, qw(v5.4 ident for_each_mem_range C)],\n    [\n        qr{^Documented in:},\n        {doc => qr{\\bmemblock\\.h.+\\b148\\b}},\n    ],\n    MUST_SUCCEED);\n\nrun_produces_ok('ident query (existent, macro, not documented)',\n    [$tenv->query_py, qw(v5.4 ident MEMBLOCK_LOW_LIMIT C)], # memblock.h:343\n    [\n        qr{^Documented in:},\n        {doc => { not => qr{/} }}\n    ],\n    MUST_SUCCEED);\n\n# Specific cases from #134\n\n# Like regmap_update_bits_base()\nrun_produces_ok('ident query (existent, function, documented in C file, nonstandard doc comment, #134)',\n    [$tenv->query_py, qw(v5.4 ident issue134_function1 C)],\n    [\n        qr{^Documented in:},\n        {doc => qr{\\bissue134\\.c.+\\b9\\b}},\n    ],\n    MUST_SUCCEED);\n\n# Like wait_for_completion()\nrun_produces_ok('ident query (existent, function, documented in C file, nonstandard doc comment, #134)',\n    [$tenv->query_py, qw(v5.4 ident issue134_function2 C)],\n    [\n        qr{^Documented in:},\n        {doc => qr{\\bissue134\\.c.+\\b25\\b}},\n    ],\n    MUST_SUCCEED);\n\n# Like v4l2_fwnode_endpoint_parse()\nrun_produces_ok('ident query (existent, prototype, documented in C file), #134',\n    [$tenv->query_py, qw(v5.4 ident issue134_function3 C)],\n    [\n        qr{^Documented in:},\n        {doc => qr{\\bissue134\\.c.+\\b38\\b}},\n    ],\n    MUST_SUCCEED);\n\n# #186\nrun_produces_ok('No warnings on macro, #186',\n    [$tenv->find_doc, File::Spec->catfile($tenv->lxr_repo_dir, 'issue186.c')],\n    [ ],\n    MUST_SUCCEED);  # warnings appear on stderr, failing the MUST_SUCCEED checks\n\n# #186 counterexamples\nrun_produces_ok('ident query (existent, documented as function), #186 counterexample',\n    [$tenv->query_py, qw(v5.4 ident i186c_fn1 C)],\n    [\n        qr{^Documented in:},\n        {doc => qr{\\bissue186-counterexamples\\.c.+\\b5\\b}},\n    ],\n    MUST_SUCCEED);\n\nrun_produces_ok('ident query (existent, documented as macro), #186 counterexample',\n    [$tenv->query_py, qw(v5.4 ident i186c_fn2 C)],\n    [\n        qr{^Documented in:},\n        {doc => qr{\\bissue186-counterexamples\\.c.+\\b20\\b}},\n    ],\n    MUST_SUCCEED);\n\n# #188\nrun_produces_ok('No warnings on indented #define, #188',\n    [$tenv->find_doc, File::Spec->catfile($tenv->lxr_repo_dir, 'issue188.c')],\n    [ ],\n    MUST_SUCCEED);  # warnings appear on stderr, failing the MUST_SUCCEED checks\n\n# #192\n\n# Like request_firmware()\nrun_produces_ok('ident query (existent, function, documented in C file, type on preceding line, #192)',\n    [$tenv->query_py, qw(v5.4 ident issue192a C)],\n    [\n        qr{^Documented in:},\n        {doc => qr{\\bissue192\\.c.+\\b5\\b}},\n    ],\n    MUST_SUCCEED);\n\nrun_produces_ok('ident query (existent, function, documented in C file, uppercase return type on preceding line, #192)',\n    [$tenv->query_py, qw(v5.4 ident issue192b C)],\n    [\n        qr{^Documented in:},\n        {doc => qr{\\bissue192\\.c.+\\b15\\b}},\n    ],\n    MUST_SUCCEED);\n\n#########################################################################\n\ndone_testing;\n"
  },
  {
    "path": "t/400-web.t",
    "content": "#!/usr/bin/env perl\n# t/400-web.pl: Test web.py\n#\n# Copyright (c) 2020 Christopher White, <cxwembedded@gmail.com>.\n#\n# Elixir is free software; you can redistribute it and/or modify\n# it under the terms of the GNU Affero General Public License as published by\n# the Free Software Foundation, either version 3 of the License, or\n# (at your option) any later version.\n#\n# Elixir is distributed in the hope that it will be useful,\n# but WITHOUT ANY WARRANTY; without even the implied warranty of\n# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n# GNU Affero General Public License for more details.\n# # You should have received a copy of the GNU Affero General Public License\n# along with Elixir.  If not, see <http://www.gnu.org/licenses/>.\n#\n# SPDX-License-Identifier: AGPL-3.0-or-later\n#\n# This file uses core Perl modules only.\n\nuse FindBin '$Bin';\nuse lib $Bin;\n\nuse Test::More;\n\nuse TestEnvironment;\nuse TestHelpers;\n\n# ===========================================================================\n# Main\n\n# Set up for the tests\nmy $tenv = TestEnvironment->new;\n$tenv->build_repo(sibling_abs_path('tree'));\t# dies on error\n$tenv->build_db;\n$tenv->update_env;\n\ndiag $tenv->report;\n\nhttp_request_ok 'index query', $tenv, '/testproj/latest/source',\n    [ qr{^Content-Type:\\s*text/html}, qr{href=\"latest/source/issue102.c\"},\n        qr{href=\"latest/source/arch\"} ], 1;\n\nhttp_request_ok 'identifier query', $tenv, '/testproj/v5.4/ident/gsb_buffer',\n    [ qr{^Content-Type:\\s*text/html}, qr{\\bgsb_buffer\\b},\n        qr{\"v5.4/source/drivers/i2c/i2c-core-acpi.c\\#L23\".+?\n            drivers/i2c/i2c-core-acpi.c.+?\n            line[ ]23.+?\n            \\bstruct\\b}x ], 1;\n\n# Doc comments: testcases pulled from t/300\nhttp_request_ok 'doc-comment query (nonexistent)', $tenv,\n    '/testproj/v5.4/ident/SOME_NONEXISTENT_IDENTIFIER_XYZZY_PLUGH',\n    [ qr{^Content-Type:\\s*text/html}, qr{<h\\d>Identifier not used</h\\d>}i], 1;\n\nhttp_request_ok 'doc-comment query (existent but not documented)', $tenv,\n    '/testproj/v5.4/ident/gsb_buffer',   # in drivers/i2c/i2c-core-acpi.c\n    [\n        qr{^Content-Type:\\s*text/html},\n        { not => qr{\\bDocumented in\\b} },\n    ], 1;\n\nhttp_request_ok 'ident query (existent, function, documented in C file)', $tenv,\n    '/testproj/v5.4/ident/i2c_acpi_get_i2c_resource',\n    [\n        qr{^Content-Type:\\s*text/html},\n        qr{\\bDocumented in \\d},\n        {doc => qr{drivers/i2c/i2c-core-acpi\\.c.+\\b45\\b}},\n    ], 1;\n\nhttp_request_ok 'ident query (existent, function, documented in C file, #102)',\n    $tenv, '/testproj/v5.4/ident/documented_function_XYZZY',\n    [\n        qr{^Content-Type:\\s*text/html},\n        qr{\\bDocumented in \\d},\n        {doc => qr{issue102\\.c.+\\b6\\b}},\n    ], 1;\n\ndone_testing;\n"
  },
  {
    "path": "t/TestClass.pm",
    "content": "# A minified OOP library - https://metacpan.org/pod/distribution/Mo/ReadMe.pod\n\npackage TestClass;\n# use Mo qw(build default is required import);\n#   The following line of code was produced from the previous line by\n#   Mo::Inline version 0.40\nno warnings;my$M=__PACKAGE__.'::';*{$M.Object::new}=sub{my$c=shift;my$s=bless{@_},$c;my%n=%{$c.'::'.':E'};map{$s->{$_}=$n{$_}->()if!exists$s->{$_}}keys%n;$s};*{$M.import}=sub{import warnings;$^H|=1538;my($P,%e,%o)=caller.'::';shift;eval\"no Mo::$_\",&{$M.$_.::e}($P,\\%e,\\%o,\\@_)for@_;return if$e{M};%e=(extends,sub{eval\"no $_[0]()\";@{$P.ISA}=$_[0]},has,sub{my$n=shift;my$m=sub{$#_?$_[0]{$n}=$_[1]:$_[0]{$n}};@_=(default,@_)if!($#_%2);$m=$o{$_}->($m,$n,@_)for sort keys%o;*{$P.$n}=$m},%e,);*{$P.$_}=$e{$_}for keys%e;@{$P.ISA}=$M.Object};*{$M.'build::e'}=sub{my($P,$e)=@_;$e->{new}=sub{$c=shift;my$s=&{$M.Object::new}($c,@_);my@B;do{@B=($c.::BUILD,@B)}while($c)=@{$c.::ISA};exists&$_&&&$_($s)for@B;$s}};*{$M.'default::e'}=sub{my($P,$e,$o)=@_;$o->{default}=sub{my($m,$n,%a)=@_;exists$a{default}or return$m;my($d,$r)=$a{default};my$g='HASH'eq($r=ref$d)?sub{+{%$d}}:'ARRAY'eq$r?sub{[@$d]}:'CODE'eq$r?$d:sub{$d};my$i=exists$a{lazy}?$a{lazy}:!${$P.':N'};$i or ${$P.':E'}{$n}=$g and return$m;sub{$#_?$m->(@_):!exists$_[0]{$n}?$_[0]{$n}=$g->(@_):$m->(@_)}}};*{$M.'is::e'}=sub{my($P,$e,$o)=@_;$o->{is}=sub{my($m,$n,%a)=@_;$a{is}or return$m;sub{$#_&&$a{is}eq'ro'&&caller ne'Mo::coerce'?die$n.' is ro':$m->(@_)}}};*{$M.'required::e'}=sub{my($P,$e,$o)=@_;$o->{required}=sub{my($m,$n,%a)=@_;if($a{required}){my$C=*{$P.\"new\"}{CODE}||*{$M.Object::new}{CODE};no warnings 'redefine';*{$P.\"new\"}=sub{my$s=$C->(@_);my%a=@_[1..$#_];die$n.\" required\"if!exists$a{$n};$s}}$m}};my$i=\\&import;*{$M.import}=sub{(@_==2 and not$_[1])?pop@_:@_==1?push@_,grep!/import/,@f:();goto&$i};@f=qw[build default is required import];use strict;use warnings;\n1;\n"
  },
  {
    "path": "t/TestEnvironment.pm",
    "content": "#!/usr/bin/env perl\n# TestEnvironment.pm: A class representing an Elixir test environment.\n# See license information at end of file.\n#\n# For a cleaner view of the documentation, run\n#   perldoc TestEnvironment.pm\n# (on Ubuntu, you may need to install the perl-doc package first.)\n#\n# SPDX-License-Identifier: AGPL-3.0-or-later\n#\n# This file uses only core Perl modules, and modules bundled with\n# the Elixir distribution.\n\n=head1 NAME\n\nTestEnvironment - Class representing an Elixir test environment\n\n=head1 SYNOPSIS\n\n    use TestEnvironment;\n    my $tenv = TestEnvironment->new;\n    $tenv->build_repo($source_path);    # Make a git repo\n    $tenv->build_db();                  # Run update.py\n    $tenv->export_env;                  # Set $LXR_* environment vars\n    # Now run tests against the database in $db_path\n\nThis module creates a temporary project dir and populates it with repo and\ndata subdirs in a single project, named \"testproj\".\n\n=cut\n\npackage TestEnvironment;\n\nuse TestClass;  # Now we are a class\nuse autodie;    # note: still need to check system() calls manually\n\nuse Cwd qw(abs_path);\nuse File::Path qw(remove_tree);\nuse File::Spec;\nuse File::Temp 0.14 qw(tempdir);\nuse FindBin;\nuse IO::Select;\nuse IPC::Open3;\nuse Symbol;\n\nuse Test::More;\n\nuse TestHelpers;\n\nuse constant PROJECT => 'testproj';\n\n=head1 ATTRIBUTES\n\n=head2 lxr_proj_dir\n\nC<$lxr_proj_dir> is the value to use in the C<LXR_PROJ_DIR> environment\nvariable.\n\n=head2 lxr_data_dir\n\nC<$lxr_data_dir> is the value to use in the C<LXR_DATA_DIR> environment\nvariable.\n\n=head2 lxr_repo_dir\n\nC<$lxr_repo_dir> is the value to use in the C<LXR_REPO_DIR> environment\nvariable.\n\n=head2 script_sh\n\nThe path to C<script.sh>.  Assigned by default using\nC<TestHelpers/find_program> if not specified.\n\n=head2 query_py\n\nAs L</script_sh>, but for C<query.py>.\n\n=head2 update_py\n\nAs L</script_sh>, but for C<update.py>.\n\n=head2 web_py\n\nAs L</script_sh>, but for C<web.py>.\n\n=head2 find_doc\n\nAs L</script_sh>, but for C<find-file-doc-comments.pl>.\n\n=cut\n\nhas lxr_proj_dir => ();\nhas lxr_data_dir => ();\nhas lxr_repo_dir => ();\nhas script_sh => (\n    default => sub { find_program('script.sh') }\n);\nhas query_py => (\n    default => sub { find_program('query.py') }\n);\nhas update_py => (\n    default => sub { find_program('update.py') }\n);\nhas web_py => (\n    default => sub { find_program(qw(http web.py)) }\n);\nhas find_doc => (\n    default => sub { find_program('find-file-doc-comments.pl') }\n);\n\n# Internal attributes\n\n# a variable representing the temporary project directory.\n# When this goes out of scope, the directory will be removed.\nhas _proj_dir_token => ();\n\n=head1 MEMBER FUNCTIONS\n\n=head2 build_repo\n\nCreate a Git repo and tag it.  Usage:\n\n    $tenv->build_repo($source_tree_dir);\n\nC<$source_tree_dir> is the directory holding the tree of source files\nyou want to index.\n\nDies on error.  On success, returns the instance, for chaining.\n\n=cut\n\nsub build_repo {\n    my ($self, $tree_src_dir) = @_;\n    die \"Incorrect parameters\" unless @_==2 && ref $self && $tree_src_dir;\n    die \"Need a source dir\" unless $tree_src_dir;\n    die \"No repo dir\" unless $self->lxr_repo_dir;\n\n\n    my $tempdir_path = $self->lxr_repo_dir;\n    my @gitopts = (\n        '-C', $tempdir_path,\n        '-c', 'init.defaultBranch=main',\n        '-c', 'user.name=test@example.com',\n        '-c', 'user.email=test');\n\n    diag \"Using temporary directory $tempdir_path\";\n    run_program('git', @gitopts, 'init', $tempdir_path) or die(\"git init failed\");\n\n    run_program('sh', '-c', \"tar cf - -C \\\"$tree_src_dir\\\" . | tar xf - -C \\\"$tempdir_path\\\"\")\n        or die(\"Could not copy files into $tempdir_path\");\n\n    run_program('sh', '-c', \"chown -R `whoami`:`id -ng` \\\"$tempdir_path\\\"\");\n    run_program('sh', '-c', \"chmod -R 775 \\\"$tempdir_path\\\"\");\n\n    run_program('git', @gitopts, 'add', '.') or die(\"git add failed\");\n    run_program('git', @gitopts, 'commit', '-am', 'Initial commit')\n        or die(\"git commit failed\");\n    run_program('git', @gitopts, 'tag', 'v5.4') or die(\"git tag failed\");\n\n    return $self;\n} #build_repo()\n\n=head2 build_db\n\nBuild a test database for the repository.  L</lxr_repo_dir> must be set\nbefore calling this.  Usage:\n\n    $tenv->build_db()\n\nDies on error.  On success, returns the instance, for chaining.\n\nB<CAUTION>: This function will remove the contents of C<< $tenv->lxr_data_dir >>\nunconditionally.\n\n=cut\n\nsub build_db {\n    my $self = shift;\n    die \"No parameters allowed\" if @_;\n    die \"No repo dir\" unless $self->lxr_repo_dir;\n    die \"No data dir\" unless $self->lxr_data_dir;\n    my $db_dir = $self->lxr_data_dir;\n\n    if(-e $db_dir) {   # Remove any existing DB dir\n        remove_tree($db_dir);\n        mkdir($db_dir) or die \"Could not create fresh $db_dir\";\n    }\n\n    local $ENV{LXR_REPO_DIR} = $self->lxr_repo_dir;\n    local $ENV{LXR_DATA_DIR} = $db_dir;\n\n    run_program($self->update_py)\n        or die \"Could not create database from $ENV{LXR_REPO_DIR} in $ENV{LXR_DATA_DIR}\";\n\n    return $self;\n} #build_db()\n\n=head2 update_env\n\nSet the C<LXR_PROJ_DIR>, C<LXR_REPO_DIR>, and C<LXR_DATA_DIR> environment\nvariables.  Will not set a variable if the corresponding member does not have\na value.\n\nReturns the instance, for chaining.\n\n=cut\n\nsub update_env {\n    my $self = shift;\n    $ENV{LXR_PROJ_DIR} = $self->lxr_proj_dir if $self->lxr_proj_dir;\n    $ENV{LXR_REPO_DIR} = $self->lxr_repo_dir if $self->lxr_repo_dir;\n    $ENV{LXR_DATA_DIR} = $self->lxr_data_dir if $self->lxr_data_dir;\n    return $self;\n} #update_env()\n\n=head2 report\n\nReturns a human-readable report of the current environment's state.\n\n=cut\n\nsub report {\n    my $self = shift;\n    return <<EOT;\nProject:    @{[$self->lxr_proj_dir || '<unknown>']}\nRepository: @{[$self->lxr_repo_dir || '<unknown>']}\nDatabase:   @{[$self->lxr_data_dir || '<unknown>']}\nscript.sh:  @{[$self->script_sh || '<unknown>']}\nupdate.py:  @{[$self->update_py || '<unknown>']}\nquery.py:   @{[$self->query_py || '<unknown>']}\nweb.py:     @{[$self->web_py || '<unknown>']}\nfind-file-doc-comments.pl: @{[$self->find_doc || '<unknown>']}\nEOT\n} #report()\n\n=head2 make_web_request\n\nRequest a URL from L</web_py>.  Usage:\n\n    my $html = $tenv->make_web_request($url);\n        # Returns the HTML from stdout, or dies\n\n    my ($exit_status, $lrStdout, $lrStderr) = $tenv->make_web_request($url);\n        # Returns the shell exit status, stdout text, and stderr text.\n\nSee L<TestEnvironment/run_program> for the details of the return values\nin the second case.\n\n=cut\n\nsub make_web_request {\n    my ($self, $url) = @_;\n\n    $self->update_env;  # just in case\n\n    local $ENV{REQUEST_URI} = $url;\n    diag \"Requesting `$url'\";\n    my ($exit_status, $lrStdout, $lrStderr) = run_program($self->web_py);\n\n    if(!wantarray) {\n        return $lrStdout;\n    } else {\n        return ($exit_status, $lrStdout, $lrStderr);\n    }\n} #make_web_request()\n\n=head2 BUILD\n\nConstructor.  Creates the temporary project dir.\n\n=cut\n\nsub BUILD {\n    my $self = shift;\n\n    my $temp_proj_dir = tempdir(CLEANUP => 1);\n    my $proj_dir = abs_path($temp_proj_dir);\n\n    # Make the directory structure\n    mkdir File::Spec->catdir($proj_dir, PROJECT);\n    my $data_dir = File::Spec->catdir($proj_dir, PROJECT, 'data');\n    my $repo_dir = File::Spec->catdir($proj_dir, PROJECT, 'repo');\n    mkdir $data_dir;\n    mkdir $repo_dir;\n\n    # Save the paths\n    $self->_proj_dir_token($temp_proj_dir);\n    $self->lxr_proj_dir($proj_dir);\n    $self->lxr_data_dir($data_dir);\n    $self->lxr_repo_dir($repo_dir);\n} #BUILD()\n\n=head2 DESTROY\n\nDestructor.  Called automatically.\n\n=cut\n\nsub DESTROY {\n    local($., $@, $!, $^E, $?);\n    my $self = shift;\n\n    # Release the temporary directories\n    $self->_proj_dir_token(undef);\n} #DESTROY()\n\n1;\n__END__\n\n\n=head1 AUTHOR\n\nChristopher White, C<< <cwhite@d3engineering.com> >>\n\n=head1 COPYRIGHT\n\nCopyright (c) 2020 D3 Engineering, LLC.\n\nElixir is free software; you can redistribute it and/or modify\nit under the terms of the GNU Affero General Public License as published by\nthe Free Software Foundation, either version 3 of the License, or\n(at your option) any later version.\n\nElixir is distributed in the hope that it will be useful,\nbut WITHOUT ANY WARRANTY; without even the implied warranty of\nMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\nGNU Affero General Public License for more details.\n\nYou should have received a copy of the GNU Affero General Public License\nalong with Elixir.  If not, see <http://www.gnu.org/licenses/>.\n\n=cut\n"
  },
  {
    "path": "t/TestHelpers.pm",
    "content": "#!/usr/bin/env perl\n# TestHelpers.pm: Common routines for use in tests.\n# See license information at end of file.\n#\n# For a cleaner view of the documentation, run\n#   perldoc TestHelpers.pm\n# (on Ubuntu, you may need to install the perl-doc package first.)\n#\n# SPDX-License-Identifier: AGPL-3.0-or-later\n#\n# This file uses core Perl modules only.\n\n=head1 NAME\n\nTestHelpers - Common routines for use in tests\n\n=head1 SYNOPSIS\n\nC<use TestHelpers;>, and all the functions below will be exported.\nTestHelpers also turns on L<strict> and L<warnings>.\n\n=cut\n\npackage TestHelpers;\n\nuse strict;\nuse warnings;\nuse autodie;    # note: still need to check system() calls manually\n\nuse Cwd qw(abs_path);\nuse File::Spec;\nuse File::Temp 0.14 qw(tempdir);\nuse FindBin;\nuse IO::Select;\nuse IPC::Open3;\nuse Symbol;\n\nuse Test::More;\n\n# Automatically export all the functions listed in @EXPORT.  The functions\n# in @EXPORT_OK can be exported on request.\nuse parent 'Exporter';\nour (@EXPORT, @EXPORT_OK, %EXPORT_TAGS);\nBEGIN {\n    @EXPORT = qw(sibling_abs_path find_program run_program ok_or_die\n                run_produces_ok http_request_ok MUST_SUCCEED);\n    @EXPORT_OK = qw(line_mark_string);\n    %EXPORT_TAGS = (\n        all => [@EXPORT, @EXPORT_OK],\n    );\n} #BEGIN\n\n# Forwards for internal functions\nsub line_mark_string;\n\n# ===========================================================================\n\n=head1 CONSTANTS\n\n=head2 MUST_SUCCEED\n\nTrue.  So that calls to L</run_produces_ok> will be more self-explanatory.\n\n=cut\n\nuse constant MUST_SUCCEED => !!1;\n\n=head1 FUNCTIONS\n\nThese are helper routines that generally perform specific tasks.\n\n=head2 sibling_abs_path\n\nReturn the absolute path of a file or directory in the same directory as\nthis file.  Usage:\n\n    $path = sibling_abs_path('name');\n\n=cut\n\nsub sibling_abs_path {\n    return File::Spec->rel2abs(File::Spec->catfile($FindBin::Bin, @_));\n} #sibling_abs_path()\n\n=head2 find_program\n\nLooks for a program in the parent directory of this script.\nUsage:\n\n    $path = find_program(['subdir', ]'program name')\n\n=cut\n\nsub find_program {\n    my $pgm_file = pop;  # Last arg\n    my @pgm_dirs = @_;  # Any args before the last are additional dirs.\n\n    my ($my_vol, $my_dirs, undef) = File::Spec->splitpath($FindBin::Bin, 1);   # 1 => is a dir\n\n    # Go up to the parent of the directory holding this file\n    my @my_dirs = File::Spec->splitdir($my_dirs);\n    die \"Cannot run from the root directory\" unless @my_dirs >= 2;\n    pop @my_dirs;\n    my $dest_dirs = File::Spec->catdir(@my_dirs, @pgm_dirs);\n\n    return File::Spec->catpath($my_vol, $dest_dirs, $pgm_file);\n} #find_program()\n\n=head2 run_program\n\nPrint a command, then run it.  Can be used three ways:\n\n=over\n\n=item In void context\n\nReturns if system() and the command succeed, dies otherwise.  Usage:\n\n    run_program('program', 'arg1', ...);\n\n=item In scalar context\n\nReturns true if system() and the command succeed, false otherwise.  Usage:\n\n    my $ok = run_program('program', 'arg1', ...);\n\n=item In list context\n\nReturns the exit status, stdout, and stderr.  Usage:\n\n    my ($exit_status, $lrStdout, $lrStderr) = run_program('program', 'arg1', ...);\n        # Returns the shell exit status, stdout text, and stderr text.\n\nC<$lrStdout> and C<$lrStderr> are references to the lists of output lines\non the respective handles.\n\nC<$exit_status> is C<128+signal> if the process was killed by C<signal>,\nfor consistency with bash (L<https://tldp.org/LDP/abs/html/exitcodes.html>).\n\n=back\n\n=cut\n\nsub _run_and_capture;   # forward\nsub _check_queries;     # forward\n\nsub run_program {\n\n    if(wantarray) {\n        goto &_run_and_capture;\n    }\n\n    my $errmsg;\n\n    diag \"Running @_\";\n    my $status = system(@_);\n\n    if ($status == -1) {\n        $errmsg = \"failed to execute $_[0]: $!\";\n    }\n    elsif ($status & 127) {\n        $errmsg = sprintf \"$_[0] died with signal %d, %s coredump\\n\",\n            ($status & 127),  ($status & 128) ? 'with' : 'without';\n    }\n    elsif($status != 0) {\n        $errmsg = sprintf \"$_[0] exited with value %d\\n\", $status >> 8;\n    }\n    else {\n        diag \"$_[0] reported success\";\n    }\n\n    if($errmsg) {\n        die $errmsg unless defined wantarray;\n        diag $errmsg;\n    }\n\n    return($status == 0);\n} #run_program()\n\n=head2 ok_or_die\n\nRun a test, but die if it fails.  Usage:\n\n    ok_or_die( <some condition>, 'description', 'what to print if it dies' )\n\n=cut\n\nsub ok_or_die {\n    my ($cond, $msg, $err_msg) = @_;\n    my (undef, $filename, $line) = caller;\n    my $retval = eval line_mark_string 1, <<EOT;    # Make the error message report the caller's line number\n    ok(\\$cond, \\$msg);\nEOT\n    die($err_msg) unless $retval;\n    return $retval;\n} #ok_or_die()\n\n=head2 run_produces_ok\n\nRun a program and check whether it produces expected output.\nUsage:\n\n    run_produces_ok($desc, \\@program_and_args, \\@conditions,\n                    <optional> $mustSucceed, <optional> $printOutput)\n\nThe test passes if each condition in C<@conditions> is true.\nIf C<$mustSucceed> is true, also tests for exit status 0 and empty stderr.\nIf C<$printOutput> is true, prints the output of C<@program_and_args>.\n\n=head3 Conditions that can be used any time\n\n=over\n\n=item *\n\nA regex: true if the regex matches at least one line in the output of\nC<@program_and_args>\n\n=item *\n\nC<< { not => regex } >>: true if the regex is NOT found in any line of\nthe output of C<@program_and_args>.\n\n=back\n\n=head3 Conditions for the output of C<query.py>\n\n=over\n\n=item *\n\nC<< { def => regex } >>: true if the regex matches at least one line in\nthe \"Symbol Definitions\" section of the output of C<@program_and_args>.\n\n=item *\n\nC<< { ref => regex } >>: true if the regex matches at least one line in\nthe \"Symbol References\" section of the output of C<@program_and_args>.\n\n=item *\n\nC<< { doc => regex } >>: true if the regex matches at least one line in\nthe \"Documented in\" section of the output of C<@program_and_args>.\n\n=back\n\n=cut\n\n# _run_and_capture: run a program and return its exit status and output.\n# Usage:\n#   my ($exit_status, \\@stdout, \\@stderr) = run_program('program', 'arg1', ...);\n\nsub _run_and_capture {\n    my ($in , $out, $err);      # Filehandles\n    $err = Symbol::gensym;\n\n    diag \"Running @_\";\n    my $pid = open3($in, $out, $err, @_);\n\n    my (@outlines, @errlines);  # Captured output\n    my $s = IO::Select->new;\n    $s->add($out);\n    $s->add($err);\n\n    while(my @ready = $s->can_read) {\n        for my $fh (@ready) {\n\n            if(eof($fh)) {\n                $s->remove($fh);\n                next;\n            }\n\n            if($fh == $out) {\n                push @outlines, scalar readline $fh;\n            } else {\n                push @errlines, scalar readline $fh;\n            }\n        }\n    }\n\n    waitpid $pid, 0;\n    my $exit_status = $?;\n\n    $exit_status = ($exit_status & 127) + 128 if $exit_status & 127;   # Killed by signal\n\n    return ($exit_status, \\@outlines, \\@errlines);\n} #_run_and_capture()\n\nsub run_produces_ok {\n    my ($desc, $lrProgram, $lrConditions, $mustSucceed, $printOutput) = @_;\n\n    my ($exit_status, $outlines, $errlines) = _run_and_capture(@$lrProgram);\n\n    _check_queries($desc, $lrConditions, $mustSucceed, $printOutput, $exit_status, $outlines, $errlines);\n} #run_produces_ok()\n\nsub _check_queries {\n    my ($desc, $lrConditions, $mustSucceed, $printOutput, $exit_status, $lrStdout, $lrStderr) = @_;\n\n    my @outlines = @$lrStdout;\n    my @errlines = @$lrStderr;\n\n    if ($printOutput) {\n        diag \"@outlines\";\n    }\n\n    # Check for and report Python errors\n    foreach(@outlines, @errlines) {\n        if (/^.*?(\\S+)\\s+contains the description of this error/) {\n            my $logfn = $1;\n\n            no autodie;\n            open my $logfh, '<', $logfn\n                or warn(\"Could not open Python log file $logfn: $!\"), last;\n            my $logtext = do { local $/; <$logfh> };\n            close $logfh;\n\n            diag \"Python error log $logfn:\\n$logtext\";\n            last;\n        }\n    }\n\n    # Basic checks\n    if($mustSucceed) {\n        eval line_mark_string 2, <<'EOT';\n        cmp_ok($exit_status, '==', 0, \"$desc: exit status 0\");\n        cmp_ok(@errlines, '==', 0, \"$desc: stderr empty\");\nEOT\n        die $@ if $@;\n    }\n\n    # Check regexes\n    my %query_py_output;    # filled in only if we see a def/ref/doc\n    for my $entry (@$lrConditions) {\n        my ($re, $negated, $source) = _parse_condition($entry);\n\n        # Parse query.py output if we need it and haven't done so\n        %query_py_output = _parseq(@outlines)\n            if $source ne 'output' && !%query_py_output;\n\n        # Build a line of test code to run\n        my $test = 'ok( ';\n        $test .= '!' if $negated;\n        $test .= '(grep { m{$re} } ';\n        if($source eq 'output') {\n            $test .= '@outlines';\n        } else {\n            $test .= '@{$query_py_output{' . $source . '}}';\n        }\n        $test .= '), \"$desc: ' . $source;\n        $test .= ($negated ? ' excludes ' : ' includes ') . \"\\Q$re\\E\" . '\");';\n\n        # Run it\n        eval line_mark_string 2, $test;\n        die $@ if $@;\n    } #foreach $entry\n\n} #run_produces_ok()\n\n=head2 http_request_ok\n\nRun C<web.py> against a given path and check whether it produces expected\noutput.  Usage:\n\n    http_request_ok($desc, $tenv, $path, \\@conditions, <optional> $printOutput)\n\nThe test passes if the HTTP request succeeds, and if each condition in\nC<@conditions> is true of the result (headers and body).\n\nC<$tenv> is a L<TestEnvironment>.\n\nC<$path> is the path part of the URL, e.g., C</testproj/latest/source>.\n\nSee L</run_produces_ok> for C<@conditions>.\n\nIf C<$printOutput> is true, prints the output of C<@program_and_args>.\n\n=cut\n\nsub http_request_ok {\n    my ($desc, $tenv, $path, $lrConditions, $printOutput) = @_;\n    die \"Invalid args\" unless $desc && ref $tenv && eval { @$lrConditions };\n\n    my ($exit_status, $lrStdout, $lrStderr) = $tenv->make_web_request($path);\n\n    _check_queries($desc, $lrConditions, MUST_SUCCEED, $printOutput,\n        $exit_status, $lrStdout, $lrStderr);\n} #http_request_ok()\n\n=head1 INTERNAL FUNCTIONS\n\nThese are ones you probably won't need to call.\n\n=head2 _parseq\n\nParse the output of query.py.  Usage:\n\n    %parsed = _parseq(@lines_of_output);\n\n=cut\n\nsub _parseq {\n    my %retval = ( def => [], ref => [], doc => [] );\n    my $list;\n    foreach(@_) {\n        chomp;\n        if(/(?:^Symbol Definitions:$)|\\bDefined in \\d+/) {\n            $list = 'def';\n            next;\n        } elsif(/(?:^Symbol References:$)|\\bReferenced in \\d+/) {\n            $list = 'ref';\n            next;\n        } elsif(/(?:^Documented in:$)|\\bDocumented in \\d+/) {\n            $list = 'doc';\n            next;\n        }\n        next unless $list;\n\n        #diag \"Adding `$_' to list $list\";\n        push @{$retval{$list}}, $_;\n    }\n    return %retval;\n} #_parseq()\n\n=head2 _parse_condition\n\nParse a condition for L</run_produces_ok>.  Usage:\n\n    ($regex, $negated, $source) = _parse_condition($entry[, $source]);\n\n=cut\n\nsub _parse_condition {\n    my ($entry, $source_in) = @_;\n    my ($regex, $negated, $source);     # Return values\n\n    # Basic cases\n    if(ref $entry eq 'Regexp') {\n        return ($entry, 0, $source_in || 'output');\n    } elsif(ref $entry eq 'HASH' && ref $entry->{not} eq 'Regexp') {\n        return ($entry->{not}, 1, $source_in || 'output');\n    }\n\n    # Sub-keys: chain\n    if(ref $entry eq 'HASH' && scalar keys %{$entry} == 1) {\n        return _parse_condition((values %{$entry})[0], (keys %{$entry})[0]);\n    }\n\n    # If we get here, we don't know how to handle it\n    die \"Invalid entry $entry\";\n} #_parse_condition()\n\n\n=head2 _croak\n\nLazy invoker for L<Carp/croak>.\n\n=cut\n\nsub _croak {\n    require Carp;\n    goto &Carp::croak;\n} #_croak()\n\n=head2 line_mark_string\n\nAdd a C<#line> directive to a string.  Usage:\n\nTo use the caller's filename and line number:\n\n    my $str = line_mark_string <<EOT ;\n    $contents\n    EOT\n\nTo use a filename and line number from higher in the call stack:\n\n    my $str = line_mark_string $level, <<EOT ;\n    $contents\n    EOT\n\nTo use a specified filename and line number:\n\n    my $str = line_mark_string __FILE__, __LINE__, <<EOT ;\n    $contents\n    EOT\n\nIn the first and second forms, information from C<caller> will be used for the\nfilename and line number.\n\nIn the first and third forms, the C<#line> directive will point to the line\nafter the C<line_mark_string> invocation, i.e., the first line of <C$contents>.\nGenerally, C<$contents> will be source code, although this is not required.\n\nC<$contents> must be defined, but can be empty.\n\n=cut\n\nsub line_mark_string {\n    my ($contents, $filename, $line);\n\n    if(@_ == 1) {\n        $contents = $_[0];\n        (undef, $filename, $line) = caller;\n        ++$line;\n    } elsif(@_ == 2) {\n        (undef, $filename, $line) = caller($_[0]);\n        $contents = $_[1];\n    } elsif(@_ == 3) {\n        ($filename, $line, $contents) = @_;\n        ++$line;\n    } else {\n        _croak \"Invalid invocation\";\n    }\n\n    _croak \"Need text\" unless defined $contents;\n    die \"Couldn't get location information\" unless $filename && $line;\n\n    $filename =~ s/\"/-/g;\n\n    return <<EOT;\n#line $line \"$filename\"\n$contents\nEOT\n} #line_mark_string()\n\n=head2 import\n\nSet up.  Called automatically.  Activates L<strict> and L<warnings>\nin the caller.\n\n=cut\n\nsub import {\n    __PACKAGE__->export_to_level(1, @_);\n    strict->import;\n    warnings->import;\n} #import()\n\n1;\n__END__\n\n=head1 AUTHOR\n\nChristopher White, C<< <cwhite@d3engineering.com> >>\n\n=head1 COPYRIGHT\n\nCopyright (c) 2020 D3 Engineering, LLC.\n\nElixir is free software; you can redistribute it and/or modify\nit under the terms of the GNU Affero General Public License as published by\nthe Free Software Foundation, either version 3 of the License, or\n(at your option) any later version.\n\nElixir is distributed in the hope that it will be useful,\nbut WITHOUT ANY WARRANTY; without even the implied warranty of\nMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\nGNU Affero General Public License for more details.\n\nYou should have received a copy of the GNU Affero General Public License\nalong with Elixir.  If not, see <http://www.gnu.org/licenses/>.\n\n=cut\n"
  },
  {
    "path": "t/api_test.py",
    "content": "#!/usr/bin/env python3\n\n#  This file is part of Elixir, a source code cross-referencer.\n#\n#  Copyright (C) 2020 Carmeli Tamir and contributors\n#\n#  Elixir is free software: you can redistribute it and/or modify\n#  it under the terms of the GNU Affero General Public License as published by\n#  the Free Software Foundation, either version 3 of the License, or\n#  (at your option) any later version.\n#\n#  Elixir is distributed in the hope that it will be useful,\n#  but WITHOUT ANY WARRANTY; without even the implied warranty of\n#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n#  GNU Affero General Public License for more details.\n#\n#  You should have received a copy of the GNU Affero General Public License\n#  along with Elixir.  If not, see <http://www.gnu.org/licenses/>.\n\nimport os\nimport sys\n\nimport falcon\nfrom falcon import testing\n\napi_dir = os.path.abspath(os.path.join(os.path.dirname(os.path.realpath(__file__)), '..','api'))\nsys.path.insert(0, api_dir)\n\nfrom api import create_ident_getter\n\nclass APITest(testing.TestCase):\n    def setUp(self):\n        super(APITest, self).setUp()\n\n        self.app = create_ident_getter()\n\n    def test_identifier_not_found(self):\n        result = self.simulate_get('/ident/testproj/SOME_NONEXISTENT_IDENTIFIER', query_string=\"version=latest&family=C\")\n\n        self.assertEqual(result.status_code, 200)\n        self.assertEqual(result.json, {'definitions': [], 'references':[], 'documentations': []})\n\n    def test_missing_version(self):\n        # A get request without a version query string\n        result = self.simulate_get('/ident/testproj/of_i2c_get_board_info', query_string=\"\")\n\n        self.assertEqual(result.status_code, 400)\n\n        required_response = falcon.HTTPMissingParam('version')\n        self.assertEqual(result.json[\"title\"], required_response.title)\n        self.assertEqual(result.json[\"description\"], required_response.description)\n\n    def test_existing_identifier(self):\n        result_for_specific_version = self.simulate_get('/ident/testproj/of_i2c_get_board_info', query_string=\"version=v5.4&family=C\")\n        result_for_latest_version = self.simulate_get('/ident/testproj/of_i2c_get_board_info', query_string=\"version=latest&family=C\")\n\n        expected_json = {\n            'definitions':\n            [\n                {'path': 'include/linux/i2c.h', 'line': 941, 'type': 'prototype'},\n                {'path': 'drivers/i2c/i2c-core-of.c', 'line': 22, 'type': 'function'},\n                {'path': 'include/linux/i2c.h', 'line': 968, 'type': 'function'}\n            ],\n            'references':\n                [\n                    {'path': 'drivers/i2c/i2c-core-of.c', 'line': '62,73', 'type': None}\n                ],\n                'documentations': []\n            }\n\n        self.assertEqual(result_for_specific_version.status_code, 200)\n        self.assertEqual(result_for_latest_version.status_code, 200)\n\n        self.assertEqual(result_for_specific_version.json, expected_json)\n        self.assertEqual(result_for_latest_version.json, expected_json)\n"
  },
  {
    "path": "t/interact.pl",
    "content": "#!/usr/bin/env perl\n# t/interact.pl: Open a shell on a DB of the files in tree/ .\n#\n# Copyright (c) 2020 Christopher White, <cxwembedded@gmail.com>.\n#\n# Elixir is free software; you can redistribute it and/or modify\n# it under the terms of the GNU Affero General Public License as published by\n# the Free Software Foundation, either version 3 of the License, or\n# (at your option) any later version.\n#\n# Elixir is distributed in the hope that it will be useful,\n# but WITHOUT ANY WARRANTY; without even the implied warranty of\n# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n# GNU Affero General Public License for more details.\n# # You should have received a copy of the GNU Affero General Public License\n# along with Elixir.  If not, see <http://www.gnu.org/licenses/>.\n#\n# SPDX-License-Identifier: AGPL-3.0-or-later\n#\n# This file uses core Perl modules only.\n\nuse FindBin '$Bin';\nuse lib $Bin;\n\nuse Cwd;\nuse TestEnvironment;\nuse TestHelpers;\n\n# ===========================================================================\n# Main\n\nmy $pwd = getcwd;\n\n# This block is all that's required to set up for a test.\nmy $tenv = TestEnvironment->new;\n$tenv->build_repo(sibling_abs_path('tree'));\t# dies on error\neval { $tenv->build_db; };\nwarn \"Could not update database: $@\" if $@;\n$tenv->update_env;\n\nprint($tenv->report);\n\n# Make some convenient symlinks\nchdir($tenv->lxr_repo_dir);\nsystem(qw(ln -s), $tenv->script_sh, 'script.sh') == 0\n    or warn \"error creating ./script.sh: $? $!\";\nsystem(qw(ln -s), $tenv->update_py, 'update.py') == 0\n    or warn \"error creating ./update.py: $? $!\";\nsystem(qw(ln -s), $tenv->query_py, 'query.py') == 0\n    or warn \"error creating ./query.py: $? $!\";\nsystem(qw(ln -s), $tenv->web_py, 'web.py') == 0\n    or warn \"error creating ./web.py: $? $!\";\nsystem(qw(ln -s), $tenv->find_doc, 'find-file-doc-comments.pl') == 0\n    or warn \"error creating ./find-file-doc-comments.pl: $? $!\";\n\nprint(\"Exit when done, and the repository and database will be removed.\\n\");\nmy $retval = system($ENV{SHELL} || 'sh');\n\n# Don't stay in the temp dir --- the dir can't be removed if we are there.\nchdir $pwd;\n\nexit $retval>>8;\n"
  },
  {
    "path": "t/tree/arch/arm/xen/hypercall.S",
    "content": "/******************************************************************************\n * hypercall.S\n *\n * Xen hypercall wrappers\n *\n * Stefano Stabellini <stefano.stabellini@eu.citrix.com>, Citrix, 2012\n *\n * This program is free software; you can redistribute it and/or\n * modify it under the terms of the GNU General Public License version 2\n * as published by the Free Software Foundation; or, when distributed\n * separately from the Linux kernel or incorporated into other\n * software packages, subject to the following license:\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this source file (the \"Software\"), to deal in the Software without\n * restriction, including without limitation the rights to use, copy, modify,\n * merge, publish, distribute, sublicense, and/or sell copies of the Software,\n * and to permit persons to whom the Software is furnished to do so, subject to\n * the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\n/*\n * The Xen hypercall calling convention is very similar to the ARM\n * procedure calling convention: the first paramter is passed in r0, the\n * second in r1, the third in r2 and the fourth in r3. Considering that\n * Xen hypercalls have 5 arguments at most, the fifth paramter is passed\n * in r4, differently from the procedure calling convention of using the\n * stack for that case.\n *\n * The hypercall number is passed in r12.\n *\n * The return value is in r0.\n *\n * The hvc ISS is required to be 0xEA1, that is the Xen specific ARM\n * hypercall tag.\n */\n\n#include <linux/linkage.h>\n#include <asm/assembler.h>\n#include <asm/opcodes-virt.h>\n#include <xen/interface/xen.h>\n\n\n#define XEN_IMM 0xEA1\n\n#define HYPERCALL_SIMPLE(hypercall)\t\t\\\nENTRY(HYPERVISOR_##hypercall)\t\t\t\\\n\tmov r12, #__HYPERVISOR_##hypercall;\t\\\n\t__HVC(XEN_IMM);\t\t\t\t\t\t\\\n\tret lr;\t\t\t\t\t\\\nENDPROC(HYPERVISOR_##hypercall)\n\n#define HYPERCALL0 HYPERCALL_SIMPLE\n#define HYPERCALL1 HYPERCALL_SIMPLE\n#define HYPERCALL2 HYPERCALL_SIMPLE\n#define HYPERCALL3 HYPERCALL_SIMPLE\n#define HYPERCALL4 HYPERCALL_SIMPLE\n\n#define HYPERCALL5(hypercall)\t\t\t\\\nENTRY(HYPERVISOR_##hypercall)\t\t\t\\\n\tstmdb sp!, {r4}\t\t\t\t\t\t\\\n\tldr r4, [sp, #4]\t\t\t\t\t\\\n\tmov r12, #__HYPERVISOR_##hypercall;\t\\\n\t__HVC(XEN_IMM);\t\t\t\t\t\t\\\n\tldm sp!, {r4}\t\t\t\t\t\t\\\n\tret lr\t\t\t\t\t\\\nENDPROC(HYPERVISOR_##hypercall)\n\n                .text\n\nHYPERCALL2(xen_version);\nHYPERCALL3(console_io);\nHYPERCALL3(grant_table_op);\nHYPERCALL2(sched_op);\nHYPERCALL2(event_channel_op);\nHYPERCALL2(hvm_op);\nHYPERCALL2(memory_op);\nHYPERCALL2(physdev_op);\nHYPERCALL3(vcpu_op);\nHYPERCALL1(tmem_op);\nHYPERCALL1(platform_op_raw);\nHYPERCALL2(multicall);\nHYPERCALL2(vm_assist);\nHYPERCALL3(dm_op);\n\nENTRY(privcmd_call)\n\tstmdb sp!, {r4}\n\tmov r12, r0\n\tmov r0, r1\n\tmov r1, r2\n\tmov r2, r3\n\tldr r3, [sp, #8]\n\t/*\n\t * Privcmd calls are issued by the userspace. We need to allow the\n\t * kernel to access the userspace memory before issuing the hypercall.\n\t */\n\tuaccess_enable r4\n\n\t/* r4 is loaded now as we use it as scratch register before */\n\tldr r4, [sp, #4]\n\t__HVC(XEN_IMM)\n\n\t/*\n\t * Disable userspace access from kernel. This is fine to do it\n\t * unconditionally as no set_fs(KERNEL_DS) is called before.\n\t */\n\tuaccess_disable r4\n\n\tldm sp!, {r4}\n\tret lr\nENDPROC(privcmd_call);"
  },
  {
    "path": "t/tree/arch/x86/include/asm/acpi.h",
    "content": "/* SPDX-License-Identifier: GPL-2.0-or-later */\n#ifndef _ASM_X86_ACPI_H\n#define _ASM_X86_ACPI_H\n\n/*\n *  Copyright (C) 2001 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>\n *  Copyright (C) 2001 Patrick Mochel <mochel@osdl.org>\n */\n#include <acpi/pdc_intel.h>\n\n#include <asm/numa.h>\n#include <asm/fixmap.h>\n#include <asm/processor.h>\n#include <asm/mmu.h>\n#include <asm/mpspec.h>\n#include <asm/realmode.h>\n#include <asm/x86_init.h>\n\n#ifdef CONFIG_ACPI_APEI\n# include <asm/pgtable_types.h>\n#endif\n\n#ifdef CONFIG_ACPI\nextern int acpi_lapic;\nextern int acpi_ioapic;\nextern int acpi_noirq;\nextern int acpi_strict;\nextern int acpi_disabled;\nextern int acpi_pci_disabled;\nextern int acpi_skip_timer_override;\nextern int acpi_use_timer_override;\nextern int acpi_fix_pin2_polarity;\nextern int acpi_disable_cmcff;\n\nextern u8 acpi_sci_flags;\nextern u32 acpi_sci_override_gsi;\nvoid acpi_pic_sci_set_trigger(unsigned int, u16);\n\nstruct device;\n\nextern int (*__acpi_register_gsi)(struct device *dev, u32 gsi,\n\t\t\t\t  int trigger, int polarity);\nextern void (*__acpi_unregister_gsi)(u32 gsi);\n\nstatic inline void disable_acpi(void)\n{\n\tacpi_disabled = 1;\n\tacpi_pci_disabled = 1;\n\tacpi_noirq = 1;\n}\n\nextern int acpi_gsi_to_irq(u32 gsi, unsigned int *irq);\n\nstatic inline void acpi_noirq_set(void) { acpi_noirq = 1; }\nstatic inline void acpi_disable_pci(void)\n{\n\tacpi_pci_disabled = 1;\n\tacpi_noirq_set();\n}\n\n/* Low-level suspend routine. */\nextern int (*acpi_suspend_lowlevel)(void);\n\n/* Physical address to resume after wakeup */\n#define acpi_wakeup_address ((unsigned long)(real_mode_header->wakeup_start))\n\n/*\n * Check if the CPU can handle C2 and deeper\n */\nstatic inline unsigned int acpi_processor_cstate_check(unsigned int max_cstate)\n{\n\t/*\n\t * Early models (<=5) of AMD Opterons are not supposed to go into\n\t * C2 state.\n\t *\n\t * Steppings 0x0A and later are good\n\t */\n\tif (boot_cpu_data.x86 == 0x0F &&\n\t    boot_cpu_data.x86_vendor == X86_VENDOR_AMD &&\n\t    boot_cpu_data.x86_model <= 0x05 &&\n\t    boot_cpu_data.x86_stepping < 0x0A)\n\t\treturn 1;\n\telse if (boot_cpu_has(X86_BUG_AMD_APIC_C1E))\n\t\treturn 1;\n\telse\n\t\treturn max_cstate;\n}\n\nstatic inline bool arch_has_acpi_pdc(void)\n{\n\tstruct cpuinfo_x86 *c = &cpu_data(0);\n\treturn (c->x86_vendor == X86_VENDOR_INTEL ||\n\t\tc->x86_vendor == X86_VENDOR_CENTAUR);\n}\n\nstatic inline void arch_acpi_set_pdc_bits(u32 *buf)\n{\n\tstruct cpuinfo_x86 *c = &cpu_data(0);\n\n\tbuf[2] |= ACPI_PDC_C_CAPABILITY_SMP;\n\n\tif (cpu_has(c, X86_FEATURE_EST))\n\t\tbuf[2] |= ACPI_PDC_EST_CAPABILITY_SWSMP;\n\n\tif (cpu_has(c, X86_FEATURE_ACPI))\n\t\tbuf[2] |= ACPI_PDC_T_FFH;\n\n\t/*\n\t * If mwait/monitor is unsupported, C2/C3_FFH will be disabled\n\t */\n\tif (!cpu_has(c, X86_FEATURE_MWAIT))\n\t\tbuf[2] &= ~(ACPI_PDC_C_C2C3_FFH);\n}\n\nstatic inline bool acpi_has_cpu_in_madt(void)\n{\n\treturn !!acpi_lapic;\n}\n\n#define ACPI_HAVE_ARCH_SET_ROOT_POINTER\nstatic inline void acpi_arch_set_root_pointer(u64 addr)\n{\n\tx86_init.acpi.set_root_pointer(addr);\n}\n\n#define ACPI_HAVE_ARCH_GET_ROOT_POINTER\nstatic inline u64 acpi_arch_get_root_pointer(void)\n{\n\treturn x86_init.acpi.get_root_pointer();\n}\n\nvoid acpi_generic_reduced_hw_init(void);\n\nvoid x86_default_set_root_pointer(u64 addr);\nu64 x86_default_get_root_pointer(void);\n\n#else /* !CONFIG_ACPI */\n\n#define acpi_lapic 0\n#define acpi_ioapic 0\n#define acpi_disable_cmcff 0\nstatic inline void acpi_noirq_set(void) { }\nstatic inline void acpi_disable_pci(void) { }\nstatic inline void disable_acpi(void) { }\n\nstatic inline void acpi_generic_reduced_hw_init(void) { }\n\nstatic inline void x86_default_set_root_pointer(u64 addr) { }\n\nstatic inline u64 x86_default_get_root_pointer(void)\n{\n\treturn 0;\n}\n\n#endif /* !CONFIG_ACPI */\n\n#define ARCH_HAS_POWER_INIT\t1\n\n#ifdef CONFIG_ACPI_NUMA\nextern int x86_acpi_numa_init(void);\n#endif /* CONFIG_ACPI_NUMA */\n\n#define acpi_unlazy_tlb(x)\tleave_mm(x)\n\n#ifdef CONFIG_ACPI_APEI\nstatic inline pgprot_t arch_apei_get_mem_attribute(phys_addr_t addr)\n{\n\t/*\n\t * We currently have no way to look up the EFI memory map\n\t * attributes for a region in a consistent way, because the\n\t * memmap is discarded after efi_free_boot_services(). So if\n\t * you call efi_mem_attributes() during boot and at runtime,\n\t * you could theoretically see different attributes.\n\t *\n\t * We are yet to see any x86 platforms that require anything\n\t * other than PAGE_KERNEL (some ARM64 platforms require the\n\t * equivalent of PAGE_KERNEL_NOCACHE). Additionally, if SME\n\t * is active, the ACPI information will not be encrypted,\n\t * so return PAGE_KERNEL_NOENC until we know differently.\n\t */\n\treturn PAGE_KERNEL_NOENC;\n}\n#endif\n\n#define ACPI_TABLE_UPGRADE_MAX_PHYS (max_low_pfn_mapped << PAGE_SHIFT)\n\n#endif /* _ASM_X86_ACPI_H */\n"
  },
  {
    "path": "t/tree/arch/x86/include/asm/ist.h",
    "content": "/* SPDX-License-Identifier: GPL-2.0-or-later */\n/*\n * Include file for the interface to IST BIOS\n * Copyright 2002 Andy Grover <andrew.grover@intel.com>\n */\n#ifndef _ASM_X86_IST_H\n#define _ASM_X86_IST_H\n\n#include <uapi/asm/ist.h>\n\n\nextern struct ist_info ist_info;\n\n#endif /* _ASM_X86_IST_H */\n"
  },
  {
    "path": "t/tree/arch/x86/include/asm/orc_types.h",
    "content": "/* SPDX-License-Identifier: GPL-2.0-or-later */\n/*\n * Copyright (C) 2017 Josh Poimboeuf <jpoimboe@redhat.com>\n */\n\n#ifndef _ORC_TYPES_H\n#define _ORC_TYPES_H\n\n#include <linux/types.h>\n#include <linux/compiler.h>\n\n/*\n * The ORC_REG_* registers are base registers which are used to find other\n * registers on the stack.\n *\n * ORC_REG_PREV_SP, also known as DWARF Call Frame Address (CFA), is the\n * address of the previous frame: the caller's SP before it called the current\n * function.\n *\n * ORC_REG_UNDEFINED means the corresponding register's value didn't change in\n * the current frame.\n *\n * The most commonly used base registers are SP and BP -- which the previous SP\n * is usually based on -- and PREV_SP and UNDEFINED -- which the previous BP is\n * usually based on.\n *\n * The rest of the base registers are needed for special cases like entry code\n * and GCC realigned stacks.\n */\n#define ORC_REG_UNDEFINED\t\t0\n#define ORC_REG_PREV_SP\t\t\t1\n#define ORC_REG_DX\t\t\t2\n#define ORC_REG_DI\t\t\t3\n#define ORC_REG_BP\t\t\t4\n#define ORC_REG_SP\t\t\t5\n#define ORC_REG_R10\t\t\t6\n#define ORC_REG_R13\t\t\t7\n#define ORC_REG_BP_INDIRECT\t\t8\n#define ORC_REG_SP_INDIRECT\t\t9\n#define ORC_REG_MAX\t\t\t15\n\n/*\n * ORC_TYPE_CALL: Indicates that sp_reg+sp_offset resolves to PREV_SP (the\n * caller's SP right before it made the call).  Used for all callable\n * functions, i.e. all C code and all callable asm functions.\n *\n * ORC_TYPE_REGS: Used in entry code to indicate that sp_reg+sp_offset points\n * to a fully populated pt_regs from a syscall, interrupt, or exception.\n *\n * ORC_TYPE_REGS_IRET: Used in entry code to indicate that sp_reg+sp_offset\n * points to the iret return frame.\n *\n * The UNWIND_HINT macros are used only for the unwind_hint struct.  They\n * aren't used in struct orc_entry due to size and complexity constraints.\n * Objtool converts them to real types when it converts the hints to orc\n * entries.\n */\n#define ORC_TYPE_CALL\t\t\t0\n#define ORC_TYPE_REGS\t\t\t1\n#define ORC_TYPE_REGS_IRET\t\t2\n#define UNWIND_HINT_TYPE_SAVE\t\t3\n#define UNWIND_HINT_TYPE_RESTORE\t4\n\n#ifndef __ASSEMBLY__\n/*\n * This struct is more or less a vastly simplified version of the DWARF Call\n * Frame Information standard.  It contains only the necessary parts of DWARF\n * CFI, simplified for ease of access by the in-kernel unwinder.  It tells the\n * unwinder how to find the previous SP and BP (and sometimes entry regs) on\n * the stack for a given code address.  Each instance of the struct corresponds\n * to one or more code locations.\n */\nstruct orc_entry {\n\ts16\t\tsp_offset;\n\ts16\t\tbp_offset;\n\tunsigned\tsp_reg:4;\n\tunsigned\tbp_reg:4;\n\tunsigned\ttype:2;\n\tunsigned\tend:1;\n} __packed;\n\n/*\n * This struct is used by asm and inline asm code to manually annotate the\n * location of registers on the stack for the ORC unwinder.\n *\n * Type can be either ORC_TYPE_* or UNWIND_HINT_TYPE_*.\n */\nstruct unwind_hint {\n\tu32\t\tip;\n\ts16\t\tsp_offset;\n\tu8\t\tsp_reg;\n\tu8\t\ttype;\n\tu8\t\tend;\n};\n#endif /* __ASSEMBLY__ */\n\n#endif /* _ORC_TYPES_H */\n"
  },
  {
    "path": "t/tree/arch/x86/include/asm/uprobes.h",
    "content": "/* SPDX-License-Identifier: GPL-2.0-or-later */\n#ifndef _ASM_UPROBES_H\n#define _ASM_UPROBES_H\n/*\n * User-space Probes (UProbes) for x86\n *\n * Copyright (C) IBM Corporation, 2008-2011\n * Authors:\n *\tSrikar Dronamraju\n *\tJim Keniston\n */\n\n#include <linux/notifier.h>\n\ntypedef u8 uprobe_opcode_t;\n\n#define MAX_UINSN_BYTES\t\t\t  16\n#define UPROBE_XOL_SLOT_BYTES\t\t 128\t/* to keep it cache aligned */\n\n#define UPROBE_SWBP_INSN\t\t0xcc\n#define UPROBE_SWBP_INSN_SIZE\t\t   1\n\nstruct uprobe_xol_ops;\n\nstruct arch_uprobe {\n\tunion {\n\t\tu8\t\t\tinsn[MAX_UINSN_BYTES];\n\t\tu8\t\t\tixol[MAX_UINSN_BYTES];\n\t};\n\n\tconst struct uprobe_xol_ops\t*ops;\n\n\tunion {\n\t\tstruct {\n\t\t\ts32\toffs;\n\t\t\tu8\tilen;\n\t\t\tu8\topc1;\n\t\t}\t\t\tbranch;\n\t\tstruct {\n\t\t\tu8\tfixups;\n\t\t\tu8\tilen;\n\t\t} \t\t\tdefparam;\n\t\tstruct {\n\t\t\tu8\treg_offset;\t/* to the start of pt_regs */\n\t\t\tu8\tilen;\n\t\t}\t\t\tpush;\n\t};\n};\n\nstruct arch_uprobe_task {\n#ifdef CONFIG_X86_64\n\tunsigned long\t\t\tsaved_scratch_register;\n#endif\n\tunsigned int\t\t\tsaved_trap_nr;\n\tunsigned int\t\t\tsaved_tf;\n};\n\n#endif\t/* _ASM_UPROBES_H */\n"
  },
  {
    "path": "t/tree/arch/x86/include/uapi/asm/ist.h",
    "content": "/* SPDX-License-Identifier: GPL-2.0+ WITH Linux-syscall-note */\n/*\n * Include file for the interface to IST BIOS\n * Copyright 2002 Andy Grover <andrew.grover@intel.com>\n *\n * This program is free software; you can redistribute it and/or modify it\n * under the terms of the GNU General Public License as published by the\n * Free Software Foundation; either version 2, or (at your option) any\n * later version.\n *\n * This program is distributed in the hope that it will be useful, but\n * WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n * General Public License for more details.\n */\n#ifndef _UAPI_ASM_X86_IST_H\n#define _UAPI_ASM_X86_IST_H\n\n\n\n#include <linux/types.h>\n\nstruct ist_info {\n\t__u32 signature;\n\t__u32 command;\n\t__u32 event;\n\t__u32 perf_level;\n};\n\n#endif /* _UAPI_ASM_X86_IST_H */\n"
  },
  {
    "path": "t/tree/drivers/firmware/broadcom/bcm74xx_sprom.c",
    "content": "/*\n *  Copyright (C) 2004 Florian Schirmer <jolt@tuxbox.org>\n *  Copyright (C) 2006 Felix Fietkau <nbd@openwrt.org>\n *  Copyright (C) 2006 Michael Buesch <m@bues.ch>\n *  Copyright (C) 2010 Waldemar Brodkorb <wbx@openadk.org>\n *  Copyright (C) 2010-2012 Hauke Mehrtens <hauke@hauke-m.de>\n *\n *  This program is free software; you can redistribute  it and/or modify it\n *  under  the terms of  the GNU General  Public License as published by the\n *  Free Software Foundation;  either version 2 of the  License, or (at your\n *  option) any later version.\n *\n *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED\n *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF\n *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN\n *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,\n *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT\n *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF\n *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON\n *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT\n *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF\n *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *\n *  You should have received a copy of the  GNU General Public License along\n *  with this program; if not, write  to the Free Software Foundation, Inc.,\n *  675 Mass Ave, Cambridge, MA 02139, USA.\n */\n\n#include <linux/bcm47xx_nvram.h>\n#include <linux/bcma/bcma.h>\n#include <linux/etherdevice.h>\n#include <linux/if_ether.h>\n#include <linux/ssb/ssb.h>\n\nstatic void create_key(const char *prefix, const char *postfix,\n\t\t       const char *name, char *buf, int len)\n{\n\tif (prefix && postfix)\n\t\tsnprintf(buf, len, \"%s%s%s\", prefix, name, postfix);\n\telse if (prefix)\n\t\tsnprintf(buf, len, \"%s%s\", prefix, name);\n\telse if (postfix)\n\t\tsnprintf(buf, len, \"%s%s\", name, postfix);\n\telse\n\t\tsnprintf(buf, len, \"%s\", name);\n}\n\nstatic int get_nvram_var(const char *prefix, const char *postfix,\n\t\t\t const char *name, char *buf, int len, bool fallback)\n{\n\tchar key[40];\n\tint err;\n\n\tcreate_key(prefix, postfix, name, key, sizeof(key));\n\n\terr = bcm47xx_nvram_getenv(key, buf, len);\n\tif (fallback && err == -ENOENT && prefix) {\n\t\tcreate_key(NULL, postfix, name, key, sizeof(key));\n\t\terr = bcm47xx_nvram_getenv(key, buf, len);\n\t}\n\treturn err;\n}\n\n#define NVRAM_READ_VAL(type)\t\t\t\t\t\t\\\nstatic void nvram_read_ ## type(const char *prefix,\t\t\t\\\n\t\t\t\tconst char *postfix, const char *name,\t\\\n\t\t\t\ttype *val, type allset, bool fallback)\t\\\n{\t\t\t\t\t\t\t\t\t\\\n\tchar buf[100];\t\t\t\t\t\t\t\\\n\tint err;\t\t\t\t\t\t\t\\\n\ttype var;\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\terr = get_nvram_var(prefix, postfix, name, buf, sizeof(buf),\t\\\n\t\t\t    fallback);\t\t\t\t\t\\\n\tif (err < 0)\t\t\t\t\t\t\t\\\n\t\treturn;\t\t\t\t\t\t\t\\\n\terr = kstrto ## type(strim(buf), 0, &var);\t\t\t\\\n\tif (err) {\t\t\t\t\t\t\t\\\n\t\tpr_warn(\"can not parse nvram name %s%s%s with value %s got %i\\n\",\t\\\n\t\t\tprefix, name, postfix, buf, err);\t\t\\\n\t\treturn;\t\t\t\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n\tif (allset && var == allset)\t\t\t\t\t\\\n\t\treturn;\t\t\t\t\t\t\t\\\n\t*val = var;\t\t\t\t\t\t\t\\\n}\n\nNVRAM_READ_VAL(u8)\nNVRAM_READ_VAL(s8)\nNVRAM_READ_VAL(u16)\nNVRAM_READ_VAL(u32)\n\n#undef NVRAM_READ_VAL\n\nstatic void nvram_read_u32_2(const char *prefix, const char *name,\n\t\t\t     u16 *val_lo, u16 *val_hi, bool fallback)\n{\n\tchar buf[100];\n\tint err;\n\tu32 val;\n\n\terr = get_nvram_var(prefix, NULL, name, buf, sizeof(buf), fallback);\n\tif (err < 0)\n\t\treturn;\n\terr = kstrtou32(strim(buf), 0, &val);\n\tif (err) {\n\t\tpr_warn(\"can not parse nvram name %s%s with value %s got %i\\n\",\n\t\t\tprefix, name, buf, err);\n\t\treturn;\n\t}\n\t*val_lo = (val & 0x0000FFFFU);\n\t*val_hi = (val & 0xFFFF0000U) >> 16;\n}\n\nstatic void nvram_read_leddc(const char *prefix, const char *name,\n\t\t\t     u8 *leddc_on_time, u8 *leddc_off_time,\n\t\t\t     bool fallback)\n{\n\tchar buf[100];\n\tint err;\n\tu32 val;\n\n\terr = get_nvram_var(prefix, NULL, name, buf, sizeof(buf), fallback);\n\tif (err < 0)\n\t\treturn;\n\terr = kstrtou32(strim(buf), 0, &val);\n\tif (err) {\n\t\tpr_warn(\"can not parse nvram name %s%s with value %s got %i\\n\",\n\t\t\tprefix, name, buf, err);\n\t\treturn;\n\t}\n\n\tif (val == 0xffff || val == 0xffffffff)\n\t\treturn;\n\n\t*leddc_on_time = val & 0xff;\n\t*leddc_off_time = (val >> 16) & 0xff;\n}\n\nstatic void nvram_read_macaddr(const char *prefix, const char *name,\n\t\t\t       u8 val[6], bool fallback)\n{\n\tchar buf[100];\n\tint err;\n\n\terr = get_nvram_var(prefix, NULL, name, buf, sizeof(buf), fallback);\n\tif (err < 0)\n\t\treturn;\n\n\tstrreplace(buf, '-', ':');\n\tif (!mac_pton(buf, val))\n\t\tpr_warn(\"Can not parse mac address: %s\\n\", buf);\n}\n\nstatic void nvram_read_alpha2(const char *prefix, const char *name,\n\t\t\t     char val[2], bool fallback)\n{\n\tchar buf[10];\n\tint err;\n\n\terr = get_nvram_var(prefix, NULL, name, buf, sizeof(buf), fallback);\n\tif (err < 0)\n\t\treturn;\n\tif (buf[0] == '0')\n\t\treturn;\n\tif (strlen(buf) > 2) {\n\t\tpr_warn(\"alpha2 is too long %s\\n\", buf);\n\t\treturn;\n\t}\n\tmemcpy(val, buf, 2);\n}\n\n/* This is one-function-only macro, it uses local \"sprom\" variable! */\n#define ENTRY(_revmask, _type, _prefix, _name, _val, _allset, _fallback) \\\n\tif (_revmask & BIT(sprom->revision)) \\\n\t\tnvram_read_ ## _type(_prefix, NULL, _name, &sprom->_val, \\\n\t\t\t\t     _allset, _fallback)\n/*\n * Special version of filling function that can be safely called for any SPROM\n * revision. For every NVRAM to SPROM mapping it contains bitmask of revisions\n * for which the mapping is valid.\n * It obviously requires some hexadecimal/bitmasks knowledge, but allows\n * writing cleaner code (easy revisions handling).\n * Note that while SPROM revision 0 was never used, we still keep BIT(0)\n * reserved for it, just to keep numbering sane.\n */\nstatic void bcm47xx_sprom_fill_auto(struct ssb_sprom *sprom,\n\t\t\t\t    const char *prefix, bool fallback)\n{\n\tconst char *pre = prefix;\n\tbool fb = fallback;\n\n\t/* Broadcom extracts it for rev 8+ but it was found on 2 and 4 too */\n\tENTRY(0xfffffffe, u16, pre, \"devid\", dev_id, 0, fallback);\n\n\tENTRY(0xfffffffe, u16, pre, \"boardrev\", board_rev, 0, true);\n\tENTRY(0xfffffffe, u32, pre, \"boardflags\", boardflags, 0, fb);\n\tENTRY(0xfffffff0, u32, pre, \"boardflags2\", boardflags2, 0, fb);\n\tENTRY(0xfffff800, u32, pre, \"boardflags3\", boardflags3, 0, fb);\n\tENTRY(0x00000002, u16, pre, \"boardflags\", boardflags_lo, 0, fb);\n\tENTRY(0xfffffffc, u16, pre, \"boardtype\", board_type, 0, true);\n\tENTRY(0xfffffffe, u16, pre, \"boardnum\", board_num, 0, fb);\n\tENTRY(0x00000002, u8, pre, \"cc\", country_code, 0, fb);\n\tENTRY(0xfffffff8, u8, pre, \"regrev\", regrev, 0, fb);\n\n\tENTRY(0xfffffffe, u8, pre, \"ledbh0\", gpio0, 0xff, fb);\n\tENTRY(0xfffffffe, u8, pre, \"ledbh1\", gpio1, 0xff, fb);\n\tENTRY(0xfffffffe, u8, pre, \"ledbh2\", gpio2, 0xff, fb);\n\tENTRY(0xfffffffe, u8, pre, \"ledbh3\", gpio3, 0xff, fb);\n\n\tENTRY(0x0000070e, u16, pre, \"pa0b0\", pa0b0, 0, fb);\n\tENTRY(0x0000070e, u16, pre, \"pa0b1\", pa0b1, 0, fb);\n\tENTRY(0x0000070e, u16, pre, \"pa0b2\", pa0b2, 0, fb);\n\tENTRY(0x0000070e, u8, pre, \"pa0itssit\", itssi_bg, 0, fb);\n\tENTRY(0x0000070e, u8, pre, \"pa0maxpwr\", maxpwr_bg, 0, fb);\n\n\tENTRY(0x0000070c, u8, pre, \"opo\", opo, 0, fb);\n\tENTRY(0xfffffffe, u8, pre, \"aa2g\", ant_available_bg, 0, fb);\n\tENTRY(0xfffffffe, u8, pre, \"aa5g\", ant_available_a, 0, fb);\n\tENTRY(0x000007fe, s8, pre, \"ag0\", antenna_gain.a0, 0, fb);\n\tENTRY(0x000007fe, s8, pre, \"ag1\", antenna_gain.a1, 0, fb);\n\tENTRY(0x000007f0, s8, pre, \"ag2\", antenna_gain.a2, 0, fb);\n\tENTRY(0x000007f0, s8, pre, \"ag3\", antenna_gain.a3, 0, fb);\n\n\tENTRY(0x0000070e, u16, pre, \"pa1b0\", pa1b0, 0, fb);\n\tENTRY(0x0000070e, u16, pre, \"pa1b1\", pa1b1, 0, fb);\n\tENTRY(0x0000070e, u16, pre, \"pa1b2\", pa1b2, 0, fb);\n\tENTRY(0x0000070c, u16, pre, \"pa1lob0\", pa1lob0, 0, fb);\n\tENTRY(0x0000070c, u16, pre, \"pa1lob1\", pa1lob1, 0, fb);\n\tENTRY(0x0000070c, u16, pre, \"pa1lob2\", pa1lob2, 0, fb);\n\tENTRY(0x0000070c, u16, pre, \"pa1hib0\", pa1hib0, 0, fb);\n\tENTRY(0x0000070c, u16, pre, \"pa1hib1\", pa1hib1, 0, fb);\n\tENTRY(0x0000070c, u16, pre, \"pa1hib2\", pa1hib2, 0, fb);\n\tENTRY(0x0000070e, u8, pre, \"pa1itssit\", itssi_a, 0, fb);\n\tENTRY(0x0000070e, u8, pre, \"pa1maxpwr\", maxpwr_a, 0, fb);\n\tENTRY(0x0000070c, u8, pre, \"pa1lomaxpwr\", maxpwr_al, 0, fb);\n\tENTRY(0x0000070c, u8, pre, \"pa1himaxpwr\", maxpwr_ah, 0, fb);\n\n\tENTRY(0x00000708, u8, pre, \"bxa2g\", bxa2g, 0, fb);\n\tENTRY(0x00000708, u8, pre, \"rssisav2g\", rssisav2g, 0, fb);\n\tENTRY(0x00000708, u8, pre, \"rssismc2g\", rssismc2g, 0, fb);\n\tENTRY(0x00000708, u8, pre, \"rssismf2g\", rssismf2g, 0, fb);\n\tENTRY(0x00000708, u8, pre, \"bxa5g\", bxa5g, 0, fb);\n\tENTRY(0x00000708, u8, pre, \"rssisav5g\", rssisav5g, 0, fb);\n\tENTRY(0x00000708, u8, pre, \"rssismc5g\", rssismc5g, 0, fb);\n\tENTRY(0x00000708, u8, pre, \"rssismf5g\", rssismf5g, 0, fb);\n\tENTRY(0x00000708, u8, pre, \"tri2g\", tri2g, 0, fb);\n\tENTRY(0x00000708, u8, pre, \"tri5g\", tri5g, 0, fb);\n\tENTRY(0x00000708, u8, pre, \"tri5gl\", tri5gl, 0, fb);\n\tENTRY(0x00000708, u8, pre, \"tri5gh\", tri5gh, 0, fb);\n\tENTRY(0x00000708, s8, pre, \"rxpo2g\", rxpo2g, 0, fb);\n\tENTRY(0x00000708, s8, pre, \"rxpo5g\", rxpo5g, 0, fb);\n\tENTRY(0xfffffff0, u8, pre, \"txchain\", txchain, 0xf, fb);\n\tENTRY(0xfffffff0, u8, pre, \"rxchain\", rxchain, 0xf, fb);\n\tENTRY(0xfffffff0, u8, pre, \"antswitch\", antswitch, 0xff, fb);\n\tENTRY(0x00000700, u8, pre, \"tssipos2g\", fem.ghz2.tssipos, 0, fb);\n\tENTRY(0x00000700, u8, pre, \"extpagain2g\", fem.ghz2.extpa_gain, 0, fb);\n\tENTRY(0x00000700, u8, pre, \"pdetrange2g\", fem.ghz2.pdet_range, 0, fb);\n\tENTRY(0x00000700, u8, pre, \"triso2g\", fem.ghz2.tr_iso, 0, fb);\n\tENTRY(0x00000700, u8, pre, \"antswctl2g\", fem.ghz2.antswlut, 0, fb);\n\tENTRY(0x00000700, u8, pre, \"tssipos5g\", fem.ghz5.tssipos, 0, fb);\n\tENTRY(0x00000700, u8, pre, \"extpagain5g\", fem.ghz5.extpa_gain, 0, fb);\n\tENTRY(0x00000700, u8, pre, \"pdetrange5g\", fem.ghz5.pdet_range, 0, fb);\n\tENTRY(0x00000700, u8, pre, \"triso5g\", fem.ghz5.tr_iso, 0, fb);\n\tENTRY(0x00000700, u8, pre, \"antswctl5g\", fem.ghz5.antswlut, 0, fb);\n\tENTRY(0x000000f0, u8, pre, \"txpid2ga0\", txpid2g[0], 0, fb);\n\tENTRY(0x000000f0, u8, pre, \"txpid2ga1\", txpid2g[1], 0, fb);\n\tENTRY(0x000000f0, u8, pre, \"txpid2ga2\", txpid2g[2], 0, fb);\n\tENTRY(0x000000f0, u8, pre, \"txpid2ga3\", txpid2g[3], 0, fb);\n\tENTRY(0x000000f0, u8, pre, \"txpid5ga0\", txpid5g[0], 0, fb);\n\tENTRY(0x000000f0, u8, pre, \"txpid5ga1\", txpid5g[1], 0, fb);\n\tENTRY(0x000000f0, u8, pre, \"txpid5ga2\", txpid5g[2], 0, fb);\n\tENTRY(0x000000f0, u8, pre, \"txpid5ga3\", txpid5g[3], 0, fb);\n\tENTRY(0x000000f0, u8, pre, \"txpid5gla0\", txpid5gl[0], 0, fb);\n\tENTRY(0x000000f0, u8, pre, \"txpid5gla1\", txpid5gl[1], 0, fb);\n\tENTRY(0x000000f0, u8, pre, \"txpid5gla2\", txpid5gl[2], 0, fb);\n\tENTRY(0x000000f0, u8, pre, \"txpid5gla3\", txpid5gl[3], 0, fb);\n\tENTRY(0x000000f0, u8, pre, \"txpid5gha0\", txpid5gh[0], 0, fb);\n\tENTRY(0x000000f0, u8, pre, \"txpid5gha1\", txpid5gh[1], 0, fb);\n\tENTRY(0x000000f0, u8, pre, \"txpid5gha2\", txpid5gh[2], 0, fb);\n\tENTRY(0x000000f0, u8, pre, \"txpid5gha3\", txpid5gh[3], 0, fb);\n\n\tENTRY(0xffffff00, u8, pre, \"tempthresh\", tempthresh, 0, fb);\n\tENTRY(0xffffff00, u8, pre, \"tempoffset\", tempoffset, 0, fb);\n\tENTRY(0xffffff00, u16, pre, \"rawtempsense\", rawtempsense, 0, fb);\n\tENTRY(0xffffff00, u8, pre, \"measpower\", measpower, 0, fb);\n\tENTRY(0xffffff00, u8, pre, \"tempsense_slope\", tempsense_slope, 0, fb);\n\tENTRY(0xffffff00, u8, pre, \"tempcorrx\", tempcorrx, 0, fb);\n\tENTRY(0xffffff00, u8, pre, \"tempsense_option\", tempsense_option, 0, fb);\n\tENTRY(0x00000700, u8, pre, \"freqoffset_corr\", freqoffset_corr, 0, fb);\n\tENTRY(0x00000700, u8, pre, \"iqcal_swp_dis\", iqcal_swp_dis, 0, fb);\n\tENTRY(0x00000700, u8, pre, \"hw_iqcal_en\", hw_iqcal_en, 0, fb);\n\tENTRY(0x00000700, u8, pre, \"elna2g\", elna2g, 0, fb);\n\tENTRY(0x00000700, u8, pre, \"elna5g\", elna5g, 0, fb);\n\tENTRY(0xffffff00, u8, pre, \"phycal_tempdelta\", phycal_tempdelta, 0, fb);\n\tENTRY(0xffffff00, u8, pre, \"temps_period\", temps_period, 0, fb);\n\tENTRY(0xffffff00, u8, pre, \"temps_hysteresis\", temps_hysteresis, 0, fb);\n\tENTRY(0xffffff00, u8, pre, \"measpower1\", measpower1, 0, fb);\n\tENTRY(0xffffff00, u8, pre, \"measpower2\", measpower2, 0, fb);\n\n\tENTRY(0x000001f0, u16, pre, \"cck2gpo\", cck2gpo, 0, fb);\n\tENTRY(0x000001f0, u32, pre, \"ofdm2gpo\", ofdm2gpo, 0, fb);\n\tENTRY(0x000001f0, u32, pre, \"ofdm5gpo\", ofdm5gpo, 0, fb);\n\tENTRY(0x000001f0, u32, pre, \"ofdm5glpo\", ofdm5glpo, 0, fb);\n\tENTRY(0x000001f0, u32, pre, \"ofdm5ghpo\", ofdm5ghpo, 0, fb);\n\tENTRY(0x000001f0, u16, pre, \"mcs2gpo0\", mcs2gpo[0], 0, fb);\n\tENTRY(0x000001f0, u16, pre, \"mcs2gpo1\", mcs2gpo[1], 0, fb);\n\tENTRY(0x000001f0, u16, pre, \"mcs2gpo2\", mcs2gpo[2], 0, fb);\n\tENTRY(0x000001f0, u16, pre, \"mcs2gpo3\", mcs2gpo[3], 0, fb);\n\tENTRY(0x000001f0, u16, pre, \"mcs2gpo4\", mcs2gpo[4], 0, fb);\n\tENTRY(0x000001f0, u16, pre, \"mcs2gpo5\", mcs2gpo[5], 0, fb);\n\tENTRY(0x000001f0, u16, pre, \"mcs2gpo6\", mcs2gpo[6], 0, fb);\n\tENTRY(0x000001f0, u16, pre, \"mcs2gpo7\", mcs2gpo[7], 0, fb);\n\tENTRY(0x000001f0, u16, pre, \"mcs5gpo0\", mcs5gpo[0], 0, fb);\n\tENTRY(0x000001f0, u16, pre, \"mcs5gpo1\", mcs5gpo[1], 0, fb);\n\tENTRY(0x000001f0, u16, pre, \"mcs5gpo2\", mcs5gpo[2], 0, fb);\n\tENTRY(0x000001f0, u16, pre, \"mcs5gpo3\", mcs5gpo[3], 0, fb);\n\tENTRY(0x000001f0, u16, pre, \"mcs5gpo4\", mcs5gpo[4], 0, fb);\n\tENTRY(0x000001f0, u16, pre, \"mcs5gpo5\", mcs5gpo[5], 0, fb);\n\tENTRY(0x000001f0, u16, pre, \"mcs5gpo6\", mcs5gpo[6], 0, fb);\n\tENTRY(0x000001f0, u16, pre, \"mcs5gpo7\", mcs5gpo[7], 0, fb);\n\tENTRY(0x000001f0, u16, pre, \"mcs5glpo0\", mcs5glpo[0], 0, fb);\n\tENTRY(0x000001f0, u16, pre, \"mcs5glpo1\", mcs5glpo[1], 0, fb);\n\tENTRY(0x000001f0, u16, pre, \"mcs5glpo2\", mcs5glpo[2], 0, fb);\n\tENTRY(0x000001f0, u16, pre, \"mcs5glpo3\", mcs5glpo[3], 0, fb);\n\tENTRY(0x000001f0, u16, pre, \"mcs5glpo4\", mcs5glpo[4], 0, fb);\n\tENTRY(0x000001f0, u16, pre, \"mcs5glpo5\", mcs5glpo[5], 0, fb);\n\tENTRY(0x000001f0, u16, pre, \"mcs5glpo6\", mcs5glpo[6], 0, fb);\n\tENTRY(0x000001f0, u16, pre, \"mcs5glpo7\", mcs5glpo[7], 0, fb);\n\tENTRY(0x000001f0, u16, pre, \"mcs5ghpo0\", mcs5ghpo[0], 0, fb);\n\tENTRY(0x000001f0, u16, pre, \"mcs5ghpo1\", mcs5ghpo[1], 0, fb);\n\tENTRY(0x000001f0, u16, pre, \"mcs5ghpo2\", mcs5ghpo[2], 0, fb);\n\tENTRY(0x000001f0, u16, pre, \"mcs5ghpo3\", mcs5ghpo[3], 0, fb);\n\tENTRY(0x000001f0, u16, pre, \"mcs5ghpo4\", mcs5ghpo[4], 0, fb);\n\tENTRY(0x000001f0, u16, pre, \"mcs5ghpo5\", mcs5ghpo[5], 0, fb);\n\tENTRY(0x000001f0, u16, pre, \"mcs5ghpo6\", mcs5ghpo[6], 0, fb);\n\tENTRY(0x000001f0, u16, pre, \"mcs5ghpo7\", mcs5ghpo[7], 0, fb);\n\tENTRY(0x000001f0, u16, pre, \"cddpo\", cddpo, 0, fb);\n\tENTRY(0x000001f0, u16, pre, \"stbcpo\", stbcpo, 0, fb);\n\tENTRY(0x000001f0, u16, pre, \"bw40po\", bw40po, 0, fb);\n\tENTRY(0x000001f0, u16, pre, \"bwduppo\", bwduppo, 0, fb);\n\n\tENTRY(0xfffffe00, u16, pre, \"cckbw202gpo\", cckbw202gpo, 0, fb);\n\tENTRY(0xfffffe00, u16, pre, \"cckbw20ul2gpo\", cckbw20ul2gpo, 0, fb);\n\tENTRY(0x00000600, u32, pre, \"legofdmbw202gpo\", legofdmbw202gpo, 0, fb);\n\tENTRY(0x00000600, u32, pre, \"legofdmbw20ul2gpo\", legofdmbw20ul2gpo, 0, fb);\n\tENTRY(0x00000600, u32, pre, \"legofdmbw205glpo\", legofdmbw205glpo, 0, fb);\n\tENTRY(0x00000600, u32, pre, \"legofdmbw20ul5glpo\", legofdmbw20ul5glpo, 0, fb);\n\tENTRY(0x00000600, u32, pre, \"legofdmbw205gmpo\", legofdmbw205gmpo, 0, fb);\n\tENTRY(0x00000600, u32, pre, \"legofdmbw20ul5gmpo\", legofdmbw20ul5gmpo, 0, fb);\n\tENTRY(0x00000600, u32, pre, \"legofdmbw205ghpo\", legofdmbw205ghpo, 0, fb);\n\tENTRY(0x00000600, u32, pre, \"legofdmbw20ul5ghpo\", legofdmbw20ul5ghpo, 0, fb);\n\tENTRY(0xfffffe00, u32, pre, \"mcsbw202gpo\", mcsbw202gpo, 0, fb);\n\tENTRY(0x00000600, u32, pre, \"mcsbw20ul2gpo\", mcsbw20ul2gpo, 0, fb);\n\tENTRY(0xfffffe00, u32, pre, \"mcsbw402gpo\", mcsbw402gpo, 0, fb);\n\tENTRY(0xfffffe00, u32, pre, \"mcsbw205glpo\", mcsbw205glpo, 0, fb);\n\tENTRY(0x00000600, u32, pre, \"mcsbw20ul5glpo\", mcsbw20ul5glpo, 0, fb);\n\tENTRY(0xfffffe00, u32, pre, \"mcsbw405glpo\", mcsbw405glpo, 0, fb);\n\tENTRY(0xfffffe00, u32, pre, \"mcsbw205gmpo\", mcsbw205gmpo, 0, fb);\n\tENTRY(0x00000600, u32, pre, \"mcsbw20ul5gmpo\", mcsbw20ul5gmpo, 0, fb);\n\tENTRY(0xfffffe00, u32, pre, \"mcsbw405gmpo\", mcsbw405gmpo, 0, fb);\n\tENTRY(0xfffffe00, u32, pre, \"mcsbw205ghpo\", mcsbw205ghpo, 0, fb);\n\tENTRY(0x00000600, u32, pre, \"mcsbw20ul5ghpo\", mcsbw20ul5ghpo, 0, fb);\n\tENTRY(0xfffffe00, u32, pre, \"mcsbw405ghpo\", mcsbw405ghpo, 0, fb);\n\tENTRY(0x00000600, u16, pre, \"mcs32po\", mcs32po, 0, fb);\n\tENTRY(0x00000600, u16, pre, \"legofdm40duppo\", legofdm40duppo, 0, fb);\n\tENTRY(0x00000700, u8, pre, \"pcieingress_war\", pcieingress_war, 0, fb);\n\n\t/* TODO: rev 11 support */\n\tENTRY(0x00000700, u8, pre, \"rxgainerr2ga0\", rxgainerr2ga[0], 0, fb);\n\tENTRY(0x00000700, u8, pre, \"rxgainerr2ga1\", rxgainerr2ga[1], 0, fb);\n\tENTRY(0x00000700, u8, pre, \"rxgainerr2ga2\", rxgainerr2ga[2], 0, fb);\n\tENTRY(0x00000700, u8, pre, \"rxgainerr5gla0\", rxgainerr5gla[0], 0, fb);\n\tENTRY(0x00000700, u8, pre, \"rxgainerr5gla1\", rxgainerr5gla[1], 0, fb);\n\tENTRY(0x00000700, u8, pre, \"rxgainerr5gla2\", rxgainerr5gla[2], 0, fb);\n\tENTRY(0x00000700, u8, pre, \"rxgainerr5gma0\", rxgainerr5gma[0], 0, fb);\n\tENTRY(0x00000700, u8, pre, \"rxgainerr5gma1\", rxgainerr5gma[1], 0, fb);\n\tENTRY(0x00000700, u8, pre, \"rxgainerr5gma2\", rxgainerr5gma[2], 0, fb);\n\tENTRY(0x00000700, u8, pre, \"rxgainerr5gha0\", rxgainerr5gha[0], 0, fb);\n\tENTRY(0x00000700, u8, pre, \"rxgainerr5gha1\", rxgainerr5gha[1], 0, fb);\n\tENTRY(0x00000700, u8, pre, \"rxgainerr5gha2\", rxgainerr5gha[2], 0, fb);\n\tENTRY(0x00000700, u8, pre, \"rxgainerr5gua0\", rxgainerr5gua[0], 0, fb);\n\tENTRY(0x00000700, u8, pre, \"rxgainerr5gua1\", rxgainerr5gua[1], 0, fb);\n\tENTRY(0x00000700, u8, pre, \"rxgainerr5gua2\", rxgainerr5gua[2], 0, fb);\n\n\tENTRY(0xfffffe00, u8, pre, \"sar2g\", sar2g, 0, fb);\n\tENTRY(0xfffffe00, u8, pre, \"sar5g\", sar5g, 0, fb);\n\n\t/* TODO: rev 11 support */\n\tENTRY(0x00000700, u8, pre, \"noiselvl2ga0\", noiselvl2ga[0], 0, fb);\n\tENTRY(0x00000700, u8, pre, \"noiselvl2ga1\", noiselvl2ga[1], 0, fb);\n\tENTRY(0x00000700, u8, pre, \"noiselvl2ga2\", noiselvl2ga[2], 0, fb);\n\tENTRY(0x00000700, u8, pre, \"noiselvl5gla0\", noiselvl5gla[0], 0, fb);\n\tENTRY(0x00000700, u8, pre, \"noiselvl5gla1\", noiselvl5gla[1], 0, fb);\n\tENTRY(0x00000700, u8, pre, \"noiselvl5gla2\", noiselvl5gla[2], 0, fb);\n\tENTRY(0x00000700, u8, pre, \"noiselvl5gma0\", noiselvl5gma[0], 0, fb);\n\tENTRY(0x00000700, u8, pre, \"noiselvl5gma1\", noiselvl5gma[1], 0, fb);\n\tENTRY(0x00000700, u8, pre, \"noiselvl5gma2\", noiselvl5gma[2], 0, fb);\n\tENTRY(0x00000700, u8, pre, \"noiselvl5gha0\", noiselvl5gha[0], 0, fb);\n\tENTRY(0x00000700, u8, pre, \"noiselvl5gha1\", noiselvl5gha[1], 0, fb);\n\tENTRY(0x00000700, u8, pre, \"noiselvl5gha2\", noiselvl5gha[2], 0, fb);\n\tENTRY(0x00000700, u8, pre, \"noiselvl5gua0\", noiselvl5gua[0], 0, fb);\n\tENTRY(0x00000700, u8, pre, \"noiselvl5gua1\", noiselvl5gua[1], 0, fb);\n\tENTRY(0x00000700, u8, pre, \"noiselvl5gua2\", noiselvl5gua[2], 0, fb);\n}\n#undef ENTRY /* It's specififc, uses local variable, don't use it (again). */\n\nstatic void bcm47xx_fill_sprom_path_r4589(struct ssb_sprom *sprom,\n\t\t\t\t\t  const char *prefix, bool fallback)\n{\n\tchar postfix[2];\n\tint i;\n\n\tfor (i = 0; i < ARRAY_SIZE(sprom->core_pwr_info); i++) {\n\t\tstruct ssb_sprom_core_pwr_info *pwr_info;\n\n\t\tpwr_info = &sprom->core_pwr_info[i];\n\n\t\tsnprintf(postfix, sizeof(postfix), \"%i\", i);\n\t\tnvram_read_u8(prefix, postfix, \"maxp2ga\",\n\t\t\t      &pwr_info->maxpwr_2g, 0, fallback);\n\t\tnvram_read_u8(prefix, postfix, \"itt2ga\",\n\t\t\t      &pwr_info->itssi_2g, 0, fallback);\n\t\tnvram_read_u8(prefix, postfix, \"itt5ga\",\n\t\t\t      &pwr_info->itssi_5g, 0, fallback);\n\t\tnvram_read_u16(prefix, postfix, \"pa2gw0a\",\n\t\t\t       &pwr_info->pa_2g[0], 0, fallback);\n\t\tnvram_read_u16(prefix, postfix, \"pa2gw1a\",\n\t\t\t       &pwr_info->pa_2g[1], 0, fallback);\n\t\tnvram_read_u16(prefix, postfix, \"pa2gw2a\",\n\t\t\t       &pwr_info->pa_2g[2], 0, fallback);\n\t\tnvram_read_u8(prefix, postfix, \"maxp5ga\",\n\t\t\t      &pwr_info->maxpwr_5g, 0, fallback);\n\t\tnvram_read_u8(prefix, postfix, \"maxp5gha\",\n\t\t\t      &pwr_info->maxpwr_5gh, 0, fallback);\n\t\tnvram_read_u8(prefix, postfix, \"maxp5gla\",\n\t\t\t      &pwr_info->maxpwr_5gl, 0, fallback);\n\t\tnvram_read_u16(prefix, postfix, \"pa5gw0a\",\n\t\t\t       &pwr_info->pa_5g[0], 0, fallback);\n\t\tnvram_read_u16(prefix, postfix, \"pa5gw1a\",\n\t\t\t       &pwr_info->pa_5g[1], 0, fallback);\n\t\tnvram_read_u16(prefix, postfix, \"pa5gw2a\",\n\t\t\t       &pwr_info->pa_5g[2], 0, fallback);\n\t\tnvram_read_u16(prefix, postfix, \"pa5glw0a\",\n\t\t\t       &pwr_info->pa_5gl[0], 0, fallback);\n\t\tnvram_read_u16(prefix, postfix, \"pa5glw1a\",\n\t\t\t       &pwr_info->pa_5gl[1], 0, fallback);\n\t\tnvram_read_u16(prefix, postfix, \"pa5glw2a\",\n\t\t\t       &pwr_info->pa_5gl[2], 0, fallback);\n\t\tnvram_read_u16(prefix, postfix, \"pa5ghw0a\",\n\t\t\t       &pwr_info->pa_5gh[0], 0, fallback);\n\t\tnvram_read_u16(prefix, postfix, \"pa5ghw1a\",\n\t\t\t       &pwr_info->pa_5gh[1], 0, fallback);\n\t\tnvram_read_u16(prefix, postfix, \"pa5ghw2a\",\n\t\t\t       &pwr_info->pa_5gh[2], 0, fallback);\n\t}\n}\n\nstatic void bcm47xx_fill_sprom_path_r45(struct ssb_sprom *sprom,\n\t\t\t\t\tconst char *prefix, bool fallback)\n{\n\tchar postfix[2];\n\tint i;\n\n\tfor (i = 0; i < ARRAY_SIZE(sprom->core_pwr_info); i++) {\n\t\tstruct ssb_sprom_core_pwr_info *pwr_info;\n\n\t\tpwr_info = &sprom->core_pwr_info[i];\n\n\t\tsnprintf(postfix, sizeof(postfix), \"%i\", i);\n\t\tnvram_read_u16(prefix, postfix, \"pa2gw3a\",\n\t\t\t       &pwr_info->pa_2g[3], 0, fallback);\n\t\tnvram_read_u16(prefix, postfix, \"pa5gw3a\",\n\t\t\t       &pwr_info->pa_5g[3], 0, fallback);\n\t\tnvram_read_u16(prefix, postfix, \"pa5glw3a\",\n\t\t\t       &pwr_info->pa_5gl[3], 0, fallback);\n\t\tnvram_read_u16(prefix, postfix, \"pa5ghw3a\",\n\t\t\t       &pwr_info->pa_5gh[3], 0, fallback);\n\t}\n}\n\nstatic bool bcm47xx_is_valid_mac(u8 *mac)\n{\n\treturn mac && !(mac[0] == 0x00 && mac[1] == 0x90 && mac[2] == 0x4c);\n}\n\nstatic int bcm47xx_increase_mac_addr(u8 *mac, u8 num)\n{\n\tu8 *oui = mac + ETH_ALEN/2 - 1;\n\tu8 *p = mac + ETH_ALEN - 1;\n\n\tdo {\n\t\t(*p) += num;\n\t\tif (*p > num)\n\t\t\tbreak;\n\t\tp--;\n\t\tnum = 1;\n\t} while (p != oui);\n\n\tif (p == oui) {\n\t\tpr_err(\"unable to fetch mac address\\n\");\n\t\treturn -ENOENT;\n\t}\n\treturn 0;\n}\n\nstatic int mac_addr_used = 2;\n\nstatic void bcm47xx_fill_sprom_ethernet(struct ssb_sprom *sprom,\n\t\t\t\t\tconst char *prefix, bool fallback)\n{\n\tbool fb = fallback;\n\n\tnvram_read_macaddr(prefix, \"et0macaddr\", sprom->et0mac, fallback);\n\tnvram_read_u8(prefix, NULL, \"et0mdcport\", &sprom->et0mdcport, 0,\n\t\t      fallback);\n\tnvram_read_u8(prefix, NULL, \"et0phyaddr\", &sprom->et0phyaddr, 0,\n\t\t      fallback);\n\n\tnvram_read_macaddr(prefix, \"et1macaddr\", sprom->et1mac, fallback);\n\tnvram_read_u8(prefix, NULL, \"et1mdcport\", &sprom->et1mdcport, 0,\n\t\t      fallback);\n\tnvram_read_u8(prefix, NULL, \"et1phyaddr\", &sprom->et1phyaddr, 0,\n\t\t      fallback);\n\n\tnvram_read_macaddr(prefix, \"et2macaddr\", sprom->et2mac, fb);\n\tnvram_read_u8(prefix, NULL, \"et2mdcport\", &sprom->et2mdcport, 0, fb);\n\tnvram_read_u8(prefix, NULL, \"et2phyaddr\", &sprom->et2phyaddr, 0, fb);\n\n\tnvram_read_macaddr(prefix, \"macaddr\", sprom->il0mac, fallback);\n\tnvram_read_macaddr(prefix, \"il0macaddr\", sprom->il0mac, fallback);\n\n\t/* The address prefix 00:90:4C is used by Broadcom in their initial\n\t * configuration. When a mac address with the prefix 00:90:4C is used\n\t * all devices from the same series are sharing the same mac address.\n\t * To prevent mac address collisions we replace them with a mac address\n\t * based on the base address.\n\t */\n\tif (!bcm47xx_is_valid_mac(sprom->il0mac)) {\n\t\tu8 mac[6];\n\n\t\tnvram_read_macaddr(NULL, \"et0macaddr\", mac, false);\n\t\tif (bcm47xx_is_valid_mac(mac)) {\n\t\t\tint err = bcm47xx_increase_mac_addr(mac, mac_addr_used);\n\n\t\t\tif (!err) {\n\t\t\t\tether_addr_copy(sprom->il0mac, mac);\n\t\t\t\tmac_addr_used++;\n\t\t\t}\n\t\t}\n\t}\n}\n\nstatic void bcm47xx_fill_board_data(struct ssb_sprom *sprom, const char *prefix,\n\t\t\t\t    bool fallback)\n{\n\tnvram_read_u32_2(prefix, \"boardflags\", &sprom->boardflags_lo,\n\t\t\t &sprom->boardflags_hi, fallback);\n\tnvram_read_u32_2(prefix, \"boardflags2\", &sprom->boardflags2_lo,\n\t\t\t &sprom->boardflags2_hi, fallback);\n}\n\nvoid bcm47xx_fill_sprom(struct ssb_sprom *sprom, const char *prefix,\n\t\t\tbool fallback)\n{\n\tbcm47xx_fill_sprom_ethernet(sprom, prefix, fallback);\n\tbcm47xx_fill_board_data(sprom, prefix, fallback);\n\n\tnvram_read_u8(prefix, NULL, \"sromrev\", &sprom->revision, 0, fallback);\n\n\t/* Entries requiring custom functions */\n\tnvram_read_alpha2(prefix, \"ccode\", sprom->alpha2, fallback);\n\tif (sprom->revision >= 3)\n\t\tnvram_read_leddc(prefix, \"leddc\", &sprom->leddc_on_time,\n\t\t\t\t &sprom->leddc_off_time, fallback);\n\n\tswitch (sprom->revision) {\n\tcase 4:\n\tcase 5:\n\t\tbcm47xx_fill_sprom_path_r4589(sprom, prefix, fallback);\n\t\tbcm47xx_fill_sprom_path_r45(sprom, prefix, fallback);\n\t\tbreak;\n\tcase 8:\n\tcase 9:\n\t\tbcm47xx_fill_sprom_path_r4589(sprom, prefix, fallback);\n\t\tbreak;\n\t}\n\n\tbcm47xx_sprom_fill_auto(sprom, prefix, fallback);\n}\n\n#if IS_BUILTIN(CONFIG_SSB) && IS_ENABLED(CONFIG_SSB_SPROM)\nstatic int bcm47xx_get_sprom_ssb(struct ssb_bus *bus, struct ssb_sprom *out)\n{\n\tchar prefix[10];\n\n\tswitch (bus->bustype) {\n\tcase SSB_BUSTYPE_SSB:\n\t\tbcm47xx_fill_sprom(out, NULL, false);\n\t\treturn 0;\n\tcase SSB_BUSTYPE_PCI:\n\t\tmemset(out, 0, sizeof(struct ssb_sprom));\n\t\tsnprintf(prefix, sizeof(prefix), \"pci/%u/%u/\",\n\t\t\t bus->host_pci->bus->number + 1,\n\t\t\t PCI_SLOT(bus->host_pci->devfn));\n\t\tbcm47xx_fill_sprom(out, prefix, false);\n\t\treturn 0;\n\tdefault:\n\t\tpr_warn(\"Unable to fill SPROM for given bustype.\\n\");\n\t\treturn -EINVAL;\n\t}\n}\n#endif\n\n#if IS_BUILTIN(CONFIG_BCMA)\n/*\n * Having many NVRAM entries for PCI devices led to repeating prefixes like\n * pci/1/1/ all the time and wasting flash space. So at some point Broadcom\n * decided to introduce prefixes like 0: 1: 2: etc.\n * If we find e.g. devpath0=pci/2/1 or devpath0=pci/2/1/ we should use 0:\n * instead of pci/2/1/.\n */\nstatic void bcm47xx_sprom_apply_prefix_alias(char *prefix, size_t prefix_size)\n{\n\tsize_t prefix_len = strlen(prefix);\n\tsize_t short_len = prefix_len - 1;\n\tchar nvram_var[10];\n\tchar buf[20];\n\tint i;\n\n\t/* Passed prefix has to end with a slash */\n\tif (prefix_len <= 0 || prefix[prefix_len - 1] != '/')\n\t\treturn;\n\n\tfor (i = 0; i < 3; i++) {\n\t\tif (snprintf(nvram_var, sizeof(nvram_var), \"devpath%d\", i) <= 0)\n\t\t\tcontinue;\n\t\tif (bcm47xx_nvram_getenv(nvram_var, buf, sizeof(buf)) < 0)\n\t\t\tcontinue;\n\t\tif (!strcmp(buf, prefix) ||\n\t\t    (short_len && strlen(buf) == short_len && !strncmp(buf, prefix, short_len))) {\n\t\t\tsnprintf(prefix, prefix_size, \"%d:\", i);\n\t\t\treturn;\n\t\t}\n\t}\n}\n\nstatic int bcm47xx_get_sprom_bcma(struct bcma_bus *bus, struct ssb_sprom *out)\n{\n\tstruct bcma_boardinfo *binfo = &bus->boardinfo;\n\tstruct bcma_device *core;\n\tchar buf[10];\n\tchar *prefix;\n\tbool fallback = false;\n\n\tswitch (bus->hosttype) {\n\tcase BCMA_HOSTTYPE_PCI:\n\t\tmemset(out, 0, sizeof(struct ssb_sprom));\n\t\t/* On BCM47XX all PCI buses share the same domain */\n\t\tif (IS_ENABLED(CONFIG_BCM47XX))\n\t\t\tsnprintf(buf, sizeof(buf), \"pci/%u/%u/\",\n\t\t\t\t bus->host_pci->bus->number + 1,\n\t\t\t\t PCI_SLOT(bus->host_pci->devfn));\n\t\telse\n\t\t\tsnprintf(buf, sizeof(buf), \"pci/%u/%u/\",\n\t\t\t\t pci_domain_nr(bus->host_pci->bus) + 1,\n\t\t\t\t bus->host_pci->bus->number);\n\t\tbcm47xx_sprom_apply_prefix_alias(buf, sizeof(buf));\n\t\tprefix = buf;\n\t\tbreak;\n\tcase BCMA_HOSTTYPE_SOC:\n\t\tmemset(out, 0, sizeof(struct ssb_sprom));\n\t\tcore = bcma_find_core(bus, BCMA_CORE_80211);\n\t\tif (core) {\n\t\t\tsnprintf(buf, sizeof(buf), \"sb/%u/\",\n\t\t\t\t core->core_index);\n\t\t\tprefix = buf;\n\t\t\tfallback = true;\n\t\t} else {\n\t\t\tprefix = NULL;\n\t\t}\n\t\tbreak;\n\tdefault:\n\t\tpr_warn(\"Unable to fill SPROM for given bustype.\\n\");\n\t\treturn -EINVAL;\n\t}\n\n\tnvram_read_u16(prefix, NULL, \"boardvendor\", &binfo->vendor, 0, true);\n\tif (!binfo->vendor)\n\t\tbinfo->vendor = SSB_BOARDVENDOR_BCM;\n\tnvram_read_u16(prefix, NULL, \"boardtype\", &binfo->type, 0, true);\n\n\tbcm47xx_fill_sprom(out, prefix, fallback);\n\n\treturn 0;\n}\n#endif\n\nstatic unsigned int bcm47xx_sprom_registered;\n\n/*\n * On bcm47xx we need to register SPROM fallback handler very early, so we can't\n * use anything like platform device / driver for this.\n */\nint bcm47xx_sprom_register_fallbacks(void)\n{\n\tif (bcm47xx_sprom_registered)\n\t\treturn 0;\n\n#if IS_BUILTIN(CONFIG_SSB) && IS_ENABLED(CONFIG_SSB_SPROM)\n\tif (ssb_arch_register_fallback_sprom(&bcm47xx_get_sprom_ssb))\n\t\tpr_warn(\"Failed to register ssb SPROM handler\\n\");\n#endif\n\n#if IS_BUILTIN(CONFIG_BCMA)\n\tif (bcma_arch_register_fallback_sprom(&bcm47xx_get_sprom_bcma))\n\t\tpr_warn(\"Failed to register bcma SPROM handler\\n\");\n#endif\n\n\tbcm47xx_sprom_registered = 1;\n\n\treturn 0;\n}\n\nfs_initcall(bcm47xx_sprom_register_fallbacks);\n"
  },
  {
    "path": "t/tree/drivers/i2c/i2c-boardinfo.c",
    "content": "// SPDX-License-Identifier: GPL-2.0-or-later\n/*\n * i2c-boardinfo.c - collect pre-declarations of I2C devices\n */\n\n#include <linux/export.h>\n#include <linux/i2c.h>\n#include <linux/kernel.h>\n#include <linux/property.h>\n#include <linux/rwsem.h>\n#include <linux/slab.h>\n\n#include \"i2c-core.h\"\n\n\n/* These symbols are exported ONLY FOR the i2c core.\n * No other users will be supported.\n */\nDECLARE_RWSEM(__i2c_board_lock);\nEXPORT_SYMBOL_GPL(__i2c_board_lock);\n\nLIST_HEAD(__i2c_board_list);\nEXPORT_SYMBOL_GPL(__i2c_board_list);\n\nint __i2c_first_dynamic_bus_num;\nEXPORT_SYMBOL_GPL(__i2c_first_dynamic_bus_num);\n\n\n/**\n * i2c_register_board_info - statically declare I2C devices\n * @busnum: identifies the bus to which these devices belong\n * @info: vector of i2c device descriptors\n * @len: how many descriptors in the vector; may be zero to reserve\n *\tthe specified bus number.\n *\n * Systems using the Linux I2C driver stack can declare tables of board info\n * while they initialize.  This should be done in board-specific init code\n * near arch_initcall() time, or equivalent, before any I2C adapter driver is\n * registered.  For example, mainboard init code could define several devices,\n * as could the init code for each daughtercard in a board stack.\n *\n * The I2C devices will be created later, after the adapter for the relevant\n * bus has been registered.  After that moment, standard driver model tools\n * are used to bind \"new style\" I2C drivers to the devices.  The bus number\n * for any device declared using this routine is not available for dynamic\n * allocation.\n *\n * The board info passed can safely be __initdata, but be careful of embedded\n * pointers (for platform_data, functions, etc) since that won't be copied.\n * Device properties are deep-copied though.\n */\nint i2c_register_board_info(int busnum, struct i2c_board_info const *info, unsigned len)\n{\n\tint status;\n\n\tdown_write(&__i2c_board_lock);\n\n\t/* dynamic bus numbers will be assigned after the last static one */\n\tif (busnum >= __i2c_first_dynamic_bus_num)\n\t\t__i2c_first_dynamic_bus_num = busnum + 1;\n\n\tfor (status = 0; len; len--, info++) {\n\t\tstruct i2c_devinfo\t*devinfo;\n\n\t\tdevinfo = kzalloc(sizeof(*devinfo), GFP_KERNEL);\n\t\tif (!devinfo) {\n\t\t\tpr_debug(\"i2c-core: can't register boardinfo!\\n\");\n\t\t\tstatus = -ENOMEM;\n\t\t\tbreak;\n\t\t}\n\n\t\tdevinfo->busnum = busnum;\n\t\tdevinfo->board_info = *info;\n\n\t\tif (info->properties) {\n\t\t\tdevinfo->board_info.properties =\n\t\t\t\t\tproperty_entries_dup(info->properties);\n\t\t\tif (IS_ERR(devinfo->board_info.properties)) {\n\t\t\t\tstatus = PTR_ERR(devinfo->board_info.properties);\n\t\t\t\tkfree(devinfo);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\tif (info->resources) {\n\t\t\tdevinfo->board_info.resources =\n\t\t\t\tkmemdup(info->resources,\n\t\t\t\t\tinfo->num_resources *\n\t\t\t\t\t\tsizeof(*info->resources),\n\t\t\t\t\tGFP_KERNEL);\n\t\t\tif (!devinfo->board_info.resources) {\n\t\t\t\tstatus = -ENOMEM;\n\t\t\t\tkfree(devinfo);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\tlist_add_tail(&devinfo->list, &__i2c_board_list);\n\t}\n\n\tup_write(&__i2c_board_lock);\n\n\treturn status;\n}\n"
  },
  {
    "path": "t/tree/drivers/i2c/i2c-core-acpi.c",
    "content": "// SPDX-License-Identifier: GPL-2.0-or-later\n/*\n * Linux I2C core ACPI support code\n *\n * Copyright (C) 2014 Intel Corp, Author: Lan Tianyu <tianyu.lan@intel.com>\n */\n\n#include <linux/acpi.h>\n#include <linux/device.h>\n#include <linux/err.h>\n#include <linux/i2c.h>\n#include <linux/list.h>\n#include <linux/module.h>\n#include <linux/slab.h>\n\n#include \"i2c-core.h\"\n\nstruct i2c_acpi_handler_data {\n\tstruct acpi_connection_info info;\n\tstruct i2c_adapter *adapter;\n};\n\nstruct gsb_buffer {\n\tu8\tstatus;\n\tu8\tlen;\n\tunion {\n\t\tu16\twdata;\n\t\tu8\tbdata;\n\t\tu8\tdata[0];\n\t};\n} __packed;\n\nstruct i2c_acpi_lookup {\n\tstruct i2c_board_info *info;\n\tacpi_handle adapter_handle;\n\tacpi_handle device_handle;\n\tacpi_handle search_handle;\n\tint n;\n\tint index;\n\tu32 speed;\n\tu32 min_speed;\n\tu32 force_speed;\n};\n\n/**\n * i2c_acpi_get_i2c_resource - Gets I2cSerialBus resource if type matches\n * @ares:\tACPI resource\n * @i2c:\tPointer to I2cSerialBus resource will be returned here\n *\n * Checks if the given ACPI resource is of type I2cSerialBus.\n * In this case, returns a pointer to it to the caller.\n *\n * Returns true if resource type is of I2cSerialBus, otherwise false.\n */\nbool i2c_acpi_get_i2c_resource(struct acpi_resource *ares,\n\t\t\t       struct acpi_resource_i2c_serialbus **i2c)\n{\n\tstruct acpi_resource_i2c_serialbus *sb;\n\n\tif (ares->type != ACPI_RESOURCE_TYPE_SERIAL_BUS)\n\t\treturn false;\n\n\tsb = &ares->data.i2c_serial_bus;\n\tif (sb->type != ACPI_RESOURCE_SERIAL_TYPE_I2C)\n\t\treturn false;\n\n\t*i2c = sb;\n\treturn true;\n}\nEXPORT_SYMBOL_GPL(i2c_acpi_get_i2c_resource);\n\nstatic int i2c_acpi_fill_info(struct acpi_resource *ares, void *data)\n{\n\tstruct i2c_acpi_lookup *lookup = data;\n\tstruct i2c_board_info *info = lookup->info;\n\tstruct acpi_resource_i2c_serialbus *sb;\n\tacpi_status status;\n\n\tif (info->addr || !i2c_acpi_get_i2c_resource(ares, &sb))\n\t\treturn 1;\n\n\tif (lookup->index != -1 && lookup->n++ != lookup->index)\n\t\treturn 1;\n\n\tstatus = acpi_get_handle(lookup->device_handle,\n\t\t\t\t sb->resource_source.string_ptr,\n\t\t\t\t &lookup->adapter_handle);\n\tif (ACPI_FAILURE(status))\n\t\treturn 1;\n\n\tinfo->addr = sb->slave_address;\n\tlookup->speed = sb->connection_speed;\n\tif (sb->access_mode == ACPI_I2C_10BIT_MODE)\n\t\tinfo->flags |= I2C_CLIENT_TEN;\n\n\treturn 1;\n}\n\nstatic const struct acpi_device_id i2c_acpi_ignored_device_ids[] = {\n\t/*\n\t * ACPI video acpi_devices, which are handled by the acpi-video driver\n\t * sometimes contain a SERIAL_TYPE_I2C ACPI resource, ignore these.\n\t */\n\t{ ACPI_VIDEO_HID, 0 },\n\t{}\n};\n\nstatic int i2c_acpi_do_lookup(struct acpi_device *adev,\n\t\t\t      struct i2c_acpi_lookup *lookup)\n{\n\tstruct i2c_board_info *info = lookup->info;\n\tstruct list_head resource_list;\n\tint ret;\n\n\tif (acpi_bus_get_status(adev) || !adev->status.present)\n\t\treturn -EINVAL;\n\n\tif (acpi_match_device_ids(adev, i2c_acpi_ignored_device_ids) == 0)\n\t\treturn -ENODEV;\n\n\tmemset(info, 0, sizeof(*info));\n\tlookup->device_handle = acpi_device_handle(adev);\n\n\t/* Look up for I2cSerialBus resource */\n\tINIT_LIST_HEAD(&resource_list);\n\tret = acpi_dev_get_resources(adev, &resource_list,\n\t\t\t\t     i2c_acpi_fill_info, lookup);\n\tacpi_dev_free_resource_list(&resource_list);\n\n\tif (ret < 0 || !info->addr)\n\t\treturn -EINVAL;\n\n\treturn 0;\n}\n\nstatic int i2c_acpi_add_resource(struct acpi_resource *ares, void *data)\n{\n\tint *irq = data;\n\tstruct resource r;\n\n\tif (*irq <= 0 && acpi_dev_resource_interrupt(ares, 0, &r))\n\t\t*irq = i2c_dev_irq_from_resources(&r, 1);\n\n\treturn 1; /* No need to add resource to the list */\n}\n\n/**\n * i2c_acpi_get_irq - get device IRQ number from ACPI\n * @client: Pointer to the I2C client device\n *\n * Find the IRQ number used by a specific client device.\n *\n * Return: The IRQ number or an error code.\n */\nint i2c_acpi_get_irq(struct i2c_client *client)\n{\n\tstruct acpi_device *adev = ACPI_COMPANION(&client->dev);\n\tstruct list_head resource_list;\n\tint irq = -ENOENT;\n\tint ret;\n\n\tINIT_LIST_HEAD(&resource_list);\n\n\tret = acpi_dev_get_resources(adev, &resource_list,\n\t\t\t\t     i2c_acpi_add_resource, &irq);\n\tif (ret < 0)\n\t\treturn ret;\n\n\tacpi_dev_free_resource_list(&resource_list);\n\n\tif (irq == -ENOENT)\n\t\tirq = acpi_dev_gpio_irq_get(adev, 0);\n\n\treturn irq;\n}\n\nstatic int i2c_acpi_get_info(struct acpi_device *adev,\n\t\t\t     struct i2c_board_info *info,\n\t\t\t     struct i2c_adapter *adapter,\n\t\t\t     acpi_handle *adapter_handle)\n{\n\tstruct i2c_acpi_lookup lookup;\n\tint ret;\n\n\tmemset(&lookup, 0, sizeof(lookup));\n\tlookup.info = info;\n\tlookup.index = -1;\n\n\tif (acpi_device_enumerated(adev))\n\t\treturn -EINVAL;\n\n\tret = i2c_acpi_do_lookup(adev, &lookup);\n\tif (ret)\n\t\treturn ret;\n\n\tif (adapter) {\n\t\t/* The adapter must match the one in I2cSerialBus() connector */\n\t\tif (ACPI_HANDLE(&adapter->dev) != lookup.adapter_handle)\n\t\t\treturn -ENODEV;\n\t} else {\n\t\tstruct acpi_device *adapter_adev;\n\n\t\t/* The adapter must be present */\n\t\tif (acpi_bus_get_device(lookup.adapter_handle, &adapter_adev))\n\t\t\treturn -ENODEV;\n\t\tif (acpi_bus_get_status(adapter_adev) ||\n\t\t    !adapter_adev->status.present)\n\t\t\treturn -ENODEV;\n\t}\n\n\tinfo->fwnode = acpi_fwnode_handle(adev);\n\tif (adapter_handle)\n\t\t*adapter_handle = lookup.adapter_handle;\n\n\tacpi_set_modalias(adev, dev_name(&adev->dev), info->type,\n\t\t\t  sizeof(info->type));\n\n\treturn 0;\n}\n\nstatic void i2c_acpi_register_device(struct i2c_adapter *adapter,\n\t\t\t\t     struct acpi_device *adev,\n\t\t\t\t     struct i2c_board_info *info)\n{\n\tadev->power.flags.ignore_parent = true;\n\tacpi_device_set_enumerated(adev);\n\n\tif (!i2c_new_device(adapter, info)) {\n\t\tadev->power.flags.ignore_parent = false;\n\t\tdev_err(&adapter->dev,\n\t\t\t\"failed to add I2C device %s from ACPI\\n\",\n\t\t\tdev_name(&adev->dev));\n\t}\n}\n\nstatic acpi_status i2c_acpi_add_device(acpi_handle handle, u32 level,\n\t\t\t\t       void *data, void **return_value)\n{\n\tstruct i2c_adapter *adapter = data;\n\tstruct acpi_device *adev;\n\tstruct i2c_board_info info;\n\n\tif (acpi_bus_get_device(handle, &adev))\n\t\treturn AE_OK;\n\n\tif (i2c_acpi_get_info(adev, &info, adapter, NULL))\n\t\treturn AE_OK;\n\n\ti2c_acpi_register_device(adapter, adev, &info);\n\n\treturn AE_OK;\n}\n\n#define I2C_ACPI_MAX_SCAN_DEPTH 32\n\n/**\n * i2c_acpi_register_devices - enumerate I2C slave devices behind adapter\n * @adap: pointer to adapter\n *\n * Enumerate all I2C slave devices behind this adapter by walking the ACPI\n * namespace. When a device is found it will be added to the Linux device\n * model and bound to the corresponding ACPI handle.\n */\nvoid i2c_acpi_register_devices(struct i2c_adapter *adap)\n{\n\tacpi_status status;\n\n\tif (!has_acpi_companion(&adap->dev))\n\t\treturn;\n\n\tstatus = acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,\n\t\t\t\t     I2C_ACPI_MAX_SCAN_DEPTH,\n\t\t\t\t     i2c_acpi_add_device, NULL,\n\t\t\t\t     adap, NULL);\n\tif (ACPI_FAILURE(status))\n\t\tdev_warn(&adap->dev, \"failed to enumerate I2C slaves\\n\");\n}\n\nconst struct acpi_device_id *\ni2c_acpi_match_device(const struct acpi_device_id *matches,\n\t\t      struct i2c_client *client)\n{\n\tif (!(client && matches))\n\t\treturn NULL;\n\n\treturn acpi_match_device(matches, &client->dev);\n}\n\nstatic const struct acpi_device_id i2c_acpi_force_400khz_device_ids[] = {\n\t/*\n\t * These Silead touchscreen controllers only work at 400KHz, for\n\t * some reason they do not work at 100KHz. On some devices the ACPI\n\t * tables list another device at their bus as only being capable\n\t * of 100KHz, testing has shown that these other devices work fine\n\t * at 400KHz (as can be expected of any recent i2c hw) so we force\n\t * the speed of the bus to 400 KHz if a Silead device is present.\n\t */\n\t{ \"MSSL1680\", 0 },\n\t{}\n};\n\nstatic acpi_status i2c_acpi_lookup_speed(acpi_handle handle, u32 level,\n\t\t\t\t\t   void *data, void **return_value)\n{\n\tstruct i2c_acpi_lookup *lookup = data;\n\tstruct acpi_device *adev;\n\n\tif (acpi_bus_get_device(handle, &adev))\n\t\treturn AE_OK;\n\n\tif (i2c_acpi_do_lookup(adev, lookup))\n\t\treturn AE_OK;\n\n\tif (lookup->search_handle != lookup->adapter_handle)\n\t\treturn AE_OK;\n\n\tif (lookup->speed <= lookup->min_speed)\n\t\tlookup->min_speed = lookup->speed;\n\n\tif (acpi_match_device_ids(adev, i2c_acpi_force_400khz_device_ids) == 0)\n\t\tlookup->force_speed = 400000;\n\n\treturn AE_OK;\n}\n\n/**\n * i2c_acpi_find_bus_speed - find I2C bus speed from ACPI\n * @dev: The device owning the bus\n *\n * Find the I2C bus speed by walking the ACPI namespace for all I2C slaves\n * devices connected to this bus and use the speed of slowest device.\n *\n * Returns the speed in Hz or zero\n */\nu32 i2c_acpi_find_bus_speed(struct device *dev)\n{\n\tstruct i2c_acpi_lookup lookup;\n\tstruct i2c_board_info dummy;\n\tacpi_status status;\n\n\tif (!has_acpi_companion(dev))\n\t\treturn 0;\n\n\tmemset(&lookup, 0, sizeof(lookup));\n\tlookup.search_handle = ACPI_HANDLE(dev);\n\tlookup.min_speed = UINT_MAX;\n\tlookup.info = &dummy;\n\tlookup.index = -1;\n\n\tstatus = acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,\n\t\t\t\t     I2C_ACPI_MAX_SCAN_DEPTH,\n\t\t\t\t     i2c_acpi_lookup_speed, NULL,\n\t\t\t\t     &lookup, NULL);\n\n\tif (ACPI_FAILURE(status)) {\n\t\tdev_warn(dev, \"unable to find I2C bus speed from ACPI\\n\");\n\t\treturn 0;\n\t}\n\n\tif (lookup.force_speed) {\n\t\tif (lookup.force_speed != lookup.min_speed)\n\t\t\tdev_warn(dev, FW_BUG \"DSDT uses known not-working I2C bus speed %d, forcing it to %d\\n\",\n\t\t\t\t lookup.min_speed, lookup.force_speed);\n\t\treturn lookup.force_speed;\n\t} else if (lookup.min_speed != UINT_MAX) {\n\t\treturn lookup.min_speed;\n\t} else {\n\t\treturn 0;\n\t}\n}\nEXPORT_SYMBOL_GPL(i2c_acpi_find_bus_speed);\n\nstatic int i2c_acpi_find_match_adapter(struct device *dev, const void *data)\n{\n\tstruct i2c_adapter *adapter = i2c_verify_adapter(dev);\n\n\tif (!adapter)\n\t\treturn 0;\n\n\treturn ACPI_HANDLE(dev) == (acpi_handle)data;\n}\n\nstruct i2c_adapter *i2c_acpi_find_adapter_by_handle(acpi_handle handle)\n{\n\tstruct device *dev;\n\n\tdev = bus_find_device(&i2c_bus_type, NULL, handle,\n\t\t\t      i2c_acpi_find_match_adapter);\n\n\treturn dev ? i2c_verify_adapter(dev) : NULL;\n}\nEXPORT_SYMBOL_GPL(i2c_acpi_find_adapter_by_handle);\n\nstatic struct i2c_client *i2c_acpi_find_client_by_adev(struct acpi_device *adev)\n{\n\tstruct device *dev;\n\n\tdev = bus_find_device_by_acpi_dev(&i2c_bus_type, adev);\n\treturn dev ? i2c_verify_client(dev) : NULL;\n}\n\nstatic int i2c_acpi_notify(struct notifier_block *nb, unsigned long value,\n\t\t\t   void *arg)\n{\n\tstruct acpi_device *adev = arg;\n\tstruct i2c_board_info info;\n\tacpi_handle adapter_handle;\n\tstruct i2c_adapter *adapter;\n\tstruct i2c_client *client;\n\n\tswitch (value) {\n\tcase ACPI_RECONFIG_DEVICE_ADD:\n\t\tif (i2c_acpi_get_info(adev, &info, NULL, &adapter_handle))\n\t\t\tbreak;\n\n\t\tadapter = i2c_acpi_find_adapter_by_handle(adapter_handle);\n\t\tif (!adapter)\n\t\t\tbreak;\n\n\t\ti2c_acpi_register_device(adapter, adev, &info);\n\t\tbreak;\n\tcase ACPI_RECONFIG_DEVICE_REMOVE:\n\t\tif (!acpi_device_enumerated(adev))\n\t\t\tbreak;\n\n\t\tclient = i2c_acpi_find_client_by_adev(adev);\n\t\tif (!client)\n\t\t\tbreak;\n\n\t\ti2c_unregister_device(client);\n\t\tput_device(&client->dev);\n\t\tbreak;\n\t}\n\n\treturn NOTIFY_OK;\n}\n\nstruct notifier_block i2c_acpi_notifier = {\n\t.notifier_call = i2c_acpi_notify,\n};\n\n/**\n * i2c_acpi_new_device - Create i2c-client for the Nth I2cSerialBus resource\n * @dev:     Device owning the ACPI resources to get the client from\n * @index:   Index of ACPI resource to get\n * @info:    describes the I2C device; note this is modified (addr gets set)\n * Context: can sleep\n *\n * By default the i2c subsys creates an i2c-client for the first I2cSerialBus\n * resource of an acpi_device, but some acpi_devices have multiple I2cSerialBus\n * resources, in that case this function can be used to create an i2c-client\n * for other I2cSerialBus resources in the Current Resource Settings table.\n *\n * Also see i2c_new_device, which this function calls to create the i2c-client.\n *\n * Returns a pointer to the new i2c-client, or error pointer in case of failure.\n * Specifically, -EPROBE_DEFER is returned if the adapter is not found.\n */\nstruct i2c_client *i2c_acpi_new_device(struct device *dev, int index,\n\t\t\t\t       struct i2c_board_info *info)\n{\n\tstruct i2c_acpi_lookup lookup;\n\tstruct i2c_adapter *adapter;\n\tstruct i2c_client *client;\n\tstruct acpi_device *adev;\n\tLIST_HEAD(resource_list);\n\tint ret;\n\n\tadev = ACPI_COMPANION(dev);\n\tif (!adev)\n\t\treturn ERR_PTR(-EINVAL);\n\n\tmemset(&lookup, 0, sizeof(lookup));\n\tlookup.info = info;\n\tlookup.device_handle = acpi_device_handle(adev);\n\tlookup.index = index;\n\n\tret = acpi_dev_get_resources(adev, &resource_list,\n\t\t\t\t     i2c_acpi_fill_info, &lookup);\n\tif (ret < 0)\n\t\treturn ERR_PTR(ret);\n\n\tacpi_dev_free_resource_list(&resource_list);\n\n\tif (!info->addr)\n\t\treturn ERR_PTR(-EADDRNOTAVAIL);\n\n\tadapter = i2c_acpi_find_adapter_by_handle(lookup.adapter_handle);\n\tif (!adapter)\n\t\treturn ERR_PTR(-EPROBE_DEFER);\n\n\tclient = i2c_new_device(adapter, info);\n\tif (!client)\n\t\treturn ERR_PTR(-ENODEV);\n\n\treturn client;\n}\nEXPORT_SYMBOL_GPL(i2c_acpi_new_device);\n\n#ifdef CONFIG_ACPI_I2C_OPREGION\nstatic int acpi_gsb_i2c_read_bytes(struct i2c_client *client,\n\t\tu8 cmd, u8 *data, u8 data_len)\n{\n\n\tstruct i2c_msg msgs[2];\n\tint ret;\n\tu8 *buffer;\n\n\tbuffer = kzalloc(data_len, GFP_KERNEL);\n\tif (!buffer)\n\t\treturn AE_NO_MEMORY;\n\n\tmsgs[0].addr = client->addr;\n\tmsgs[0].flags = client->flags;\n\tmsgs[0].len = 1;\n\tmsgs[0].buf = &cmd;\n\n\tmsgs[1].addr = client->addr;\n\tmsgs[1].flags = client->flags | I2C_M_RD;\n\tmsgs[1].len = data_len;\n\tmsgs[1].buf = buffer;\n\n\tret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));\n\tif (ret < 0) {\n\t\t/* Getting a NACK is unfortunately normal with some DSTDs */\n\t\tif (ret == -EREMOTEIO)\n\t\t\tdev_dbg(&client->adapter->dev, \"i2c read %d bytes from client@%#x starting at reg %#x failed, error: %d\\n\",\n\t\t\t\tdata_len, client->addr, cmd, ret);\n\t\telse\n\t\t\tdev_err(&client->adapter->dev, \"i2c read %d bytes from client@%#x starting at reg %#x failed, error: %d\\n\",\n\t\t\t\tdata_len, client->addr, cmd, ret);\n\t/* 2 transfers must have completed successfully */\n\t} else if (ret == 2) {\n\t\tmemcpy(data, buffer, data_len);\n\t\tret = 0;\n\t} else {\n\t\tret = -EIO;\n\t}\n\n\tkfree(buffer);\n\treturn ret;\n}\n\nstatic int acpi_gsb_i2c_write_bytes(struct i2c_client *client,\n\t\tu8 cmd, u8 *data, u8 data_len)\n{\n\n\tstruct i2c_msg msgs[1];\n\tu8 *buffer;\n\tint ret = AE_OK;\n\n\tbuffer = kzalloc(data_len + 1, GFP_KERNEL);\n\tif (!buffer)\n\t\treturn AE_NO_MEMORY;\n\n\tbuffer[0] = cmd;\n\tmemcpy(buffer + 1, data, data_len);\n\n\tmsgs[0].addr = client->addr;\n\tmsgs[0].flags = client->flags;\n\tmsgs[0].len = data_len + 1;\n\tmsgs[0].buf = buffer;\n\n\tret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));\n\n\tkfree(buffer);\n\n\tif (ret < 0) {\n\t\tdev_err(&client->adapter->dev, \"i2c write failed: %d\\n\", ret);\n\t\treturn ret;\n\t}\n\n\t/* 1 transfer must have completed successfully */\n\treturn (ret == 1) ? 0 : -EIO;\n}\n\nstatic acpi_status\ni2c_acpi_space_handler(u32 function, acpi_physical_address command,\n\t\t\tu32 bits, u64 *value64,\n\t\t\tvoid *handler_context, void *region_context)\n{\n\tstruct gsb_buffer *gsb = (struct gsb_buffer *)value64;\n\tstruct i2c_acpi_handler_data *data = handler_context;\n\tstruct acpi_connection_info *info = &data->info;\n\tstruct acpi_resource_i2c_serialbus *sb;\n\tstruct i2c_adapter *adapter = data->adapter;\n\tstruct i2c_client *client;\n\tstruct acpi_resource *ares;\n\tu32 accessor_type = function >> 16;\n\tu8 action = function & ACPI_IO_MASK;\n\tacpi_status ret;\n\tint status;\n\n\tret = acpi_buffer_to_resource(info->connection, info->length, &ares);\n\tif (ACPI_FAILURE(ret))\n\t\treturn ret;\n\n\tclient = kzalloc(sizeof(*client), GFP_KERNEL);\n\tif (!client) {\n\t\tret = AE_NO_MEMORY;\n\t\tgoto err;\n\t}\n\n\tif (!value64 || !i2c_acpi_get_i2c_resource(ares, &sb)) {\n\t\tret = AE_BAD_PARAMETER;\n\t\tgoto err;\n\t}\n\n\tclient->adapter = adapter;\n\tclient->addr = sb->slave_address;\n\n\tif (sb->access_mode == ACPI_I2C_10BIT_MODE)\n\t\tclient->flags |= I2C_CLIENT_TEN;\n\n\tswitch (accessor_type) {\n\tcase ACPI_GSB_ACCESS_ATTRIB_SEND_RCV:\n\t\tif (action == ACPI_READ) {\n\t\t\tstatus = i2c_smbus_read_byte(client);\n\t\t\tif (status >= 0) {\n\t\t\t\tgsb->bdata = status;\n\t\t\t\tstatus = 0;\n\t\t\t}\n\t\t} else {\n\t\t\tstatus = i2c_smbus_write_byte(client, gsb->bdata);\n\t\t}\n\t\tbreak;\n\n\tcase ACPI_GSB_ACCESS_ATTRIB_BYTE:\n\t\tif (action == ACPI_READ) {\n\t\t\tstatus = i2c_smbus_read_byte_data(client, command);\n\t\t\tif (status >= 0) {\n\t\t\t\tgsb->bdata = status;\n\t\t\t\tstatus = 0;\n\t\t\t}\n\t\t} else {\n\t\t\tstatus = i2c_smbus_write_byte_data(client, command,\n\t\t\t\t\tgsb->bdata);\n\t\t}\n\t\tbreak;\n\n\tcase ACPI_GSB_ACCESS_ATTRIB_WORD:\n\t\tif (action == ACPI_READ) {\n\t\t\tstatus = i2c_smbus_read_word_data(client, command);\n\t\t\tif (status >= 0) {\n\t\t\t\tgsb->wdata = status;\n\t\t\t\tstatus = 0;\n\t\t\t}\n\t\t} else {\n\t\t\tstatus = i2c_smbus_write_word_data(client, command,\n\t\t\t\t\tgsb->wdata);\n\t\t}\n\t\tbreak;\n\n\tcase ACPI_GSB_ACCESS_ATTRIB_BLOCK:\n\t\tif (action == ACPI_READ) {\n\t\t\tstatus = i2c_smbus_read_block_data(client, command,\n\t\t\t\t\tgsb->data);\n\t\t\tif (status >= 0) {\n\t\t\t\tgsb->len = status;\n\t\t\t\tstatus = 0;\n\t\t\t}\n\t\t} else {\n\t\t\tstatus = i2c_smbus_write_block_data(client, command,\n\t\t\t\t\tgsb->len, gsb->data);\n\t\t}\n\t\tbreak;\n\n\tcase ACPI_GSB_ACCESS_ATTRIB_MULTIBYTE:\n\t\tif (action == ACPI_READ) {\n\t\t\tstatus = acpi_gsb_i2c_read_bytes(client, command,\n\t\t\t\t\tgsb->data, info->access_length);\n\t\t} else {\n\t\t\tstatus = acpi_gsb_i2c_write_bytes(client, command,\n\t\t\t\t\tgsb->data, info->access_length);\n\t\t}\n\t\tbreak;\n\n\tdefault:\n\t\tdev_warn(&adapter->dev, \"protocol 0x%02x not supported for client 0x%02x\\n\",\n\t\t\t accessor_type, client->addr);\n\t\tret = AE_BAD_PARAMETER;\n\t\tgoto err;\n\t}\n\n\tgsb->status = status;\n\n err:\n\tkfree(client);\n\tACPI_FREE(ares);\n\treturn ret;\n}\n\n\nint i2c_acpi_install_space_handler(struct i2c_adapter *adapter)\n{\n\tacpi_handle handle;\n\tstruct i2c_acpi_handler_data *data;\n\tacpi_status status;\n\n\tif (!adapter->dev.parent)\n\t\treturn -ENODEV;\n\n\thandle = ACPI_HANDLE(adapter->dev.parent);\n\n\tif (!handle)\n\t\treturn -ENODEV;\n\n\tdata = kzalloc(sizeof(struct i2c_acpi_handler_data),\n\t\t\t    GFP_KERNEL);\n\tif (!data)\n\t\treturn -ENOMEM;\n\n\tdata->adapter = adapter;\n\tstatus = acpi_bus_attach_private_data(handle, (void *)data);\n\tif (ACPI_FAILURE(status)) {\n\t\tkfree(data);\n\t\treturn -ENOMEM;\n\t}\n\n\tstatus = acpi_install_address_space_handler(handle,\n\t\t\t\tACPI_ADR_SPACE_GSBUS,\n\t\t\t\t&i2c_acpi_space_handler,\n\t\t\t\tNULL,\n\t\t\t\tdata);\n\tif (ACPI_FAILURE(status)) {\n\t\tdev_err(&adapter->dev, \"Error installing i2c space handler\\n\");\n\t\tacpi_bus_detach_private_data(handle);\n\t\tkfree(data);\n\t\treturn -ENOMEM;\n\t}\n\n\tacpi_walk_dep_device_list(handle);\n\treturn 0;\n}\n\nvoid i2c_acpi_remove_space_handler(struct i2c_adapter *adapter)\n{\n\tacpi_handle handle;\n\tstruct i2c_acpi_handler_data *data;\n\tacpi_status status;\n\n\tif (!adapter->dev.parent)\n\t\treturn;\n\n\thandle = ACPI_HANDLE(adapter->dev.parent);\n\n\tif (!handle)\n\t\treturn;\n\n\tacpi_remove_address_space_handler(handle,\n\t\t\t\tACPI_ADR_SPACE_GSBUS,\n\t\t\t\t&i2c_acpi_space_handler);\n\n\tstatus = acpi_bus_get_private_data(handle, (void **)&data);\n\tif (ACPI_SUCCESS(status))\n\t\tkfree(data);\n\n\tacpi_bus_detach_private_data(handle);\n}\n#endif /* CONFIG_ACPI_I2C_OPREGION */\n"
  },
  {
    "path": "t/tree/drivers/i2c/i2c-core-base.c",
    "content": "// SPDX-License-Identifier: GPL-2.0-or-later\n/*\n * Linux I2C core\n *\n * Copyright (C) 1995-99 Simon G. Vogl\n *   With some changes from Kyösti Mälkki <kmalkki@cc.hut.fi>\n *   Mux support by Rodolfo Giometti <giometti@enneenne.com> and\n *   Michael Lawnick <michael.lawnick.ext@nsn.com>\n *\n * Copyright (C) 2013-2017 Wolfram Sang <wsa@the-dreams.de>\n */\n\n#define pr_fmt(fmt) \"i2c-core: \" fmt\n\n#include <dt-bindings/i2c/i2c.h>\n#include <linux/acpi.h>\n#include <linux/clk/clk-conf.h>\n#include <linux/completion.h>\n#include <linux/delay.h>\n#include <linux/err.h>\n#include <linux/errno.h>\n#include <linux/gpio/consumer.h>\n#include <linux/i2c.h>\n#include <linux/i2c-smbus.h>\n#include <linux/idr.h>\n#include <linux/init.h>\n#include <linux/irqflags.h>\n#include <linux/jump_label.h>\n#include <linux/kernel.h>\n#include <linux/module.h>\n#include <linux/mutex.h>\n#include <linux/of_device.h>\n#include <linux/of.h>\n#include <linux/of_irq.h>\n#include <linux/pm_domain.h>\n#include <linux/pm_runtime.h>\n#include <linux/pm_wakeirq.h>\n#include <linux/property.h>\n#include <linux/rwsem.h>\n#include <linux/slab.h>\n\n#include \"i2c-core.h\"\n\n#define CREATE_TRACE_POINTS\n#include <trace/events/i2c.h>\n\n#define I2C_ADDR_OFFSET_TEN_BIT\t0xa000\n#define I2C_ADDR_OFFSET_SLAVE\t0x1000\n\n#define I2C_ADDR_7BITS_MAX\t0x77\n#define I2C_ADDR_7BITS_COUNT\t(I2C_ADDR_7BITS_MAX + 1)\n\n#define I2C_ADDR_DEVICE_ID\t0x7c\n\n/*\n * core_lock protects i2c_adapter_idr, and guarantees that device detection,\n * deletion of detected devices are serialized\n */\nstatic DEFINE_MUTEX(core_lock);\nstatic DEFINE_IDR(i2c_adapter_idr);\n\nstatic int i2c_detect(struct i2c_adapter *adapter, struct i2c_driver *driver);\n\nstatic DEFINE_STATIC_KEY_FALSE(i2c_trace_msg_key);\nstatic bool is_registered;\n\nint i2c_transfer_trace_reg(void)\n{\n\tstatic_branch_inc(&i2c_trace_msg_key);\n\treturn 0;\n}\n\nvoid i2c_transfer_trace_unreg(void)\n{\n\tstatic_branch_dec(&i2c_trace_msg_key);\n}\n\nconst struct i2c_device_id *i2c_match_id(const struct i2c_device_id *id,\n\t\t\t\t\t\tconst struct i2c_client *client)\n{\n\tif (!(id && client))\n\t\treturn NULL;\n\n\twhile (id->name[0]) {\n\t\tif (strcmp(client->name, id->name) == 0)\n\t\t\treturn id;\n\t\tid++;\n\t}\n\treturn NULL;\n}\nEXPORT_SYMBOL_GPL(i2c_match_id);\n\nstatic int i2c_device_match(struct device *dev, struct device_driver *drv)\n{\n\tstruct i2c_client\t*client = i2c_verify_client(dev);\n\tstruct i2c_driver\t*driver;\n\n\n\t/* Attempt an OF style match */\n\tif (i2c_of_match_device(drv->of_match_table, client))\n\t\treturn 1;\n\n\t/* Then ACPI style match */\n\tif (acpi_driver_match_device(dev, drv))\n\t\treturn 1;\n\n\tdriver = to_i2c_driver(drv);\n\n\t/* Finally an I2C match */\n\tif (i2c_match_id(driver->id_table, client))\n\t\treturn 1;\n\n\treturn 0;\n}\n\nstatic int i2c_device_uevent(struct device *dev, struct kobj_uevent_env *env)\n{\n\tstruct i2c_client *client = to_i2c_client(dev);\n\tint rc;\n\n\trc = of_device_uevent_modalias(dev, env);\n\tif (rc != -ENODEV)\n\t\treturn rc;\n\n\trc = acpi_device_uevent_modalias(dev, env);\n\tif (rc != -ENODEV)\n\t\treturn rc;\n\n\treturn add_uevent_var(env, \"MODALIAS=%s%s\", I2C_MODULE_PREFIX, client->name);\n}\n\n/* i2c bus recovery routines */\nstatic int get_scl_gpio_value(struct i2c_adapter *adap)\n{\n\treturn gpiod_get_value_cansleep(adap->bus_recovery_info->scl_gpiod);\n}\n\nstatic void set_scl_gpio_value(struct i2c_adapter *adap, int val)\n{\n\tgpiod_set_value_cansleep(adap->bus_recovery_info->scl_gpiod, val);\n}\n\nstatic int get_sda_gpio_value(struct i2c_adapter *adap)\n{\n\treturn gpiod_get_value_cansleep(adap->bus_recovery_info->sda_gpiod);\n}\n\nstatic void set_sda_gpio_value(struct i2c_adapter *adap, int val)\n{\n\tgpiod_set_value_cansleep(adap->bus_recovery_info->sda_gpiod, val);\n}\n\nstatic int i2c_generic_bus_free(struct i2c_adapter *adap)\n{\n\tstruct i2c_bus_recovery_info *bri = adap->bus_recovery_info;\n\tint ret = -EOPNOTSUPP;\n\n\tif (bri->get_bus_free)\n\t\tret = bri->get_bus_free(adap);\n\telse if (bri->get_sda)\n\t\tret = bri->get_sda(adap);\n\n\tif (ret < 0)\n\t\treturn ret;\n\n\treturn ret ? 0 : -EBUSY;\n}\n\n/*\n * We are generating clock pulses. ndelay() determines durating of clk pulses.\n * We will generate clock with rate 100 KHz and so duration of both clock levels\n * is: delay in ns = (10^6 / 100) / 2\n */\n#define RECOVERY_NDELAY\t\t5000\n#define RECOVERY_CLK_CNT\t9\n\nint i2c_generic_scl_recovery(struct i2c_adapter *adap)\n{\n\tstruct i2c_bus_recovery_info *bri = adap->bus_recovery_info;\n\tint i = 0, scl = 1, ret = 0;\n\n\tif (bri->prepare_recovery)\n\t\tbri->prepare_recovery(adap);\n\n\t/*\n\t * If we can set SDA, we will always create a STOP to ensure additional\n\t * pulses will do no harm. This is achieved by letting SDA follow SCL\n\t * half a cycle later. Check the 'incomplete_write_byte' fault injector\n\t * for details.\n\t */\n\tbri->set_scl(adap, scl);\n\tndelay(RECOVERY_NDELAY / 2);\n\tif (bri->set_sda)\n\t\tbri->set_sda(adap, scl);\n\tndelay(RECOVERY_NDELAY / 2);\n\n\t/*\n\t * By this time SCL is high, as we need to give 9 falling-rising edges\n\t */\n\twhile (i++ < RECOVERY_CLK_CNT * 2) {\n\t\tif (scl) {\n\t\t\t/* SCL shouldn't be low here */\n\t\t\tif (!bri->get_scl(adap)) {\n\t\t\t\tdev_err(&adap->dev,\n\t\t\t\t\t\"SCL is stuck low, exit recovery\\n\");\n\t\t\t\tret = -EBUSY;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\tscl = !scl;\n\t\tbri->set_scl(adap, scl);\n\t\t/* Creating STOP again, see above */\n\t\tndelay(RECOVERY_NDELAY / 2);\n\t\tif (bri->set_sda)\n\t\t\tbri->set_sda(adap, scl);\n\t\tndelay(RECOVERY_NDELAY / 2);\n\n\t\tif (scl) {\n\t\t\tret = i2c_generic_bus_free(adap);\n\t\t\tif (ret == 0)\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\t/* If we can't check bus status, assume recovery worked */\n\tif (ret == -EOPNOTSUPP)\n\t\tret = 0;\n\n\tif (bri->unprepare_recovery)\n\t\tbri->unprepare_recovery(adap);\n\n\treturn ret;\n}\nEXPORT_SYMBOL_GPL(i2c_generic_scl_recovery);\n\nint i2c_recover_bus(struct i2c_adapter *adap)\n{\n\tif (!adap->bus_recovery_info)\n\t\treturn -EOPNOTSUPP;\n\n\tdev_dbg(&adap->dev, \"Trying i2c bus recovery\\n\");\n\treturn adap->bus_recovery_info->recover_bus(adap);\n}\nEXPORT_SYMBOL_GPL(i2c_recover_bus);\n\nstatic void i2c_init_recovery(struct i2c_adapter *adap)\n{\n\tstruct i2c_bus_recovery_info *bri = adap->bus_recovery_info;\n\tchar *err_str;\n\n\tif (!bri)\n\t\treturn;\n\n\tif (!bri->recover_bus) {\n\t\terr_str = \"no recover_bus() found\";\n\t\tgoto err;\n\t}\n\n\tif (bri->scl_gpiod && bri->recover_bus == i2c_generic_scl_recovery) {\n\t\tbri->get_scl = get_scl_gpio_value;\n\t\tbri->set_scl = set_scl_gpio_value;\n\t\tif (bri->sda_gpiod) {\n\t\t\tbri->get_sda = get_sda_gpio_value;\n\t\t\t/* FIXME: add proper flag instead of '0' once available */\n\t\t\tif (gpiod_get_direction(bri->sda_gpiod) == 0)\n\t\t\t\tbri->set_sda = set_sda_gpio_value;\n\t\t}\n\t\treturn;\n\t}\n\n\tif (bri->recover_bus == i2c_generic_scl_recovery) {\n\t\t/* Generic SCL recovery */\n\t\tif (!bri->set_scl || !bri->get_scl) {\n\t\t\terr_str = \"no {get|set}_scl() found\";\n\t\t\tgoto err;\n\t\t}\n\t\tif (!bri->set_sda && !bri->get_sda) {\n\t\t\terr_str = \"either get_sda() or set_sda() needed\";\n\t\t\tgoto err;\n\t\t}\n\t}\n\n\treturn;\n err:\n\tdev_err(&adap->dev, \"Not using recovery: %s\\n\", err_str);\n\tadap->bus_recovery_info = NULL;\n}\n\nstatic int i2c_smbus_host_notify_to_irq(const struct i2c_client *client)\n{\n\tstruct i2c_adapter *adap = client->adapter;\n\tunsigned int irq;\n\n\tif (!adap->host_notify_domain)\n\t\treturn -ENXIO;\n\n\tif (client->flags & I2C_CLIENT_TEN)\n\t\treturn -EINVAL;\n\n\tirq = irq_create_mapping(adap->host_notify_domain, client->addr);\n\n\treturn irq > 0 ? irq : -ENXIO;\n}\n\nstatic int i2c_device_probe(struct device *dev)\n{\n\tstruct i2c_client\t*client = i2c_verify_client(dev);\n\tstruct i2c_driver\t*driver;\n\tint status;\n\n\tif (!client)\n\t\treturn 0;\n\n\tdriver = to_i2c_driver(dev->driver);\n\n\tclient->irq = client->init_irq;\n\n\tif (!client->irq && !driver->disable_i2c_core_irq_mapping) {\n\t\tint irq = -ENOENT;\n\n\t\tif (client->flags & I2C_CLIENT_HOST_NOTIFY) {\n\t\t\tdev_dbg(dev, \"Using Host Notify IRQ\\n\");\n\t\t\t/* Keep adapter active when Host Notify is required */\n\t\t\tpm_runtime_get_sync(&client->adapter->dev);\n\t\t\tirq = i2c_smbus_host_notify_to_irq(client);\n\t\t} else if (dev->of_node) {\n\t\t\tirq = of_irq_get_byname(dev->of_node, \"irq\");\n\t\t\tif (irq == -EINVAL || irq == -ENODATA)\n\t\t\t\tirq = of_irq_get(dev->of_node, 0);\n\t\t} else if (ACPI_COMPANION(dev)) {\n\t\t\tirq = i2c_acpi_get_irq(client);\n\t\t}\n\t\tif (irq == -EPROBE_DEFER)\n\t\t\treturn irq;\n\n\t\tif (irq < 0)\n\t\t\tirq = 0;\n\n\t\tclient->irq = irq;\n\t}\n\n\t/*\n\t * An I2C ID table is not mandatory, if and only if, a suitable OF\n\t * or ACPI ID table is supplied for the probing device.\n\t */\n\tif (!driver->id_table &&\n\t    !i2c_acpi_match_device(dev->driver->acpi_match_table, client) &&\n\t    !i2c_of_match_device(dev->driver->of_match_table, client))\n\t\treturn -ENODEV;\n\n\tif (client->flags & I2C_CLIENT_WAKE) {\n\t\tint wakeirq;\n\n\t\twakeirq = of_irq_get_byname(dev->of_node, \"wakeup\");\n\t\tif (wakeirq == -EPROBE_DEFER)\n\t\t\treturn wakeirq;\n\n\t\tdevice_init_wakeup(&client->dev, true);\n\n\t\tif (wakeirq > 0 && wakeirq != client->irq)\n\t\t\tstatus = dev_pm_set_dedicated_wake_irq(dev, wakeirq);\n\t\telse if (client->irq > 0)\n\t\t\tstatus = dev_pm_set_wake_irq(dev, client->irq);\n\t\telse\n\t\t\tstatus = 0;\n\n\t\tif (status)\n\t\t\tdev_warn(&client->dev, \"failed to set up wakeup irq\\n\");\n\t}\n\n\tdev_dbg(dev, \"probe\\n\");\n\n\tstatus = of_clk_set_defaults(dev->of_node, false);\n\tif (status < 0)\n\t\tgoto err_clear_wakeup_irq;\n\n\tstatus = dev_pm_domain_attach(&client->dev, true);\n\tif (status)\n\t\tgoto err_clear_wakeup_irq;\n\n\t/*\n\t * When there are no more users of probe(),\n\t * rename probe_new to probe.\n\t */\n\tif (driver->probe_new)\n\t\tstatus = driver->probe_new(client);\n\telse if (driver->probe)\n\t\tstatus = driver->probe(client,\n\t\t\t\t       i2c_match_id(driver->id_table, client));\n\telse\n\t\tstatus = -EINVAL;\n\n\tif (status)\n\t\tgoto err_detach_pm_domain;\n\n\treturn 0;\n\nerr_detach_pm_domain:\n\tdev_pm_domain_detach(&client->dev, true);\nerr_clear_wakeup_irq:\n\tdev_pm_clear_wake_irq(&client->dev);\n\tdevice_init_wakeup(&client->dev, false);\n\treturn status;\n}\n\nstatic int i2c_device_remove(struct device *dev)\n{\n\tstruct i2c_client\t*client = i2c_verify_client(dev);\n\tstruct i2c_driver\t*driver;\n\tint status = 0;\n\n\tif (!client || !dev->driver)\n\t\treturn 0;\n\n\tdriver = to_i2c_driver(dev->driver);\n\tif (driver->remove) {\n\t\tdev_dbg(dev, \"remove\\n\");\n\t\tstatus = driver->remove(client);\n\t}\n\n\tdev_pm_domain_detach(&client->dev, true);\n\n\tdev_pm_clear_wake_irq(&client->dev);\n\tdevice_init_wakeup(&client->dev, false);\n\n\tclient->irq = 0;\n\tif (client->flags & I2C_CLIENT_HOST_NOTIFY)\n\t\tpm_runtime_put(&client->adapter->dev);\n\n\treturn status;\n}\n\nstatic void i2c_device_shutdown(struct device *dev)\n{\n\tstruct i2c_client *client = i2c_verify_client(dev);\n\tstruct i2c_driver *driver;\n\n\tif (!client || !dev->driver)\n\t\treturn;\n\tdriver = to_i2c_driver(dev->driver);\n\tif (driver->shutdown)\n\t\tdriver->shutdown(client);\n}\n\nstatic void i2c_client_dev_release(struct device *dev)\n{\n\tkfree(to_i2c_client(dev));\n}\n\nstatic ssize_t\nshow_name(struct device *dev, struct device_attribute *attr, char *buf)\n{\n\treturn sprintf(buf, \"%s\\n\", dev->type == &i2c_client_type ?\n\t\t       to_i2c_client(dev)->name : to_i2c_adapter(dev)->name);\n}\nstatic DEVICE_ATTR(name, S_IRUGO, show_name, NULL);\n\nstatic ssize_t\nshow_modalias(struct device *dev, struct device_attribute *attr, char *buf)\n{\n\tstruct i2c_client *client = to_i2c_client(dev);\n\tint len;\n\n\tlen = of_device_modalias(dev, buf, PAGE_SIZE);\n\tif (len != -ENODEV)\n\t\treturn len;\n\n\tlen = acpi_device_modalias(dev, buf, PAGE_SIZE -1);\n\tif (len != -ENODEV)\n\t\treturn len;\n\n\treturn sprintf(buf, \"%s%s\\n\", I2C_MODULE_PREFIX, client->name);\n}\nstatic DEVICE_ATTR(modalias, S_IRUGO, show_modalias, NULL);\n\nstatic struct attribute *i2c_dev_attrs[] = {\n\t&dev_attr_name.attr,\n\t/* modalias helps coldplug:  modprobe $(cat .../modalias) */\n\t&dev_attr_modalias.attr,\n\tNULL\n};\nATTRIBUTE_GROUPS(i2c_dev);\n\nstruct bus_type i2c_bus_type = {\n\t.name\t\t= \"i2c\",\n\t.match\t\t= i2c_device_match,\n\t.probe\t\t= i2c_device_probe,\n\t.remove\t\t= i2c_device_remove,\n\t.shutdown\t= i2c_device_shutdown,\n};\nEXPORT_SYMBOL_GPL(i2c_bus_type);\n\nstruct device_type i2c_client_type = {\n\t.groups\t\t= i2c_dev_groups,\n\t.uevent\t\t= i2c_device_uevent,\n\t.release\t= i2c_client_dev_release,\n};\nEXPORT_SYMBOL_GPL(i2c_client_type);\n\n\n/**\n * i2c_verify_client - return parameter as i2c_client, or NULL\n * @dev: device, probably from some driver model iterator\n *\n * When traversing the driver model tree, perhaps using driver model\n * iterators like @device_for_each_child(), you can't assume very much\n * about the nodes you find.  Use this function to avoid oopses caused\n * by wrongly treating some non-I2C device as an i2c_client.\n */\nstruct i2c_client *i2c_verify_client(struct device *dev)\n{\n\treturn (dev->type == &i2c_client_type)\n\t\t\t? to_i2c_client(dev)\n\t\t\t: NULL;\n}\nEXPORT_SYMBOL(i2c_verify_client);\n\n\n/* Return a unique address which takes the flags of the client into account */\nstatic unsigned short i2c_encode_flags_to_addr(struct i2c_client *client)\n{\n\tunsigned short addr = client->addr;\n\n\t/* For some client flags, add an arbitrary offset to avoid collisions */\n\tif (client->flags & I2C_CLIENT_TEN)\n\t\taddr |= I2C_ADDR_OFFSET_TEN_BIT;\n\n\tif (client->flags & I2C_CLIENT_SLAVE)\n\t\taddr |= I2C_ADDR_OFFSET_SLAVE;\n\n\treturn addr;\n}\n\n/* This is a permissive address validity check, I2C address map constraints\n * are purposely not enforced, except for the general call address. */\nstatic int i2c_check_addr_validity(unsigned int addr, unsigned short flags)\n{\n\tif (flags & I2C_CLIENT_TEN) {\n\t\t/* 10-bit address, all values are valid */\n\t\tif (addr > 0x3ff)\n\t\t\treturn -EINVAL;\n\t} else {\n\t\t/* 7-bit address, reject the general call address */\n\t\tif (addr == 0x00 || addr > 0x7f)\n\t\t\treturn -EINVAL;\n\t}\n\treturn 0;\n}\n\n/* And this is a strict address validity check, used when probing. If a\n * device uses a reserved address, then it shouldn't be probed. 7-bit\n * addressing is assumed, 10-bit address devices are rare and should be\n * explicitly enumerated. */\nint i2c_check_7bit_addr_validity_strict(unsigned short addr)\n{\n\t/*\n\t * Reserved addresses per I2C specification:\n\t *  0x00       General call address / START byte\n\t *  0x01       CBUS address\n\t *  0x02       Reserved for different bus format\n\t *  0x03       Reserved for future purposes\n\t *  0x04-0x07  Hs-mode master code\n\t *  0x78-0x7b  10-bit slave addressing\n\t *  0x7c-0x7f  Reserved for future purposes\n\t */\n\tif (addr < 0x08 || addr > 0x77)\n\t\treturn -EINVAL;\n\treturn 0;\n}\n\nstatic int __i2c_check_addr_busy(struct device *dev, void *addrp)\n{\n\tstruct i2c_client\t*client = i2c_verify_client(dev);\n\tint\t\t\taddr = *(int *)addrp;\n\n\tif (client && i2c_encode_flags_to_addr(client) == addr)\n\t\treturn -EBUSY;\n\treturn 0;\n}\n\n/* walk up mux tree */\nstatic int i2c_check_mux_parents(struct i2c_adapter *adapter, int addr)\n{\n\tstruct i2c_adapter *parent = i2c_parent_is_i2c_adapter(adapter);\n\tint result;\n\n\tresult = device_for_each_child(&adapter->dev, &addr,\n\t\t\t\t\t__i2c_check_addr_busy);\n\n\tif (!result && parent)\n\t\tresult = i2c_check_mux_parents(parent, addr);\n\n\treturn result;\n}\n\n/* recurse down mux tree */\nstatic int i2c_check_mux_children(struct device *dev, void *addrp)\n{\n\tint result;\n\n\tif (dev->type == &i2c_adapter_type)\n\t\tresult = device_for_each_child(dev, addrp,\n\t\t\t\t\t\ti2c_check_mux_children);\n\telse\n\t\tresult = __i2c_check_addr_busy(dev, addrp);\n\n\treturn result;\n}\n\nstatic int i2c_check_addr_busy(struct i2c_adapter *adapter, int addr)\n{\n\tstruct i2c_adapter *parent = i2c_parent_is_i2c_adapter(adapter);\n\tint result = 0;\n\n\tif (parent)\n\t\tresult = i2c_check_mux_parents(parent, addr);\n\n\tif (!result)\n\t\tresult = device_for_each_child(&adapter->dev, &addr,\n\t\t\t\t\t\ti2c_check_mux_children);\n\n\treturn result;\n}\n\n/**\n * i2c_adapter_lock_bus - Get exclusive access to an I2C bus segment\n * @adapter: Target I2C bus segment\n * @flags: I2C_LOCK_ROOT_ADAPTER locks the root i2c adapter, I2C_LOCK_SEGMENT\n *\tlocks only this branch in the adapter tree\n */\nstatic void i2c_adapter_lock_bus(struct i2c_adapter *adapter,\n\t\t\t\t unsigned int flags)\n{\n\trt_mutex_lock_nested(&adapter->bus_lock, i2c_adapter_depth(adapter));\n}\n\n/**\n * i2c_adapter_trylock_bus - Try to get exclusive access to an I2C bus segment\n * @adapter: Target I2C bus segment\n * @flags: I2C_LOCK_ROOT_ADAPTER trylocks the root i2c adapter, I2C_LOCK_SEGMENT\n *\ttrylocks only this branch in the adapter tree\n */\nstatic int i2c_adapter_trylock_bus(struct i2c_adapter *adapter,\n\t\t\t\t   unsigned int flags)\n{\n\treturn rt_mutex_trylock(&adapter->bus_lock);\n}\n\n/**\n * i2c_adapter_unlock_bus - Release exclusive access to an I2C bus segment\n * @adapter: Target I2C bus segment\n * @flags: I2C_LOCK_ROOT_ADAPTER unlocks the root i2c adapter, I2C_LOCK_SEGMENT\n *\tunlocks only this branch in the adapter tree\n */\nstatic void i2c_adapter_unlock_bus(struct i2c_adapter *adapter,\n\t\t\t\t   unsigned int flags)\n{\n\trt_mutex_unlock(&adapter->bus_lock);\n}\n\nstatic void i2c_dev_set_name(struct i2c_adapter *adap,\n\t\t\t     struct i2c_client *client,\n\t\t\t     struct i2c_board_info const *info)\n{\n\tstruct acpi_device *adev = ACPI_COMPANION(&client->dev);\n\n\tif (info && info->dev_name) {\n\t\tdev_set_name(&client->dev, \"i2c-%s\", info->dev_name);\n\t\treturn;\n\t}\n\n\tif (adev) {\n\t\tdev_set_name(&client->dev, \"i2c-%s\", acpi_dev_name(adev));\n\t\treturn;\n\t}\n\n\tdev_set_name(&client->dev, \"%d-%04x\", i2c_adapter_id(adap),\n\t\t     i2c_encode_flags_to_addr(client));\n}\n\nint i2c_dev_irq_from_resources(const struct resource *resources,\n\t\t\t       unsigned int num_resources)\n{\n\tstruct irq_data *irqd;\n\tint i;\n\n\tfor (i = 0; i < num_resources; i++) {\n\t\tconst struct resource *r = &resources[i];\n\n\t\tif (resource_type(r) != IORESOURCE_IRQ)\n\t\t\tcontinue;\n\n\t\tif (r->flags & IORESOURCE_BITS) {\n\t\t\tirqd = irq_get_irq_data(r->start);\n\t\t\tif (!irqd)\n\t\t\t\tbreak;\n\n\t\t\tirqd_set_trigger_type(irqd, r->flags & IORESOURCE_BITS);\n\t\t}\n\n\t\treturn r->start;\n\t}\n\n\treturn 0;\n}\n\n/**\n * i2c_new_client_device - instantiate an i2c device\n * @adap: the adapter managing the device\n * @info: describes one I2C device; bus_num is ignored\n * Context: can sleep\n *\n * Create an i2c device. Binding is handled through driver model\n * probe()/remove() methods.  A driver may be bound to this device when we\n * return from this function, or any later moment (e.g. maybe hotplugging will\n * load the driver module).  This call is not appropriate for use by mainboard\n * initialization logic, which usually runs during an arch_initcall() long\n * before any i2c_adapter could exist.\n *\n * This returns the new i2c client, which may be saved for later use with\n * i2c_unregister_device(); or an ERR_PTR to describe the error.\n */\nstruct i2c_client *\ni2c_new_client_device(struct i2c_adapter *adap, struct i2c_board_info const *info)\n{\n\tstruct i2c_client\t*client;\n\tint\t\t\tstatus;\n\n\tclient = kzalloc(sizeof *client, GFP_KERNEL);\n\tif (!client)\n\t\treturn ERR_PTR(-ENOMEM);\n\n\tclient->adapter = adap;\n\n\tclient->dev.platform_data = info->platform_data;\n\tclient->flags = info->flags;\n\tclient->addr = info->addr;\n\n\tclient->init_irq = info->irq;\n\tif (!client->init_irq)\n\t\tclient->init_irq = i2c_dev_irq_from_resources(info->resources,\n\t\t\t\t\t\t\t info->num_resources);\n\n\tstrlcpy(client->name, info->type, sizeof(client->name));\n\n\tstatus = i2c_check_addr_validity(client->addr, client->flags);\n\tif (status) {\n\t\tdev_err(&adap->dev, \"Invalid %d-bit I2C address 0x%02hx\\n\",\n\t\t\tclient->flags & I2C_CLIENT_TEN ? 10 : 7, client->addr);\n\t\tgoto out_err_silent;\n\t}\n\n\t/* Check for address business */\n\tstatus = i2c_check_addr_busy(adap, i2c_encode_flags_to_addr(client));\n\tif (status)\n\t\tgoto out_err;\n\n\tclient->dev.parent = &client->adapter->dev;\n\tclient->dev.bus = &i2c_bus_type;\n\tclient->dev.type = &i2c_client_type;\n\tclient->dev.of_node = of_node_get(info->of_node);\n\tclient->dev.fwnode = info->fwnode;\n\n\ti2c_dev_set_name(adap, client, info);\n\n\tif (info->properties) {\n\t\tstatus = device_add_properties(&client->dev, info->properties);\n\t\tif (status) {\n\t\t\tdev_err(&adap->dev,\n\t\t\t\t\"Failed to add properties to client %s: %d\\n\",\n\t\t\t\tclient->name, status);\n\t\t\tgoto out_err_put_of_node;\n\t\t}\n\t}\n\n\tstatus = device_register(&client->dev);\n\tif (status)\n\t\tgoto out_free_props;\n\n\tdev_dbg(&adap->dev, \"client [%s] registered with bus id %s\\n\",\n\t\tclient->name, dev_name(&client->dev));\n\n\treturn client;\n\nout_free_props:\n\tif (info->properties)\n\t\tdevice_remove_properties(&client->dev);\nout_err_put_of_node:\n\tof_node_put(info->of_node);\nout_err:\n\tdev_err(&adap->dev,\n\t\t\"Failed to register i2c client %s at 0x%02x (%d)\\n\",\n\t\tclient->name, client->addr, status);\nout_err_silent:\n\tkfree(client);\n\treturn ERR_PTR(status);\n}\nEXPORT_SYMBOL_GPL(i2c_new_client_device);\n\n/**\n * i2c_new_device - instantiate an i2c device\n * @adap: the adapter managing the device\n * @info: describes one I2C device; bus_num is ignored\n * Context: can sleep\n *\n * This deprecated function has the same functionality as\n * @i2c_new_client_device, it just returns NULL instead of an ERR_PTR in case of\n * an error for compatibility with current I2C API. It will be removed once all\n * users are converted.\n *\n * This returns the new i2c client, which may be saved for later use with\n * i2c_unregister_device(); or NULL to indicate an error.\n */\nstruct i2c_client *\ni2c_new_device(struct i2c_adapter *adap, struct i2c_board_info const *info)\n{\n\tstruct i2c_client *ret;\n\n\tret = i2c_new_client_device(adap, info);\n\treturn IS_ERR(ret) ? NULL : ret;\n}\nEXPORT_SYMBOL_GPL(i2c_new_device);\n\n\n/**\n * i2c_unregister_device - reverse effect of i2c_new_device()\n * @client: value returned from i2c_new_device()\n * Context: can sleep\n */\nvoid i2c_unregister_device(struct i2c_client *client)\n{\n\tif (IS_ERR_OR_NULL(client))\n\t\treturn;\n\n\tif (client->dev.of_node) {\n\t\tof_node_clear_flag(client->dev.of_node, OF_POPULATED);\n\t\tof_node_put(client->dev.of_node);\n\t}\n\n\tif (ACPI_COMPANION(&client->dev))\n\t\tacpi_device_clear_enumerated(ACPI_COMPANION(&client->dev));\n\tdevice_unregister(&client->dev);\n}\nEXPORT_SYMBOL_GPL(i2c_unregister_device);\n\n\nstatic const struct i2c_device_id dummy_id[] = {\n\t{ \"dummy\", 0 },\n\t{ },\n};\n\nstatic int dummy_probe(struct i2c_client *client,\n\t\t       const struct i2c_device_id *id)\n{\n\treturn 0;\n}\n\nstatic int dummy_remove(struct i2c_client *client)\n{\n\treturn 0;\n}\n\nstatic struct i2c_driver dummy_driver = {\n\t.driver.name\t= \"dummy\",\n\t.probe\t\t= dummy_probe,\n\t.remove\t\t= dummy_remove,\n\t.id_table\t= dummy_id,\n};\n\n/**\n * i2c_new_dummy_device - return a new i2c device bound to a dummy driver\n * @adapter: the adapter managing the device\n * @address: seven bit address to be used\n * Context: can sleep\n *\n * This returns an I2C client bound to the \"dummy\" driver, intended for use\n * with devices that consume multiple addresses.  Examples of such chips\n * include various EEPROMS (like 24c04 and 24c08 models).\n *\n * These dummy devices have two main uses.  First, most I2C and SMBus calls\n * except i2c_transfer() need a client handle; the dummy will be that handle.\n * And second, this prevents the specified address from being bound to a\n * different driver.\n *\n * This returns the new i2c client, which should be saved for later use with\n * i2c_unregister_device(); or an ERR_PTR to describe the error.\n */\nstruct i2c_client *i2c_new_dummy_device(struct i2c_adapter *adapter, u16 address)\n{\n\tstruct i2c_board_info info = {\n\t\tI2C_BOARD_INFO(\"dummy\", address),\n\t};\n\n\treturn i2c_new_client_device(adapter, &info);\n}\nEXPORT_SYMBOL_GPL(i2c_new_dummy_device);\n\n/**\n * i2c_new_dummy - return a new i2c device bound to a dummy driver\n * @adapter: the adapter managing the device\n * @address: seven bit address to be used\n * Context: can sleep\n *\n * This deprecated function has the same functionality as @i2c_new_dummy_device,\n * it just returns NULL instead of an ERR_PTR in case of an error for\n * compatibility with current I2C API. It will be removed once all users are\n * converted.\n *\n * This returns the new i2c client, which should be saved for later use with\n * i2c_unregister_device(); or NULL to indicate an error.\n */\nstruct i2c_client *i2c_new_dummy(struct i2c_adapter *adapter, u16 address)\n{\n\tstruct i2c_client *ret;\n\n\tret = i2c_new_dummy_device(adapter, address);\n\treturn IS_ERR(ret) ? NULL : ret;\n}\nEXPORT_SYMBOL_GPL(i2c_new_dummy);\n\nstruct i2c_dummy_devres {\n\tstruct i2c_client *client;\n};\n\nstatic void devm_i2c_release_dummy(struct device *dev, void *res)\n{\n\tstruct i2c_dummy_devres *this = res;\n\n\ti2c_unregister_device(this->client);\n}\n\n/**\n * devm_i2c_new_dummy_device - return a new i2c device bound to a dummy driver\n * @dev: device the managed resource is bound to\n * @adapter: the adapter managing the device\n * @address: seven bit address to be used\n * Context: can sleep\n *\n * This is the device-managed version of @i2c_new_dummy_device. It returns the\n * new i2c client or an ERR_PTR in case of an error.\n */\nstruct i2c_client *devm_i2c_new_dummy_device(struct device *dev,\n\t\t\t\t\t     struct i2c_adapter *adapter,\n\t\t\t\t\t     u16 address)\n{\n\tstruct i2c_dummy_devres *dr;\n\tstruct i2c_client *client;\n\n\tdr = devres_alloc(devm_i2c_release_dummy, sizeof(*dr), GFP_KERNEL);\n\tif (!dr)\n\t\treturn ERR_PTR(-ENOMEM);\n\n\tclient = i2c_new_dummy_device(adapter, address);\n\tif (IS_ERR(client)) {\n\t\tdevres_free(dr);\n\t} else {\n\t\tdr->client = client;\n\t\tdevres_add(dev, dr);\n\t}\n\n\treturn client;\n}\nEXPORT_SYMBOL_GPL(devm_i2c_new_dummy_device);\n\n/**\n * i2c_new_ancillary_device - Helper to get the instantiated secondary address\n * and create the associated device\n * @client: Handle to the primary client\n * @name: Handle to specify which secondary address to get\n * @default_addr: Used as a fallback if no secondary address was specified\n * Context: can sleep\n *\n * I2C clients can be composed of multiple I2C slaves bound together in a single\n * component. The I2C client driver then binds to the master I2C slave and needs\n * to create I2C dummy clients to communicate with all the other slaves.\n *\n * This function creates and returns an I2C dummy client whose I2C address is\n * retrieved from the platform firmware based on the given slave name. If no\n * address is specified by the firmware default_addr is used.\n *\n * On DT-based platforms the address is retrieved from the \"reg\" property entry\n * cell whose \"reg-names\" value matches the slave name.\n *\n * This returns the new i2c client, which should be saved for later use with\n * i2c_unregister_device(); or an ERR_PTR to describe the error.\n */\nstruct i2c_client *i2c_new_ancillary_device(struct i2c_client *client,\n\t\t\t\t\t\tconst char *name,\n\t\t\t\t\t\tu16 default_addr)\n{\n\tstruct device_node *np = client->dev.of_node;\n\tu32 addr = default_addr;\n\tint i;\n\n\tif (np) {\n\t\ti = of_property_match_string(np, \"reg-names\", name);\n\t\tif (i >= 0)\n\t\t\tof_property_read_u32_index(np, \"reg\", i, &addr);\n\t}\n\n\tdev_dbg(&client->adapter->dev, \"Address for %s : 0x%x\\n\", name, addr);\n\treturn i2c_new_dummy_device(client->adapter, addr);\n}\nEXPORT_SYMBOL_GPL(i2c_new_ancillary_device);\n\n/* ------------------------------------------------------------------------- */\n\n/* I2C bus adapters -- one roots each I2C or SMBUS segment */\n\nstatic void i2c_adapter_dev_release(struct device *dev)\n{\n\tstruct i2c_adapter *adap = to_i2c_adapter(dev);\n\tcomplete(&adap->dev_released);\n}\n\nunsigned int i2c_adapter_depth(struct i2c_adapter *adapter)\n{\n\tunsigned int depth = 0;\n\n\twhile ((adapter = i2c_parent_is_i2c_adapter(adapter)))\n\t\tdepth++;\n\n\tWARN_ONCE(depth >= MAX_LOCKDEP_SUBCLASSES,\n\t\t  \"adapter depth exceeds lockdep subclass limit\\n\");\n\n\treturn depth;\n}\nEXPORT_SYMBOL_GPL(i2c_adapter_depth);\n\n/*\n * Let users instantiate I2C devices through sysfs. This can be used when\n * platform initialization code doesn't contain the proper data for\n * whatever reason. Also useful for drivers that do device detection and\n * detection fails, either because the device uses an unexpected address,\n * or this is a compatible device with different ID register values.\n *\n * Parameter checking may look overzealous, but we really don't want\n * the user to provide incorrect parameters.\n */\nstatic ssize_t\ni2c_sysfs_new_device(struct device *dev, struct device_attribute *attr,\n\t\t     const char *buf, size_t count)\n{\n\tstruct i2c_adapter *adap = to_i2c_adapter(dev);\n\tstruct i2c_board_info info;\n\tstruct i2c_client *client;\n\tchar *blank, end;\n\tint res;\n\n\tmemset(&info, 0, sizeof(struct i2c_board_info));\n\n\tblank = strchr(buf, ' ');\n\tif (!blank) {\n\t\tdev_err(dev, \"%s: Missing parameters\\n\", \"new_device\");\n\t\treturn -EINVAL;\n\t}\n\tif (blank - buf > I2C_NAME_SIZE - 1) {\n\t\tdev_err(dev, \"%s: Invalid device name\\n\", \"new_device\");\n\t\treturn -EINVAL;\n\t}\n\tmemcpy(info.type, buf, blank - buf);\n\n\t/* Parse remaining parameters, reject extra parameters */\n\tres = sscanf(++blank, \"%hi%c\", &info.addr, &end);\n\tif (res < 1) {\n\t\tdev_err(dev, \"%s: Can't parse I2C address\\n\", \"new_device\");\n\t\treturn -EINVAL;\n\t}\n\tif (res > 1  && end != '\\n') {\n\t\tdev_err(dev, \"%s: Extra parameters\\n\", \"new_device\");\n\t\treturn -EINVAL;\n\t}\n\n\tif ((info.addr & I2C_ADDR_OFFSET_TEN_BIT) == I2C_ADDR_OFFSET_TEN_BIT) {\n\t\tinfo.addr &= ~I2C_ADDR_OFFSET_TEN_BIT;\n\t\tinfo.flags |= I2C_CLIENT_TEN;\n\t}\n\n\tif (info.addr & I2C_ADDR_OFFSET_SLAVE) {\n\t\tinfo.addr &= ~I2C_ADDR_OFFSET_SLAVE;\n\t\tinfo.flags |= I2C_CLIENT_SLAVE;\n\t}\n\n\tclient = i2c_new_client_device(adap, &info);\n\tif (IS_ERR(client))\n\t\treturn PTR_ERR(client);\n\n\t/* Keep track of the added device */\n\tmutex_lock(&adap->userspace_clients_lock);\n\tlist_add_tail(&client->detected, &adap->userspace_clients);\n\tmutex_unlock(&adap->userspace_clients_lock);\n\tdev_info(dev, \"%s: Instantiated device %s at 0x%02hx\\n\", \"new_device\",\n\t\t info.type, info.addr);\n\n\treturn count;\n}\nstatic DEVICE_ATTR(new_device, S_IWUSR, NULL, i2c_sysfs_new_device);\n\n/*\n * And of course let the users delete the devices they instantiated, if\n * they got it wrong. This interface can only be used to delete devices\n * instantiated by i2c_sysfs_new_device above. This guarantees that we\n * don't delete devices to which some kernel code still has references.\n *\n * Parameter checking may look overzealous, but we really don't want\n * the user to delete the wrong device.\n */\nstatic ssize_t\ni2c_sysfs_delete_device(struct device *dev, struct device_attribute *attr,\n\t\t\tconst char *buf, size_t count)\n{\n\tstruct i2c_adapter *adap = to_i2c_adapter(dev);\n\tstruct i2c_client *client, *next;\n\tunsigned short addr;\n\tchar end;\n\tint res;\n\n\t/* Parse parameters, reject extra parameters */\n\tres = sscanf(buf, \"%hi%c\", &addr, &end);\n\tif (res < 1) {\n\t\tdev_err(dev, \"%s: Can't parse I2C address\\n\", \"delete_device\");\n\t\treturn -EINVAL;\n\t}\n\tif (res > 1  && end != '\\n') {\n\t\tdev_err(dev, \"%s: Extra parameters\\n\", \"delete_device\");\n\t\treturn -EINVAL;\n\t}\n\n\t/* Make sure the device was added through sysfs */\n\tres = -ENOENT;\n\tmutex_lock_nested(&adap->userspace_clients_lock,\n\t\t\t  i2c_adapter_depth(adap));\n\tlist_for_each_entry_safe(client, next, &adap->userspace_clients,\n\t\t\t\t detected) {\n\t\tif (i2c_encode_flags_to_addr(client) == addr) {\n\t\t\tdev_info(dev, \"%s: Deleting device %s at 0x%02hx\\n\",\n\t\t\t\t \"delete_device\", client->name, client->addr);\n\n\t\t\tlist_del(&client->detected);\n\t\t\ti2c_unregister_device(client);\n\t\t\tres = count;\n\t\t\tbreak;\n\t\t}\n\t}\n\tmutex_unlock(&adap->userspace_clients_lock);\n\n\tif (res < 0)\n\t\tdev_err(dev, \"%s: Can't find device in list\\n\",\n\t\t\t\"delete_device\");\n\treturn res;\n}\nstatic DEVICE_ATTR_IGNORE_LOCKDEP(delete_device, S_IWUSR, NULL,\n\t\t\t\t   i2c_sysfs_delete_device);\n\nstatic struct attribute *i2c_adapter_attrs[] = {\n\t&dev_attr_name.attr,\n\t&dev_attr_new_device.attr,\n\t&dev_attr_delete_device.attr,\n\tNULL\n};\nATTRIBUTE_GROUPS(i2c_adapter);\n\nstruct device_type i2c_adapter_type = {\n\t.groups\t\t= i2c_adapter_groups,\n\t.release\t= i2c_adapter_dev_release,\n};\nEXPORT_SYMBOL_GPL(i2c_adapter_type);\n\n/**\n * i2c_verify_adapter - return parameter as i2c_adapter or NULL\n * @dev: device, probably from some driver model iterator\n *\n * When traversing the driver model tree, perhaps using driver model\n * iterators like @device_for_each_child(), you can't assume very much\n * about the nodes you find.  Use this function to avoid oopses caused\n * by wrongly treating some non-I2C device as an i2c_adapter.\n */\nstruct i2c_adapter *i2c_verify_adapter(struct device *dev)\n{\n\treturn (dev->type == &i2c_adapter_type)\n\t\t\t? to_i2c_adapter(dev)\n\t\t\t: NULL;\n}\nEXPORT_SYMBOL(i2c_verify_adapter);\n\n#ifdef CONFIG_I2C_COMPAT\nstatic struct class_compat *i2c_adapter_compat_class;\n#endif\n\nstatic void i2c_scan_static_board_info(struct i2c_adapter *adapter)\n{\n\tstruct i2c_devinfo\t*devinfo;\n\n\tdown_read(&__i2c_board_lock);\n\tlist_for_each_entry(devinfo, &__i2c_board_list, list) {\n\t\tif (devinfo->busnum == adapter->nr\n\t\t\t\t&& !i2c_new_device(adapter,\n\t\t\t\t\t\t&devinfo->board_info))\n\t\t\tdev_err(&adapter->dev,\n\t\t\t\t\"Can't create device at 0x%02x\\n\",\n\t\t\t\tdevinfo->board_info.addr);\n\t}\n\tup_read(&__i2c_board_lock);\n}\n\nstatic int i2c_do_add_adapter(struct i2c_driver *driver,\n\t\t\t      struct i2c_adapter *adap)\n{\n\t/* Detect supported devices on that bus, and instantiate them */\n\ti2c_detect(adap, driver);\n\n\treturn 0;\n}\n\nstatic int __process_new_adapter(struct device_driver *d, void *data)\n{\n\treturn i2c_do_add_adapter(to_i2c_driver(d), data);\n}\n\nstatic const struct i2c_lock_operations i2c_adapter_lock_ops = {\n\t.lock_bus =    i2c_adapter_lock_bus,\n\t.trylock_bus = i2c_adapter_trylock_bus,\n\t.unlock_bus =  i2c_adapter_unlock_bus,\n};\n\nstatic void i2c_host_notify_irq_teardown(struct i2c_adapter *adap)\n{\n\tstruct irq_domain *domain = adap->host_notify_domain;\n\tirq_hw_number_t hwirq;\n\n\tif (!domain)\n\t\treturn;\n\n\tfor (hwirq = 0 ; hwirq < I2C_ADDR_7BITS_COUNT ; hwirq++)\n\t\tirq_dispose_mapping(irq_find_mapping(domain, hwirq));\n\n\tirq_domain_remove(domain);\n\tadap->host_notify_domain = NULL;\n}\n\nstatic int i2c_host_notify_irq_map(struct irq_domain *h,\n\t\t\t\t\t  unsigned int virq,\n\t\t\t\t\t  irq_hw_number_t hw_irq_num)\n{\n\tirq_set_chip_and_handler(virq, &dummy_irq_chip, handle_simple_irq);\n\n\treturn 0;\n}\n\nstatic const struct irq_domain_ops i2c_host_notify_irq_ops = {\n\t.map = i2c_host_notify_irq_map,\n};\n\nstatic int i2c_setup_host_notify_irq_domain(struct i2c_adapter *adap)\n{\n\tstruct irq_domain *domain;\n\n\tif (!i2c_check_functionality(adap, I2C_FUNC_SMBUS_HOST_NOTIFY))\n\t\treturn 0;\n\n\tdomain = irq_domain_create_linear(adap->dev.fwnode,\n\t\t\t\t\t  I2C_ADDR_7BITS_COUNT,\n\t\t\t\t\t  &i2c_host_notify_irq_ops, adap);\n\tif (!domain)\n\t\treturn -ENOMEM;\n\n\tadap->host_notify_domain = domain;\n\n\treturn 0;\n}\n\n/**\n * i2c_handle_smbus_host_notify - Forward a Host Notify event to the correct\n * I2C client.\n * @adap: the adapter\n * @addr: the I2C address of the notifying device\n * Context: can't sleep\n *\n * Helper function to be called from an I2C bus driver's interrupt\n * handler. It will schedule the Host Notify IRQ.\n */\nint i2c_handle_smbus_host_notify(struct i2c_adapter *adap, unsigned short addr)\n{\n\tint irq;\n\n\tif (!adap)\n\t\treturn -EINVAL;\n\n\tirq = irq_find_mapping(adap->host_notify_domain, addr);\n\tif (irq <= 0)\n\t\treturn -ENXIO;\n\n\tgeneric_handle_irq(irq);\n\n\treturn 0;\n}\nEXPORT_SYMBOL_GPL(i2c_handle_smbus_host_notify);\n\nstatic int i2c_register_adapter(struct i2c_adapter *adap)\n{\n\tint res = -EINVAL;\n\n\t/* Can't register until after driver model init */\n\tif (WARN_ON(!is_registered)) {\n\t\tres = -EAGAIN;\n\t\tgoto out_list;\n\t}\n\n\t/* Sanity checks */\n\tif (WARN(!adap->name[0], \"i2c adapter has no name\"))\n\t\tgoto out_list;\n\n\tif (!adap->algo) {\n\t\tpr_err(\"adapter '%s': no algo supplied!\\n\", adap->name);\n\t\tgoto out_list;\n\t}\n\n\tif (!adap->lock_ops)\n\t\tadap->lock_ops = &i2c_adapter_lock_ops;\n\n\tadap->locked_flags = 0;\n\trt_mutex_init(&adap->bus_lock);\n\trt_mutex_init(&adap->mux_lock);\n\tmutex_init(&adap->userspace_clients_lock);\n\tINIT_LIST_HEAD(&adap->userspace_clients);\n\n\t/* Set default timeout to 1 second if not already set */\n\tif (adap->timeout == 0)\n\t\tadap->timeout = HZ;\n\n\t/* register soft irqs for Host Notify */\n\tres = i2c_setup_host_notify_irq_domain(adap);\n\tif (res) {\n\t\tpr_err(\"adapter '%s': can't create Host Notify IRQs (%d)\\n\",\n\t\t       adap->name, res);\n\t\tgoto out_list;\n\t}\n\n\tdev_set_name(&adap->dev, \"i2c-%d\", adap->nr);\n\tadap->dev.bus = &i2c_bus_type;\n\tadap->dev.type = &i2c_adapter_type;\n\tres = device_register(&adap->dev);\n\tif (res) {\n\t\tpr_err(\"adapter '%s': can't register device (%d)\\n\", adap->name, res);\n\t\tgoto out_list;\n\t}\n\n\tres = of_i2c_setup_smbus_alert(adap);\n\tif (res)\n\t\tgoto out_reg;\n\n\tdev_dbg(&adap->dev, \"adapter [%s] registered\\n\", adap->name);\n\n\tpm_runtime_no_callbacks(&adap->dev);\n\tpm_suspend_ignore_children(&adap->dev, true);\n\tpm_runtime_enable(&adap->dev);\n\n#ifdef CONFIG_I2C_COMPAT\n\tres = class_compat_create_link(i2c_adapter_compat_class, &adap->dev,\n\t\t\t\t       adap->dev.parent);\n\tif (res)\n\t\tdev_warn(&adap->dev,\n\t\t\t \"Failed to create compatibility class link\\n\");\n#endif\n\n\ti2c_init_recovery(adap);\n\n\t/* create pre-declared device nodes */\n\tof_i2c_register_devices(adap);\n\ti2c_acpi_register_devices(adap);\n\ti2c_acpi_install_space_handler(adap);\n\n\tif (adap->nr < __i2c_first_dynamic_bus_num)\n\t\ti2c_scan_static_board_info(adap);\n\n\t/* Notify drivers */\n\tmutex_lock(&core_lock);\n\tbus_for_each_drv(&i2c_bus_type, NULL, adap, __process_new_adapter);\n\tmutex_unlock(&core_lock);\n\n\treturn 0;\n\nout_reg:\n\tinit_completion(&adap->dev_released);\n\tdevice_unregister(&adap->dev);\n\twait_for_completion(&adap->dev_released);\nout_list:\n\tmutex_lock(&core_lock);\n\tidr_remove(&i2c_adapter_idr, adap->nr);\n\tmutex_unlock(&core_lock);\n\treturn res;\n}\n\n/**\n * __i2c_add_numbered_adapter - i2c_add_numbered_adapter where nr is never -1\n * @adap: the adapter to register (with adap->nr initialized)\n * Context: can sleep\n *\n * See i2c_add_numbered_adapter() for details.\n */\nstatic int __i2c_add_numbered_adapter(struct i2c_adapter *adap)\n{\n\tint id;\n\n\tmutex_lock(&core_lock);\n\tid = idr_alloc(&i2c_adapter_idr, adap, adap->nr, adap->nr + 1, GFP_KERNEL);\n\tmutex_unlock(&core_lock);\n\tif (WARN(id < 0, \"couldn't get idr\"))\n\t\treturn id == -ENOSPC ? -EBUSY : id;\n\n\treturn i2c_register_adapter(adap);\n}\n\n/**\n * i2c_add_adapter - declare i2c adapter, use dynamic bus number\n * @adapter: the adapter to add\n * Context: can sleep\n *\n * This routine is used to declare an I2C adapter when its bus number\n * doesn't matter or when its bus number is specified by an dt alias.\n * Examples of bases when the bus number doesn't matter: I2C adapters\n * dynamically added by USB links or PCI plugin cards.\n *\n * When this returns zero, a new bus number was allocated and stored\n * in adap->nr, and the specified adapter became available for clients.\n * Otherwise, a negative errno value is returned.\n */\nint i2c_add_adapter(struct i2c_adapter *adapter)\n{\n\tstruct device *dev = &adapter->dev;\n\tint id;\n\n\tif (dev->of_node) {\n\t\tid = of_alias_get_id(dev->of_node, \"i2c\");\n\t\tif (id >= 0) {\n\t\t\tadapter->nr = id;\n\t\t\treturn __i2c_add_numbered_adapter(adapter);\n\t\t}\n\t}\n\n\tmutex_lock(&core_lock);\n\tid = idr_alloc(&i2c_adapter_idr, adapter,\n\t\t       __i2c_first_dynamic_bus_num, 0, GFP_KERNEL);\n\tmutex_unlock(&core_lock);\n\tif (WARN(id < 0, \"couldn't get idr\"))\n\t\treturn id;\n\n\tadapter->nr = id;\n\n\treturn i2c_register_adapter(adapter);\n}\nEXPORT_SYMBOL(i2c_add_adapter);\n\n/**\n * i2c_add_numbered_adapter - declare i2c adapter, use static bus number\n * @adap: the adapter to register (with adap->nr initialized)\n * Context: can sleep\n *\n * This routine is used to declare an I2C adapter when its bus number\n * matters.  For example, use it for I2C adapters from system-on-chip CPUs,\n * or otherwise built in to the system's mainboard, and where i2c_board_info\n * is used to properly configure I2C devices.\n *\n * If the requested bus number is set to -1, then this function will behave\n * identically to i2c_add_adapter, and will dynamically assign a bus number.\n *\n * If no devices have pre-been declared for this bus, then be sure to\n * register the adapter before any dynamically allocated ones.  Otherwise\n * the required bus ID may not be available.\n *\n * When this returns zero, the specified adapter became available for\n * clients using the bus number provided in adap->nr.  Also, the table\n * of I2C devices pre-declared using i2c_register_board_info() is scanned,\n * and the appropriate driver model device nodes are created.  Otherwise, a\n * negative errno value is returned.\n */\nint i2c_add_numbered_adapter(struct i2c_adapter *adap)\n{\n\tif (adap->nr == -1) /* -1 means dynamically assign bus id */\n\t\treturn i2c_add_adapter(adap);\n\n\treturn __i2c_add_numbered_adapter(adap);\n}\nEXPORT_SYMBOL_GPL(i2c_add_numbered_adapter);\n\nstatic void i2c_do_del_adapter(struct i2c_driver *driver,\n\t\t\t      struct i2c_adapter *adapter)\n{\n\tstruct i2c_client *client, *_n;\n\n\t/* Remove the devices we created ourselves as the result of hardware\n\t * probing (using a driver's detect method) */\n\tlist_for_each_entry_safe(client, _n, &driver->clients, detected) {\n\t\tif (client->adapter == adapter) {\n\t\t\tdev_dbg(&adapter->dev, \"Removing %s at 0x%x\\n\",\n\t\t\t\tclient->name, client->addr);\n\t\t\tlist_del(&client->detected);\n\t\t\ti2c_unregister_device(client);\n\t\t}\n\t}\n}\n\nstatic int __unregister_client(struct device *dev, void *dummy)\n{\n\tstruct i2c_client *client = i2c_verify_client(dev);\n\tif (client && strcmp(client->name, \"dummy\"))\n\t\ti2c_unregister_device(client);\n\treturn 0;\n}\n\nstatic int __unregister_dummy(struct device *dev, void *dummy)\n{\n\tstruct i2c_client *client = i2c_verify_client(dev);\n\ti2c_unregister_device(client);\n\treturn 0;\n}\n\nstatic int __process_removed_adapter(struct device_driver *d, void *data)\n{\n\ti2c_do_del_adapter(to_i2c_driver(d), data);\n\treturn 0;\n}\n\n/**\n * i2c_del_adapter - unregister I2C adapter\n * @adap: the adapter being unregistered\n * Context: can sleep\n *\n * This unregisters an I2C adapter which was previously registered\n * by @i2c_add_adapter or @i2c_add_numbered_adapter.\n */\nvoid i2c_del_adapter(struct i2c_adapter *adap)\n{\n\tstruct i2c_adapter *found;\n\tstruct i2c_client *client, *next;\n\n\t/* First make sure that this adapter was ever added */\n\tmutex_lock(&core_lock);\n\tfound = idr_find(&i2c_adapter_idr, adap->nr);\n\tmutex_unlock(&core_lock);\n\tif (found != adap) {\n\t\tpr_debug(\"attempting to delete unregistered adapter [%s]\\n\", adap->name);\n\t\treturn;\n\t}\n\n\ti2c_acpi_remove_space_handler(adap);\n\t/* Tell drivers about this removal */\n\tmutex_lock(&core_lock);\n\tbus_for_each_drv(&i2c_bus_type, NULL, adap,\n\t\t\t       __process_removed_adapter);\n\tmutex_unlock(&core_lock);\n\n\t/* Remove devices instantiated from sysfs */\n\tmutex_lock_nested(&adap->userspace_clients_lock,\n\t\t\t  i2c_adapter_depth(adap));\n\tlist_for_each_entry_safe(client, next, &adap->userspace_clients,\n\t\t\t\t detected) {\n\t\tdev_dbg(&adap->dev, \"Removing %s at 0x%x\\n\", client->name,\n\t\t\tclient->addr);\n\t\tlist_del(&client->detected);\n\t\ti2c_unregister_device(client);\n\t}\n\tmutex_unlock(&adap->userspace_clients_lock);\n\n\t/* Detach any active clients. This can't fail, thus we do not\n\t * check the returned value. This is a two-pass process, because\n\t * we can't remove the dummy devices during the first pass: they\n\t * could have been instantiated by real devices wishing to clean\n\t * them up properly, so we give them a chance to do that first. */\n\tdevice_for_each_child(&adap->dev, NULL, __unregister_client);\n\tdevice_for_each_child(&adap->dev, NULL, __unregister_dummy);\n\n#ifdef CONFIG_I2C_COMPAT\n\tclass_compat_remove_link(i2c_adapter_compat_class, &adap->dev,\n\t\t\t\t adap->dev.parent);\n#endif\n\n\t/* device name is gone after device_unregister */\n\tdev_dbg(&adap->dev, \"adapter [%s] unregistered\\n\", adap->name);\n\n\tpm_runtime_disable(&adap->dev);\n\n\ti2c_host_notify_irq_teardown(adap);\n\n\t/* wait until all references to the device are gone\n\t *\n\t * FIXME: This is old code and should ideally be replaced by an\n\t * alternative which results in decoupling the lifetime of the struct\n\t * device from the i2c_adapter, like spi or netdev do. Any solution\n\t * should be thoroughly tested with DEBUG_KOBJECT_RELEASE enabled!\n\t */\n\tinit_completion(&adap->dev_released);\n\tdevice_unregister(&adap->dev);\n\twait_for_completion(&adap->dev_released);\n\n\t/* free bus id */\n\tmutex_lock(&core_lock);\n\tidr_remove(&i2c_adapter_idr, adap->nr);\n\tmutex_unlock(&core_lock);\n\n\t/* Clear the device structure in case this adapter is ever going to be\n\t   added again */\n\tmemset(&adap->dev, 0, sizeof(adap->dev));\n}\nEXPORT_SYMBOL(i2c_del_adapter);\n\n/**\n * i2c_parse_fw_timings - get I2C related timing parameters from firmware\n * @dev: The device to scan for I2C timing properties\n * @t: the i2c_timings struct to be filled with values\n * @use_defaults: bool to use sane defaults derived from the I2C specification\n *\t\t  when properties are not found, otherwise use 0\n *\n * Scan the device for the generic I2C properties describing timing parameters\n * for the signal and fill the given struct with the results. If a property was\n * not found and use_defaults was true, then maximum timings are assumed which\n * are derived from the I2C specification. If use_defaults is not used, the\n * results will be 0, so drivers can apply their own defaults later. The latter\n * is mainly intended for avoiding regressions of existing drivers which want\n * to switch to this function. New drivers almost always should use the defaults.\n */\n\nvoid i2c_parse_fw_timings(struct device *dev, struct i2c_timings *t, bool use_defaults)\n{\n\tint ret;\n\n\tmemset(t, 0, sizeof(*t));\n\n\tret = device_property_read_u32(dev, \"clock-frequency\", &t->bus_freq_hz);\n\tif (ret && use_defaults)\n\t\tt->bus_freq_hz = 100000;\n\n\tret = device_property_read_u32(dev, \"i2c-scl-rising-time-ns\", &t->scl_rise_ns);\n\tif (ret && use_defaults) {\n\t\tif (t->bus_freq_hz <= 100000)\n\t\t\tt->scl_rise_ns = 1000;\n\t\telse if (t->bus_freq_hz <= 400000)\n\t\t\tt->scl_rise_ns = 300;\n\t\telse\n\t\t\tt->scl_rise_ns = 120;\n\t}\n\n\tret = device_property_read_u32(dev, \"i2c-scl-falling-time-ns\", &t->scl_fall_ns);\n\tif (ret && use_defaults) {\n\t\tif (t->bus_freq_hz <= 400000)\n\t\t\tt->scl_fall_ns = 300;\n\t\telse\n\t\t\tt->scl_fall_ns = 120;\n\t}\n\n\tdevice_property_read_u32(dev, \"i2c-scl-internal-delay-ns\", &t->scl_int_delay_ns);\n\n\tret = device_property_read_u32(dev, \"i2c-sda-falling-time-ns\", &t->sda_fall_ns);\n\tif (ret && use_defaults)\n\t\tt->sda_fall_ns = t->scl_fall_ns;\n\n\tdevice_property_read_u32(dev, \"i2c-sda-hold-time-ns\", &t->sda_hold_ns);\n}\nEXPORT_SYMBOL_GPL(i2c_parse_fw_timings);\n\n/* ------------------------------------------------------------------------- */\n\nint i2c_for_each_dev(void *data, int (*fn)(struct device *dev, void *data))\n{\n\tint res;\n\n\tmutex_lock(&core_lock);\n\tres = bus_for_each_dev(&i2c_bus_type, NULL, data, fn);\n\tmutex_unlock(&core_lock);\n\n\treturn res;\n}\nEXPORT_SYMBOL_GPL(i2c_for_each_dev);\n\nstatic int __process_new_driver(struct device *dev, void *data)\n{\n\tif (dev->type != &i2c_adapter_type)\n\t\treturn 0;\n\treturn i2c_do_add_adapter(data, to_i2c_adapter(dev));\n}\n\n/*\n * An i2c_driver is used with one or more i2c_client (device) nodes to access\n * i2c slave chips, on a bus instance associated with some i2c_adapter.\n */\n\nint i2c_register_driver(struct module *owner, struct i2c_driver *driver)\n{\n\tint res;\n\n\t/* Can't register until after driver model init */\n\tif (WARN_ON(!is_registered))\n\t\treturn -EAGAIN;\n\n\t/* add the driver to the list of i2c drivers in the driver core */\n\tdriver->driver.owner = owner;\n\tdriver->driver.bus = &i2c_bus_type;\n\tINIT_LIST_HEAD(&driver->clients);\n\n\t/* When registration returns, the driver core\n\t * will have called probe() for all matching-but-unbound devices.\n\t */\n\tres = driver_register(&driver->driver);\n\tif (res)\n\t\treturn res;\n\n\tpr_debug(\"driver [%s] registered\\n\", driver->driver.name);\n\n\t/* Walk the adapters that are already present */\n\ti2c_for_each_dev(driver, __process_new_driver);\n\n\treturn 0;\n}\nEXPORT_SYMBOL(i2c_register_driver);\n\nstatic int __process_removed_driver(struct device *dev, void *data)\n{\n\tif (dev->type == &i2c_adapter_type)\n\t\ti2c_do_del_adapter(data, to_i2c_adapter(dev));\n\treturn 0;\n}\n\n/**\n * i2c_del_driver - unregister I2C driver\n * @driver: the driver being unregistered\n * Context: can sleep\n */\nvoid i2c_del_driver(struct i2c_driver *driver)\n{\n\ti2c_for_each_dev(driver, __process_removed_driver);\n\n\tdriver_unregister(&driver->driver);\n\tpr_debug(\"driver [%s] unregistered\\n\", driver->driver.name);\n}\nEXPORT_SYMBOL(i2c_del_driver);\n\n/* ------------------------------------------------------------------------- */\n\n/**\n * i2c_use_client - increments the reference count of the i2c client structure\n * @client: the client being referenced\n *\n * Each live reference to a client should be refcounted. The driver model does\n * that automatically as part of driver binding, so that most drivers don't\n * need to do this explicitly: they hold a reference until they're unbound\n * from the device.\n *\n * A pointer to the client with the incremented reference counter is returned.\n */\nstruct i2c_client *i2c_use_client(struct i2c_client *client)\n{\n\tif (client && get_device(&client->dev))\n\t\treturn client;\n\treturn NULL;\n}\nEXPORT_SYMBOL(i2c_use_client);\n\n/**\n * i2c_release_client - release a use of the i2c client structure\n * @client: the client being no longer referenced\n *\n * Must be called when a user of a client is finished with it.\n */\nvoid i2c_release_client(struct i2c_client *client)\n{\n\tif (client)\n\t\tput_device(&client->dev);\n}\nEXPORT_SYMBOL(i2c_release_client);\n\nstruct i2c_cmd_arg {\n\tunsigned\tcmd;\n\tvoid\t\t*arg;\n};\n\nstatic int i2c_cmd(struct device *dev, void *_arg)\n{\n\tstruct i2c_client\t*client = i2c_verify_client(dev);\n\tstruct i2c_cmd_arg\t*arg = _arg;\n\tstruct i2c_driver\t*driver;\n\n\tif (!client || !client->dev.driver)\n\t\treturn 0;\n\n\tdriver = to_i2c_driver(client->dev.driver);\n\tif (driver->command)\n\t\tdriver->command(client, arg->cmd, arg->arg);\n\treturn 0;\n}\n\nvoid i2c_clients_command(struct i2c_adapter *adap, unsigned int cmd, void *arg)\n{\n\tstruct i2c_cmd_arg\tcmd_arg;\n\n\tcmd_arg.cmd = cmd;\n\tcmd_arg.arg = arg;\n\tdevice_for_each_child(&adap->dev, &cmd_arg, i2c_cmd);\n}\nEXPORT_SYMBOL(i2c_clients_command);\n\nstatic int __init i2c_init(void)\n{\n\tint retval;\n\n\tretval = of_alias_get_highest_id(\"i2c\");\n\n\tdown_write(&__i2c_board_lock);\n\tif (retval >= __i2c_first_dynamic_bus_num)\n\t\t__i2c_first_dynamic_bus_num = retval + 1;\n\tup_write(&__i2c_board_lock);\n\n\tretval = bus_register(&i2c_bus_type);\n\tif (retval)\n\t\treturn retval;\n\n\tis_registered = true;\n\n#ifdef CONFIG_I2C_COMPAT\n\ti2c_adapter_compat_class = class_compat_register(\"i2c-adapter\");\n\tif (!i2c_adapter_compat_class) {\n\t\tretval = -ENOMEM;\n\t\tgoto bus_err;\n\t}\n#endif\n\tretval = i2c_add_driver(&dummy_driver);\n\tif (retval)\n\t\tgoto class_err;\n\n\tif (IS_ENABLED(CONFIG_OF_DYNAMIC))\n\t\tWARN_ON(of_reconfig_notifier_register(&i2c_of_notifier));\n\tif (IS_ENABLED(CONFIG_ACPI))\n\t\tWARN_ON(acpi_reconfig_notifier_register(&i2c_acpi_notifier));\n\n\treturn 0;\n\nclass_err:\n#ifdef CONFIG_I2C_COMPAT\n\tclass_compat_unregister(i2c_adapter_compat_class);\nbus_err:\n#endif\n\tis_registered = false;\n\tbus_unregister(&i2c_bus_type);\n\treturn retval;\n}\n\nstatic void __exit i2c_exit(void)\n{\n\tif (IS_ENABLED(CONFIG_ACPI))\n\t\tWARN_ON(acpi_reconfig_notifier_unregister(&i2c_acpi_notifier));\n\tif (IS_ENABLED(CONFIG_OF_DYNAMIC))\n\t\tWARN_ON(of_reconfig_notifier_unregister(&i2c_of_notifier));\n\ti2c_del_driver(&dummy_driver);\n#ifdef CONFIG_I2C_COMPAT\n\tclass_compat_unregister(i2c_adapter_compat_class);\n#endif\n\tbus_unregister(&i2c_bus_type);\n\ttracepoint_synchronize_unregister();\n}\n\n/* We must initialize early, because some subsystems register i2c drivers\n * in subsys_initcall() code, but are linked (and initialized) before i2c.\n */\npostcore_initcall(i2c_init);\nmodule_exit(i2c_exit);\n\n/* ----------------------------------------------------\n * the functional interface to the i2c busses.\n * ----------------------------------------------------\n */\n\n/* Check if val is exceeding the quirk IFF quirk is non 0 */\n#define i2c_quirk_exceeded(val, quirk) ((quirk) && ((val) > (quirk)))\n\nstatic int i2c_quirk_error(struct i2c_adapter *adap, struct i2c_msg *msg, char *err_msg)\n{\n\tdev_err_ratelimited(&adap->dev, \"adapter quirk: %s (addr 0x%04x, size %u, %s)\\n\",\n\t\t\t    err_msg, msg->addr, msg->len,\n\t\t\t    msg->flags & I2C_M_RD ? \"read\" : \"write\");\n\treturn -EOPNOTSUPP;\n}\n\nstatic int i2c_check_for_quirks(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)\n{\n\tconst struct i2c_adapter_quirks *q = adap->quirks;\n\tint max_num = q->max_num_msgs, i;\n\tbool do_len_check = true;\n\n\tif (q->flags & I2C_AQ_COMB) {\n\t\tmax_num = 2;\n\n\t\t/* special checks for combined messages */\n\t\tif (num == 2) {\n\t\t\tif (q->flags & I2C_AQ_COMB_WRITE_FIRST && msgs[0].flags & I2C_M_RD)\n\t\t\t\treturn i2c_quirk_error(adap, &msgs[0], \"1st comb msg must be write\");\n\n\t\t\tif (q->flags & I2C_AQ_COMB_READ_SECOND && !(msgs[1].flags & I2C_M_RD))\n\t\t\t\treturn i2c_quirk_error(adap, &msgs[1], \"2nd comb msg must be read\");\n\n\t\t\tif (q->flags & I2C_AQ_COMB_SAME_ADDR && msgs[0].addr != msgs[1].addr)\n\t\t\t\treturn i2c_quirk_error(adap, &msgs[0], \"comb msg only to same addr\");\n\n\t\t\tif (i2c_quirk_exceeded(msgs[0].len, q->max_comb_1st_msg_len))\n\t\t\t\treturn i2c_quirk_error(adap, &msgs[0], \"msg too long\");\n\n\t\t\tif (i2c_quirk_exceeded(msgs[1].len, q->max_comb_2nd_msg_len))\n\t\t\t\treturn i2c_quirk_error(adap, &msgs[1], \"msg too long\");\n\n\t\t\tdo_len_check = false;\n\t\t}\n\t}\n\n\tif (i2c_quirk_exceeded(num, max_num))\n\t\treturn i2c_quirk_error(adap, &msgs[0], \"too many messages\");\n\n\tfor (i = 0; i < num; i++) {\n\t\tu16 len = msgs[i].len;\n\n\t\tif (msgs[i].flags & I2C_M_RD) {\n\t\t\tif (do_len_check && i2c_quirk_exceeded(len, q->max_read_len))\n\t\t\t\treturn i2c_quirk_error(adap, &msgs[i], \"msg too long\");\n\n\t\t\tif (q->flags & I2C_AQ_NO_ZERO_LEN_READ && len == 0)\n\t\t\t\treturn i2c_quirk_error(adap, &msgs[i], \"no zero length\");\n\t\t} else {\n\t\t\tif (do_len_check && i2c_quirk_exceeded(len, q->max_write_len))\n\t\t\t\treturn i2c_quirk_error(adap, &msgs[i], \"msg too long\");\n\n\t\t\tif (q->flags & I2C_AQ_NO_ZERO_LEN_WRITE && len == 0)\n\t\t\t\treturn i2c_quirk_error(adap, &msgs[i], \"no zero length\");\n\t\t}\n\t}\n\n\treturn 0;\n}\n\n/**\n * __i2c_transfer - unlocked flavor of i2c_transfer\n * @adap: Handle to I2C bus\n * @msgs: One or more messages to execute before STOP is issued to\n *\tterminate the operation; each message begins with a START.\n * @num: Number of messages to be executed.\n *\n * Returns negative errno, else the number of messages executed.\n *\n * Adapter lock must be held when calling this function. No debug logging\n * takes place. adap->algo->master_xfer existence isn't checked.\n */\nint __i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)\n{\n\tunsigned long orig_jiffies;\n\tint ret, try;\n\n\tif (WARN_ON(!msgs || num < 1))\n\t\treturn -EINVAL;\n\n\tret = __i2c_check_suspended(adap);\n\tif (ret)\n\t\treturn ret;\n\n\tif (adap->quirks && i2c_check_for_quirks(adap, msgs, num))\n\t\treturn -EOPNOTSUPP;\n\n\t/*\n\t * i2c_trace_msg_key gets enabled when tracepoint i2c_transfer gets\n\t * enabled.  This is an efficient way of keeping the for-loop from\n\t * being executed when not needed.\n\t */\n\tif (static_branch_unlikely(&i2c_trace_msg_key)) {\n\t\tint i;\n\t\tfor (i = 0; i < num; i++)\n\t\t\tif (msgs[i].flags & I2C_M_RD)\n\t\t\t\ttrace_i2c_read(adap, &msgs[i], i);\n\t\t\telse\n\t\t\t\ttrace_i2c_write(adap, &msgs[i], i);\n\t}\n\n\t/* Retry automatically on arbitration loss */\n\torig_jiffies = jiffies;\n\tfor (ret = 0, try = 0; try <= adap->retries; try++) {\n\t\tif (i2c_in_atomic_xfer_mode() && adap->algo->master_xfer_atomic)\n\t\t\tret = adap->algo->master_xfer_atomic(adap, msgs, num);\n\t\telse\n\t\t\tret = adap->algo->master_xfer(adap, msgs, num);\n\n\t\tif (ret != -EAGAIN)\n\t\t\tbreak;\n\t\tif (time_after(jiffies, orig_jiffies + adap->timeout))\n\t\t\tbreak;\n\t}\n\n\tif (static_branch_unlikely(&i2c_trace_msg_key)) {\n\t\tint i;\n\t\tfor (i = 0; i < ret; i++)\n\t\t\tif (msgs[i].flags & I2C_M_RD)\n\t\t\t\ttrace_i2c_reply(adap, &msgs[i], i);\n\t\ttrace_i2c_result(adap, num, ret);\n\t}\n\n\treturn ret;\n}\nEXPORT_SYMBOL(__i2c_transfer);\n\n/**\n * i2c_transfer - execute a single or combined I2C message\n * @adap: Handle to I2C bus\n * @msgs: One or more messages to execute before STOP is issued to\n *\tterminate the operation; each message begins with a START.\n * @num: Number of messages to be executed.\n *\n * Returns negative errno, else the number of messages executed.\n *\n * Note that there is no requirement that each message be sent to\n * the same slave address, although that is the most common model.\n */\nint i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)\n{\n\tint ret;\n\n\tif (!adap->algo->master_xfer) {\n\t\tdev_dbg(&adap->dev, \"I2C level transfers not supported\\n\");\n\t\treturn -EOPNOTSUPP;\n\t}\n\n\t/* REVISIT the fault reporting model here is weak:\n\t *\n\t *  - When we get an error after receiving N bytes from a slave,\n\t *    there is no way to report \"N\".\n\t *\n\t *  - When we get a NAK after transmitting N bytes to a slave,\n\t *    there is no way to report \"N\" ... or to let the master\n\t *    continue executing the rest of this combined message, if\n\t *    that's the appropriate response.\n\t *\n\t *  - When for example \"num\" is two and we successfully complete\n\t *    the first message but get an error part way through the\n\t *    second, it's unclear whether that should be reported as\n\t *    one (discarding status on the second message) or errno\n\t *    (discarding status on the first one).\n\t */\n\tret = __i2c_lock_bus_helper(adap);\n\tif (ret)\n\t\treturn ret;\n\n\tret = __i2c_transfer(adap, msgs, num);\n\ti2c_unlock_bus(adap, I2C_LOCK_SEGMENT);\n\n\treturn ret;\n}\nEXPORT_SYMBOL(i2c_transfer);\n\n/**\n * i2c_transfer_buffer_flags - issue a single I2C message transferring data\n *\t\t\t       to/from a buffer\n * @client: Handle to slave device\n * @buf: Where the data is stored\n * @count: How many bytes to transfer, must be less than 64k since msg.len is u16\n * @flags: The flags to be used for the message, e.g. I2C_M_RD for reads\n *\n * Returns negative errno, or else the number of bytes transferred.\n */\nint i2c_transfer_buffer_flags(const struct i2c_client *client, char *buf,\n\t\t\t      int count, u16 flags)\n{\n\tint ret;\n\tstruct i2c_msg msg = {\n\t\t.addr = client->addr,\n\t\t.flags = flags | (client->flags & I2C_M_TEN),\n\t\t.len = count,\n\t\t.buf = buf,\n\t};\n\n\tret = i2c_transfer(client->adapter, &msg, 1);\n\n\t/*\n\t * If everything went ok (i.e. 1 msg transferred), return #bytes\n\t * transferred, else error code.\n\t */\n\treturn (ret == 1) ? count : ret;\n}\nEXPORT_SYMBOL(i2c_transfer_buffer_flags);\n\n/**\n * i2c_get_device_id - get manufacturer, part id and die revision of a device\n * @client: The device to query\n * @id: The queried information\n *\n * Returns negative errno on error, zero on success.\n */\nint i2c_get_device_id(const struct i2c_client *client,\n\t\t      struct i2c_device_identity *id)\n{\n\tstruct i2c_adapter *adap = client->adapter;\n\tunion i2c_smbus_data raw_id;\n\tint ret;\n\n\tif (!i2c_check_functionality(adap, I2C_FUNC_SMBUS_READ_I2C_BLOCK))\n\t\treturn -EOPNOTSUPP;\n\n\traw_id.block[0] = 3;\n\tret = i2c_smbus_xfer(adap, I2C_ADDR_DEVICE_ID, 0,\n\t\t\t     I2C_SMBUS_READ, client->addr << 1,\n\t\t\t     I2C_SMBUS_I2C_BLOCK_DATA, &raw_id);\n\tif (ret)\n\t\treturn ret;\n\n\tid->manufacturer_id = (raw_id.block[1] << 4) | (raw_id.block[2] >> 4);\n\tid->part_id = ((raw_id.block[2] & 0xf) << 5) | (raw_id.block[3] >> 3);\n\tid->die_revision = raw_id.block[3] & 0x7;\n\treturn 0;\n}\nEXPORT_SYMBOL_GPL(i2c_get_device_id);\n\n/* ----------------------------------------------------\n * the i2c address scanning function\n * Will not work for 10-bit addresses!\n * ----------------------------------------------------\n */\n\n/*\n * Legacy default probe function, mostly relevant for SMBus. The default\n * probe method is a quick write, but it is known to corrupt the 24RF08\n * EEPROMs due to a state machine bug, and could also irreversibly\n * write-protect some EEPROMs, so for address ranges 0x30-0x37 and 0x50-0x5f,\n * we use a short byte read instead. Also, some bus drivers don't implement\n * quick write, so we fallback to a byte read in that case too.\n * On x86, there is another special case for FSC hardware monitoring chips,\n * which want regular byte reads (address 0x73.) Fortunately, these are the\n * only known chips using this I2C address on PC hardware.\n * Returns 1 if probe succeeded, 0 if not.\n */\nstatic int i2c_default_probe(struct i2c_adapter *adap, unsigned short addr)\n{\n\tint err;\n\tunion i2c_smbus_data dummy;\n\n#ifdef CONFIG_X86\n\tif (addr == 0x73 && (adap->class & I2C_CLASS_HWMON)\n\t && i2c_check_functionality(adap, I2C_FUNC_SMBUS_READ_BYTE_DATA))\n\t\terr = i2c_smbus_xfer(adap, addr, 0, I2C_SMBUS_READ, 0,\n\t\t\t\t     I2C_SMBUS_BYTE_DATA, &dummy);\n\telse\n#endif\n\tif (!((addr & ~0x07) == 0x30 || (addr & ~0x0f) == 0x50)\n\t && i2c_check_functionality(adap, I2C_FUNC_SMBUS_QUICK))\n\t\terr = i2c_smbus_xfer(adap, addr, 0, I2C_SMBUS_WRITE, 0,\n\t\t\t\t     I2C_SMBUS_QUICK, NULL);\n\telse if (i2c_check_functionality(adap, I2C_FUNC_SMBUS_READ_BYTE))\n\t\terr = i2c_smbus_xfer(adap, addr, 0, I2C_SMBUS_READ, 0,\n\t\t\t\t     I2C_SMBUS_BYTE, &dummy);\n\telse {\n\t\tdev_warn(&adap->dev, \"No suitable probing method supported for address 0x%02X\\n\",\n\t\t\t addr);\n\t\terr = -EOPNOTSUPP;\n\t}\n\n\treturn err >= 0;\n}\n\nstatic int i2c_detect_address(struct i2c_client *temp_client,\n\t\t\t      struct i2c_driver *driver)\n{\n\tstruct i2c_board_info info;\n\tstruct i2c_adapter *adapter = temp_client->adapter;\n\tint addr = temp_client->addr;\n\tint err;\n\n\t/* Make sure the address is valid */\n\terr = i2c_check_7bit_addr_validity_strict(addr);\n\tif (err) {\n\t\tdev_warn(&adapter->dev, \"Invalid probe address 0x%02x\\n\",\n\t\t\t addr);\n\t\treturn err;\n\t}\n\n\t/* Skip if already in use (7 bit, no need to encode flags) */\n\tif (i2c_check_addr_busy(adapter, addr))\n\t\treturn 0;\n\n\t/* Make sure there is something at this address */\n\tif (!i2c_default_probe(adapter, addr))\n\t\treturn 0;\n\n\t/* Finally call the custom detection function */\n\tmemset(&info, 0, sizeof(struct i2c_board_info));\n\tinfo.addr = addr;\n\terr = driver->detect(temp_client, &info);\n\tif (err) {\n\t\t/* -ENODEV is returned if the detection fails. We catch it\n\t\t   here as this isn't an error. */\n\t\treturn err == -ENODEV ? 0 : err;\n\t}\n\n\t/* Consistency check */\n\tif (info.type[0] == '\\0') {\n\t\tdev_err(&adapter->dev,\n\t\t\t\"%s detection function provided no name for 0x%x\\n\",\n\t\t\tdriver->driver.name, addr);\n\t} else {\n\t\tstruct i2c_client *client;\n\n\t\t/* Detection succeeded, instantiate the device */\n\t\tif (adapter->class & I2C_CLASS_DEPRECATED)\n\t\t\tdev_warn(&adapter->dev,\n\t\t\t\t\"This adapter will soon drop class based instantiation of devices. \"\n\t\t\t\t\"Please make sure client 0x%02x gets instantiated by other means. \"\n\t\t\t\t\"Check 'Documentation/i2c/instantiating-devices.rst' for details.\\n\",\n\t\t\t\tinfo.addr);\n\n\t\tdev_dbg(&adapter->dev, \"Creating %s at 0x%02x\\n\",\n\t\t\tinfo.type, info.addr);\n\t\tclient = i2c_new_device(adapter, &info);\n\t\tif (client)\n\t\t\tlist_add_tail(&client->detected, &driver->clients);\n\t\telse\n\t\t\tdev_err(&adapter->dev, \"Failed creating %s at 0x%02x\\n\",\n\t\t\t\tinfo.type, info.addr);\n\t}\n\treturn 0;\n}\n\nstatic int i2c_detect(struct i2c_adapter *adapter, struct i2c_driver *driver)\n{\n\tconst unsigned short *address_list;\n\tstruct i2c_client *temp_client;\n\tint i, err = 0;\n\tint adap_id = i2c_adapter_id(adapter);\n\n\taddress_list = driver->address_list;\n\tif (!driver->detect || !address_list)\n\t\treturn 0;\n\n\t/* Warn that the adapter lost class based instantiation */\n\tif (adapter->class == I2C_CLASS_DEPRECATED) {\n\t\tdev_dbg(&adapter->dev,\n\t\t\t\"This adapter dropped support for I2C classes and won't auto-detect %s devices anymore. \"\n\t\t\t\"If you need it, check 'Documentation/i2c/instantiating-devices.rst' for alternatives.\\n\",\n\t\t\tdriver->driver.name);\n\t\treturn 0;\n\t}\n\n\t/* Stop here if the classes do not match */\n\tif (!(adapter->class & driver->class))\n\t\treturn 0;\n\n\t/* Set up a temporary client to help detect callback */\n\ttemp_client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);\n\tif (!temp_client)\n\t\treturn -ENOMEM;\n\ttemp_client->adapter = adapter;\n\n\tfor (i = 0; address_list[i] != I2C_CLIENT_END; i += 1) {\n\t\tdev_dbg(&adapter->dev,\n\t\t\t\"found normal entry for adapter %d, addr 0x%02x\\n\",\n\t\t\tadap_id, address_list[i]);\n\t\ttemp_client->addr = address_list[i];\n\t\terr = i2c_detect_address(temp_client, driver);\n\t\tif (unlikely(err))\n\t\t\tbreak;\n\t}\n\n\tkfree(temp_client);\n\treturn err;\n}\n\nint i2c_probe_func_quick_read(struct i2c_adapter *adap, unsigned short addr)\n{\n\treturn i2c_smbus_xfer(adap, addr, 0, I2C_SMBUS_READ, 0,\n\t\t\t      I2C_SMBUS_QUICK, NULL) >= 0;\n}\nEXPORT_SYMBOL_GPL(i2c_probe_func_quick_read);\n\nstruct i2c_client *\ni2c_new_probed_device(struct i2c_adapter *adap,\n\t\t      struct i2c_board_info *info,\n\t\t      unsigned short const *addr_list,\n\t\t      int (*probe)(struct i2c_adapter *adap, unsigned short addr))\n{\n\tint i;\n\n\tif (!probe)\n\t\tprobe = i2c_default_probe;\n\n\tfor (i = 0; addr_list[i] != I2C_CLIENT_END; i++) {\n\t\t/* Check address validity */\n\t\tif (i2c_check_7bit_addr_validity_strict(addr_list[i]) < 0) {\n\t\t\tdev_warn(&adap->dev, \"Invalid 7-bit address 0x%02x\\n\",\n\t\t\t\t addr_list[i]);\n\t\t\tcontinue;\n\t\t}\n\n\t\t/* Check address availability (7 bit, no need to encode flags) */\n\t\tif (i2c_check_addr_busy(adap, addr_list[i])) {\n\t\t\tdev_dbg(&adap->dev,\n\t\t\t\t\"Address 0x%02x already in use, not probing\\n\",\n\t\t\t\taddr_list[i]);\n\t\t\tcontinue;\n\t\t}\n\n\t\t/* Test address responsiveness */\n\t\tif (probe(adap, addr_list[i]))\n\t\t\tbreak;\n\t}\n\n\tif (addr_list[i] == I2C_CLIENT_END) {\n\t\tdev_dbg(&adap->dev, \"Probing failed, no device found\\n\");\n\t\treturn NULL;\n\t}\n\n\tinfo->addr = addr_list[i];\n\treturn i2c_new_device(adap, info);\n}\nEXPORT_SYMBOL_GPL(i2c_new_probed_device);\n\nstruct i2c_adapter *i2c_get_adapter(int nr)\n{\n\tstruct i2c_adapter *adapter;\n\n\tmutex_lock(&core_lock);\n\tadapter = idr_find(&i2c_adapter_idr, nr);\n\tif (!adapter)\n\t\tgoto exit;\n\n\tif (try_module_get(adapter->owner))\n\t\tget_device(&adapter->dev);\n\telse\n\t\tadapter = NULL;\n\n exit:\n\tmutex_unlock(&core_lock);\n\treturn adapter;\n}\nEXPORT_SYMBOL(i2c_get_adapter);\n\nvoid i2c_put_adapter(struct i2c_adapter *adap)\n{\n\tif (!adap)\n\t\treturn;\n\n\tput_device(&adap->dev);\n\tmodule_put(adap->owner);\n}\nEXPORT_SYMBOL(i2c_put_adapter);\n\n/**\n * i2c_get_dma_safe_msg_buf() - get a DMA safe buffer for the given i2c_msg\n * @msg: the message to be checked\n * @threshold: the minimum number of bytes for which using DMA makes sense.\n *\t       Should at least be 1.\n *\n * Return: NULL if a DMA safe buffer was not obtained. Use msg->buf with PIO.\n *\t   Or a valid pointer to be used with DMA. After use, release it by\n *\t   calling i2c_put_dma_safe_msg_buf().\n *\n * This function must only be called from process context!\n */\nu8 *i2c_get_dma_safe_msg_buf(struct i2c_msg *msg, unsigned int threshold)\n{\n\t/* also skip 0-length msgs for bogus thresholds of 0 */\n\tif (!threshold)\n\t\tpr_debug(\"DMA buffer for addr=0x%02x with length 0 is bogus\\n\",\n\t\t\t msg->addr);\n\tif (msg->len < threshold || msg->len == 0)\n\t\treturn NULL;\n\n\tif (msg->flags & I2C_M_DMA_SAFE)\n\t\treturn msg->buf;\n\n\tpr_debug(\"using bounce buffer for addr=0x%02x, len=%d\\n\",\n\t\t msg->addr, msg->len);\n\n\tif (msg->flags & I2C_M_RD)\n\t\treturn kzalloc(msg->len, GFP_KERNEL);\n\telse\n\t\treturn kmemdup(msg->buf, msg->len, GFP_KERNEL);\n}\nEXPORT_SYMBOL_GPL(i2c_get_dma_safe_msg_buf);\n\n/**\n * i2c_put_dma_safe_msg_buf - release DMA safe buffer and sync with i2c_msg\n * @buf: the buffer obtained from i2c_get_dma_safe_msg_buf(). May be NULL.\n * @msg: the message which the buffer corresponds to\n * @xferred: bool saying if the message was transferred\n */\nvoid i2c_put_dma_safe_msg_buf(u8 *buf, struct i2c_msg *msg, bool xferred)\n{\n\tif (!buf || buf == msg->buf)\n\t\treturn;\n\n\tif (xferred && msg->flags & I2C_M_RD)\n\t\tmemcpy(msg->buf, buf, msg->len);\n\n\tkfree(buf);\n}\nEXPORT_SYMBOL_GPL(i2c_put_dma_safe_msg_buf);\n\nMODULE_AUTHOR(\"Simon G. Vogl <simon@tk.uni-linz.ac.at>\");\nMODULE_DESCRIPTION(\"I2C-Bus main module\");\nMODULE_LICENSE(\"GPL\");\n"
  },
  {
    "path": "t/tree/drivers/i2c/i2c-core-of.c",
    "content": "// SPDX-License-Identifier: GPL-2.0-or-later\n/*\n * Linux I2C core OF support code\n *\n * Copyright (C) 2008 Jochen Friedrich <jochen@scram.de>\n * based on a previous patch from Jon Smirl <jonsmirl@gmail.com>\n *\n * Copyright (C) 2013, 2018 Wolfram Sang <wsa@the-dreams.de>\n */\n\n#include <dt-bindings/i2c/i2c.h>\n#include <linux/device.h>\n#include <linux/err.h>\n#include <linux/i2c.h>\n#include <linux/module.h>\n#include <linux/of.h>\n#include <linux/of_device.h>\n#include <linux/sysfs.h>\n\n#include \"i2c-core.h\"\n\nint of_i2c_get_board_info(struct device *dev, struct device_node *node,\n\t\t\t  struct i2c_board_info *info)\n{\n\tu32 addr;\n\tint ret;\n\n\tmemset(info, 0, sizeof(*info));\n\n\tif (of_modalias_node(node, info->type, sizeof(info->type)) < 0) {\n\t\tdev_err(dev, \"of_i2c: modalias failure on %pOF\\n\", node);\n\t\treturn -EINVAL;\n\t}\n\n\tret = of_property_read_u32(node, \"reg\", &addr);\n\tif (ret) {\n\t\tdev_err(dev, \"of_i2c: invalid reg on %pOF\\n\", node);\n\t\treturn ret;\n\t}\n\n\tif (addr & I2C_TEN_BIT_ADDRESS) {\n\t\taddr &= ~I2C_TEN_BIT_ADDRESS;\n\t\tinfo->flags |= I2C_CLIENT_TEN;\n\t}\n\n\tif (addr & I2C_OWN_SLAVE_ADDRESS) {\n\t\taddr &= ~I2C_OWN_SLAVE_ADDRESS;\n\t\tinfo->flags |= I2C_CLIENT_SLAVE;\n\t}\n\n\tinfo->addr = addr;\n\tinfo->of_node = node;\n\n\tif (of_property_read_bool(node, \"host-notify\"))\n\t\tinfo->flags |= I2C_CLIENT_HOST_NOTIFY;\n\n\tif (of_get_property(node, \"wakeup-source\", NULL))\n\t\tinfo->flags |= I2C_CLIENT_WAKE;\n\n\treturn 0;\n}\nEXPORT_SYMBOL_GPL(of_i2c_get_board_info);\n\nstatic struct i2c_client *of_i2c_register_device(struct i2c_adapter *adap,\n\t\t\t\t\t\t struct device_node *node)\n{\n\tstruct i2c_client *client;\n\tstruct i2c_board_info info;\n\tint ret;\n\n\tdev_dbg(&adap->dev, \"of_i2c: register %pOF\\n\", node);\n\n\tret = of_i2c_get_board_info(&adap->dev, node, &info);\n\tif (ret)\n\t\treturn ERR_PTR(ret);\n\n\tclient = i2c_new_device(adap, &info);\n\tif (!client) {\n\t\tdev_err(&adap->dev, \"of_i2c: Failure registering %pOF\\n\", node);\n\t\treturn ERR_PTR(-EINVAL);\n\t}\n\treturn client;\n}\n\nvoid of_i2c_register_devices(struct i2c_adapter *adap)\n{\n\tstruct device_node *bus, *node;\n\tstruct i2c_client *client;\n\n\t/* Only register child devices if the adapter has a node pointer set */\n\tif (!adap->dev.of_node)\n\t\treturn;\n\n\tdev_dbg(&adap->dev, \"of_i2c: walking child nodes\\n\");\n\n\tbus = of_get_child_by_name(adap->dev.of_node, \"i2c-bus\");\n\tif (!bus)\n\t\tbus = of_node_get(adap->dev.of_node);\n\n\tfor_each_available_child_of_node(bus, node) {\n\t\tif (of_node_test_and_set_flag(node, OF_POPULATED))\n\t\t\tcontinue;\n\n\t\tclient = of_i2c_register_device(adap, node);\n\t\tif (IS_ERR(client)) {\n\t\t\tdev_err(&adap->dev,\n\t\t\t\t \"Failed to create I2C device for %pOF\\n\",\n\t\t\t\t node);\n\t\t\tof_node_clear_flag(node, OF_POPULATED);\n\t\t}\n\t}\n\n\tof_node_put(bus);\n}\n\nstatic int of_dev_or_parent_node_match(struct device *dev, const void *data)\n{\n\tif (dev->of_node == data)\n\t\treturn 1;\n\n\tif (dev->parent)\n\t\treturn dev->parent->of_node == data;\n\n\treturn 0;\n}\n\n/* must call put_device() when done with returned i2c_client device */\nstruct i2c_client *of_find_i2c_device_by_node(struct device_node *node)\n{\n\tstruct device *dev;\n\tstruct i2c_client *client;\n\n\tdev = bus_find_device_by_of_node(&i2c_bus_type, node);\n\tif (!dev)\n\t\treturn NULL;\n\n\tclient = i2c_verify_client(dev);\n\tif (!client)\n\t\tput_device(dev);\n\n\treturn client;\n}\nEXPORT_SYMBOL(of_find_i2c_device_by_node);\n\n/* must call put_device() when done with returned i2c_adapter device */\nstruct i2c_adapter *of_find_i2c_adapter_by_node(struct device_node *node)\n{\n\tstruct device *dev;\n\tstruct i2c_adapter *adapter;\n\n\tdev = bus_find_device(&i2c_bus_type, NULL, node,\n\t\t\t      of_dev_or_parent_node_match);\n\tif (!dev)\n\t\treturn NULL;\n\n\tadapter = i2c_verify_adapter(dev);\n\tif (!adapter)\n\t\tput_device(dev);\n\n\treturn adapter;\n}\nEXPORT_SYMBOL(of_find_i2c_adapter_by_node);\n\n/* must call i2c_put_adapter() when done with returned i2c_adapter device */\nstruct i2c_adapter *of_get_i2c_adapter_by_node(struct device_node *node)\n{\n\tstruct i2c_adapter *adapter;\n\n\tadapter = of_find_i2c_adapter_by_node(node);\n\tif (!adapter)\n\t\treturn NULL;\n\n\tif (!try_module_get(adapter->owner)) {\n\t\tput_device(&adapter->dev);\n\t\tadapter = NULL;\n\t}\n\n\treturn adapter;\n}\nEXPORT_SYMBOL(of_get_i2c_adapter_by_node);\n\nstatic const struct of_device_id*\ni2c_of_match_device_sysfs(const struct of_device_id *matches,\n\t\t\t\t  struct i2c_client *client)\n{\n\tconst char *name;\n\n\tfor (; matches->compatible[0]; matches++) {\n\t\t/*\n\t\t * Adding devices through the i2c sysfs interface provides us\n\t\t * a string to match which may be compatible with the device\n\t\t * tree compatible strings, however with no actual of_node the\n\t\t * of_match_device() will not match\n\t\t */\n\t\tif (sysfs_streq(client->name, matches->compatible))\n\t\t\treturn matches;\n\n\t\tname = strchr(matches->compatible, ',');\n\t\tif (!name)\n\t\t\tname = matches->compatible;\n\t\telse\n\t\t\tname++;\n\n\t\tif (sysfs_streq(client->name, name))\n\t\t\treturn matches;\n\t}\n\n\treturn NULL;\n}\n\nconst struct of_device_id\n*i2c_of_match_device(const struct of_device_id *matches,\n\t\t     struct i2c_client *client)\n{\n\tconst struct of_device_id *match;\n\n\tif (!(client && matches))\n\t\treturn NULL;\n\n\tmatch = of_match_device(matches, &client->dev);\n\tif (match)\n\t\treturn match;\n\n\treturn i2c_of_match_device_sysfs(matches, client);\n}\nEXPORT_SYMBOL_GPL(i2c_of_match_device);\n\n#if IS_ENABLED(CONFIG_OF_DYNAMIC)\nstatic int of_i2c_notify(struct notifier_block *nb, unsigned long action,\n\t\t\t void *arg)\n{\n\tstruct of_reconfig_data *rd = arg;\n\tstruct i2c_adapter *adap;\n\tstruct i2c_client *client;\n\n\tswitch (of_reconfig_get_state_change(action, rd)) {\n\tcase OF_RECONFIG_CHANGE_ADD:\n\t\tadap = of_find_i2c_adapter_by_node(rd->dn->parent);\n\t\tif (adap == NULL)\n\t\t\treturn NOTIFY_OK;\t/* not for us */\n\n\t\tif (of_node_test_and_set_flag(rd->dn, OF_POPULATED)) {\n\t\t\tput_device(&adap->dev);\n\t\t\treturn NOTIFY_OK;\n\t\t}\n\n\t\tclient = of_i2c_register_device(adap, rd->dn);\n\t\tif (IS_ERR(client)) {\n\t\t\tdev_err(&adap->dev, \"failed to create client for '%pOF'\\n\",\n\t\t\t\t rd->dn);\n\t\t\tput_device(&adap->dev);\n\t\t\tof_node_clear_flag(rd->dn, OF_POPULATED);\n\t\t\treturn notifier_from_errno(PTR_ERR(client));\n\t\t}\n\t\tput_device(&adap->dev);\n\t\tbreak;\n\tcase OF_RECONFIG_CHANGE_REMOVE:\n\t\t/* already depopulated? */\n\t\tif (!of_node_check_flag(rd->dn, OF_POPULATED))\n\t\t\treturn NOTIFY_OK;\n\n\t\t/* find our device by node */\n\t\tclient = of_find_i2c_device_by_node(rd->dn);\n\t\tif (client == NULL)\n\t\t\treturn NOTIFY_OK;\t/* no? not meant for us */\n\n\t\t/* unregister takes one ref away */\n\t\ti2c_unregister_device(client);\n\n\t\t/* and put the reference of the find */\n\t\tput_device(&client->dev);\n\t\tbreak;\n\t}\n\n\treturn NOTIFY_OK;\n}\n\nstruct notifier_block i2c_of_notifier = {\n\t.notifier_call = of_i2c_notify,\n};\n#endif /* CONFIG_OF_DYNAMIC */\n"
  },
  {
    "path": "t/tree/drivers/i2c/i2c-core-slave.c",
    "content": "// SPDX-License-Identifier: GPL-2.0-or-later\n/*\n * Linux I2C core slave support code\n *\n * Copyright (C) 2014 by Wolfram Sang <wsa@sang-engineering.com>\n */\n\n#include <dt-bindings/i2c/i2c.h>\n#include <linux/acpi.h>\n#include <linux/device.h>\n#include <linux/err.h>\n#include <linux/i2c.h>\n#include <linux/of.h>\n\n#include \"i2c-core.h\"\n\nint i2c_slave_register(struct i2c_client *client, i2c_slave_cb_t slave_cb)\n{\n\tint ret;\n\n\tif (!client || !slave_cb) {\n\t\tWARN(1, \"insufficient data\\n\");\n\t\treturn -EINVAL;\n\t}\n\n\tif (!(client->flags & I2C_CLIENT_SLAVE))\n\t\tdev_warn(&client->dev, \"%s: client slave flag not set. You might see address collisions\\n\",\n\t\t\t __func__);\n\n\tif (!(client->flags & I2C_CLIENT_TEN)) {\n\t\t/* Enforce stricter address checking */\n\t\tret = i2c_check_7bit_addr_validity_strict(client->addr);\n\t\tif (ret) {\n\t\t\tdev_err(&client->dev, \"%s: invalid address\\n\", __func__);\n\t\t\treturn ret;\n\t\t}\n\t}\n\n\tif (!client->adapter->algo->reg_slave) {\n\t\tdev_err(&client->dev, \"%s: not supported by adapter\\n\", __func__);\n\t\treturn -EOPNOTSUPP;\n\t}\n\n\tclient->slave_cb = slave_cb;\n\n\ti2c_lock_bus(client->adapter, I2C_LOCK_ROOT_ADAPTER);\n\tret = client->adapter->algo->reg_slave(client);\n\ti2c_unlock_bus(client->adapter, I2C_LOCK_ROOT_ADAPTER);\n\n\tif (ret) {\n\t\tclient->slave_cb = NULL;\n\t\tdev_err(&client->dev, \"%s: adapter returned error %d\\n\", __func__, ret);\n\t}\n\n\treturn ret;\n}\nEXPORT_SYMBOL_GPL(i2c_slave_register);\n\nint i2c_slave_unregister(struct i2c_client *client)\n{\n\tint ret;\n\n\tif (!client->adapter->algo->unreg_slave) {\n\t\tdev_err(&client->dev, \"%s: not supported by adapter\\n\", __func__);\n\t\treturn -EOPNOTSUPP;\n\t}\n\n\ti2c_lock_bus(client->adapter, I2C_LOCK_ROOT_ADAPTER);\n\tret = client->adapter->algo->unreg_slave(client);\n\ti2c_unlock_bus(client->adapter, I2C_LOCK_ROOT_ADAPTER);\n\n\tif (ret == 0)\n\t\tclient->slave_cb = NULL;\n\telse\n\t\tdev_err(&client->dev, \"%s: adapter returned error %d\\n\", __func__, ret);\n\n\treturn ret;\n}\nEXPORT_SYMBOL_GPL(i2c_slave_unregister);\n\n/**\n * i2c_detect_slave_mode - detect operation mode\n * @dev: The device owning the bus\n *\n * This checks the device nodes for an I2C slave by checking the address\n * used in the reg property. If the address match the I2C_OWN_SLAVE_ADDRESS\n * flag this means the device is configured to act as a I2C slave and it will\n * be listening at that address.\n *\n * Returns true if an I2C own slave address is detected, otherwise returns\n * false.\n */\nbool i2c_detect_slave_mode(struct device *dev)\n{\n\tif (IS_BUILTIN(CONFIG_OF) && dev->of_node) {\n\t\tstruct device_node *child;\n\t\tu32 reg;\n\n\t\tfor_each_child_of_node(dev->of_node, child) {\n\t\t\tof_property_read_u32(child, \"reg\", &reg);\n\t\t\tif (reg & I2C_OWN_SLAVE_ADDRESS) {\n\t\t\t\tof_node_put(child);\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\t} else if (IS_BUILTIN(CONFIG_ACPI) && ACPI_HANDLE(dev)) {\n\t\tdev_dbg(dev, \"ACPI slave is not supported yet\\n\");\n\t}\n\treturn false;\n}\nEXPORT_SYMBOL_GPL(i2c_detect_slave_mode);\n"
  },
  {
    "path": "t/tree/drivers/i2c/i2c-core-smbus.c",
    "content": "// SPDX-License-Identifier: GPL-2.0-or-later\n/*\n * Linux I2C core SMBus and SMBus emulation code\n *\n * This file contains the SMBus functions which are always included in the I2C\n * core because they can be emulated via I2C. SMBus specific extensions\n * (e.g. smbalert) are handled in a seperate i2c-smbus module.\n *\n * All SMBus-related things are written by Frodo Looijaard <frodol@dds.nl>\n * SMBus 2.0 support by Mark Studebaker <mdsxyz123@yahoo.com> and\n * Jean Delvare <jdelvare@suse.de>\n */\n#include <linux/device.h>\n#include <linux/err.h>\n#include <linux/i2c.h>\n#include <linux/i2c-smbus.h>\n#include <linux/slab.h>\n\n#include \"i2c-core.h\"\n\n#define CREATE_TRACE_POINTS\n#include <trace/events/smbus.h>\n\n\n/* The SMBus parts */\n\n#define POLY    (0x1070U << 3)\nstatic u8 crc8(u16 data)\n{\n\tint i;\n\n\tfor (i = 0; i < 8; i++) {\n\t\tif (data & 0x8000)\n\t\t\tdata = data ^ POLY;\n\t\tdata = data << 1;\n\t}\n\treturn (u8)(data >> 8);\n}\n\n/* Incremental CRC8 over count bytes in the array pointed to by p */\nstatic u8 i2c_smbus_pec(u8 crc, u8 *p, size_t count)\n{\n\tint i;\n\n\tfor (i = 0; i < count; i++)\n\t\tcrc = crc8((crc ^ p[i]) << 8);\n\treturn crc;\n}\n\n/* Assume a 7-bit address, which is reasonable for SMBus */\nstatic u8 i2c_smbus_msg_pec(u8 pec, struct i2c_msg *msg)\n{\n\t/* The address will be sent first */\n\tu8 addr = i2c_8bit_addr_from_msg(msg);\n\tpec = i2c_smbus_pec(pec, &addr, 1);\n\n\t/* The data buffer follows */\n\treturn i2c_smbus_pec(pec, msg->buf, msg->len);\n}\n\n/* Used for write only transactions */\nstatic inline void i2c_smbus_add_pec(struct i2c_msg *msg)\n{\n\tmsg->buf[msg->len] = i2c_smbus_msg_pec(0, msg);\n\tmsg->len++;\n}\n\n/* Return <0 on CRC error\n   If there was a write before this read (most cases) we need to take the\n   partial CRC from the write part into account.\n   Note that this function does modify the message (we need to decrease the\n   message length to hide the CRC byte from the caller). */\nstatic int i2c_smbus_check_pec(u8 cpec, struct i2c_msg *msg)\n{\n\tu8 rpec = msg->buf[--msg->len];\n\tcpec = i2c_smbus_msg_pec(cpec, msg);\n\n\tif (rpec != cpec) {\n\t\tpr_debug(\"Bad PEC 0x%02x vs. 0x%02x\\n\",\n\t\t\trpec, cpec);\n\t\treturn -EBADMSG;\n\t}\n\treturn 0;\n}\n\n/**\n * i2c_smbus_read_byte - SMBus \"receive byte\" protocol\n * @client: Handle to slave device\n *\n * This executes the SMBus \"receive byte\" protocol, returning negative errno\n * else the byte received from the device.\n */\ns32 i2c_smbus_read_byte(const struct i2c_client *client)\n{\n\tunion i2c_smbus_data data;\n\tint status;\n\n\tstatus = i2c_smbus_xfer(client->adapter, client->addr, client->flags,\n\t\t\t\tI2C_SMBUS_READ, 0,\n\t\t\t\tI2C_SMBUS_BYTE, &data);\n\treturn (status < 0) ? status : data.byte;\n}\nEXPORT_SYMBOL(i2c_smbus_read_byte);\n\n/**\n * i2c_smbus_write_byte - SMBus \"send byte\" protocol\n * @client: Handle to slave device\n * @value: Byte to be sent\n *\n * This executes the SMBus \"send byte\" protocol, returning negative errno\n * else zero on success.\n */\ns32 i2c_smbus_write_byte(const struct i2c_client *client, u8 value)\n{\n\treturn i2c_smbus_xfer(client->adapter, client->addr, client->flags,\n\t                      I2C_SMBUS_WRITE, value, I2C_SMBUS_BYTE, NULL);\n}\nEXPORT_SYMBOL(i2c_smbus_write_byte);\n\n/**\n * i2c_smbus_read_byte_data - SMBus \"read byte\" protocol\n * @client: Handle to slave device\n * @command: Byte interpreted by slave\n *\n * This executes the SMBus \"read byte\" protocol, returning negative errno\n * else a data byte received from the device.\n */\ns32 i2c_smbus_read_byte_data(const struct i2c_client *client, u8 command)\n{\n\tunion i2c_smbus_data data;\n\tint status;\n\n\tstatus = i2c_smbus_xfer(client->adapter, client->addr, client->flags,\n\t\t\t\tI2C_SMBUS_READ, command,\n\t\t\t\tI2C_SMBUS_BYTE_DATA, &data);\n\treturn (status < 0) ? status : data.byte;\n}\nEXPORT_SYMBOL(i2c_smbus_read_byte_data);\n\n/**\n * i2c_smbus_write_byte_data - SMBus \"write byte\" protocol\n * @client: Handle to slave device\n * @command: Byte interpreted by slave\n * @value: Byte being written\n *\n * This executes the SMBus \"write byte\" protocol, returning negative errno\n * else zero on success.\n */\ns32 i2c_smbus_write_byte_data(const struct i2c_client *client, u8 command,\n\t\t\t      u8 value)\n{\n\tunion i2c_smbus_data data;\n\tdata.byte = value;\n\treturn i2c_smbus_xfer(client->adapter, client->addr, client->flags,\n\t\t\t      I2C_SMBUS_WRITE, command,\n\t\t\t      I2C_SMBUS_BYTE_DATA, &data);\n}\nEXPORT_SYMBOL(i2c_smbus_write_byte_data);\n\n/**\n * i2c_smbus_read_word_data - SMBus \"read word\" protocol\n * @client: Handle to slave device\n * @command: Byte interpreted by slave\n *\n * This executes the SMBus \"read word\" protocol, returning negative errno\n * else a 16-bit unsigned \"word\" received from the device.\n */\ns32 i2c_smbus_read_word_data(const struct i2c_client *client, u8 command)\n{\n\tunion i2c_smbus_data data;\n\tint status;\n\n\tstatus = i2c_smbus_xfer(client->adapter, client->addr, client->flags,\n\t\t\t\tI2C_SMBUS_READ, command,\n\t\t\t\tI2C_SMBUS_WORD_DATA, &data);\n\treturn (status < 0) ? status : data.word;\n}\nEXPORT_SYMBOL(i2c_smbus_read_word_data);\n\n/**\n * i2c_smbus_write_word_data - SMBus \"write word\" protocol\n * @client: Handle to slave device\n * @command: Byte interpreted by slave\n * @value: 16-bit \"word\" being written\n *\n * This executes the SMBus \"write word\" protocol, returning negative errno\n * else zero on success.\n */\ns32 i2c_smbus_write_word_data(const struct i2c_client *client, u8 command,\n\t\t\t      u16 value)\n{\n\tunion i2c_smbus_data data;\n\tdata.word = value;\n\treturn i2c_smbus_xfer(client->adapter, client->addr, client->flags,\n\t\t\t      I2C_SMBUS_WRITE, command,\n\t\t\t      I2C_SMBUS_WORD_DATA, &data);\n}\nEXPORT_SYMBOL(i2c_smbus_write_word_data);\n\n/**\n * i2c_smbus_read_block_data - SMBus \"block read\" protocol\n * @client: Handle to slave device\n * @command: Byte interpreted by slave\n * @values: Byte array into which data will be read; big enough to hold\n *\tthe data returned by the slave.  SMBus allows at most 32 bytes.\n *\n * This executes the SMBus \"block read\" protocol, returning negative errno\n * else the number of data bytes in the slave's response.\n *\n * Note that using this function requires that the client's adapter support\n * the I2C_FUNC_SMBUS_READ_BLOCK_DATA functionality.  Not all adapter drivers\n * support this; its emulation through I2C messaging relies on a specific\n * mechanism (I2C_M_RECV_LEN) which may not be implemented.\n */\ns32 i2c_smbus_read_block_data(const struct i2c_client *client, u8 command,\n\t\t\t      u8 *values)\n{\n\tunion i2c_smbus_data data;\n\tint status;\n\n\tstatus = i2c_smbus_xfer(client->adapter, client->addr, client->flags,\n\t\t\t\tI2C_SMBUS_READ, command,\n\t\t\t\tI2C_SMBUS_BLOCK_DATA, &data);\n\tif (status)\n\t\treturn status;\n\n\tmemcpy(values, &data.block[1], data.block[0]);\n\treturn data.block[0];\n}\nEXPORT_SYMBOL(i2c_smbus_read_block_data);\n\n/**\n * i2c_smbus_write_block_data - SMBus \"block write\" protocol\n * @client: Handle to slave device\n * @command: Byte interpreted by slave\n * @length: Size of data block; SMBus allows at most 32 bytes\n * @values: Byte array which will be written.\n *\n * This executes the SMBus \"block write\" protocol, returning negative errno\n * else zero on success.\n */\ns32 i2c_smbus_write_block_data(const struct i2c_client *client, u8 command,\n\t\t\t       u8 length, const u8 *values)\n{\n\tunion i2c_smbus_data data;\n\n\tif (length > I2C_SMBUS_BLOCK_MAX)\n\t\tlength = I2C_SMBUS_BLOCK_MAX;\n\tdata.block[0] = length;\n\tmemcpy(&data.block[1], values, length);\n\treturn i2c_smbus_xfer(client->adapter, client->addr, client->flags,\n\t\t\t      I2C_SMBUS_WRITE, command,\n\t\t\t      I2C_SMBUS_BLOCK_DATA, &data);\n}\nEXPORT_SYMBOL(i2c_smbus_write_block_data);\n\n/* Returns the number of read bytes */\ns32 i2c_smbus_read_i2c_block_data(const struct i2c_client *client, u8 command,\n\t\t\t\t  u8 length, u8 *values)\n{\n\tunion i2c_smbus_data data;\n\tint status;\n\n\tif (length > I2C_SMBUS_BLOCK_MAX)\n\t\tlength = I2C_SMBUS_BLOCK_MAX;\n\tdata.block[0] = length;\n\tstatus = i2c_smbus_xfer(client->adapter, client->addr, client->flags,\n\t\t\t\tI2C_SMBUS_READ, command,\n\t\t\t\tI2C_SMBUS_I2C_BLOCK_DATA, &data);\n\tif (status < 0)\n\t\treturn status;\n\n\tmemcpy(values, &data.block[1], data.block[0]);\n\treturn data.block[0];\n}\nEXPORT_SYMBOL(i2c_smbus_read_i2c_block_data);\n\ns32 i2c_smbus_write_i2c_block_data(const struct i2c_client *client, u8 command,\n\t\t\t\t   u8 length, const u8 *values)\n{\n\tunion i2c_smbus_data data;\n\n\tif (length > I2C_SMBUS_BLOCK_MAX)\n\t\tlength = I2C_SMBUS_BLOCK_MAX;\n\tdata.block[0] = length;\n\tmemcpy(data.block + 1, values, length);\n\treturn i2c_smbus_xfer(client->adapter, client->addr, client->flags,\n\t\t\t      I2C_SMBUS_WRITE, command,\n\t\t\t      I2C_SMBUS_I2C_BLOCK_DATA, &data);\n}\nEXPORT_SYMBOL(i2c_smbus_write_i2c_block_data);\n\nstatic void i2c_smbus_try_get_dmabuf(struct i2c_msg *msg, u8 init_val)\n{\n\tbool is_read = msg->flags & I2C_M_RD;\n\tunsigned char *dma_buf;\n\n\tdma_buf = kzalloc(I2C_SMBUS_BLOCK_MAX + (is_read ? 2 : 3), GFP_KERNEL);\n\tif (!dma_buf)\n\t\treturn;\n\n\tmsg->buf = dma_buf;\n\tmsg->flags |= I2C_M_DMA_SAFE;\n\n\tif (init_val)\n\t\tmsg->buf[0] = init_val;\n}\n\n/*\n * Simulate a SMBus command using the I2C protocol.\n * No checking of parameters is done!\n */\nstatic s32 i2c_smbus_xfer_emulated(struct i2c_adapter *adapter, u16 addr,\n\t\t\t\t   unsigned short flags,\n\t\t\t\t   char read_write, u8 command, int size,\n\t\t\t\t   union i2c_smbus_data *data)\n{\n\t/*\n\t * So we need to generate a series of msgs. In the case of writing, we\n\t * need to use only one message; when reading, we need two. We\n\t * initialize most things with sane defaults, to keep the code below\n\t * somewhat simpler.\n\t */\n\tunsigned char msgbuf0[I2C_SMBUS_BLOCK_MAX+3];\n\tunsigned char msgbuf1[I2C_SMBUS_BLOCK_MAX+2];\n\tint num = read_write == I2C_SMBUS_READ ? 2 : 1;\n\tint i;\n\tu8 partial_pec = 0;\n\tint status;\n\tstruct i2c_msg msg[2] = {\n\t\t{\n\t\t\t.addr = addr,\n\t\t\t.flags = flags,\n\t\t\t.len = 1,\n\t\t\t.buf = msgbuf0,\n\t\t}, {\n\t\t\t.addr = addr,\n\t\t\t.flags = flags | I2C_M_RD,\n\t\t\t.len = 0,\n\t\t\t.buf = msgbuf1,\n\t\t},\n\t};\n\n\tmsgbuf0[0] = command;\n\tswitch (size) {\n\tcase I2C_SMBUS_QUICK:\n\t\tmsg[0].len = 0;\n\t\t/* Special case: The read/write field is used as data */\n\t\tmsg[0].flags = flags | (read_write == I2C_SMBUS_READ ?\n\t\t\t\t\tI2C_M_RD : 0);\n\t\tnum = 1;\n\t\tbreak;\n\tcase I2C_SMBUS_BYTE:\n\t\tif (read_write == I2C_SMBUS_READ) {\n\t\t\t/* Special case: only a read! */\n\t\t\tmsg[0].flags = I2C_M_RD | flags;\n\t\t\tnum = 1;\n\t\t}\n\t\tbreak;\n\tcase I2C_SMBUS_BYTE_DATA:\n\t\tif (read_write == I2C_SMBUS_READ)\n\t\t\tmsg[1].len = 1;\n\t\telse {\n\t\t\tmsg[0].len = 2;\n\t\t\tmsgbuf0[1] = data->byte;\n\t\t}\n\t\tbreak;\n\tcase I2C_SMBUS_WORD_DATA:\n\t\tif (read_write == I2C_SMBUS_READ)\n\t\t\tmsg[1].len = 2;\n\t\telse {\n\t\t\tmsg[0].len = 3;\n\t\t\tmsgbuf0[1] = data->word & 0xff;\n\t\t\tmsgbuf0[2] = data->word >> 8;\n\t\t}\n\t\tbreak;\n\tcase I2C_SMBUS_PROC_CALL:\n\t\tnum = 2; /* Special case */\n\t\tread_write = I2C_SMBUS_READ;\n\t\tmsg[0].len = 3;\n\t\tmsg[1].len = 2;\n\t\tmsgbuf0[1] = data->word & 0xff;\n\t\tmsgbuf0[2] = data->word >> 8;\n\t\tbreak;\n\tcase I2C_SMBUS_BLOCK_DATA:\n\t\tif (read_write == I2C_SMBUS_READ) {\n\t\t\tmsg[1].flags |= I2C_M_RECV_LEN;\n\t\t\tmsg[1].len = 1; /* block length will be added by\n\t\t\t\t\t   the underlying bus driver */\n\t\t\ti2c_smbus_try_get_dmabuf(&msg[1], 0);\n\t\t} else {\n\t\t\tmsg[0].len = data->block[0] + 2;\n\t\t\tif (msg[0].len > I2C_SMBUS_BLOCK_MAX + 2) {\n\t\t\t\tdev_err(&adapter->dev,\n\t\t\t\t\t\"Invalid block write size %d\\n\",\n\t\t\t\t\tdata->block[0]);\n\t\t\t\treturn -EINVAL;\n\t\t\t}\n\n\t\t\ti2c_smbus_try_get_dmabuf(&msg[0], command);\n\t\t\tfor (i = 1; i < msg[0].len; i++)\n\t\t\t\tmsg[0].buf[i] = data->block[i - 1];\n\t\t}\n\t\tbreak;\n\tcase I2C_SMBUS_BLOCK_PROC_CALL:\n\t\tnum = 2; /* Another special case */\n\t\tread_write = I2C_SMBUS_READ;\n\t\tif (data->block[0] > I2C_SMBUS_BLOCK_MAX) {\n\t\t\tdev_err(&adapter->dev,\n\t\t\t\t\"Invalid block write size %d\\n\",\n\t\t\t\tdata->block[0]);\n\t\t\treturn -EINVAL;\n\t\t}\n\n\t\tmsg[0].len = data->block[0] + 2;\n\t\ti2c_smbus_try_get_dmabuf(&msg[0], command);\n\t\tfor (i = 1; i < msg[0].len; i++)\n\t\t\tmsg[0].buf[i] = data->block[i - 1];\n\n\t\tmsg[1].flags |= I2C_M_RECV_LEN;\n\t\tmsg[1].len = 1; /* block length will be added by\n\t\t\t\t   the underlying bus driver */\n\t\ti2c_smbus_try_get_dmabuf(&msg[1], 0);\n\t\tbreak;\n\tcase I2C_SMBUS_I2C_BLOCK_DATA:\n\t\tif (data->block[0] > I2C_SMBUS_BLOCK_MAX) {\n\t\t\tdev_err(&adapter->dev, \"Invalid block %s size %d\\n\",\n\t\t\t\tread_write == I2C_SMBUS_READ ? \"read\" : \"write\",\n\t\t\t\tdata->block[0]);\n\t\t\treturn -EINVAL;\n\t\t}\n\n\t\tif (read_write == I2C_SMBUS_READ) {\n\t\t\tmsg[1].len = data->block[0];\n\t\t\ti2c_smbus_try_get_dmabuf(&msg[1], 0);\n\t\t} else {\n\t\t\tmsg[0].len = data->block[0] + 1;\n\n\t\t\ti2c_smbus_try_get_dmabuf(&msg[0], command);\n\t\t\tfor (i = 1; i <= data->block[0]; i++)\n\t\t\t\tmsg[0].buf[i] = data->block[i];\n\t\t}\n\t\tbreak;\n\tdefault:\n\t\tdev_err(&adapter->dev, \"Unsupported transaction %d\\n\", size);\n\t\treturn -EOPNOTSUPP;\n\t}\n\n\ti = ((flags & I2C_CLIENT_PEC) && size != I2C_SMBUS_QUICK\n\t\t\t\t      && size != I2C_SMBUS_I2C_BLOCK_DATA);\n\tif (i) {\n\t\t/* Compute PEC if first message is a write */\n\t\tif (!(msg[0].flags & I2C_M_RD)) {\n\t\t\tif (num == 1) /* Write only */\n\t\t\t\ti2c_smbus_add_pec(&msg[0]);\n\t\t\telse /* Write followed by read */\n\t\t\t\tpartial_pec = i2c_smbus_msg_pec(0, &msg[0]);\n\t\t}\n\t\t/* Ask for PEC if last message is a read */\n\t\tif (msg[num-1].flags & I2C_M_RD)\n\t\t\tmsg[num-1].len++;\n\t}\n\n\tstatus = __i2c_transfer(adapter, msg, num);\n\tif (status < 0)\n\t\tgoto cleanup;\n\tif (status != num) {\n\t\tstatus = -EIO;\n\t\tgoto cleanup;\n\t}\n\tstatus = 0;\n\n\t/* Check PEC if last message is a read */\n\tif (i && (msg[num-1].flags & I2C_M_RD)) {\n\t\tstatus = i2c_smbus_check_pec(partial_pec, &msg[num-1]);\n\t\tif (status < 0)\n\t\t\tgoto cleanup;\n\t}\n\n\tif (read_write == I2C_SMBUS_READ)\n\t\tswitch (size) {\n\t\tcase I2C_SMBUS_BYTE:\n\t\t\tdata->byte = msgbuf0[0];\n\t\t\tbreak;\n\t\tcase I2C_SMBUS_BYTE_DATA:\n\t\t\tdata->byte = msgbuf1[0];\n\t\t\tbreak;\n\t\tcase I2C_SMBUS_WORD_DATA:\n\t\tcase I2C_SMBUS_PROC_CALL:\n\t\t\tdata->word = msgbuf1[0] | (msgbuf1[1] << 8);\n\t\t\tbreak;\n\t\tcase I2C_SMBUS_I2C_BLOCK_DATA:\n\t\t\tfor (i = 0; i < data->block[0]; i++)\n\t\t\t\tdata->block[i + 1] = msg[1].buf[i];\n\t\t\tbreak;\n\t\tcase I2C_SMBUS_BLOCK_DATA:\n\t\tcase I2C_SMBUS_BLOCK_PROC_CALL:\n\t\t\tfor (i = 0; i < msg[1].buf[0] + 1; i++)\n\t\t\t\tdata->block[i] = msg[1].buf[i];\n\t\t\tbreak;\n\t\t}\n\ncleanup:\n\tif (msg[0].flags & I2C_M_DMA_SAFE)\n\t\tkfree(msg[0].buf);\n\tif (msg[1].flags & I2C_M_DMA_SAFE)\n\t\tkfree(msg[1].buf);\n\n\treturn status;\n}\n\n/**\n * i2c_smbus_xfer - execute SMBus protocol operations\n * @adapter: Handle to I2C bus\n * @addr: Address of SMBus slave on that bus\n * @flags: I2C_CLIENT_* flags (usually zero or I2C_CLIENT_PEC)\n * @read_write: I2C_SMBUS_READ or I2C_SMBUS_WRITE\n * @command: Byte interpreted by slave, for protocols which use such bytes\n * @protocol: SMBus protocol operation to execute, such as I2C_SMBUS_PROC_CALL\n * @data: Data to be read or written\n *\n * This executes an SMBus protocol operation, and returns a negative\n * errno code else zero on success.\n */\ns32 i2c_smbus_xfer(struct i2c_adapter *adapter, u16 addr,\n\t\t   unsigned short flags, char read_write,\n\t\t   u8 command, int protocol, union i2c_smbus_data *data)\n{\n\ts32 res;\n\n\tres = __i2c_lock_bus_helper(adapter);\n\tif (res)\n\t\treturn res;\n\n\tres = __i2c_smbus_xfer(adapter, addr, flags, read_write,\n\t\t\t       command, protocol, data);\n\ti2c_unlock_bus(adapter, I2C_LOCK_SEGMENT);\n\n\treturn res;\n}\nEXPORT_SYMBOL(i2c_smbus_xfer);\n\ns32 __i2c_smbus_xfer(struct i2c_adapter *adapter, u16 addr,\n\t\t     unsigned short flags, char read_write,\n\t\t     u8 command, int protocol, union i2c_smbus_data *data)\n{\n\tint (*xfer_func)(struct i2c_adapter *adap, u16 addr,\n\t\t\t unsigned short flags, char read_write,\n\t\t\t u8 command, int size, union i2c_smbus_data *data);\n\tunsigned long orig_jiffies;\n\tint try;\n\ts32 res;\n\n\tres = __i2c_check_suspended(adapter);\n\tif (res)\n\t\treturn res;\n\n\t/* If enabled, the following two tracepoints are conditional on\n\t * read_write and protocol.\n\t */\n\ttrace_smbus_write(adapter, addr, flags, read_write,\n\t\t\t  command, protocol, data);\n\ttrace_smbus_read(adapter, addr, flags, read_write,\n\t\t\t command, protocol);\n\n\tflags &= I2C_M_TEN | I2C_CLIENT_PEC | I2C_CLIENT_SCCB;\n\n\txfer_func = adapter->algo->smbus_xfer;\n\tif (i2c_in_atomic_xfer_mode()) {\n\t\tif (adapter->algo->smbus_xfer_atomic)\n\t\t\txfer_func = adapter->algo->smbus_xfer_atomic;\n\t\telse if (adapter->algo->master_xfer_atomic)\n\t\t\txfer_func = NULL; /* fallback to I2C emulation */\n\t}\n\n\tif (xfer_func) {\n\t\t/* Retry automatically on arbitration loss */\n\t\torig_jiffies = jiffies;\n\t\tfor (res = 0, try = 0; try <= adapter->retries; try++) {\n\t\t\tres = xfer_func(adapter, addr, flags, read_write,\n\t\t\t\t\tcommand, protocol, data);\n\t\t\tif (res != -EAGAIN)\n\t\t\t\tbreak;\n\t\t\tif (time_after(jiffies,\n\t\t\t\t       orig_jiffies + adapter->timeout))\n\t\t\t\tbreak;\n\t\t}\n\n\t\tif (res != -EOPNOTSUPP || !adapter->algo->master_xfer)\n\t\t\tgoto trace;\n\t\t/*\n\t\t * Fall back to i2c_smbus_xfer_emulated if the adapter doesn't\n\t\t * implement native support for the SMBus operation.\n\t\t */\n\t}\n\n\tres = i2c_smbus_xfer_emulated(adapter, addr, flags, read_write,\n\t\t\t\t      command, protocol, data);\n\ntrace:\n\t/* If enabled, the reply tracepoint is conditional on read_write. */\n\ttrace_smbus_reply(adapter, addr, flags, read_write,\n\t\t\t  command, protocol, data, res);\n\ttrace_smbus_result(adapter, addr, flags, read_write,\n\t\t\t   command, protocol, res);\n\n\treturn res;\n}\nEXPORT_SYMBOL(__i2c_smbus_xfer);\n\n/**\n * i2c_smbus_read_i2c_block_data_or_emulated - read block or emulate\n * @client: Handle to slave device\n * @command: Byte interpreted by slave\n * @length: Size of data block; SMBus allows at most I2C_SMBUS_BLOCK_MAX bytes\n * @values: Byte array into which data will be read; big enough to hold\n *\tthe data returned by the slave.  SMBus allows at most\n *\tI2C_SMBUS_BLOCK_MAX bytes.\n *\n * This executes the SMBus \"block read\" protocol if supported by the adapter.\n * If block read is not supported, it emulates it using either word or byte\n * read protocols depending on availability.\n *\n * The addresses of the I2C slave device that are accessed with this function\n * must be mapped to a linear region, so that a block read will have the same\n * effect as a byte read. Before using this function you must double-check\n * if the I2C slave does support exchanging a block transfer with a byte\n * transfer.\n */\ns32 i2c_smbus_read_i2c_block_data_or_emulated(const struct i2c_client *client,\n\t\t\t\t\t      u8 command, u8 length, u8 *values)\n{\n\tu8 i = 0;\n\tint status;\n\n\tif (length > I2C_SMBUS_BLOCK_MAX)\n\t\tlength = I2C_SMBUS_BLOCK_MAX;\n\n\tif (i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_READ_I2C_BLOCK))\n\t\treturn i2c_smbus_read_i2c_block_data(client, command, length, values);\n\n\tif (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_READ_BYTE_DATA))\n\t\treturn -EOPNOTSUPP;\n\n\tif (i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_READ_WORD_DATA)) {\n\t\twhile ((i + 2) <= length) {\n\t\t\tstatus = i2c_smbus_read_word_data(client, command + i);\n\t\t\tif (status < 0)\n\t\t\t\treturn status;\n\t\t\tvalues[i] = status & 0xff;\n\t\t\tvalues[i + 1] = status >> 8;\n\t\t\ti += 2;\n\t\t}\n\t}\n\n\twhile (i < length) {\n\t\tstatus = i2c_smbus_read_byte_data(client, command + i);\n\t\tif (status < 0)\n\t\t\treturn status;\n\t\tvalues[i] = status;\n\t\ti++;\n\t}\n\n\treturn i;\n}\nEXPORT_SYMBOL(i2c_smbus_read_i2c_block_data_or_emulated);\n\n/**\n * i2c_setup_smbus_alert - Setup SMBus alert support\n * @adapter: the target adapter\n * @setup: setup data for the SMBus alert handler\n * Context: can sleep\n *\n * Setup handling of the SMBus alert protocol on a given I2C bus segment.\n *\n * Handling can be done either through our IRQ handler, or by the\n * adapter (from its handler, periodic polling, or whatever).\n *\n * NOTE that if we manage the IRQ, we *MUST* know if it's level or\n * edge triggered in order to hand it to the workqueue correctly.\n * If triggering the alert seems to wedge the system, you probably\n * should have said it's level triggered.\n *\n * This returns the ara client, which should be saved for later use with\n * i2c_handle_smbus_alert() and ultimately i2c_unregister_device(); or NULL\n * to indicate an error.\n */\nstruct i2c_client *i2c_setup_smbus_alert(struct i2c_adapter *adapter,\n\t\t\t\t\t struct i2c_smbus_alert_setup *setup)\n{\n\tstruct i2c_board_info ara_board_info = {\n\t\tI2C_BOARD_INFO(\"smbus_alert\", 0x0c),\n\t\t.platform_data = setup,\n\t};\n\n\treturn i2c_new_device(adapter, &ara_board_info);\n}\nEXPORT_SYMBOL_GPL(i2c_setup_smbus_alert);\n\n#if IS_ENABLED(CONFIG_I2C_SMBUS) && IS_ENABLED(CONFIG_OF)\nint of_i2c_setup_smbus_alert(struct i2c_adapter *adapter)\n{\n\tstruct i2c_client *client;\n\tint irq;\n\n\tirq = of_property_match_string(adapter->dev.of_node, \"interrupt-names\",\n\t\t\t\t       \"smbus_alert\");\n\tif (irq == -EINVAL || irq == -ENODATA)\n\t\treturn 0;\n\telse if (irq < 0)\n\t\treturn irq;\n\n\tclient = i2c_setup_smbus_alert(adapter, NULL);\n\tif (!client)\n\t\treturn -ENODEV;\n\n\treturn 0;\n}\nEXPORT_SYMBOL_GPL(of_i2c_setup_smbus_alert);\n#endif\n"
  },
  {
    "path": "t/tree/drivers/i2c/i2c-core.h",
    "content": "/* SPDX-License-Identifier: GPL-2.0-or-later */\n/*\n * i2c-core.h - interfaces internal to the I2C framework\n */\n\n#include <linux/rwsem.h>\n\nstruct i2c_devinfo {\n\tstruct list_head\tlist;\n\tint\t\t\tbusnum;\n\tstruct i2c_board_info\tboard_info;\n};\n\n/* board_lock protects board_list and first_dynamic_bus_num.\n * only i2c core components are allowed to use these symbols.\n */\nextern struct rw_semaphore\t__i2c_board_lock;\nextern struct list_head\t__i2c_board_list;\nextern int\t\t__i2c_first_dynamic_bus_num;\n\nint i2c_check_7bit_addr_validity_strict(unsigned short addr);\nint i2c_dev_irq_from_resources(const struct resource *resources,\n\t\t\t       unsigned int num_resources);\n\n/*\n * We only allow atomic transfers for very late communication, e.g. to send\n * the powerdown command to a PMIC. Atomic transfers are a corner case and not\n * for generic use!\n */\nstatic inline bool i2c_in_atomic_xfer_mode(void)\n{\n\treturn system_state > SYSTEM_RUNNING && irqs_disabled();\n}\n\nstatic inline int __i2c_lock_bus_helper(struct i2c_adapter *adap)\n{\n\tint ret = 0;\n\n\tif (i2c_in_atomic_xfer_mode()) {\n\t\tWARN(!adap->algo->master_xfer_atomic && !adap->algo->smbus_xfer_atomic,\n\t\t     \"No atomic I2C transfer handler for '%s'\\n\", dev_name(&adap->dev));\n\t\tret = i2c_trylock_bus(adap, I2C_LOCK_SEGMENT) ? 0 : -EAGAIN;\n\t} else {\n\t\ti2c_lock_bus(adap, I2C_LOCK_SEGMENT);\n\t}\n\n\treturn ret;\n}\n\nstatic inline int __i2c_check_suspended(struct i2c_adapter *adap)\n{\n\tif (test_bit(I2C_ALF_IS_SUSPENDED, &adap->locked_flags)) {\n\t\tif (!test_and_set_bit(I2C_ALF_SUSPEND_REPORTED, &adap->locked_flags))\n\t\t\tdev_WARN(&adap->dev, \"Transfer while suspended\\n\");\n\t\treturn -ESHUTDOWN;\n\t}\n\n\treturn 0;\n}\n\n#ifdef CONFIG_ACPI\nconst struct acpi_device_id *\ni2c_acpi_match_device(const struct acpi_device_id *matches,\n\t\t      struct i2c_client *client);\nvoid i2c_acpi_register_devices(struct i2c_adapter *adap);\n\nint i2c_acpi_get_irq(struct i2c_client *client);\n#else /* CONFIG_ACPI */\nstatic inline void i2c_acpi_register_devices(struct i2c_adapter *adap) { }\nstatic inline const struct acpi_device_id *\ni2c_acpi_match_device(const struct acpi_device_id *matches,\n\t\t      struct i2c_client *client)\n{\n\treturn NULL;\n}\n\nstatic inline int i2c_acpi_get_irq(struct i2c_client *client)\n{\n\treturn 0;\n}\n#endif /* CONFIG_ACPI */\nextern struct notifier_block i2c_acpi_notifier;\n\n#ifdef CONFIG_ACPI_I2C_OPREGION\nint i2c_acpi_install_space_handler(struct i2c_adapter *adapter);\nvoid i2c_acpi_remove_space_handler(struct i2c_adapter *adapter);\n#else /* CONFIG_ACPI_I2C_OPREGION */\nstatic inline int i2c_acpi_install_space_handler(struct i2c_adapter *adapter) { return 0; }\nstatic inline void i2c_acpi_remove_space_handler(struct i2c_adapter *adapter) { }\n#endif /* CONFIG_ACPI_I2C_OPREGION */\n\n#ifdef CONFIG_OF\nvoid of_i2c_register_devices(struct i2c_adapter *adap);\n#else\nstatic inline void of_i2c_register_devices(struct i2c_adapter *adap) { }\n#endif\nextern struct notifier_block i2c_of_notifier;\n"
  },
  {
    "path": "t/tree/drivers/i2c/i2c-dev.c",
    "content": "// SPDX-License-Identifier: GPL-2.0-or-later\n/*\n    i2c-dev.c - i2c-bus driver, char device interface\n\n    Copyright (C) 1995-97 Simon G. Vogl\n    Copyright (C) 1998-99 Frodo Looijaard <frodol@dds.nl>\n    Copyright (C) 2003 Greg Kroah-Hartman <greg@kroah.com>\n\n*/\n\n/* Note that this is a complete rewrite of Simon Vogl's i2c-dev module.\n   But I have used so much of his original code and ideas that it seems\n   only fair to recognize him as co-author -- Frodo */\n\n/* The I2C_RDWR ioctl code is written by Kolja Waschk <waschk@telos.de> */\n\n#include <linux/cdev.h>\n#include <linux/device.h>\n#include <linux/fs.h>\n#include <linux/i2c-dev.h>\n#include <linux/i2c.h>\n#include <linux/init.h>\n#include <linux/jiffies.h>\n#include <linux/kernel.h>\n#include <linux/list.h>\n#include <linux/module.h>\n#include <linux/notifier.h>\n#include <linux/slab.h>\n#include <linux/uaccess.h>\n#include <linux/compat.h>\n\n/*\n * An i2c_dev represents an i2c_adapter ... an I2C or SMBus master, not a\n * slave (i2c_client) with which messages will be exchanged.  It's coupled\n * with a character special file which is accessed by user mode drivers.\n *\n * The list of i2c_dev structures is parallel to the i2c_adapter lists\n * maintained by the driver model, and is updated using bus notifications.\n */\nstruct i2c_dev {\n\tstruct list_head list;\n\tstruct i2c_adapter *adap;\n\tstruct device *dev;\n\tstruct cdev cdev;\n};\n\n#define I2C_MINORS\t(MINORMASK + 1)\nstatic LIST_HEAD(i2c_dev_list);\nstatic DEFINE_SPINLOCK(i2c_dev_list_lock);\n\nstatic struct i2c_dev *i2c_dev_get_by_minor(unsigned index)\n{\n\tstruct i2c_dev *i2c_dev;\n\n\tspin_lock(&i2c_dev_list_lock);\n\tlist_for_each_entry(i2c_dev, &i2c_dev_list, list) {\n\t\tif (i2c_dev->adap->nr == index)\n\t\t\tgoto found;\n\t}\n\ti2c_dev = NULL;\nfound:\n\tspin_unlock(&i2c_dev_list_lock);\n\treturn i2c_dev;\n}\n\nstatic struct i2c_dev *get_free_i2c_dev(struct i2c_adapter *adap)\n{\n\tstruct i2c_dev *i2c_dev;\n\n\tif (adap->nr >= I2C_MINORS) {\n\t\tprintk(KERN_ERR \"i2c-dev: Out of device minors (%d)\\n\",\n\t\t       adap->nr);\n\t\treturn ERR_PTR(-ENODEV);\n\t}\n\n\ti2c_dev = kzalloc(sizeof(*i2c_dev), GFP_KERNEL);\n\tif (!i2c_dev)\n\t\treturn ERR_PTR(-ENOMEM);\n\ti2c_dev->adap = adap;\n\n\tspin_lock(&i2c_dev_list_lock);\n\tlist_add_tail(&i2c_dev->list, &i2c_dev_list);\n\tspin_unlock(&i2c_dev_list_lock);\n\treturn i2c_dev;\n}\n\nstatic void put_i2c_dev(struct i2c_dev *i2c_dev)\n{\n\tspin_lock(&i2c_dev_list_lock);\n\tlist_del(&i2c_dev->list);\n\tspin_unlock(&i2c_dev_list_lock);\n\tkfree(i2c_dev);\n}\n\nstatic ssize_t name_show(struct device *dev,\n\t\t\t struct device_attribute *attr, char *buf)\n{\n\tstruct i2c_dev *i2c_dev = i2c_dev_get_by_minor(MINOR(dev->devt));\n\n\tif (!i2c_dev)\n\t\treturn -ENODEV;\n\treturn sprintf(buf, \"%s\\n\", i2c_dev->adap->name);\n}\nstatic DEVICE_ATTR_RO(name);\n\nstatic struct attribute *i2c_attrs[] = {\n\t&dev_attr_name.attr,\n\tNULL,\n};\nATTRIBUTE_GROUPS(i2c);\n\n/* ------------------------------------------------------------------------- */\n\n/*\n * After opening an instance of this character special file, a file\n * descriptor starts out associated only with an i2c_adapter (and bus).\n *\n * Using the I2C_RDWR ioctl(), you can then *immediately* issue i2c_msg\n * traffic to any devices on the bus used by that adapter.  That's because\n * the i2c_msg vectors embed all the addressing information they need, and\n * are submitted directly to an i2c_adapter.  However, SMBus-only adapters\n * don't support that interface.\n *\n * To use read()/write() system calls on that file descriptor, or to use\n * SMBus interfaces (and work with SMBus-only hosts!), you must first issue\n * an I2C_SLAVE (or I2C_SLAVE_FORCE) ioctl.  That configures an anonymous\n * (never registered) i2c_client so it holds the addressing information\n * needed by those system calls and by this SMBus interface.\n */\n\nstatic ssize_t i2cdev_read(struct file *file, char __user *buf, size_t count,\n\t\tloff_t *offset)\n{\n\tchar *tmp;\n\tint ret;\n\n\tstruct i2c_client *client = file->private_data;\n\n\tif (count > 8192)\n\t\tcount = 8192;\n\n\ttmp = kmalloc(count, GFP_KERNEL);\n\tif (tmp == NULL)\n\t\treturn -ENOMEM;\n\n\tpr_debug(\"i2c-dev: i2c-%d reading %zu bytes.\\n\",\n\t\timinor(file_inode(file)), count);\n\n\tret = i2c_master_recv(client, tmp, count);\n\tif (ret >= 0)\n\t\tret = copy_to_user(buf, tmp, count) ? -EFAULT : ret;\n\tkfree(tmp);\n\treturn ret;\n}\n\nstatic ssize_t i2cdev_write(struct file *file, const char __user *buf,\n\t\tsize_t count, loff_t *offset)\n{\n\tint ret;\n\tchar *tmp;\n\tstruct i2c_client *client = file->private_data;\n\n\tif (count > 8192)\n\t\tcount = 8192;\n\n\ttmp = memdup_user(buf, count);\n\tif (IS_ERR(tmp))\n\t\treturn PTR_ERR(tmp);\n\n\tpr_debug(\"i2c-dev: i2c-%d writing %zu bytes.\\n\",\n\t\timinor(file_inode(file)), count);\n\n\tret = i2c_master_send(client, tmp, count);\n\tkfree(tmp);\n\treturn ret;\n}\n\nstatic int i2cdev_check(struct device *dev, void *addrp)\n{\n\tstruct i2c_client *client = i2c_verify_client(dev);\n\n\tif (!client || client->addr != *(unsigned int *)addrp)\n\t\treturn 0;\n\n\treturn dev->driver ? -EBUSY : 0;\n}\n\n/* walk up mux tree */\nstatic int i2cdev_check_mux_parents(struct i2c_adapter *adapter, int addr)\n{\n\tstruct i2c_adapter *parent = i2c_parent_is_i2c_adapter(adapter);\n\tint result;\n\n\tresult = device_for_each_child(&adapter->dev, &addr, i2cdev_check);\n\tif (!result && parent)\n\t\tresult = i2cdev_check_mux_parents(parent, addr);\n\n\treturn result;\n}\n\n/* recurse down mux tree */\nstatic int i2cdev_check_mux_children(struct device *dev, void *addrp)\n{\n\tint result;\n\n\tif (dev->type == &i2c_adapter_type)\n\t\tresult = device_for_each_child(dev, addrp,\n\t\t\t\t\t\ti2cdev_check_mux_children);\n\telse\n\t\tresult = i2cdev_check(dev, addrp);\n\n\treturn result;\n}\n\n/* This address checking function differs from the one in i2c-core\n   in that it considers an address with a registered device, but no\n   driver bound to it, as NOT busy. */\nstatic int i2cdev_check_addr(struct i2c_adapter *adapter, unsigned int addr)\n{\n\tstruct i2c_adapter *parent = i2c_parent_is_i2c_adapter(adapter);\n\tint result = 0;\n\n\tif (parent)\n\t\tresult = i2cdev_check_mux_parents(parent, addr);\n\n\tif (!result)\n\t\tresult = device_for_each_child(&adapter->dev, &addr,\n\t\t\t\t\t\ti2cdev_check_mux_children);\n\n\treturn result;\n}\n\nstatic noinline int i2cdev_ioctl_rdwr(struct i2c_client *client,\n\t\tunsigned nmsgs, struct i2c_msg *msgs)\n{\n\tu8 __user **data_ptrs;\n\tint i, res;\n\n\tdata_ptrs = kmalloc_array(nmsgs, sizeof(u8 __user *), GFP_KERNEL);\n\tif (data_ptrs == NULL) {\n\t\tkfree(msgs);\n\t\treturn -ENOMEM;\n\t}\n\n\tres = 0;\n\tfor (i = 0; i < nmsgs; i++) {\n\t\t/* Limit the size of the message to a sane amount */\n\t\tif (msgs[i].len > 8192) {\n\t\t\tres = -EINVAL;\n\t\t\tbreak;\n\t\t}\n\n\t\tdata_ptrs[i] = (u8 __user *)msgs[i].buf;\n\t\tmsgs[i].buf = memdup_user(data_ptrs[i], msgs[i].len);\n\t\tif (IS_ERR(msgs[i].buf)) {\n\t\t\tres = PTR_ERR(msgs[i].buf);\n\t\t\tbreak;\n\t\t}\n\t\t/* memdup_user allocates with GFP_KERNEL, so DMA is ok */\n\t\tmsgs[i].flags |= I2C_M_DMA_SAFE;\n\n\t\t/*\n\t\t * If the message length is received from the slave (similar\n\t\t * to SMBus block read), we must ensure that the buffer will\n\t\t * be large enough to cope with a message length of\n\t\t * I2C_SMBUS_BLOCK_MAX as this is the maximum underlying bus\n\t\t * drivers allow. The first byte in the buffer must be\n\t\t * pre-filled with the number of extra bytes, which must be\n\t\t * at least one to hold the message length, but can be\n\t\t * greater (for example to account for a checksum byte at\n\t\t * the end of the message.)\n\t\t */\n\t\tif (msgs[i].flags & I2C_M_RECV_LEN) {\n\t\t\tif (!(msgs[i].flags & I2C_M_RD) ||\n\t\t\t    msgs[i].len < 1 || msgs[i].buf[0] < 1 ||\n\t\t\t    msgs[i].len < msgs[i].buf[0] +\n\t\t\t\t\t     I2C_SMBUS_BLOCK_MAX) {\n\t\t\t\ti++;\n\t\t\t\tres = -EINVAL;\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tmsgs[i].len = msgs[i].buf[0];\n\t\t}\n\t}\n\tif (res < 0) {\n\t\tint j;\n\t\tfor (j = 0; j < i; ++j)\n\t\t\tkfree(msgs[j].buf);\n\t\tkfree(data_ptrs);\n\t\tkfree(msgs);\n\t\treturn res;\n\t}\n\n\tres = i2c_transfer(client->adapter, msgs, nmsgs);\n\twhile (i-- > 0) {\n\t\tif (res >= 0 && (msgs[i].flags & I2C_M_RD)) {\n\t\t\tif (copy_to_user(data_ptrs[i], msgs[i].buf,\n\t\t\t\t\t msgs[i].len))\n\t\t\t\tres = -EFAULT;\n\t\t}\n\t\tkfree(msgs[i].buf);\n\t}\n\tkfree(data_ptrs);\n\tkfree(msgs);\n\treturn res;\n}\n\nstatic noinline int i2cdev_ioctl_smbus(struct i2c_client *client,\n\t\tu8 read_write, u8 command, u32 size,\n\t\tunion i2c_smbus_data __user *data)\n{\n\tunion i2c_smbus_data temp = {};\n\tint datasize, res;\n\n\tif ((size != I2C_SMBUS_BYTE) &&\n\t    (size != I2C_SMBUS_QUICK) &&\n\t    (size != I2C_SMBUS_BYTE_DATA) &&\n\t    (size != I2C_SMBUS_WORD_DATA) &&\n\t    (size != I2C_SMBUS_PROC_CALL) &&\n\t    (size != I2C_SMBUS_BLOCK_DATA) &&\n\t    (size != I2C_SMBUS_I2C_BLOCK_BROKEN) &&\n\t    (size != I2C_SMBUS_I2C_BLOCK_DATA) &&\n\t    (size != I2C_SMBUS_BLOCK_PROC_CALL)) {\n\t\tdev_dbg(&client->adapter->dev,\n\t\t\t\"size out of range (%x) in ioctl I2C_SMBUS.\\n\",\n\t\t\tsize);\n\t\treturn -EINVAL;\n\t}\n\t/* Note that I2C_SMBUS_READ and I2C_SMBUS_WRITE are 0 and 1,\n\t   so the check is valid if size==I2C_SMBUS_QUICK too. */\n\tif ((read_write != I2C_SMBUS_READ) &&\n\t    (read_write != I2C_SMBUS_WRITE)) {\n\t\tdev_dbg(&client->adapter->dev,\n\t\t\t\"read_write out of range (%x) in ioctl I2C_SMBUS.\\n\",\n\t\t\tread_write);\n\t\treturn -EINVAL;\n\t}\n\n\t/* Note that command values are always valid! */\n\n\tif ((size == I2C_SMBUS_QUICK) ||\n\t    ((size == I2C_SMBUS_BYTE) &&\n\t    (read_write == I2C_SMBUS_WRITE)))\n\t\t/* These are special: we do not use data */\n\t\treturn i2c_smbus_xfer(client->adapter, client->addr,\n\t\t\t\t      client->flags, read_write,\n\t\t\t\t      command, size, NULL);\n\n\tif (data == NULL) {\n\t\tdev_dbg(&client->adapter->dev,\n\t\t\t\"data is NULL pointer in ioctl I2C_SMBUS.\\n\");\n\t\treturn -EINVAL;\n\t}\n\n\tif ((size == I2C_SMBUS_BYTE_DATA) ||\n\t    (size == I2C_SMBUS_BYTE))\n\t\tdatasize = sizeof(data->byte);\n\telse if ((size == I2C_SMBUS_WORD_DATA) ||\n\t\t (size == I2C_SMBUS_PROC_CALL))\n\t\tdatasize = sizeof(data->word);\n\telse /* size == smbus block, i2c block, or block proc. call */\n\t\tdatasize = sizeof(data->block);\n\n\tif ((size == I2C_SMBUS_PROC_CALL) ||\n\t    (size == I2C_SMBUS_BLOCK_PROC_CALL) ||\n\t    (size == I2C_SMBUS_I2C_BLOCK_DATA) ||\n\t    (read_write == I2C_SMBUS_WRITE)) {\n\t\tif (copy_from_user(&temp, data, datasize))\n\t\t\treturn -EFAULT;\n\t}\n\tif (size == I2C_SMBUS_I2C_BLOCK_BROKEN) {\n\t\t/* Convert old I2C block commands to the new\n\t\t   convention. This preserves binary compatibility. */\n\t\tsize = I2C_SMBUS_I2C_BLOCK_DATA;\n\t\tif (read_write == I2C_SMBUS_READ)\n\t\t\ttemp.block[0] = I2C_SMBUS_BLOCK_MAX;\n\t}\n\tres = i2c_smbus_xfer(client->adapter, client->addr, client->flags,\n\t      read_write, command, size, &temp);\n\tif (!res && ((size == I2C_SMBUS_PROC_CALL) ||\n\t\t     (size == I2C_SMBUS_BLOCK_PROC_CALL) ||\n\t\t     (read_write == I2C_SMBUS_READ))) {\n\t\tif (copy_to_user(data, &temp, datasize))\n\t\t\treturn -EFAULT;\n\t}\n\treturn res;\n}\n\nstatic long i2cdev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)\n{\n\tstruct i2c_client *client = file->private_data;\n\tunsigned long funcs;\n\n\tdev_dbg(&client->adapter->dev, \"ioctl, cmd=0x%02x, arg=0x%02lx\\n\",\n\t\tcmd, arg);\n\n\tswitch (cmd) {\n\tcase I2C_SLAVE:\n\tcase I2C_SLAVE_FORCE:\n\t\tif ((arg > 0x3ff) ||\n\t\t    (((client->flags & I2C_M_TEN) == 0) && arg > 0x7f))\n\t\t\treturn -EINVAL;\n\t\tif (cmd == I2C_SLAVE && i2cdev_check_addr(client->adapter, arg))\n\t\t\treturn -EBUSY;\n\t\t/* REVISIT: address could become busy later */\n\t\tclient->addr = arg;\n\t\treturn 0;\n\tcase I2C_TENBIT:\n\t\tif (arg)\n\t\t\tclient->flags |= I2C_M_TEN;\n\t\telse\n\t\t\tclient->flags &= ~I2C_M_TEN;\n\t\treturn 0;\n\tcase I2C_PEC:\n\t\t/*\n\t\t * Setting the PEC flag here won't affect kernel drivers,\n\t\t * which will be using the i2c_client node registered with\n\t\t * the driver model core.  Likewise, when that client has\n\t\t * the PEC flag already set, the i2c-dev driver won't see\n\t\t * (or use) this setting.\n\t\t */\n\t\tif (arg)\n\t\t\tclient->flags |= I2C_CLIENT_PEC;\n\t\telse\n\t\t\tclient->flags &= ~I2C_CLIENT_PEC;\n\t\treturn 0;\n\tcase I2C_FUNCS:\n\t\tfuncs = i2c_get_functionality(client->adapter);\n\t\treturn put_user(funcs, (unsigned long __user *)arg);\n\n\tcase I2C_RDWR: {\n\t\tstruct i2c_rdwr_ioctl_data rdwr_arg;\n\t\tstruct i2c_msg *rdwr_pa;\n\n\t\tif (copy_from_user(&rdwr_arg,\n\t\t\t\t   (struct i2c_rdwr_ioctl_data __user *)arg,\n\t\t\t\t   sizeof(rdwr_arg)))\n\t\t\treturn -EFAULT;\n\n\t\t/* Put an arbitrary limit on the number of messages that can\n\t\t * be sent at once */\n\t\tif (rdwr_arg.nmsgs > I2C_RDWR_IOCTL_MAX_MSGS)\n\t\t\treturn -EINVAL;\n\n\t\trdwr_pa = memdup_user(rdwr_arg.msgs,\n\t\t\t\t      rdwr_arg.nmsgs * sizeof(struct i2c_msg));\n\t\tif (IS_ERR(rdwr_pa))\n\t\t\treturn PTR_ERR(rdwr_pa);\n\n\t\treturn i2cdev_ioctl_rdwr(client, rdwr_arg.nmsgs, rdwr_pa);\n\t}\n\n\tcase I2C_SMBUS: {\n\t\tstruct i2c_smbus_ioctl_data data_arg;\n\t\tif (copy_from_user(&data_arg,\n\t\t\t\t   (struct i2c_smbus_ioctl_data __user *) arg,\n\t\t\t\t   sizeof(struct i2c_smbus_ioctl_data)))\n\t\t\treturn -EFAULT;\n\t\treturn i2cdev_ioctl_smbus(client, data_arg.read_write,\n\t\t\t\t\t  data_arg.command,\n\t\t\t\t\t  data_arg.size,\n\t\t\t\t\t  data_arg.data);\n\t}\n\tcase I2C_RETRIES:\n\t\tif (arg > INT_MAX)\n\t\t\treturn -EINVAL;\n\n\t\tclient->adapter->retries = arg;\n\t\tbreak;\n\tcase I2C_TIMEOUT:\n\t\tif (arg > INT_MAX)\n\t\t\treturn -EINVAL;\n\n\t\t/* For historical reasons, user-space sets the timeout\n\t\t * value in units of 10 ms.\n\t\t */\n\t\tclient->adapter->timeout = msecs_to_jiffies(arg * 10);\n\t\tbreak;\n\tdefault:\n\t\t/* NOTE:  returning a fault code here could cause trouble\n\t\t * in buggy userspace code.  Some old kernel bugs returned\n\t\t * zero in this case, and userspace code might accidentally\n\t\t * have depended on that bug.\n\t\t */\n\t\treturn -ENOTTY;\n\t}\n\treturn 0;\n}\n\n#ifdef CONFIG_COMPAT\n\nstruct i2c_smbus_ioctl_data32 {\n\tu8 read_write;\n\tu8 command;\n\tu32 size;\n\tcompat_caddr_t data; /* union i2c_smbus_data *data */\n};\n\nstruct i2c_msg32 {\n\tu16 addr;\n\tu16 flags;\n\tu16 len;\n\tcompat_caddr_t buf;\n};\n\nstruct i2c_rdwr_ioctl_data32 {\n\tcompat_caddr_t msgs; /* struct i2c_msg __user *msgs */\n\tu32 nmsgs;\n};\n\nstatic long compat_i2cdev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)\n{\n\tstruct i2c_client *client = file->private_data;\n\tunsigned long funcs;\n\tswitch (cmd) {\n\tcase I2C_FUNCS:\n\t\tfuncs = i2c_get_functionality(client->adapter);\n\t\treturn put_user(funcs, (compat_ulong_t __user *)arg);\n\tcase I2C_RDWR: {\n\t\tstruct i2c_rdwr_ioctl_data32 rdwr_arg;\n\t\tstruct i2c_msg32 *p;\n\t\tstruct i2c_msg *rdwr_pa;\n\t\tint i;\n\n\t\tif (copy_from_user(&rdwr_arg,\n\t\t\t\t   (struct i2c_rdwr_ioctl_data32 __user *)arg,\n\t\t\t\t   sizeof(rdwr_arg)))\n\t\t\treturn -EFAULT;\n\n\t\tif (rdwr_arg.nmsgs > I2C_RDWR_IOCTL_MAX_MSGS)\n\t\t\treturn -EINVAL;\n\n\t\trdwr_pa = kmalloc_array(rdwr_arg.nmsgs, sizeof(struct i2c_msg),\n\t\t\t\t      GFP_KERNEL);\n\t\tif (!rdwr_pa)\n\t\t\treturn -ENOMEM;\n\n\t\tp = compat_ptr(rdwr_arg.msgs);\n\t\tfor (i = 0; i < rdwr_arg.nmsgs; i++) {\n\t\t\tstruct i2c_msg32 umsg;\n\t\t\tif (copy_from_user(&umsg, p + i, sizeof(umsg))) {\n\t\t\t\tkfree(rdwr_pa);\n\t\t\t\treturn -EFAULT;\n\t\t\t}\n\t\t\trdwr_pa[i] = (struct i2c_msg) {\n\t\t\t\t.addr = umsg.addr,\n\t\t\t\t.flags = umsg.flags,\n\t\t\t\t.len = umsg.len,\n\t\t\t\t.buf = compat_ptr(umsg.buf)\n\t\t\t};\n\t\t}\n\n\t\treturn i2cdev_ioctl_rdwr(client, rdwr_arg.nmsgs, rdwr_pa);\n\t}\n\tcase I2C_SMBUS: {\n\t\tstruct i2c_smbus_ioctl_data32\tdata32;\n\t\tif (copy_from_user(&data32,\n\t\t\t\t   (void __user *) arg,\n\t\t\t\t   sizeof(data32)))\n\t\t\treturn -EFAULT;\n\t\treturn i2cdev_ioctl_smbus(client, data32.read_write,\n\t\t\t\t\t  data32.command,\n\t\t\t\t\t  data32.size,\n\t\t\t\t\t  compat_ptr(data32.data));\n\t}\n\tdefault:\n\t\treturn i2cdev_ioctl(file, cmd, arg);\n\t}\n}\n#else\n#define compat_i2cdev_ioctl NULL\n#endif\n\nstatic int i2cdev_open(struct inode *inode, struct file *file)\n{\n\tunsigned int minor = iminor(inode);\n\tstruct i2c_client *client;\n\tstruct i2c_adapter *adap;\n\n\tadap = i2c_get_adapter(minor);\n\tif (!adap)\n\t\treturn -ENODEV;\n\n\t/* This creates an anonymous i2c_client, which may later be\n\t * pointed to some address using I2C_SLAVE or I2C_SLAVE_FORCE.\n\t *\n\t * This client is ** NEVER REGISTERED ** with the driver model\n\t * or I2C core code!!  It just holds private copies of addressing\n\t * information and maybe a PEC flag.\n\t */\n\tclient = kzalloc(sizeof(*client), GFP_KERNEL);\n\tif (!client) {\n\t\ti2c_put_adapter(adap);\n\t\treturn -ENOMEM;\n\t}\n\tsnprintf(client->name, I2C_NAME_SIZE, \"i2c-dev %d\", adap->nr);\n\n\tclient->adapter = adap;\n\tfile->private_data = client;\n\n\treturn 0;\n}\n\nstatic int i2cdev_release(struct inode *inode, struct file *file)\n{\n\tstruct i2c_client *client = file->private_data;\n\n\ti2c_put_adapter(client->adapter);\n\tkfree(client);\n\tfile->private_data = NULL;\n\n\treturn 0;\n}\n\nstatic const struct file_operations i2cdev_fops = {\n\t.owner\t\t= THIS_MODULE,\n\t.llseek\t\t= no_llseek,\n\t.read\t\t= i2cdev_read,\n\t.write\t\t= i2cdev_write,\n\t.unlocked_ioctl\t= i2cdev_ioctl,\n\t.compat_ioctl\t= compat_i2cdev_ioctl,\n\t.open\t\t= i2cdev_open,\n\t.release\t= i2cdev_release,\n};\n\n/* ------------------------------------------------------------------------- */\n\nstatic struct class *i2c_dev_class;\n\nstatic int i2cdev_attach_adapter(struct device *dev, void *dummy)\n{\n\tstruct i2c_adapter *adap;\n\tstruct i2c_dev *i2c_dev;\n\tint res;\n\n\tif (dev->type != &i2c_adapter_type)\n\t\treturn 0;\n\tadap = to_i2c_adapter(dev);\n\n\ti2c_dev = get_free_i2c_dev(adap);\n\tif (IS_ERR(i2c_dev))\n\t\treturn PTR_ERR(i2c_dev);\n\n\tcdev_init(&i2c_dev->cdev, &i2cdev_fops);\n\ti2c_dev->cdev.owner = THIS_MODULE;\n\tres = cdev_add(&i2c_dev->cdev, MKDEV(I2C_MAJOR, adap->nr), 1);\n\tif (res)\n\t\tgoto error_cdev;\n\n\t/* register this i2c device with the driver core */\n\ti2c_dev->dev = device_create(i2c_dev_class, &adap->dev,\n\t\t\t\t     MKDEV(I2C_MAJOR, adap->nr), NULL,\n\t\t\t\t     \"i2c-%d\", adap->nr);\n\tif (IS_ERR(i2c_dev->dev)) {\n\t\tres = PTR_ERR(i2c_dev->dev);\n\t\tgoto error;\n\t}\n\n\tpr_debug(\"i2c-dev: adapter [%s] registered as minor %d\\n\",\n\t\t adap->name, adap->nr);\n\treturn 0;\nerror:\n\tcdev_del(&i2c_dev->cdev);\nerror_cdev:\n\tput_i2c_dev(i2c_dev);\n\treturn res;\n}\n\nstatic int i2cdev_detach_adapter(struct device *dev, void *dummy)\n{\n\tstruct i2c_adapter *adap;\n\tstruct i2c_dev *i2c_dev;\n\n\tif (dev->type != &i2c_adapter_type)\n\t\treturn 0;\n\tadap = to_i2c_adapter(dev);\n\n\ti2c_dev = i2c_dev_get_by_minor(adap->nr);\n\tif (!i2c_dev) /* attach_adapter must have failed */\n\t\treturn 0;\n\n\tcdev_del(&i2c_dev->cdev);\n\tput_i2c_dev(i2c_dev);\n\tdevice_destroy(i2c_dev_class, MKDEV(I2C_MAJOR, adap->nr));\n\n\tpr_debug(\"i2c-dev: adapter [%s] unregistered\\n\", adap->name);\n\treturn 0;\n}\n\nstatic int i2cdev_notifier_call(struct notifier_block *nb, unsigned long action,\n\t\t\t void *data)\n{\n\tstruct device *dev = data;\n\n\tswitch (action) {\n\tcase BUS_NOTIFY_ADD_DEVICE:\n\t\treturn i2cdev_attach_adapter(dev, NULL);\n\tcase BUS_NOTIFY_DEL_DEVICE:\n\t\treturn i2cdev_detach_adapter(dev, NULL);\n\t}\n\n\treturn 0;\n}\n\nstatic struct notifier_block i2cdev_notifier = {\n\t.notifier_call = i2cdev_notifier_call,\n};\n\n/* ------------------------------------------------------------------------- */\n\n/*\n * module load/unload record keeping\n */\n\nstatic int __init i2c_dev_init(void)\n{\n\tint res;\n\n\tprintk(KERN_INFO \"i2c /dev entries driver\\n\");\n\n\tres = register_chrdev_region(MKDEV(I2C_MAJOR, 0), I2C_MINORS, \"i2c\");\n\tif (res)\n\t\tgoto out;\n\n\ti2c_dev_class = class_create(THIS_MODULE, \"i2c-dev\");\n\tif (IS_ERR(i2c_dev_class)) {\n\t\tres = PTR_ERR(i2c_dev_class);\n\t\tgoto out_unreg_chrdev;\n\t}\n\ti2c_dev_class->dev_groups = i2c_groups;\n\n\t/* Keep track of adapters which will be added or removed later */\n\tres = bus_register_notifier(&i2c_bus_type, &i2cdev_notifier);\n\tif (res)\n\t\tgoto out_unreg_class;\n\n\t/* Bind to already existing adapters right away */\n\ti2c_for_each_dev(NULL, i2cdev_attach_adapter);\n\n\treturn 0;\n\nout_unreg_class:\n\tclass_destroy(i2c_dev_class);\nout_unreg_chrdev:\n\tunregister_chrdev_region(MKDEV(I2C_MAJOR, 0), I2C_MINORS);\nout:\n\tprintk(KERN_ERR \"%s: Driver Initialisation failed\\n\", __FILE__);\n\treturn res;\n}\n\nstatic void __exit i2c_dev_exit(void)\n{\n\tbus_unregister_notifier(&i2c_bus_type, &i2cdev_notifier);\n\ti2c_for_each_dev(NULL, i2cdev_detach_adapter);\n\tclass_destroy(i2c_dev_class);\n\tunregister_chrdev_region(MKDEV(I2C_MAJOR, 0), I2C_MINORS);\n}\n\nMODULE_AUTHOR(\"Frodo Looijaard <frodol@dds.nl> and \"\n\t\t\"Simon G. Vogl <simon@tk.uni-linz.ac.at>\");\nMODULE_DESCRIPTION(\"I2C /dev entries driver\");\nMODULE_LICENSE(\"GPL\");\n\nmodule_init(i2c_dev_init);\nmodule_exit(i2c_dev_exit);\n"
  },
  {
    "path": "t/tree/drivers/i2c/i2c-smbus.c",
    "content": "// SPDX-License-Identifier: GPL-2.0-or-later\n/*\n * i2c-smbus.c - SMBus extensions to the I2C protocol\n *\n * Copyright (C) 2008 David Brownell\n * Copyright (C) 2010 Jean Delvare <jdelvare@suse.de>\n */\n\n#include <linux/device.h>\n#include <linux/i2c.h>\n#include <linux/i2c-smbus.h>\n#include <linux/interrupt.h>\n#include <linux/kernel.h>\n#include <linux/module.h>\n#include <linux/of_irq.h>\n#include <linux/slab.h>\n#include <linux/workqueue.h>\n\nstruct i2c_smbus_alert {\n\tstruct work_struct\talert;\n\tstruct i2c_client\t*ara;\t\t/* Alert response address */\n};\n\nstruct alert_data {\n\tunsigned short\t\taddr;\n\tenum i2c_alert_protocol\ttype;\n\tunsigned int\t\tdata;\n};\n\n/* If this is the alerting device, notify its driver */\nstatic int smbus_do_alert(struct device *dev, void *addrp)\n{\n\tstruct i2c_client *client = i2c_verify_client(dev);\n\tstruct alert_data *data = addrp;\n\tstruct i2c_driver *driver;\n\n\tif (!client || client->addr != data->addr)\n\t\treturn 0;\n\tif (client->flags & I2C_CLIENT_TEN)\n\t\treturn 0;\n\n\t/*\n\t * Drivers should either disable alerts, or provide at least\n\t * a minimal handler.  Lock so the driver won't change.\n\t */\n\tdevice_lock(dev);\n\tif (client->dev.driver) {\n\t\tdriver = to_i2c_driver(client->dev.driver);\n\t\tif (driver->alert)\n\t\t\tdriver->alert(client, data->type, data->data);\n\t\telse\n\t\t\tdev_warn(&client->dev, \"no driver alert()!\\n\");\n\t} else\n\t\tdev_dbg(&client->dev, \"alert with no driver\\n\");\n\tdevice_unlock(dev);\n\n\t/* Stop iterating after we find the device */\n\treturn -EBUSY;\n}\n\n/*\n * The alert IRQ handler needs to hand work off to a task which can issue\n * SMBus calls, because those sleeping calls can't be made in IRQ context.\n */\nstatic irqreturn_t smbus_alert(int irq, void *d)\n{\n\tstruct i2c_smbus_alert *alert = d;\n\tstruct i2c_client *ara;\n\tunsigned short prev_addr = 0;\t/* Not a valid address */\n\n\tara = alert->ara;\n\n\tfor (;;) {\n\t\ts32 status;\n\t\tstruct alert_data data;\n\n\t\t/*\n\t\t * Devices with pending alerts reply in address order, low\n\t\t * to high, because of slave transmit arbitration.  After\n\t\t * responding, an SMBus device stops asserting SMBALERT#.\n\t\t *\n\t\t * Note that SMBus 2.0 reserves 10-bit addresses for future\n\t\t * use.  We neither handle them, nor try to use PEC here.\n\t\t */\n\t\tstatus = i2c_smbus_read_byte(ara);\n\t\tif (status < 0)\n\t\t\tbreak;\n\n\t\tdata.data = status & 1;\n\t\tdata.addr = status >> 1;\n\t\tdata.type = I2C_PROTOCOL_SMBUS_ALERT;\n\n\t\tif (data.addr == prev_addr) {\n\t\t\tdev_warn(&ara->dev, \"Duplicate SMBALERT# from dev \"\n\t\t\t\t\"0x%02x, skipping\\n\", data.addr);\n\t\t\tbreak;\n\t\t}\n\t\tdev_dbg(&ara->dev, \"SMBALERT# from dev 0x%02x, flag %d\\n\",\n\t\t\tdata.addr, data.data);\n\n\t\t/* Notify driver for the device which issued the alert */\n\t\tdevice_for_each_child(&ara->adapter->dev, &data,\n\t\t\t\t      smbus_do_alert);\n\t\tprev_addr = data.addr;\n\t}\n\n\treturn IRQ_HANDLED;\n}\n\nstatic void smbalert_work(struct work_struct *work)\n{\n\tstruct i2c_smbus_alert *alert;\n\n\talert = container_of(work, struct i2c_smbus_alert, alert);\n\n\tsmbus_alert(0, alert);\n\n}\n\n/* Setup SMBALERT# infrastructure */\nstatic int smbalert_probe(struct i2c_client *ara,\n\t\t\t  const struct i2c_device_id *id)\n{\n\tstruct i2c_smbus_alert_setup *setup = dev_get_platdata(&ara->dev);\n\tstruct i2c_smbus_alert *alert;\n\tstruct i2c_adapter *adapter = ara->adapter;\n\tint res, irq;\n\n\talert = devm_kzalloc(&ara->dev, sizeof(struct i2c_smbus_alert),\n\t\t\t     GFP_KERNEL);\n\tif (!alert)\n\t\treturn -ENOMEM;\n\n\tif (setup) {\n\t\tirq = setup->irq;\n\t} else {\n\t\tirq = of_irq_get_byname(adapter->dev.of_node, \"smbus_alert\");\n\t\tif (irq <= 0)\n\t\t\treturn irq;\n\t}\n\n\tINIT_WORK(&alert->alert, smbalert_work);\n\talert->ara = ara;\n\n\tif (irq > 0) {\n\t\tres = devm_request_threaded_irq(&ara->dev, irq,\n\t\t\t\t\t\tNULL, smbus_alert,\n\t\t\t\t\t\tIRQF_SHARED | IRQF_ONESHOT,\n\t\t\t\t\t\t\"smbus_alert\", alert);\n\t\tif (res)\n\t\t\treturn res;\n\t}\n\n\ti2c_set_clientdata(ara, alert);\n\tdev_info(&adapter->dev, \"supports SMBALERT#\\n\");\n\n\treturn 0;\n}\n\n/* IRQ and memory resources are managed so they are freed automatically */\nstatic int smbalert_remove(struct i2c_client *ara)\n{\n\tstruct i2c_smbus_alert *alert = i2c_get_clientdata(ara);\n\n\tcancel_work_sync(&alert->alert);\n\treturn 0;\n}\n\nstatic const struct i2c_device_id smbalert_ids[] = {\n\t{ \"smbus_alert\", 0 },\n\t{ /* LIST END */ }\n};\nMODULE_DEVICE_TABLE(i2c, smbalert_ids);\n\nstatic struct i2c_driver smbalert_driver = {\n\t.driver = {\n\t\t.name\t= \"smbus_alert\",\n\t},\n\t.probe\t\t= smbalert_probe,\n\t.remove\t\t= smbalert_remove,\n\t.id_table\t= smbalert_ids,\n};\n\n/**\n * i2c_handle_smbus_alert - Handle an SMBus alert\n * @ara: the ARA client on the relevant adapter\n * Context: can't sleep\n *\n * Helper function to be called from an I2C bus driver's interrupt\n * handler. It will schedule the alert work, in turn calling the\n * corresponding I2C device driver's alert function.\n *\n * It is assumed that ara is a valid i2c client previously returned by\n * i2c_setup_smbus_alert().\n */\nint i2c_handle_smbus_alert(struct i2c_client *ara)\n{\n\tstruct i2c_smbus_alert *alert = i2c_get_clientdata(ara);\n\n\treturn schedule_work(&alert->alert);\n}\nEXPORT_SYMBOL_GPL(i2c_handle_smbus_alert);\n\nmodule_i2c_driver(smbalert_driver);\n\nMODULE_AUTHOR(\"Jean Delvare <jdelvare@suse.de>\");\nMODULE_DESCRIPTION(\"SMBus protocol extensions support\");\nMODULE_LICENSE(\"GPL\");\n"
  },
  {
    "path": "t/tree/drivers/i2c/i2c-stub.c",
    "content": "// SPDX-License-Identifier: GPL-2.0-or-later\n/*\n    i2c-stub.c - I2C/SMBus chip emulator\n\n    Copyright (c) 2004 Mark M. Hoffman <mhoffman@lightlink.com>\n    Copyright (C) 2007-2014 Jean Delvare <jdelvare@suse.de>\n\n*/\n\n#define DEBUG 1\n#define pr_fmt(fmt) \"i2c-stub: \" fmt\n\n#include <linux/errno.h>\n#include <linux/i2c.h>\n#include <linux/init.h>\n#include <linux/kernel.h>\n#include <linux/list.h>\n#include <linux/module.h>\n#include <linux/slab.h>\n\n#define MAX_CHIPS 10\n\n/*\n * Support for I2C_FUNC_SMBUS_BLOCK_DATA is disabled by default and must\n * be enabled explicitly by setting the I2C_FUNC_SMBUS_BLOCK_DATA bits\n * in the 'functionality' module parameter.\n */\n#define STUB_FUNC_DEFAULT \\\n\t\t(I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE | \\\n\t\t I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA | \\\n\t\t I2C_FUNC_SMBUS_I2C_BLOCK)\n\n#define STUB_FUNC_ALL \\\n\t\t(STUB_FUNC_DEFAULT | I2C_FUNC_SMBUS_BLOCK_DATA)\n\nstatic unsigned short chip_addr[MAX_CHIPS];\nmodule_param_array(chip_addr, ushort, NULL, S_IRUGO);\nMODULE_PARM_DESC(chip_addr,\n\t\t \"Chip addresses (up to 10, between 0x03 and 0x77)\");\n\nstatic unsigned long functionality = STUB_FUNC_DEFAULT;\nmodule_param(functionality, ulong, S_IRUGO | S_IWUSR);\nMODULE_PARM_DESC(functionality, \"Override functionality bitfield\");\n\n/* Some chips have banked register ranges */\n\nstatic u8 bank_reg[MAX_CHIPS];\nmodule_param_array(bank_reg, byte, NULL, S_IRUGO);\nMODULE_PARM_DESC(bank_reg, \"Bank register\");\n\nstatic u8 bank_mask[MAX_CHIPS];\nmodule_param_array(bank_mask, byte, NULL, S_IRUGO);\nMODULE_PARM_DESC(bank_mask, \"Bank value mask\");\n\nstatic u8 bank_start[MAX_CHIPS];\nmodule_param_array(bank_start, byte, NULL, S_IRUGO);\nMODULE_PARM_DESC(bank_start, \"First banked register\");\n\nstatic u8 bank_end[MAX_CHIPS];\nmodule_param_array(bank_end, byte, NULL, S_IRUGO);\nMODULE_PARM_DESC(bank_end, \"Last banked register\");\n\nstruct smbus_block_data {\n\tstruct list_head node;\n\tu8 command;\n\tu8 len;\n\tu8 block[I2C_SMBUS_BLOCK_MAX];\n};\n\nstruct stub_chip {\n\tu8 pointer;\n\tu16 words[256];\t\t/* Byte operations use the LSB as per SMBus\n\t\t\t\t   specification */\n\tstruct list_head smbus_blocks;\n\n\t/* For chips with banks, extra registers are allocated dynamically */\n\tu8 bank_reg;\n\tu8 bank_shift;\n\tu8 bank_mask;\n\tu8 bank_sel;\t\t/* Currently selected bank */\n\tu8 bank_start;\n\tu8 bank_end;\n\tu16 bank_size;\n\tu16 *bank_words;\t/* Room for bank_mask * bank_size registers */\n};\n\nstatic struct stub_chip *stub_chips;\nstatic int stub_chips_nr;\n\nstatic struct smbus_block_data *stub_find_block(struct device *dev,\n\t\t\t\t\t\tstruct stub_chip *chip,\n\t\t\t\t\t\tu8 command, bool create)\n{\n\tstruct smbus_block_data *b, *rb = NULL;\n\n\tlist_for_each_entry(b, &chip->smbus_blocks, node) {\n\t\tif (b->command == command) {\n\t\t\trb = b;\n\t\t\tbreak;\n\t\t}\n\t}\n\tif (rb == NULL && create) {\n\t\trb = devm_kzalloc(dev, sizeof(*rb), GFP_KERNEL);\n\t\tif (rb == NULL)\n\t\t\treturn rb;\n\t\trb->command = command;\n\t\tlist_add(&rb->node, &chip->smbus_blocks);\n\t}\n\treturn rb;\n}\n\nstatic u16 *stub_get_wordp(struct stub_chip *chip, u8 offset)\n{\n\tif (chip->bank_sel &&\n\t    offset >= chip->bank_start && offset <= chip->bank_end)\n\t\treturn chip->bank_words +\n\t\t       (chip->bank_sel - 1) * chip->bank_size +\n\t\t       offset - chip->bank_start;\n\telse\n\t\treturn chip->words + offset;\n}\n\n/* Return negative errno on error. */\nstatic s32 stub_xfer(struct i2c_adapter *adap, u16 addr, unsigned short flags,\n\tchar read_write, u8 command, int size, union i2c_smbus_data *data)\n{\n\ts32 ret;\n\tint i, len;\n\tstruct stub_chip *chip = NULL;\n\tstruct smbus_block_data *b;\n\tu16 *wordp;\n\n\t/* Search for the right chip */\n\tfor (i = 0; i < stub_chips_nr; i++) {\n\t\tif (addr == chip_addr[i]) {\n\t\t\tchip = stub_chips + i;\n\t\t\tbreak;\n\t\t}\n\t}\n\tif (!chip)\n\t\treturn -ENODEV;\n\n\tswitch (size) {\n\n\tcase I2C_SMBUS_QUICK:\n\t\tdev_dbg(&adap->dev, \"smbus quick - addr 0x%02x\\n\", addr);\n\t\tret = 0;\n\t\tbreak;\n\n\tcase I2C_SMBUS_BYTE:\n\t\tif (read_write == I2C_SMBUS_WRITE) {\n\t\t\tchip->pointer = command;\n\t\t\tdev_dbg(&adap->dev,\n\t\t\t\t\"smbus byte - addr 0x%02x, wrote 0x%02x.\\n\",\n\t\t\t\taddr, command);\n\t\t} else {\n\t\t\twordp = stub_get_wordp(chip, chip->pointer++);\n\t\t\tdata->byte = *wordp & 0xff;\n\t\t\tdev_dbg(&adap->dev,\n\t\t\t\t\"smbus byte - addr 0x%02x, read  0x%02x.\\n\",\n\t\t\t\taddr, data->byte);\n\t\t}\n\n\t\tret = 0;\n\t\tbreak;\n\n\tcase I2C_SMBUS_BYTE_DATA:\n\t\twordp = stub_get_wordp(chip, command);\n\t\tif (read_write == I2C_SMBUS_WRITE) {\n\t\t\t*wordp &= 0xff00;\n\t\t\t*wordp |= data->byte;\n\t\t\tdev_dbg(&adap->dev,\n\t\t\t\t\"smbus byte data - addr 0x%02x, wrote 0x%02x at 0x%02x.\\n\",\n\t\t\t\taddr, data->byte, command);\n\n\t\t\t/* Set the bank as needed */\n\t\t\tif (chip->bank_words && command == chip->bank_reg) {\n\t\t\t\tchip->bank_sel =\n\t\t\t\t\t(data->byte >> chip->bank_shift)\n\t\t\t\t\t& chip->bank_mask;\n\t\t\t\tdev_dbg(&adap->dev,\n\t\t\t\t\t\"switching to bank %u.\\n\",\n\t\t\t\t\tchip->bank_sel);\n\t\t\t}\n\t\t} else {\n\t\t\tdata->byte = *wordp & 0xff;\n\t\t\tdev_dbg(&adap->dev,\n\t\t\t\t\"smbus byte data - addr 0x%02x, read  0x%02x at 0x%02x.\\n\",\n\t\t\t\taddr, data->byte, command);\n\t\t}\n\t\tchip->pointer = command + 1;\n\n\t\tret = 0;\n\t\tbreak;\n\n\tcase I2C_SMBUS_WORD_DATA:\n\t\twordp = stub_get_wordp(chip, command);\n\t\tif (read_write == I2C_SMBUS_WRITE) {\n\t\t\t*wordp = data->word;\n\t\t\tdev_dbg(&adap->dev,\n\t\t\t\t\"smbus word data - addr 0x%02x, wrote 0x%04x at 0x%02x.\\n\",\n\t\t\t\taddr, data->word, command);\n\t\t} else {\n\t\t\tdata->word = *wordp;\n\t\t\tdev_dbg(&adap->dev,\n\t\t\t\t\"smbus word data - addr 0x%02x, read  0x%04x at 0x%02x.\\n\",\n\t\t\t\taddr, data->word, command);\n\t\t}\n\n\t\tret = 0;\n\t\tbreak;\n\n\tcase I2C_SMBUS_I2C_BLOCK_DATA:\n\t\t/*\n\t\t * We ignore banks here, because banked chips don't use I2C\n\t\t * block transfers\n\t\t */\n\t\tif (data->block[0] > 256 - command)\t/* Avoid overrun */\n\t\t\tdata->block[0] = 256 - command;\n\t\tlen = data->block[0];\n\t\tif (read_write == I2C_SMBUS_WRITE) {\n\t\t\tfor (i = 0; i < len; i++) {\n\t\t\t\tchip->words[command + i] &= 0xff00;\n\t\t\t\tchip->words[command + i] |= data->block[1 + i];\n\t\t\t}\n\t\t\tdev_dbg(&adap->dev,\n\t\t\t\t\"i2c block data - addr 0x%02x, wrote %d bytes at 0x%02x.\\n\",\n\t\t\t\taddr, len, command);\n\t\t} else {\n\t\t\tfor (i = 0; i < len; i++) {\n\t\t\t\tdata->block[1 + i] =\n\t\t\t\t\tchip->words[command + i] & 0xff;\n\t\t\t}\n\t\t\tdev_dbg(&adap->dev,\n\t\t\t\t\"i2c block data - addr 0x%02x, read  %d bytes at 0x%02x.\\n\",\n\t\t\t\taddr, len, command);\n\t\t}\n\n\t\tret = 0;\n\t\tbreak;\n\n\tcase I2C_SMBUS_BLOCK_DATA:\n\t\t/*\n\t\t * We ignore banks here, because chips typically don't use both\n\t\t * banks and SMBus block transfers\n\t\t */\n\t\tb = stub_find_block(&adap->dev, chip, command, false);\n\t\tif (read_write == I2C_SMBUS_WRITE) {\n\t\t\tlen = data->block[0];\n\t\t\tif (len == 0 || len > I2C_SMBUS_BLOCK_MAX) {\n\t\t\t\tret = -EINVAL;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tif (b == NULL) {\n\t\t\t\tb = stub_find_block(&adap->dev, chip, command,\n\t\t\t\t\t\t    true);\n\t\t\t\tif (b == NULL) {\n\t\t\t\t\tret = -ENOMEM;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\t/* Largest write sets read block length */\n\t\t\tif (len > b->len)\n\t\t\t\tb->len = len;\n\t\t\tfor (i = 0; i < len; i++)\n\t\t\t\tb->block[i] = data->block[i + 1];\n\t\t\t/* update for byte and word commands */\n\t\t\tchip->words[command] = (b->block[0] << 8) | b->len;\n\t\t\tdev_dbg(&adap->dev,\n\t\t\t\t\"smbus block data - addr 0x%02x, wrote %d bytes at 0x%02x.\\n\",\n\t\t\t\taddr, len, command);\n\t\t} else {\n\t\t\tif (b == NULL) {\n\t\t\t\tdev_dbg(&adap->dev,\n\t\t\t\t\t\"SMBus block read command without prior block write not supported\\n\");\n\t\t\t\tret = -EOPNOTSUPP;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tlen = b->len;\n\t\t\tdata->block[0] = len;\n\t\t\tfor (i = 0; i < len; i++)\n\t\t\t\tdata->block[i + 1] = b->block[i];\n\t\t\tdev_dbg(&adap->dev,\n\t\t\t\t\"smbus block data - addr 0x%02x, read  %d bytes at 0x%02x.\\n\",\n\t\t\t\taddr, len, command);\n\t\t}\n\n\t\tret = 0;\n\t\tbreak;\n\n\tdefault:\n\t\tdev_dbg(&adap->dev, \"Unsupported I2C/SMBus command\\n\");\n\t\tret = -EOPNOTSUPP;\n\t\tbreak;\n\t} /* switch (size) */\n\n\treturn ret;\n}\n\nstatic u32 stub_func(struct i2c_adapter *adapter)\n{\n\treturn STUB_FUNC_ALL & functionality;\n}\n\nstatic const struct i2c_algorithm smbus_algorithm = {\n\t.functionality\t= stub_func,\n\t.smbus_xfer\t= stub_xfer,\n};\n\nstatic struct i2c_adapter stub_adapter = {\n\t.owner\t\t= THIS_MODULE,\n\t.class\t\t= I2C_CLASS_HWMON | I2C_CLASS_SPD,\n\t.algo\t\t= &smbus_algorithm,\n\t.name\t\t= \"SMBus stub driver\",\n};\n\nstatic int __init i2c_stub_allocate_banks(int i)\n{\n\tstruct stub_chip *chip = stub_chips + i;\n\n\tchip->bank_reg = bank_reg[i];\n\tchip->bank_start = bank_start[i];\n\tchip->bank_end = bank_end[i];\n\tchip->bank_size = bank_end[i] - bank_start[i] + 1;\n\n\t/* We assume that all bits in the mask are contiguous */\n\tchip->bank_mask = bank_mask[i];\n\twhile (!(chip->bank_mask & 1)) {\n\t\tchip->bank_shift++;\n\t\tchip->bank_mask >>= 1;\n\t}\n\n\tchip->bank_words = kcalloc(chip->bank_mask * chip->bank_size,\n\t\t\t\t   sizeof(u16),\n\t\t\t\t   GFP_KERNEL);\n\tif (!chip->bank_words)\n\t\treturn -ENOMEM;\n\n\tpr_debug(\"Allocated %u banks of %u words each (registers 0x%02x to 0x%02x)\\n\",\n\t\t chip->bank_mask, chip->bank_size, chip->bank_start,\n\t\t chip->bank_end);\n\n\treturn 0;\n}\n\nstatic void i2c_stub_free(void)\n{\n\tint i;\n\n\tfor (i = 0; i < stub_chips_nr; i++)\n\t\tkfree(stub_chips[i].bank_words);\n\tkfree(stub_chips);\n}\n\nstatic int __init i2c_stub_init(void)\n{\n\tint i, ret;\n\n\tif (!chip_addr[0]) {\n\t\tpr_err(\"Please specify a chip address\\n\");\n\t\treturn -ENODEV;\n\t}\n\n\tfor (i = 0; i < MAX_CHIPS && chip_addr[i]; i++) {\n\t\tif (chip_addr[i] < 0x03 || chip_addr[i] > 0x77) {\n\t\t\tpr_err(\"Invalid chip address 0x%02x\\n\",\n\t\t\t       chip_addr[i]);\n\t\t\treturn -EINVAL;\n\t\t}\n\n\t\tpr_info(\"Virtual chip at 0x%02x\\n\", chip_addr[i]);\n\t}\n\n\t/* Allocate memory for all chips at once */\n\tstub_chips_nr = i;\n\tstub_chips = kcalloc(stub_chips_nr, sizeof(struct stub_chip),\n\t\t\t     GFP_KERNEL);\n\tif (!stub_chips)\n\t\treturn -ENOMEM;\n\n\tfor (i = 0; i < stub_chips_nr; i++) {\n\t\tINIT_LIST_HEAD(&stub_chips[i].smbus_blocks);\n\n\t\t/* Allocate extra memory for banked register ranges */\n\t\tif (bank_mask[i]) {\n\t\t\tret = i2c_stub_allocate_banks(i);\n\t\t\tif (ret)\n\t\t\t\tgoto fail_free;\n\t\t}\n\t}\n\n\tret = i2c_add_adapter(&stub_adapter);\n\tif (ret)\n\t\tgoto fail_free;\n\n\treturn 0;\n\n fail_free:\n\ti2c_stub_free();\n\treturn ret;\n}\n\nstatic void __exit i2c_stub_exit(void)\n{\n\ti2c_del_adapter(&stub_adapter);\n\ti2c_stub_free();\n}\n\nMODULE_AUTHOR(\"Mark M. Hoffman <mhoffman@lightlink.com>\");\nMODULE_DESCRIPTION(\"I2C stub driver\");\nMODULE_LICENSE(\"GPL\");\n\nmodule_init(i2c_stub_init);\nmodule_exit(i2c_stub_exit);\n"
  },
  {
    "path": "t/tree/include/acpi/acpi_bus.h",
    "content": "/* SPDX-License-Identifier: GPL-2.0-or-later */\n/*\n *  acpi_bus.h - ACPI Bus Driver ($Revision: 22 $)\n *\n *  Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com>\n *  Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>\n */\n\n#ifndef __ACPI_BUS_H__\n#define __ACPI_BUS_H__\n\n#include <linux/device.h>\n#include <linux/property.h>\n\n/* TBD: Make dynamic */\n#define ACPI_MAX_HANDLES\t10\nstruct acpi_handle_list {\n\tu32 count;\n\tacpi_handle handles[ACPI_MAX_HANDLES];\n};\n\n/* acpi_utils.h */\nacpi_status\nacpi_extract_package(union acpi_object *package,\n\t\t     struct acpi_buffer *format, struct acpi_buffer *buffer);\nacpi_status\nacpi_evaluate_integer(acpi_handle handle,\n\t\t      acpi_string pathname,\n\t\t      struct acpi_object_list *arguments, unsigned long long *data);\nacpi_status\nacpi_evaluate_reference(acpi_handle handle,\n\t\t\tacpi_string pathname,\n\t\t\tstruct acpi_object_list *arguments,\n\t\t\tstruct acpi_handle_list *list);\nacpi_status\nacpi_evaluate_ost(acpi_handle handle, u32 source_event, u32 status_code,\n\t\t  struct acpi_buffer *status_buf);\n\nacpi_status\nacpi_get_physical_device_location(acpi_handle handle, struct acpi_pld_info **pld);\n\nbool acpi_has_method(acpi_handle handle, char *name);\nacpi_status acpi_execute_simple_method(acpi_handle handle, char *method,\n\t\t\t\t       u64 arg);\nacpi_status acpi_evaluate_ej0(acpi_handle handle);\nacpi_status acpi_evaluate_lck(acpi_handle handle, int lock);\nbool acpi_ata_match(acpi_handle handle);\nbool acpi_bay_match(acpi_handle handle);\nbool acpi_dock_match(acpi_handle handle);\n\nbool acpi_check_dsm(acpi_handle handle, const guid_t *guid, u64 rev, u64 funcs);\nunion acpi_object *acpi_evaluate_dsm(acpi_handle handle, const guid_t *guid,\n\t\t\tu64 rev, u64 func, union acpi_object *argv4);\n\nstatic inline union acpi_object *\nacpi_evaluate_dsm_typed(acpi_handle handle, const guid_t *guid, u64 rev,\n\t\t\tu64 func, union acpi_object *argv4,\n\t\t\tacpi_object_type type)\n{\n\tunion acpi_object *obj;\n\n\tobj = acpi_evaluate_dsm(handle, guid, rev, func, argv4);\n\tif (obj && obj->type != type) {\n\t\tACPI_FREE(obj);\n\t\tobj = NULL;\n\t}\n\n\treturn obj;\n}\n\n#define\tACPI_INIT_DSM_ARGV4(cnt, eles)\t\t\t\\\n\t{\t\t\t\t\t\t\\\n\t  .package.type = ACPI_TYPE_PACKAGE,\t\t\\\n\t  .package.count = (cnt),\t\t\t\\\n\t  .package.elements = (eles)\t\t\t\\\n\t}\n\nbool acpi_dev_found(const char *hid);\nbool acpi_dev_present(const char *hid, const char *uid, s64 hrv);\n\nstruct acpi_device *\nacpi_dev_get_first_match_dev(const char *hid, const char *uid, s64 hrv);\n\n#ifdef CONFIG_ACPI\n\n#include <linux/proc_fs.h>\n\n#define ACPI_BUS_FILE_ROOT\t\"acpi\"\nextern struct proc_dir_entry *acpi_root_dir;\n\nenum acpi_bus_device_type {\n\tACPI_BUS_TYPE_DEVICE = 0,\n\tACPI_BUS_TYPE_POWER,\n\tACPI_BUS_TYPE_PROCESSOR,\n\tACPI_BUS_TYPE_THERMAL,\n\tACPI_BUS_TYPE_POWER_BUTTON,\n\tACPI_BUS_TYPE_SLEEP_BUTTON,\n\tACPI_BUS_TYPE_ECDT_EC,\n\tACPI_BUS_DEVICE_TYPE_COUNT\n};\n\nstruct acpi_driver;\nstruct acpi_device;\n\n/*\n * ACPI Scan Handler\n * -----------------\n */\n\nstruct acpi_hotplug_profile {\n\tstruct kobject kobj;\n\tint (*scan_dependent)(struct acpi_device *adev);\n\tvoid (*notify_online)(struct acpi_device *adev);\n\tbool enabled:1;\n\tbool demand_offline:1;\n};\n\nstatic inline struct acpi_hotplug_profile *to_acpi_hotplug_profile(\n\t\t\t\t\t\tstruct kobject *kobj)\n{\n\treturn container_of(kobj, struct acpi_hotplug_profile, kobj);\n}\n\nstruct acpi_scan_handler {\n\tconst struct acpi_device_id *ids;\n\tstruct list_head list_node;\n\tbool (*match)(const char *idstr, const struct acpi_device_id **matchid);\n\tint (*attach)(struct acpi_device *dev, const struct acpi_device_id *id);\n\tvoid (*detach)(struct acpi_device *dev);\n\tvoid (*bind)(struct device *phys_dev);\n\tvoid (*unbind)(struct device *phys_dev);\n\tstruct acpi_hotplug_profile hotplug;\n};\n\n/*\n * ACPI Hotplug Context\n * --------------------\n */\n\nstruct acpi_hotplug_context {\n\tstruct acpi_device *self;\n\tint (*notify)(struct acpi_device *, u32);\n\tvoid (*uevent)(struct acpi_device *, u32);\n\tvoid (*fixup)(struct acpi_device *);\n};\n\n/*\n * ACPI Driver\n * -----------\n */\n\ntypedef int (*acpi_op_add) (struct acpi_device * device);\ntypedef int (*acpi_op_remove) (struct acpi_device * device);\ntypedef void (*acpi_op_notify) (struct acpi_device * device, u32 event);\n\nstruct acpi_device_ops {\n\tacpi_op_add add;\n\tacpi_op_remove remove;\n\tacpi_op_notify notify;\n};\n\n#define ACPI_DRIVER_ALL_NOTIFY_EVENTS\t0x1\t/* system AND device events */\n\nstruct acpi_driver {\n\tchar name[80];\n\tchar class[80];\n\tconst struct acpi_device_id *ids; /* Supported Hardware IDs */\n\tunsigned int flags;\n\tstruct acpi_device_ops ops;\n\tstruct device_driver drv;\n\tstruct module *owner;\n};\n\n/*\n * ACPI Device\n * -----------\n */\n\n/* Status (_STA) */\n\nstruct acpi_device_status {\n\tu32 present:1;\n\tu32 enabled:1;\n\tu32 show_in_ui:1;\n\tu32 functional:1;\n\tu32 battery_present:1;\n\tu32 reserved:27;\n};\n\n/* Flags */\n\nstruct acpi_device_flags {\n\tu32 dynamic_status:1;\n\tu32 removable:1;\n\tu32 ejectable:1;\n\tu32 power_manageable:1;\n\tu32 match_driver:1;\n\tu32 initialized:1;\n\tu32 visited:1;\n\tu32 hotplug_notify:1;\n\tu32 is_dock_station:1;\n\tu32 of_compatible_ok:1;\n\tu32 coherent_dma:1;\n\tu32 cca_seen:1;\n\tu32 enumeration_by_parent:1;\n\tu32 reserved:19;\n};\n\n/* File System */\n\nstruct acpi_device_dir {\n\tstruct proc_dir_entry *entry;\n};\n\n#define acpi_device_dir(d)\t((d)->dir.entry)\n\n/* Plug and Play */\n\ntypedef char acpi_bus_id[8];\ntypedef u64 acpi_bus_address;\ntypedef char acpi_device_name[40];\ntypedef char acpi_device_class[20];\n\nstruct acpi_hardware_id {\n\tstruct list_head list;\n\tconst char *id;\n};\n\nstruct acpi_pnp_type {\n\tu32 hardware_id:1;\n\tu32 bus_address:1;\n\tu32 platform_id:1;\n\tu32 reserved:29;\n};\n\nstruct acpi_device_pnp {\n\tacpi_bus_id bus_id;\t\t/* Object name */\n\tstruct acpi_pnp_type type;\t/* ID type */\n\tacpi_bus_address bus_address;\t/* _ADR */\n\tchar *unique_id;\t\t/* _UID */\n\tstruct list_head ids;\t\t/* _HID and _CIDs */\n\tacpi_device_name device_name;\t/* Driver-determined */\n\tacpi_device_class device_class;\t/*        \"          */\n\tunion acpi_object *str_obj;\t/* unicode string for _STR method */\n};\n\n#define acpi_device_bid(d)\t((d)->pnp.bus_id)\n#define acpi_device_adr(d)\t((d)->pnp.bus_address)\nconst char *acpi_device_hid(struct acpi_device *device);\n#define acpi_device_uid(d)\t((d)->pnp.unique_id)\n#define acpi_device_name(d)\t((d)->pnp.device_name)\n#define acpi_device_class(d)\t((d)->pnp.device_class)\n\n/* Power Management */\n\nstruct acpi_device_power_flags {\n\tu32 explicit_get:1;\t/* _PSC present? */\n\tu32 power_resources:1;\t/* Power resources */\n\tu32 inrush_current:1;\t/* Serialize Dx->D0 */\n\tu32 power_removed:1;\t/* Optimize Dx->D0 */\n\tu32 ignore_parent:1;\t/* Power is independent of parent power state */\n\tu32 dsw_present:1;\t/* _DSW present? */\n\tu32 reserved:26;\n};\n\nstruct acpi_device_power_state {\n\tstruct {\n\t\tu8 valid:1;\n\t\tu8 explicit_set:1;\t/* _PSx present? */\n\t\tu8 reserved:6;\n\t} flags;\n\tint power;\t\t/* % Power (compared to D0) */\n\tint latency;\t\t/* Dx->D0 time (microseconds) */\n\tstruct list_head resources;\t/* Power resources referenced */\n};\n\nstruct acpi_device_power {\n\tint state;\t\t/* Current state */\n\tstruct acpi_device_power_flags flags;\n\tstruct acpi_device_power_state states[ACPI_D_STATE_COUNT];\t/* Power states (D0-D3Cold) */\n};\n\n/* Performance Management */\n\nstruct acpi_device_perf_flags {\n\tu8 reserved:8;\n};\n\nstruct acpi_device_perf_state {\n\tstruct {\n\t\tu8 valid:1;\n\t\tu8 reserved:7;\n\t} flags;\n\tu8 power;\t\t/* % Power (compared to P0) */\n\tu8 performance;\t\t/* % Performance (    \"   ) */\n\tint latency;\t\t/* Px->P0 time (microseconds) */\n};\n\nstruct acpi_device_perf {\n\tint state;\n\tstruct acpi_device_perf_flags flags;\n\tint state_count;\n\tstruct acpi_device_perf_state *states;\n};\n\n/* Wakeup Management */\nstruct acpi_device_wakeup_flags {\n\tu8 valid:1;\t\t/* Can successfully enable wakeup? */\n\tu8 notifier_present:1;  /* Wake-up notify handler has been installed */\n};\n\nstruct acpi_device_wakeup_context {\n\tvoid (*func)(struct acpi_device_wakeup_context *context);\n\tstruct device *dev;\n};\n\nstruct acpi_device_wakeup {\n\tacpi_handle gpe_device;\n\tu64 gpe_number;\n\tu64 sleep_state;\n\tstruct list_head resources;\n\tstruct acpi_device_wakeup_flags flags;\n\tstruct acpi_device_wakeup_context context;\n\tstruct wakeup_source *ws;\n\tint prepare_count;\n\tint enable_count;\n};\n\nstruct acpi_device_physical_node {\n\tunsigned int node_id;\n\tstruct list_head node;\n\tstruct device *dev;\n\tbool put_online:1;\n};\n\nstruct acpi_device_properties {\n\tconst guid_t *guid;\n\tconst union acpi_object *properties;\n\tstruct list_head list;\n};\n\n/* ACPI Device Specific Data (_DSD) */\nstruct acpi_device_data {\n\tconst union acpi_object *pointer;\n\tstruct list_head properties;\n\tconst union acpi_object *of_compatible;\n\tstruct list_head subnodes;\n};\n\nstruct acpi_gpio_mapping;\n\n/* Device */\nstruct acpi_device {\n\tint device_type;\n\tacpi_handle handle;\t\t/* no handle for fixed hardware */\n\tstruct fwnode_handle fwnode;\n\tstruct acpi_device *parent;\n\tstruct list_head children;\n\tstruct list_head node;\n\tstruct list_head wakeup_list;\n\tstruct list_head del_list;\n\tstruct acpi_device_status status;\n\tstruct acpi_device_flags flags;\n\tstruct acpi_device_pnp pnp;\n\tstruct acpi_device_power power;\n\tstruct acpi_device_wakeup wakeup;\n\tstruct acpi_device_perf performance;\n\tstruct acpi_device_dir dir;\n\tstruct acpi_device_data data;\n\tstruct acpi_scan_handler *handler;\n\tstruct acpi_hotplug_context *hp;\n\tstruct acpi_driver *driver;\n\tconst struct acpi_gpio_mapping *driver_gpios;\n\tvoid *driver_data;\n\tstruct device dev;\n\tunsigned int physical_node_count;\n\tunsigned int dep_unmet;\n\tstruct list_head physical_node_list;\n\tstruct mutex physical_node_lock;\n\tvoid (*remove)(struct acpi_device *);\n};\n\n/* Non-device subnode */\nstruct acpi_data_node {\n\tconst char *name;\n\tacpi_handle handle;\n\tstruct fwnode_handle fwnode;\n\tstruct fwnode_handle *parent;\n\tstruct acpi_device_data data;\n\tstruct list_head sibling;\n\tstruct kobject kobj;\n\tstruct completion kobj_done;\n};\n\nextern const struct fwnode_operations acpi_device_fwnode_ops;\nextern const struct fwnode_operations acpi_data_fwnode_ops;\nextern const struct fwnode_operations acpi_static_fwnode_ops;\n\nbool is_acpi_device_node(const struct fwnode_handle *fwnode);\nbool is_acpi_data_node(const struct fwnode_handle *fwnode);\n\nstatic inline bool is_acpi_node(const struct fwnode_handle *fwnode)\n{\n\treturn (is_acpi_device_node(fwnode) || is_acpi_data_node(fwnode));\n}\n\n#define to_acpi_device_node(__fwnode)\t\t\t\t\t\\\n\t({\t\t\t\t\t\t\t\t\\\n\t\ttypeof(__fwnode) __to_acpi_device_node_fwnode = __fwnode; \\\n\t\t\t\t\t\t\t\t\t\\\n\t\tis_acpi_device_node(__to_acpi_device_node_fwnode) ?\t\\\n\t\t\tcontainer_of(__to_acpi_device_node_fwnode,\t\\\n\t\t\t\t     struct acpi_device, fwnode) :\t\\\n\t\t\tNULL;\t\t\t\t\t\t\\\n\t})\n\n#define to_acpi_data_node(__fwnode)\t\t\t\t\t\\\n\t({\t\t\t\t\t\t\t\t\\\n\t\ttypeof(__fwnode) __to_acpi_data_node_fwnode = __fwnode;\t\\\n\t\t\t\t\t\t\t\t\t\\\n\t\tis_acpi_data_node(__to_acpi_data_node_fwnode) ?\t\t\\\n\t\t\tcontainer_of(__to_acpi_data_node_fwnode,\t\\\n\t\t\t\t     struct acpi_data_node, fwnode) :\t\\\n\t\t\tNULL;\t\t\t\t\t\t\\\n\t})\n\nstatic inline bool is_acpi_static_node(const struct fwnode_handle *fwnode)\n{\n\treturn !IS_ERR_OR_NULL(fwnode) &&\n\t\tfwnode->ops == &acpi_static_fwnode_ops;\n}\n\nstatic inline bool acpi_data_node_match(const struct fwnode_handle *fwnode,\n\t\t\t\t\tconst char *name)\n{\n\treturn is_acpi_data_node(fwnode) ?\n\t\t(!strcmp(to_acpi_data_node(fwnode)->name, name)) : false;\n}\n\nstatic inline struct fwnode_handle *acpi_fwnode_handle(struct acpi_device *adev)\n{\n\treturn &adev->fwnode;\n}\n\nstatic inline void *acpi_driver_data(struct acpi_device *d)\n{\n\treturn d->driver_data;\n}\n\n#define to_acpi_device(d)\tcontainer_of(d, struct acpi_device, dev)\n#define to_acpi_driver(d)\tcontainer_of(d, struct acpi_driver, drv)\n\nstatic inline void acpi_set_device_status(struct acpi_device *adev, u32 sta)\n{\n\t*((u32 *)&adev->status) = sta;\n}\n\nstatic inline void acpi_set_hp_context(struct acpi_device *adev,\n\t\t\t\t       struct acpi_hotplug_context *hp)\n{\n\thp->self = adev;\n\tadev->hp = hp;\n}\n\nvoid acpi_initialize_hp_context(struct acpi_device *adev,\n\t\t\t\tstruct acpi_hotplug_context *hp,\n\t\t\t\tint (*notify)(struct acpi_device *, u32),\n\t\t\t\tvoid (*uevent)(struct acpi_device *, u32));\n\n/* acpi_device.dev.bus == &acpi_bus_type */\nextern struct bus_type acpi_bus_type;\n\n/*\n * Events\n * ------\n */\n\nstruct acpi_bus_event {\n\tstruct list_head node;\n\tacpi_device_class device_class;\n\tacpi_bus_id bus_id;\n\tu32 type;\n\tu32 data;\n};\n\nextern struct kobject *acpi_kobj;\nextern int acpi_bus_generate_netlink_event(const char*, const char*, u8, int);\nvoid acpi_bus_private_data_handler(acpi_handle, void *);\nint acpi_bus_get_private_data(acpi_handle, void **);\nint acpi_bus_attach_private_data(acpi_handle, void *);\nvoid acpi_bus_detach_private_data(acpi_handle);\nextern int acpi_notifier_call_chain(struct acpi_device *, u32, u32);\nextern int register_acpi_notifier(struct notifier_block *);\nextern int unregister_acpi_notifier(struct notifier_block *);\n\n/*\n * External Functions\n */\n\nint acpi_bus_get_device(acpi_handle handle, struct acpi_device **device);\nstruct acpi_device *acpi_bus_get_acpi_device(acpi_handle handle);\nvoid acpi_bus_put_acpi_device(struct acpi_device *adev);\nacpi_status acpi_bus_get_status_handle(acpi_handle handle,\n\t\t\t\t       unsigned long long *sta);\nint acpi_bus_get_status(struct acpi_device *device);\n\nint acpi_bus_set_power(acpi_handle handle, int state);\nconst char *acpi_power_state_string(int state);\nint acpi_device_set_power(struct acpi_device *device, int state);\nint acpi_bus_init_power(struct acpi_device *device);\nint acpi_device_fix_up_power(struct acpi_device *device);\nint acpi_bus_update_power(acpi_handle handle, int *state_p);\nint acpi_device_update_power(struct acpi_device *device, int *state_p);\nbool acpi_bus_power_manageable(acpi_handle handle);\nint acpi_device_power_add_dependent(struct acpi_device *adev,\n\t\t\t\t    struct device *dev);\nvoid acpi_device_power_remove_dependent(struct acpi_device *adev,\n\t\t\t\t\tstruct device *dev);\n\n#ifdef CONFIG_PM\nbool acpi_bus_can_wakeup(acpi_handle handle);\n#else\nstatic inline bool acpi_bus_can_wakeup(acpi_handle handle) { return false; }\n#endif\n\nvoid acpi_scan_lock_acquire(void);\nvoid acpi_scan_lock_release(void);\nvoid acpi_lock_hp_context(void);\nvoid acpi_unlock_hp_context(void);\nint acpi_scan_add_handler(struct acpi_scan_handler *handler);\nint acpi_bus_register_driver(struct acpi_driver *driver);\nvoid acpi_bus_unregister_driver(struct acpi_driver *driver);\nint acpi_bus_scan(acpi_handle handle);\nvoid acpi_bus_trim(struct acpi_device *start);\nacpi_status acpi_bus_get_ejd(acpi_handle handle, acpi_handle * ejd);\nint acpi_match_device_ids(struct acpi_device *device,\n\t\t\t  const struct acpi_device_id *ids);\nvoid acpi_set_modalias(struct acpi_device *adev, const char *default_id,\n\t\t       char *modalias, size_t len);\nint acpi_create_dir(struct acpi_device *);\nvoid acpi_remove_dir(struct acpi_device *);\n\nstatic inline bool acpi_device_enumerated(struct acpi_device *adev)\n{\n\treturn adev && adev->flags.initialized && adev->flags.visited;\n}\n\n/**\n * module_acpi_driver(acpi_driver) - Helper macro for registering an ACPI driver\n * @__acpi_driver: acpi_driver struct\n *\n * Helper macro for ACPI drivers which do not do anything special in module\n * init/exit. This eliminates a lot of boilerplate. Each module may only\n * use this macro once, and calling it replaces module_init() and module_exit()\n */\n#define module_acpi_driver(__acpi_driver) \\\n\tmodule_driver(__acpi_driver, acpi_bus_register_driver, \\\n\t\t      acpi_bus_unregister_driver)\n\n/*\n * Bind physical devices with ACPI devices\n */\nstruct acpi_bus_type {\n\tstruct list_head list;\n\tconst char *name;\n\tbool (*match)(struct device *dev);\n\tstruct acpi_device * (*find_companion)(struct device *);\n\tvoid (*setup)(struct device *);\n\tvoid (*cleanup)(struct device *);\n};\nint register_acpi_bus_type(struct acpi_bus_type *);\nint unregister_acpi_bus_type(struct acpi_bus_type *);\nint acpi_bind_one(struct device *dev, struct acpi_device *adev);\nint acpi_unbind_one(struct device *dev);\n\nstruct acpi_pci_root {\n\tstruct acpi_device * device;\n\tstruct pci_bus *bus;\n\tu16 segment;\n\tstruct resource secondary;\t/* downstream bus range */\n\n\tu32 osc_support_set;\t/* _OSC state of support bits */\n\tu32 osc_control_set;\t/* _OSC state of control bits */\n\tphys_addr_t mcfg_addr;\n};\n\n/* helper */\n\nbool acpi_dma_supported(struct acpi_device *adev);\nenum dev_dma_attr acpi_get_dma_attr(struct acpi_device *adev);\nint acpi_dma_get_range(struct device *dev, u64 *dma_addr, u64 *offset,\n\t\t       u64 *size);\nint acpi_dma_configure(struct device *dev, enum dev_dma_attr attr);\n\nstruct acpi_device *acpi_find_child_device(struct acpi_device *parent,\n\t\t\t\t\t   u64 address, bool check_children);\nint acpi_is_root_bridge(acpi_handle);\nstruct acpi_pci_root *acpi_pci_find_root(acpi_handle handle);\n\nint acpi_enable_wakeup_device_power(struct acpi_device *dev, int state);\nint acpi_disable_wakeup_device_power(struct acpi_device *dev);\n\n#ifdef CONFIG_X86\nbool acpi_device_always_present(struct acpi_device *adev);\n#else\nstatic inline bool acpi_device_always_present(struct acpi_device *adev)\n{\n\treturn false;\n}\n#endif\n\n#ifdef CONFIG_PM\nvoid acpi_pm_wakeup_event(struct device *dev);\nacpi_status acpi_add_pm_notifier(struct acpi_device *adev, struct device *dev,\n\t\t\tvoid (*func)(struct acpi_device_wakeup_context *context));\nacpi_status acpi_remove_pm_notifier(struct acpi_device *adev);\nbool acpi_pm_device_can_wakeup(struct device *dev);\nint acpi_pm_device_sleep_state(struct device *, int *, int);\nint acpi_pm_set_device_wakeup(struct device *dev, bool enable);\nint acpi_pm_set_bridge_wakeup(struct device *dev, bool enable);\n#else\nstatic inline void acpi_pm_wakeup_event(struct device *dev)\n{\n}\nstatic inline acpi_status acpi_add_pm_notifier(struct acpi_device *adev,\n\t\t\t\t\t       struct device *dev,\n\t\t\t\t\t       void (*func)(struct acpi_device_wakeup_context *context))\n{\n\treturn AE_SUPPORT;\n}\nstatic inline acpi_status acpi_remove_pm_notifier(struct acpi_device *adev)\n{\n\treturn AE_SUPPORT;\n}\nstatic inline bool acpi_pm_device_can_wakeup(struct device *dev)\n{\n\treturn false;\n}\nstatic inline int acpi_pm_device_sleep_state(struct device *d, int *p, int m)\n{\n\tif (p)\n\t\t*p = ACPI_STATE_D0;\n\n\treturn (m >= ACPI_STATE_D0 && m <= ACPI_STATE_D3_COLD) ?\n\t\tm : ACPI_STATE_D0;\n}\nstatic inline int acpi_pm_set_device_wakeup(struct device *dev, bool enable)\n{\n\treturn -ENODEV;\n}\nstatic inline int acpi_pm_set_bridge_wakeup(struct device *dev, bool enable)\n{\n\treturn -ENODEV;\n}\n#endif\n\n#ifdef CONFIG_ACPI_SYSTEM_POWER_STATES_SUPPORT\nbool acpi_sleep_state_supported(u8 sleep_state);\n#else\nstatic inline bool acpi_sleep_state_supported(u8 sleep_state) { return false; }\n#endif\n\n#ifdef CONFIG_ACPI_SLEEP\nu32 acpi_target_system_state(void);\n#else\nstatic inline u32 acpi_target_system_state(void) { return ACPI_STATE_S0; }\n#endif\n\nstatic inline bool acpi_device_power_manageable(struct acpi_device *adev)\n{\n\treturn adev->flags.power_manageable;\n}\n\nstatic inline bool acpi_device_can_wakeup(struct acpi_device *adev)\n{\n\treturn adev->wakeup.flags.valid;\n}\n\nstatic inline bool acpi_device_can_poweroff(struct acpi_device *adev)\n{\n\treturn adev->power.states[ACPI_STATE_D3_COLD].flags.valid ||\n\t\t((acpi_gbl_FADT.header.revision < 6) &&\n\t\tadev->power.states[ACPI_STATE_D3_HOT].flags.explicit_set);\n}\n\nstatic inline void acpi_dev_put(struct acpi_device *adev)\n{\n\tput_device(&adev->dev);\n}\n#else\t/* CONFIG_ACPI */\n\nstatic inline int register_acpi_bus_type(void *bus) { return 0; }\nstatic inline int unregister_acpi_bus_type(void *bus) { return 0; }\n\n#endif\t\t\t\t/* CONFIG_ACPI */\n\n#endif /*__ACPI_BUS_H__*/\n"
  },
  {
    "path": "t/tree/include/acpi/acpi_drivers.h",
    "content": "/* SPDX-License-Identifier: GPL-2.0-or-later */\n/*\n *  acpi_drivers.h  ($Revision: 31 $)\n *\n *  Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com>\n *  Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>\n */\n\n#ifndef __ACPI_DRIVERS_H__\n#define __ACPI_DRIVERS_H__\n\n#define ACPI_MAX_STRING\t\t\t80\n\n/*\n * Please update drivers/acpi/debug.c and Documentation/firmware-guide/acpi/debug.rst\n * if you add to this list.\n */\n#define ACPI_BUS_COMPONENT\t\t0x00010000\n#define ACPI_AC_COMPONENT\t\t0x00020000\n#define ACPI_BATTERY_COMPONENT\t\t0x00040000\n#define ACPI_BUTTON_COMPONENT\t\t0x00080000\n#define ACPI_SBS_COMPONENT\t\t0x00100000\n#define ACPI_FAN_COMPONENT\t\t0x00200000\n#define ACPI_PCI_COMPONENT\t\t0x00400000\n#define ACPI_POWER_COMPONENT\t\t0x00800000\n#define ACPI_CONTAINER_COMPONENT\t0x01000000\n#define ACPI_SYSTEM_COMPONENT\t\t0x02000000\n#define ACPI_THERMAL_COMPONENT\t\t0x04000000\n#define ACPI_MEMORY_DEVICE_COMPONENT\t0x08000000\n#define ACPI_VIDEO_COMPONENT\t\t0x10000000\n#define ACPI_PROCESSOR_COMPONENT\t0x20000000\n\n/*\n * _HID definitions\n * HIDs must conform to ACPI spec(6.1.4)\n * Linux specific HIDs do not apply to this and begin with LNX:\n */\n\n#define ACPI_POWER_HID\t\t\t\"LNXPOWER\"\n#define ACPI_PROCESSOR_OBJECT_HID\t\"LNXCPU\"\n#define ACPI_SYSTEM_HID\t\t\t\"LNXSYSTM\"\n#define ACPI_THERMAL_HID\t\t\"LNXTHERM\"\n#define ACPI_BUTTON_HID_POWERF\t\t\"LNXPWRBN\"\n#define ACPI_BUTTON_HID_SLEEPF\t\t\"LNXSLPBN\"\n#define ACPI_VIDEO_HID\t\t\t\"LNXVIDEO\"\n#define ACPI_BAY_HID\t\t\t\"LNXIOBAY\"\n#define ACPI_DOCK_HID\t\t\t\"LNXDOCK\"\n#define ACPI_ECDT_HID\t\t\t\"LNXEC\"\n/* Quirk for broken IBM BIOSes */\n#define ACPI_SMBUS_IBM_HID\t\t\"SMBUSIBM\"\n\n/*\n * For fixed hardware buttons, we fabricate acpi_devices with HID\n * ACPI_BUTTON_HID_POWERF or ACPI_BUTTON_HID_SLEEPF.  Fixed hardware\n * signals only an event; it doesn't supply a notification value.\n * To allow drivers to treat notifications from fixed hardware the\n * same as those from real devices, we turn the events into this\n * notification value.\n */\n#define ACPI_FIXED_HARDWARE_EVENT\t0x100\n\n/* --------------------------------------------------------------------------\n                                       PCI\n   -------------------------------------------------------------------------- */\n\n\n/* ACPI PCI Interrupt Link (pci_link.c) */\n\nint acpi_irq_penalty_init(void);\nint acpi_pci_link_allocate_irq(acpi_handle handle, int index, int *triggering,\n\t\t\t       int *polarity, char **name);\nint acpi_pci_link_free_irq(acpi_handle handle);\n\n/* ACPI PCI Device Binding (pci_bind.c) */\n\nstruct pci_bus;\n\n#ifdef CONFIG_PCI\nstruct pci_dev *acpi_get_pci_dev(acpi_handle);\n#else\nstatic inline struct pci_dev *acpi_get_pci_dev(acpi_handle handle)\n{\n\treturn NULL;\n}\n#endif\n\n/* Arch-defined function to add a bus to the system */\n\nstruct pci_bus *pci_acpi_scan_root(struct acpi_pci_root *root);\n\n#ifdef CONFIG_X86\nvoid pci_acpi_crs_quirks(void);\n#else\nstatic inline void pci_acpi_crs_quirks(void) { }\n#endif\n\n/* --------------------------------------------------------------------------\n                                    Processor\n   -------------------------------------------------------------------------- */\n\n#define ACPI_PROCESSOR_LIMIT_NONE\t0x00\n#define ACPI_PROCESSOR_LIMIT_INCREMENT\t0x01\n#define ACPI_PROCESSOR_LIMIT_DECREMENT\t0x02\n\n/*--------------------------------------------------------------------------\n                                  Dock Station\n  -------------------------------------------------------------------------- */\n\n#ifdef CONFIG_ACPI_DOCK\nextern int is_dock_device(struct acpi_device *adev);\n#else\nstatic inline int is_dock_device(struct acpi_device *adev)\n{\n\treturn 0;\n}\n#endif /* CONFIG_ACPI_DOCK */\n\n#endif /*__ACPI_DRIVERS_H__*/\n"
  },
  {
    "path": "t/tree/include/asm-generic/barrier.h",
    "content": "/* SPDX-License-Identifier: GPL-2.0-or-later */\n/*\n * Generic barrier definitions.\n *\n * It should be possible to use these on really simple architectures,\n * but it serves more as a starting point for new ports.\n *\n * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.\n * Written by David Howells (dhowells@redhat.com)\n */\n#ifndef __ASM_GENERIC_BARRIER_H\n#define __ASM_GENERIC_BARRIER_H\n\n#ifndef __ASSEMBLY__\n\n#include <linux/compiler.h>\n\n#ifndef nop\n#define nop()\tasm volatile (\"nop\")\n#endif\n\n/*\n * Force strict CPU ordering. And yes, this is required on UP too when we're\n * talking to devices.\n *\n * Fall back to compiler barriers if nothing better is provided.\n */\n\n#ifndef mb\n#define mb()\tbarrier()\n#endif\n\n#ifndef rmb\n#define rmb()\tmb()\n#endif\n\n#ifndef wmb\n#define wmb()\tmb()\n#endif\n\n#ifndef dma_rmb\n#define dma_rmb()\trmb()\n#endif\n\n#ifndef dma_wmb\n#define dma_wmb()\twmb()\n#endif\n\n#ifndef read_barrier_depends\n#define read_barrier_depends()\t\tdo { } while (0)\n#endif\n\n#ifndef __smp_mb\n#define __smp_mb()\tmb()\n#endif\n\n#ifndef __smp_rmb\n#define __smp_rmb()\trmb()\n#endif\n\n#ifndef __smp_wmb\n#define __smp_wmb()\twmb()\n#endif\n\n#ifndef __smp_read_barrier_depends\n#define __smp_read_barrier_depends()\tread_barrier_depends()\n#endif\n\n#ifdef CONFIG_SMP\n\n#ifndef smp_mb\n#define smp_mb()\t__smp_mb()\n#endif\n\n#ifndef smp_rmb\n#define smp_rmb()\t__smp_rmb()\n#endif\n\n#ifndef smp_wmb\n#define smp_wmb()\t__smp_wmb()\n#endif\n\n#ifndef smp_read_barrier_depends\n#define smp_read_barrier_depends()\t__smp_read_barrier_depends()\n#endif\n\n#else\t/* !CONFIG_SMP */\n\n#ifndef smp_mb\n#define smp_mb()\tbarrier()\n#endif\n\n#ifndef smp_rmb\n#define smp_rmb()\tbarrier()\n#endif\n\n#ifndef smp_wmb\n#define smp_wmb()\tbarrier()\n#endif\n\n#ifndef smp_read_barrier_depends\n#define smp_read_barrier_depends()\tdo { } while (0)\n#endif\n\n#endif\t/* CONFIG_SMP */\n\n#ifndef __smp_store_mb\n#define __smp_store_mb(var, value)  do { WRITE_ONCE(var, value); __smp_mb(); } while (0)\n#endif\n\n#ifndef __smp_mb__before_atomic\n#define __smp_mb__before_atomic()\t__smp_mb()\n#endif\n\n#ifndef __smp_mb__after_atomic\n#define __smp_mb__after_atomic()\t__smp_mb()\n#endif\n\n#ifndef __smp_store_release\n#define __smp_store_release(p, v)\t\t\t\t\t\\\ndo {\t\t\t\t\t\t\t\t\t\\\n\tcompiletime_assert_atomic_type(*p);\t\t\t\t\\\n\t__smp_mb();\t\t\t\t\t\t\t\\\n\tWRITE_ONCE(*p, v);\t\t\t\t\t\t\\\n} while (0)\n#endif\n\n#ifndef __smp_load_acquire\n#define __smp_load_acquire(p)\t\t\t\t\t\t\\\n({\t\t\t\t\t\t\t\t\t\\\n\ttypeof(*p) ___p1 = READ_ONCE(*p);\t\t\t\t\\\n\tcompiletime_assert_atomic_type(*p);\t\t\t\t\\\n\t__smp_mb();\t\t\t\t\t\t\t\\\n\t___p1;\t\t\t\t\t\t\t\t\\\n})\n#endif\n\n#ifdef CONFIG_SMP\n\n#ifndef smp_store_mb\n#define smp_store_mb(var, value)  __smp_store_mb(var, value)\n#endif\n\n#ifndef smp_mb__before_atomic\n#define smp_mb__before_atomic()\t__smp_mb__before_atomic()\n#endif\n\n#ifndef smp_mb__after_atomic\n#define smp_mb__after_atomic()\t__smp_mb__after_atomic()\n#endif\n\n#ifndef smp_store_release\n#define smp_store_release(p, v) __smp_store_release(p, v)\n#endif\n\n#ifndef smp_load_acquire\n#define smp_load_acquire(p) __smp_load_acquire(p)\n#endif\n\n#else\t/* !CONFIG_SMP */\n\n#ifndef smp_store_mb\n#define smp_store_mb(var, value)  do { WRITE_ONCE(var, value); barrier(); } while (0)\n#endif\n\n#ifndef smp_mb__before_atomic\n#define smp_mb__before_atomic()\tbarrier()\n#endif\n\n#ifndef smp_mb__after_atomic\n#define smp_mb__after_atomic()\tbarrier()\n#endif\n\n#ifndef smp_store_release\n#define smp_store_release(p, v)\t\t\t\t\t\t\\\ndo {\t\t\t\t\t\t\t\t\t\\\n\tcompiletime_assert_atomic_type(*p);\t\t\t\t\\\n\tbarrier();\t\t\t\t\t\t\t\\\n\tWRITE_ONCE(*p, v);\t\t\t\t\t\t\\\n} while (0)\n#endif\n\n#ifndef smp_load_acquire\n#define smp_load_acquire(p)\t\t\t\t\t\t\\\n({\t\t\t\t\t\t\t\t\t\\\n\ttypeof(*p) ___p1 = READ_ONCE(*p);\t\t\t\t\\\n\tcompiletime_assert_atomic_type(*p);\t\t\t\t\\\n\tbarrier();\t\t\t\t\t\t\t\\\n\t___p1;\t\t\t\t\t\t\t\t\\\n})\n#endif\n\n#endif\t/* CONFIG_SMP */\n\n/* Barriers for virtual machine guests when talking to an SMP host */\n#define virt_mb() __smp_mb()\n#define virt_rmb() __smp_rmb()\n#define virt_wmb() __smp_wmb()\n#define virt_read_barrier_depends() __smp_read_barrier_depends()\n#define virt_store_mb(var, value) __smp_store_mb(var, value)\n#define virt_mb__before_atomic() __smp_mb__before_atomic()\n#define virt_mb__after_atomic()\t__smp_mb__after_atomic()\n#define virt_store_release(p, v) __smp_store_release(p, v)\n#define virt_load_acquire(p) __smp_load_acquire(p)\n\n/**\n * smp_acquire__after_ctrl_dep() - Provide ACQUIRE ordering after a control dependency\n *\n * A control dependency provides a LOAD->STORE order, the additional RMB\n * provides LOAD->LOAD order, together they provide LOAD->{LOAD,STORE} order,\n * aka. (load)-ACQUIRE.\n *\n * Architectures that do not do load speculation can have this be barrier().\n */\n#ifndef smp_acquire__after_ctrl_dep\n#define smp_acquire__after_ctrl_dep()\t\tsmp_rmb()\n#endif\n\n/**\n * smp_cond_load_relaxed() - (Spin) wait for cond with no ordering guarantees\n * @ptr: pointer to the variable to wait on\n * @cond: boolean expression to wait for\n *\n * Equivalent to using READ_ONCE() on the condition variable.\n *\n * Due to C lacking lambda expressions we load the value of *ptr into a\n * pre-named variable @VAL to be used in @cond.\n */\n#ifndef smp_cond_load_relaxed\n#define smp_cond_load_relaxed(ptr, cond_expr) ({\t\t\\\n\ttypeof(ptr) __PTR = (ptr);\t\t\t\t\\\n\ttypeof(*ptr) VAL;\t\t\t\t\t\\\n\tfor (;;) {\t\t\t\t\t\t\\\n\t\tVAL = READ_ONCE(*__PTR);\t\t\t\\\n\t\tif (cond_expr)\t\t\t\t\t\\\n\t\t\tbreak;\t\t\t\t\t\\\n\t\tcpu_relax();\t\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\\\n\tVAL;\t\t\t\t\t\t\t\\\n})\n#endif\n\n/**\n * smp_cond_load_acquire() - (Spin) wait for cond with ACQUIRE ordering\n * @ptr: pointer to the variable to wait on\n * @cond: boolean expression to wait for\n *\n * Equivalent to using smp_load_acquire() on the condition variable but employs\n * the control dependency of the wait to reduce the barrier on many platforms.\n */\n#ifndef smp_cond_load_acquire\n#define smp_cond_load_acquire(ptr, cond_expr) ({\t\t\\\n\ttypeof(*ptr) _val;\t\t\t\t\t\\\n\t_val = smp_cond_load_relaxed(ptr, cond_expr);\t\t\\\n\tsmp_acquire__after_ctrl_dep();\t\t\t\t\\\n\t_val;\t\t\t\t\t\t\t\\\n})\n#endif\n\n#endif /* !__ASSEMBLY__ */\n#endif /* __ASM_GENERIC_BARRIER_H */\n"
  },
  {
    "path": "t/tree/include/asm-generic/io.h",
    "content": "/* SPDX-License-Identifier: GPL-2.0-or-later */\n/* Generic I/O port emulation.\n *\n * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.\n * Written by David Howells (dhowells@redhat.com)\n */\n#ifndef __ASM_GENERIC_IO_H\n#define __ASM_GENERIC_IO_H\n\n#include <asm/page.h> /* I/O is all done through memory accesses */\n#include <linux/string.h> /* for memset() and memcpy() */\n#include <linux/types.h>\n\n#ifdef CONFIG_GENERIC_IOMAP\n#include <asm-generic/iomap.h>\n#endif\n\n#include <asm/mmiowb.h>\n#include <asm-generic/pci_iomap.h>\n\n#ifndef __io_br\n#define __io_br()      barrier()\n#endif\n\n/* prevent prefetching of coherent DMA data ahead of a dma-complete */\n#ifndef __io_ar\n#ifdef rmb\n#define __io_ar(v)      rmb()\n#else\n#define __io_ar(v)      barrier()\n#endif\n#endif\n\n/* flush writes to coherent DMA data before possibly triggering a DMA read */\n#ifndef __io_bw\n#ifdef wmb\n#define __io_bw()      wmb()\n#else\n#define __io_bw()      barrier()\n#endif\n#endif\n\n/* serialize device access against a spin_unlock, usually handled there. */\n#ifndef __io_aw\n#define __io_aw()      mmiowb_set_pending()\n#endif\n\n#ifndef __io_pbw\n#define __io_pbw()     __io_bw()\n#endif\n\n#ifndef __io_paw\n#define __io_paw()     __io_aw()\n#endif\n\n#ifndef __io_pbr\n#define __io_pbr()     __io_br()\n#endif\n\n#ifndef __io_par\n#define __io_par(v)     __io_ar(v)\n#endif\n\n\n/*\n * __raw_{read,write}{b,w,l,q}() access memory in native endianness.\n *\n * On some architectures memory mapped IO needs to be accessed differently.\n * On the simple architectures, we just read/write the memory location\n * directly.\n */\n\n#ifndef __raw_readb\n#define __raw_readb __raw_readb\nstatic inline u8 __raw_readb(const volatile void __iomem *addr)\n{\n\treturn *(const volatile u8 __force *)addr;\n}\n#endif\n\n#ifndef __raw_readw\n#define __raw_readw __raw_readw\nstatic inline u16 __raw_readw(const volatile void __iomem *addr)\n{\n\treturn *(const volatile u16 __force *)addr;\n}\n#endif\n\n#ifndef __raw_readl\n#define __raw_readl __raw_readl\nstatic inline u32 __raw_readl(const volatile void __iomem *addr)\n{\n\treturn *(const volatile u32 __force *)addr;\n}\n#endif\n\n#ifdef CONFIG_64BIT\n#ifndef __raw_readq\n#define __raw_readq __raw_readq\nstatic inline u64 __raw_readq(const volatile void __iomem *addr)\n{\n\treturn *(const volatile u64 __force *)addr;\n}\n#endif\n#endif /* CONFIG_64BIT */\n\n#ifndef __raw_writeb\n#define __raw_writeb __raw_writeb\nstatic inline void __raw_writeb(u8 value, volatile void __iomem *addr)\n{\n\t*(volatile u8 __force *)addr = value;\n}\n#endif\n\n#ifndef __raw_writew\n#define __raw_writew __raw_writew\nstatic inline void __raw_writew(u16 value, volatile void __iomem *addr)\n{\n\t*(volatile u16 __force *)addr = value;\n}\n#endif\n\n#ifndef __raw_writel\n#define __raw_writel __raw_writel\nstatic inline void __raw_writel(u32 value, volatile void __iomem *addr)\n{\n\t*(volatile u32 __force *)addr = value;\n}\n#endif\n\n#ifdef CONFIG_64BIT\n#ifndef __raw_writeq\n#define __raw_writeq __raw_writeq\nstatic inline void __raw_writeq(u64 value, volatile void __iomem *addr)\n{\n\t*(volatile u64 __force *)addr = value;\n}\n#endif\n#endif /* CONFIG_64BIT */\n\n/*\n * {read,write}{b,w,l,q}() access little endian memory and return result in\n * native endianness.\n */\n\n#ifndef readb\n#define readb readb\nstatic inline u8 readb(const volatile void __iomem *addr)\n{\n\tu8 val;\n\n\t__io_br();\n\tval = __raw_readb(addr);\n\t__io_ar(val);\n\treturn val;\n}\n#endif\n\n#ifndef readw\n#define readw readw\nstatic inline u16 readw(const volatile void __iomem *addr)\n{\n\tu16 val;\n\n\t__io_br();\n\tval = __le16_to_cpu(__raw_readw(addr));\n\t__io_ar(val);\n\treturn val;\n}\n#endif\n\n#ifndef readl\n#define readl readl\nstatic inline u32 readl(const volatile void __iomem *addr)\n{\n\tu32 val;\n\n\t__io_br();\n\tval = __le32_to_cpu(__raw_readl(addr));\n\t__io_ar(val);\n\treturn val;\n}\n#endif\n\n#ifdef CONFIG_64BIT\n#ifndef readq\n#define readq readq\nstatic inline u64 readq(const volatile void __iomem *addr)\n{\n\tu64 val;\n\n\t__io_br();\n\tval = __le64_to_cpu(__raw_readq(addr));\n\t__io_ar(val);\n\treturn val;\n}\n#endif\n#endif /* CONFIG_64BIT */\n\n#ifndef writeb\n#define writeb writeb\nstatic inline void writeb(u8 value, volatile void __iomem *addr)\n{\n\t__io_bw();\n\t__raw_writeb(value, addr);\n\t__io_aw();\n}\n#endif\n\n#ifndef writew\n#define writew writew\nstatic inline void writew(u16 value, volatile void __iomem *addr)\n{\n\t__io_bw();\n\t__raw_writew(cpu_to_le16(value), addr);\n\t__io_aw();\n}\n#endif\n\n#ifndef writel\n#define writel writel\nstatic inline void writel(u32 value, volatile void __iomem *addr)\n{\n\t__io_bw();\n\t__raw_writel(__cpu_to_le32(value), addr);\n\t__io_aw();\n}\n#endif\n\n#ifdef CONFIG_64BIT\n#ifndef writeq\n#define writeq writeq\nstatic inline void writeq(u64 value, volatile void __iomem *addr)\n{\n\t__io_bw();\n\t__raw_writeq(__cpu_to_le64(value), addr);\n\t__io_aw();\n}\n#endif\n#endif /* CONFIG_64BIT */\n\n/*\n * {read,write}{b,w,l,q}_relaxed() are like the regular version, but\n * are not guaranteed to provide ordering against spinlocks or memory\n * accesses.\n */\n#ifndef readb_relaxed\n#define readb_relaxed readb_relaxed\nstatic inline u8 readb_relaxed(const volatile void __iomem *addr)\n{\n\treturn __raw_readb(addr);\n}\n#endif\n\n#ifndef readw_relaxed\n#define readw_relaxed readw_relaxed\nstatic inline u16 readw_relaxed(const volatile void __iomem *addr)\n{\n\treturn __le16_to_cpu(__raw_readw(addr));\n}\n#endif\n\n#ifndef readl_relaxed\n#define readl_relaxed readl_relaxed\nstatic inline u32 readl_relaxed(const volatile void __iomem *addr)\n{\n\treturn __le32_to_cpu(__raw_readl(addr));\n}\n#endif\n\n#if defined(readq) && !defined(readq_relaxed)\n#define readq_relaxed readq_relaxed\nstatic inline u64 readq_relaxed(const volatile void __iomem *addr)\n{\n\treturn __le64_to_cpu(__raw_readq(addr));\n}\n#endif\n\n#ifndef writeb_relaxed\n#define writeb_relaxed writeb_relaxed\nstatic inline void writeb_relaxed(u8 value, volatile void __iomem *addr)\n{\n\t__raw_writeb(value, addr);\n}\n#endif\n\n#ifndef writew_relaxed\n#define writew_relaxed writew_relaxed\nstatic inline void writew_relaxed(u16 value, volatile void __iomem *addr)\n{\n\t__raw_writew(cpu_to_le16(value), addr);\n}\n#endif\n\n#ifndef writel_relaxed\n#define writel_relaxed writel_relaxed\nstatic inline void writel_relaxed(u32 value, volatile void __iomem *addr)\n{\n\t__raw_writel(__cpu_to_le32(value), addr);\n}\n#endif\n\n#if defined(writeq) && !defined(writeq_relaxed)\n#define writeq_relaxed writeq_relaxed\nstatic inline void writeq_relaxed(u64 value, volatile void __iomem *addr)\n{\n\t__raw_writeq(__cpu_to_le64(value), addr);\n}\n#endif\n\n/*\n * {read,write}s{b,w,l,q}() repeatedly access the same memory address in\n * native endianness in 8-, 16-, 32- or 64-bit chunks (@count times).\n */\n#ifndef readsb\n#define readsb readsb\nstatic inline void readsb(const volatile void __iomem *addr, void *buffer,\n\t\t\t  unsigned int count)\n{\n\tif (count) {\n\t\tu8 *buf = buffer;\n\n\t\tdo {\n\t\t\tu8 x = __raw_readb(addr);\n\t\t\t*buf++ = x;\n\t\t} while (--count);\n\t}\n}\n#endif\n\n#ifndef readsw\n#define readsw readsw\nstatic inline void readsw(const volatile void __iomem *addr, void *buffer,\n\t\t\t  unsigned int count)\n{\n\tif (count) {\n\t\tu16 *buf = buffer;\n\n\t\tdo {\n\t\t\tu16 x = __raw_readw(addr);\n\t\t\t*buf++ = x;\n\t\t} while (--count);\n\t}\n}\n#endif\n\n#ifndef readsl\n#define readsl readsl\nstatic inline void readsl(const volatile void __iomem *addr, void *buffer,\n\t\t\t  unsigned int count)\n{\n\tif (count) {\n\t\tu32 *buf = buffer;\n\n\t\tdo {\n\t\t\tu32 x = __raw_readl(addr);\n\t\t\t*buf++ = x;\n\t\t} while (--count);\n\t}\n}\n#endif\n\n#ifdef CONFIG_64BIT\n#ifndef readsq\n#define readsq readsq\nstatic inline void readsq(const volatile void __iomem *addr, void *buffer,\n\t\t\t  unsigned int count)\n{\n\tif (count) {\n\t\tu64 *buf = buffer;\n\n\t\tdo {\n\t\t\tu64 x = __raw_readq(addr);\n\t\t\t*buf++ = x;\n\t\t} while (--count);\n\t}\n}\n#endif\n#endif /* CONFIG_64BIT */\n\n#ifndef writesb\n#define writesb writesb\nstatic inline void writesb(volatile void __iomem *addr, const void *buffer,\n\t\t\t   unsigned int count)\n{\n\tif (count) {\n\t\tconst u8 *buf = buffer;\n\n\t\tdo {\n\t\t\t__raw_writeb(*buf++, addr);\n\t\t} while (--count);\n\t}\n}\n#endif\n\n#ifndef writesw\n#define writesw writesw\nstatic inline void writesw(volatile void __iomem *addr, const void *buffer,\n\t\t\t   unsigned int count)\n{\n\tif (count) {\n\t\tconst u16 *buf = buffer;\n\n\t\tdo {\n\t\t\t__raw_writew(*buf++, addr);\n\t\t} while (--count);\n\t}\n}\n#endif\n\n#ifndef writesl\n#define writesl writesl\nstatic inline void writesl(volatile void __iomem *addr, const void *buffer,\n\t\t\t   unsigned int count)\n{\n\tif (count) {\n\t\tconst u32 *buf = buffer;\n\n\t\tdo {\n\t\t\t__raw_writel(*buf++, addr);\n\t\t} while (--count);\n\t}\n}\n#endif\n\n#ifdef CONFIG_64BIT\n#ifndef writesq\n#define writesq writesq\nstatic inline void writesq(volatile void __iomem *addr, const void *buffer,\n\t\t\t   unsigned int count)\n{\n\tif (count) {\n\t\tconst u64 *buf = buffer;\n\n\t\tdo {\n\t\t\t__raw_writeq(*buf++, addr);\n\t\t} while (--count);\n\t}\n}\n#endif\n#endif /* CONFIG_64BIT */\n\n#ifndef PCI_IOBASE\n#define PCI_IOBASE ((void __iomem *)0)\n#endif\n\n#ifndef IO_SPACE_LIMIT\n#define IO_SPACE_LIMIT 0xffff\n#endif\n\n#include <linux/logic_pio.h>\n\n/*\n * {in,out}{b,w,l}() access little endian I/O. {in,out}{b,w,l}_p() can be\n * implemented on hardware that needs an additional delay for I/O accesses to\n * take effect.\n */\n\n#ifndef inb\n#define inb inb\nstatic inline u8 inb(unsigned long addr)\n{\n\tu8 val;\n\n\t__io_pbr();\n\tval = __raw_readb(PCI_IOBASE + addr);\n\t__io_par(val);\n\treturn val;\n}\n#endif\n\n#ifndef inw\n#define inw inw\nstatic inline u16 inw(unsigned long addr)\n{\n\tu16 val;\n\n\t__io_pbr();\n\tval = __le16_to_cpu(__raw_readw(PCI_IOBASE + addr));\n\t__io_par(val);\n\treturn val;\n}\n#endif\n\n#ifndef inl\n#define inl inl\nstatic inline u32 inl(unsigned long addr)\n{\n\tu32 val;\n\n\t__io_pbr();\n\tval = __le32_to_cpu(__raw_readl(PCI_IOBASE + addr));\n\t__io_par(val);\n\treturn val;\n}\n#endif\n\n#ifndef outb\n#define outb outb\nstatic inline void outb(u8 value, unsigned long addr)\n{\n\t__io_pbw();\n\t__raw_writeb(value, PCI_IOBASE + addr);\n\t__io_paw();\n}\n#endif\n\n#ifndef outw\n#define outw outw\nstatic inline void outw(u16 value, unsigned long addr)\n{\n\t__io_pbw();\n\t__raw_writew(cpu_to_le16(value), PCI_IOBASE + addr);\n\t__io_paw();\n}\n#endif\n\n#ifndef outl\n#define outl outl\nstatic inline void outl(u32 value, unsigned long addr)\n{\n\t__io_pbw();\n\t__raw_writel(cpu_to_le32(value), PCI_IOBASE + addr);\n\t__io_paw();\n}\n#endif\n\n#ifndef inb_p\n#define inb_p inb_p\nstatic inline u8 inb_p(unsigned long addr)\n{\n\treturn inb(addr);\n}\n#endif\n\n#ifndef inw_p\n#define inw_p inw_p\nstatic inline u16 inw_p(unsigned long addr)\n{\n\treturn inw(addr);\n}\n#endif\n\n#ifndef inl_p\n#define inl_p inl_p\nstatic inline u32 inl_p(unsigned long addr)\n{\n\treturn inl(addr);\n}\n#endif\n\n#ifndef outb_p\n#define outb_p outb_p\nstatic inline void outb_p(u8 value, unsigned long addr)\n{\n\toutb(value, addr);\n}\n#endif\n\n#ifndef outw_p\n#define outw_p outw_p\nstatic inline void outw_p(u16 value, unsigned long addr)\n{\n\toutw(value, addr);\n}\n#endif\n\n#ifndef outl_p\n#define outl_p outl_p\nstatic inline void outl_p(u32 value, unsigned long addr)\n{\n\toutl(value, addr);\n}\n#endif\n\n/*\n * {in,out}s{b,w,l}{,_p}() are variants of the above that repeatedly access a\n * single I/O port multiple times.\n */\n\n#ifndef insb\n#define insb insb\nstatic inline void insb(unsigned long addr, void *buffer, unsigned int count)\n{\n\treadsb(PCI_IOBASE + addr, buffer, count);\n}\n#endif\n\n#ifndef insw\n#define insw insw\nstatic inline void insw(unsigned long addr, void *buffer, unsigned int count)\n{\n\treadsw(PCI_IOBASE + addr, buffer, count);\n}\n#endif\n\n#ifndef insl\n#define insl insl\nstatic inline void insl(unsigned long addr, void *buffer, unsigned int count)\n{\n\treadsl(PCI_IOBASE + addr, buffer, count);\n}\n#endif\n\n#ifndef outsb\n#define outsb outsb\nstatic inline void outsb(unsigned long addr, const void *buffer,\n\t\t\t unsigned int count)\n{\n\twritesb(PCI_IOBASE + addr, buffer, count);\n}\n#endif\n\n#ifndef outsw\n#define outsw outsw\nstatic inline void outsw(unsigned long addr, const void *buffer,\n\t\t\t unsigned int count)\n{\n\twritesw(PCI_IOBASE + addr, buffer, count);\n}\n#endif\n\n#ifndef outsl\n#define outsl outsl\nstatic inline void outsl(unsigned long addr, const void *buffer,\n\t\t\t unsigned int count)\n{\n\twritesl(PCI_IOBASE + addr, buffer, count);\n}\n#endif\n\n#ifndef insb_p\n#define insb_p insb_p\nstatic inline void insb_p(unsigned long addr, void *buffer, unsigned int count)\n{\n\tinsb(addr, buffer, count);\n}\n#endif\n\n#ifndef insw_p\n#define insw_p insw_p\nstatic inline void insw_p(unsigned long addr, void *buffer, unsigned int count)\n{\n\tinsw(addr, buffer, count);\n}\n#endif\n\n#ifndef insl_p\n#define insl_p insl_p\nstatic inline void insl_p(unsigned long addr, void *buffer, unsigned int count)\n{\n\tinsl(addr, buffer, count);\n}\n#endif\n\n#ifndef outsb_p\n#define outsb_p outsb_p\nstatic inline void outsb_p(unsigned long addr, const void *buffer,\n\t\t\t   unsigned int count)\n{\n\toutsb(addr, buffer, count);\n}\n#endif\n\n#ifndef outsw_p\n#define outsw_p outsw_p\nstatic inline void outsw_p(unsigned long addr, const void *buffer,\n\t\t\t   unsigned int count)\n{\n\toutsw(addr, buffer, count);\n}\n#endif\n\n#ifndef outsl_p\n#define outsl_p outsl_p\nstatic inline void outsl_p(unsigned long addr, const void *buffer,\n\t\t\t   unsigned int count)\n{\n\toutsl(addr, buffer, count);\n}\n#endif\n\n#ifndef CONFIG_GENERIC_IOMAP\n#ifndef ioread8\n#define ioread8 ioread8\nstatic inline u8 ioread8(const volatile void __iomem *addr)\n{\n\treturn readb(addr);\n}\n#endif\n\n#ifndef ioread16\n#define ioread16 ioread16\nstatic inline u16 ioread16(const volatile void __iomem *addr)\n{\n\treturn readw(addr);\n}\n#endif\n\n#ifndef ioread32\n#define ioread32 ioread32\nstatic inline u32 ioread32(const volatile void __iomem *addr)\n{\n\treturn readl(addr);\n}\n#endif\n\n#ifdef CONFIG_64BIT\n#ifndef ioread64\n#define ioread64 ioread64\nstatic inline u64 ioread64(const volatile void __iomem *addr)\n{\n\treturn readq(addr);\n}\n#endif\n#endif /* CONFIG_64BIT */\n\n#ifndef iowrite8\n#define iowrite8 iowrite8\nstatic inline void iowrite8(u8 value, volatile void __iomem *addr)\n{\n\twriteb(value, addr);\n}\n#endif\n\n#ifndef iowrite16\n#define iowrite16 iowrite16\nstatic inline void iowrite16(u16 value, volatile void __iomem *addr)\n{\n\twritew(value, addr);\n}\n#endif\n\n#ifndef iowrite32\n#define iowrite32 iowrite32\nstatic inline void iowrite32(u32 value, volatile void __iomem *addr)\n{\n\twritel(value, addr);\n}\n#endif\n\n#ifdef CONFIG_64BIT\n#ifndef iowrite64\n#define iowrite64 iowrite64\nstatic inline void iowrite64(u64 value, volatile void __iomem *addr)\n{\n\twriteq(value, addr);\n}\n#endif\n#endif /* CONFIG_64BIT */\n\n#ifndef ioread16be\n#define ioread16be ioread16be\nstatic inline u16 ioread16be(const volatile void __iomem *addr)\n{\n\treturn swab16(readw(addr));\n}\n#endif\n\n#ifndef ioread32be\n#define ioread32be ioread32be\nstatic inline u32 ioread32be(const volatile void __iomem *addr)\n{\n\treturn swab32(readl(addr));\n}\n#endif\n\n#ifdef CONFIG_64BIT\n#ifndef ioread64be\n#define ioread64be ioread64be\nstatic inline u64 ioread64be(const volatile void __iomem *addr)\n{\n\treturn swab64(readq(addr));\n}\n#endif\n#endif /* CONFIG_64BIT */\n\n#ifndef iowrite16be\n#define iowrite16be iowrite16be\nstatic inline void iowrite16be(u16 value, void volatile __iomem *addr)\n{\n\twritew(swab16(value), addr);\n}\n#endif\n\n#ifndef iowrite32be\n#define iowrite32be iowrite32be\nstatic inline void iowrite32be(u32 value, volatile void __iomem *addr)\n{\n\twritel(swab32(value), addr);\n}\n#endif\n\n#ifdef CONFIG_64BIT\n#ifndef iowrite64be\n#define iowrite64be iowrite64be\nstatic inline void iowrite64be(u64 value, volatile void __iomem *addr)\n{\n\twriteq(swab64(value), addr);\n}\n#endif\n#endif /* CONFIG_64BIT */\n\n#ifndef ioread8_rep\n#define ioread8_rep ioread8_rep\nstatic inline void ioread8_rep(const volatile void __iomem *addr, void *buffer,\n\t\t\t       unsigned int count)\n{\n\treadsb(addr, buffer, count);\n}\n#endif\n\n#ifndef ioread16_rep\n#define ioread16_rep ioread16_rep\nstatic inline void ioread16_rep(const volatile void __iomem *addr,\n\t\t\t\tvoid *buffer, unsigned int count)\n{\n\treadsw(addr, buffer, count);\n}\n#endif\n\n#ifndef ioread32_rep\n#define ioread32_rep ioread32_rep\nstatic inline void ioread32_rep(const volatile void __iomem *addr,\n\t\t\t\tvoid *buffer, unsigned int count)\n{\n\treadsl(addr, buffer, count);\n}\n#endif\n\n#ifdef CONFIG_64BIT\n#ifndef ioread64_rep\n#define ioread64_rep ioread64_rep\nstatic inline void ioread64_rep(const volatile void __iomem *addr,\n\t\t\t\tvoid *buffer, unsigned int count)\n{\n\treadsq(addr, buffer, count);\n}\n#endif\n#endif /* CONFIG_64BIT */\n\n#ifndef iowrite8_rep\n#define iowrite8_rep iowrite8_rep\nstatic inline void iowrite8_rep(volatile void __iomem *addr,\n\t\t\t\tconst void *buffer,\n\t\t\t\tunsigned int count)\n{\n\twritesb(addr, buffer, count);\n}\n#endif\n\n#ifndef iowrite16_rep\n#define iowrite16_rep iowrite16_rep\nstatic inline void iowrite16_rep(volatile void __iomem *addr,\n\t\t\t\t const void *buffer,\n\t\t\t\t unsigned int count)\n{\n\twritesw(addr, buffer, count);\n}\n#endif\n\n#ifndef iowrite32_rep\n#define iowrite32_rep iowrite32_rep\nstatic inline void iowrite32_rep(volatile void __iomem *addr,\n\t\t\t\t const void *buffer,\n\t\t\t\t unsigned int count)\n{\n\twritesl(addr, buffer, count);\n}\n#endif\n\n#ifdef CONFIG_64BIT\n#ifndef iowrite64_rep\n#define iowrite64_rep iowrite64_rep\nstatic inline void iowrite64_rep(volatile void __iomem *addr,\n\t\t\t\t const void *buffer,\n\t\t\t\t unsigned int count)\n{\n\twritesq(addr, buffer, count);\n}\n#endif\n#endif /* CONFIG_64BIT */\n#endif /* CONFIG_GENERIC_IOMAP */\n\n#ifdef __KERNEL__\n\n#include <linux/vmalloc.h>\n#define __io_virt(x) ((void __force *)(x))\n\n#ifndef CONFIG_GENERIC_IOMAP\nstruct pci_dev;\nextern void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long max);\n\n#ifndef pci_iounmap\n#define pci_iounmap pci_iounmap\nstatic inline void pci_iounmap(struct pci_dev *dev, void __iomem *p)\n{\n}\n#endif\n#endif /* CONFIG_GENERIC_IOMAP */\n\n/*\n * Change virtual addresses to physical addresses and vv.\n * These are pretty trivial\n */\n#ifndef virt_to_phys\n#define virt_to_phys virt_to_phys\nstatic inline unsigned long virt_to_phys(volatile void *address)\n{\n\treturn __pa((unsigned long)address);\n}\n#endif\n\n#ifndef phys_to_virt\n#define phys_to_virt phys_to_virt\nstatic inline void *phys_to_virt(unsigned long address)\n{\n\treturn __va(address);\n}\n#endif\n\n/**\n * DOC: ioremap() and ioremap_*() variants\n *\n * If you have an IOMMU your architecture is expected to have both ioremap()\n * and iounmap() implemented otherwise the asm-generic helpers will provide a\n * direct mapping.\n *\n * There are ioremap_*() call variants, if you have no IOMMU we naturally will\n * default to direct mapping for all of them, you can override these defaults.\n * If you have an IOMMU you are highly encouraged to provide your own\n * ioremap variant implementation as there currently is no safe architecture\n * agnostic default. To avoid possible improper behaviour default asm-generic\n * ioremap_*() variants all return NULL when an IOMMU is available. If you've\n * defined your own ioremap_*() variant you must then declare your own\n * ioremap_*() variant as defined to itself to avoid the default NULL return.\n */\n\n#ifdef CONFIG_MMU\n\n#ifndef ioremap_uc\n#define ioremap_uc ioremap_uc\nstatic inline void __iomem *ioremap_uc(phys_addr_t offset, size_t size)\n{\n\treturn NULL;\n}\n#endif\n\n#else /* !CONFIG_MMU */\n\n/*\n * Change \"struct page\" to physical address.\n *\n * This implementation is for the no-MMU case only... if you have an MMU\n * you'll need to provide your own definitions.\n */\n\n#ifndef ioremap\n#define ioremap ioremap\nstatic inline void __iomem *ioremap(phys_addr_t offset, size_t size)\n{\n\treturn (void __iomem *)(unsigned long)offset;\n}\n#endif\n\n#ifndef iounmap\n#define iounmap iounmap\n\nstatic inline void iounmap(void __iomem *addr)\n{\n}\n#endif\n#endif /* CONFIG_MMU */\n#ifndef ioremap_nocache\nvoid __iomem *ioremap(phys_addr_t phys_addr, size_t size);\n#define ioremap_nocache ioremap_nocache\nstatic inline void __iomem *ioremap_nocache(phys_addr_t offset, size_t size)\n{\n\treturn ioremap(offset, size);\n}\n#endif\n\n#ifndef ioremap_uc\n#define ioremap_uc ioremap_uc\nstatic inline void __iomem *ioremap_uc(phys_addr_t offset, size_t size)\n{\n\treturn ioremap_nocache(offset, size);\n}\n#endif\n\n#ifndef ioremap_wc\n#define ioremap_wc ioremap_wc\nstatic inline void __iomem *ioremap_wc(phys_addr_t offset, size_t size)\n{\n\treturn ioremap_nocache(offset, size);\n}\n#endif\n\n#ifndef ioremap_wt\n#define ioremap_wt ioremap_wt\nstatic inline void __iomem *ioremap_wt(phys_addr_t offset, size_t size)\n{\n\treturn ioremap_nocache(offset, size);\n}\n#endif\n\n#ifdef CONFIG_HAS_IOPORT_MAP\n#ifndef CONFIG_GENERIC_IOMAP\n#ifndef ioport_map\n#define ioport_map ioport_map\nstatic inline void __iomem *ioport_map(unsigned long port, unsigned int nr)\n{\n\tport &= IO_SPACE_LIMIT;\n\treturn (port > MMIO_UPPER_LIMIT) ? NULL : PCI_IOBASE + port;\n}\n#endif\n\n#ifndef ioport_unmap\n#define ioport_unmap ioport_unmap\nstatic inline void ioport_unmap(void __iomem *p)\n{\n}\n#endif\n#else /* CONFIG_GENERIC_IOMAP */\nextern void __iomem *ioport_map(unsigned long port, unsigned int nr);\nextern void ioport_unmap(void __iomem *p);\n#endif /* CONFIG_GENERIC_IOMAP */\n#endif /* CONFIG_HAS_IOPORT_MAP */\n\n/*\n * Convert a virtual cached pointer to an uncached pointer\n */\n#ifndef xlate_dev_kmem_ptr\n#define xlate_dev_kmem_ptr xlate_dev_kmem_ptr\nstatic inline void *xlate_dev_kmem_ptr(void *addr)\n{\n\treturn addr;\n}\n#endif\n\n#ifndef xlate_dev_mem_ptr\n#define xlate_dev_mem_ptr xlate_dev_mem_ptr\nstatic inline void *xlate_dev_mem_ptr(phys_addr_t addr)\n{\n\treturn __va(addr);\n}\n#endif\n\n#ifndef unxlate_dev_mem_ptr\n#define unxlate_dev_mem_ptr unxlate_dev_mem_ptr\nstatic inline void unxlate_dev_mem_ptr(phys_addr_t phys, void *addr)\n{\n}\n#endif\n\n#ifdef CONFIG_VIRT_TO_BUS\n#ifndef virt_to_bus\nstatic inline unsigned long virt_to_bus(void *address)\n{\n\treturn (unsigned long)address;\n}\n\nstatic inline void *bus_to_virt(unsigned long address)\n{\n\treturn (void *)address;\n}\n#endif\n#endif\n\n#ifndef memset_io\n#define memset_io memset_io\n/**\n * memset_io\tSet a range of I/O memory to a constant value\n * @addr:\tThe beginning of the I/O-memory range to set\n * @val:\tThe value to set the memory to\n * @count:\tThe number of bytes to set\n *\n * Set a range of I/O memory to a given value.\n */\nstatic inline void memset_io(volatile void __iomem *addr, int value,\n\t\t\t     size_t size)\n{\n\tmemset(__io_virt(addr), value, size);\n}\n#endif\n\n#ifndef memcpy_fromio\n#define memcpy_fromio memcpy_fromio\n/**\n * memcpy_fromio\tCopy a block of data from I/O memory\n * @dst:\t\tThe (RAM) destination for the copy\n * @src:\t\tThe (I/O memory) source for the data\n * @count:\t\tThe number of bytes to copy\n *\n * Copy a block of data from I/O memory.\n */\nstatic inline void memcpy_fromio(void *buffer,\n\t\t\t\t const volatile void __iomem *addr,\n\t\t\t\t size_t size)\n{\n\tmemcpy(buffer, __io_virt(addr), size);\n}\n#endif\n\n#ifndef memcpy_toio\n#define memcpy_toio memcpy_toio\n/**\n * memcpy_toio\t\tCopy a block of data into I/O memory\n * @dst:\t\tThe (I/O memory) destination for the copy\n * @src:\t\tThe (RAM) source for the data\n * @count:\t\tThe number of bytes to copy\n *\n * Copy a block of data to I/O memory.\n */\nstatic inline void memcpy_toio(volatile void __iomem *addr, const void *buffer,\n\t\t\t       size_t size)\n{\n\tmemcpy(__io_virt(addr), buffer, size);\n}\n#endif\n\n#endif /* __KERNEL__ */\n\n#endif /* __ASM_GENERIC_IO_H */\n"
  },
  {
    "path": "t/tree/include/asm-generic/pci_iomap.h",
    "content": "/* SPDX-License-Identifier: GPL-2.0+ */\n/* Generic I/O port emulation.\n *\n * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.\n * Written by David Howells (dhowells@redhat.com)\n */\n#ifndef __ASM_GENERIC_PCI_IOMAP_H\n#define __ASM_GENERIC_PCI_IOMAP_H\n\nstruct pci_dev;\n#ifdef CONFIG_PCI\n/* Create a virtual mapping cookie for a PCI BAR (memory or IO) */\nextern void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long max);\nextern void __iomem *pci_iomap_wc(struct pci_dev *dev, int bar, unsigned long max);\nextern void __iomem *pci_iomap_range(struct pci_dev *dev, int bar,\n\t\t\t\t     unsigned long offset,\n\t\t\t\t     unsigned long maxlen);\nextern void __iomem *pci_iomap_wc_range(struct pci_dev *dev, int bar,\n\t\t\t\t\tunsigned long offset,\n\t\t\t\t\tunsigned long maxlen);\n/* Create a virtual mapping cookie for a port on a given PCI device.\n * Do not call this directly, it exists to make it easier for architectures\n * to override */\n#ifdef CONFIG_NO_GENERIC_PCI_IOPORT_MAP\nextern void __iomem *__pci_ioport_map(struct pci_dev *dev, unsigned long port,\n\t\t\t\t      unsigned int nr);\n#else\n#define __pci_ioport_map(dev, port, nr) ioport_map((port), (nr))\n#endif\n\n#elif defined(CONFIG_GENERIC_PCI_IOMAP)\nstatic inline void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long max)\n{\n\treturn NULL;\n}\n\nstatic inline void __iomem *pci_iomap_wc(struct pci_dev *dev, int bar, unsigned long max)\n{\n\treturn NULL;\n}\nstatic inline void __iomem *pci_iomap_range(struct pci_dev *dev, int bar,\n\t\t\t\t\t    unsigned long offset,\n\t\t\t\t\t    unsigned long maxlen)\n{\n\treturn NULL;\n}\nstatic inline void __iomem *pci_iomap_wc_range(struct pci_dev *dev, int bar,\n\t\t\t\t\t       unsigned long offset,\n\t\t\t\t\t       unsigned long maxlen)\n{\n\treturn NULL;\n}\n#endif\n\n#endif /* __ASM_GENERIC_IO_H */\n"
  },
  {
    "path": "t/tree/include/asm-generic/qrwlock.h",
    "content": "/* SPDX-License-Identifier: GPL-2.0-or-later */\n/*\n * Queue read/write lock\n *\n * (C) Copyright 2013-2014 Hewlett-Packard Development Company, L.P.\n *\n * Authors: Waiman Long <waiman.long@hp.com>\n */\n#ifndef __ASM_GENERIC_QRWLOCK_H\n#define __ASM_GENERIC_QRWLOCK_H\n\n#include <linux/atomic.h>\n#include <asm/barrier.h>\n#include <asm/processor.h>\n\n#include <asm-generic/qrwlock_types.h>\n\n/*\n * Writer states & reader shift and bias.\n */\n#define\t_QW_WAITING\t0x100\t\t/* A writer is waiting\t   */\n#define\t_QW_LOCKED\t0x0ff\t\t/* A writer holds the lock */\n#define\t_QW_WMASK\t0x1ff\t\t/* Writer mask\t\t   */\n#define\t_QR_SHIFT\t9\t\t/* Reader count shift\t   */\n#define _QR_BIAS\t(1U << _QR_SHIFT)\n\n/*\n * External function declarations\n */\nextern void queued_read_lock_slowpath(struct qrwlock *lock);\nextern void queued_write_lock_slowpath(struct qrwlock *lock);\n\n/**\n * queued_read_trylock - try to acquire read lock of a queue rwlock\n * @lock : Pointer to queue rwlock structure\n * Return: 1 if lock acquired, 0 if failed\n */\nstatic inline int queued_read_trylock(struct qrwlock *lock)\n{\n\tu32 cnts;\n\n\tcnts = atomic_read(&lock->cnts);\n\tif (likely(!(cnts & _QW_WMASK))) {\n\t\tcnts = (u32)atomic_add_return_acquire(_QR_BIAS, &lock->cnts);\n\t\tif (likely(!(cnts & _QW_WMASK)))\n\t\t\treturn 1;\n\t\tatomic_sub(_QR_BIAS, &lock->cnts);\n\t}\n\treturn 0;\n}\n\n/**\n * queued_write_trylock - try to acquire write lock of a queue rwlock\n * @lock : Pointer to queue rwlock structure\n * Return: 1 if lock acquired, 0 if failed\n */\nstatic inline int queued_write_trylock(struct qrwlock *lock)\n{\n\tu32 cnts;\n\n\tcnts = atomic_read(&lock->cnts);\n\tif (unlikely(cnts))\n\t\treturn 0;\n\n\treturn likely(atomic_try_cmpxchg_acquire(&lock->cnts, &cnts,\n\t\t\t\t_QW_LOCKED));\n}\n/**\n * queued_read_lock - acquire read lock of a queue rwlock\n * @lock: Pointer to queue rwlock structure\n */\nstatic inline void queued_read_lock(struct qrwlock *lock)\n{\n\tu32 cnts;\n\n\tcnts = atomic_add_return_acquire(_QR_BIAS, &lock->cnts);\n\tif (likely(!(cnts & _QW_WMASK)))\n\t\treturn;\n\n\t/* The slowpath will decrement the reader count, if necessary. */\n\tqueued_read_lock_slowpath(lock);\n}\n\n/**\n * queued_write_lock - acquire write lock of a queue rwlock\n * @lock : Pointer to queue rwlock structure\n */\nstatic inline void queued_write_lock(struct qrwlock *lock)\n{\n\tu32 cnts = 0;\n\t/* Optimize for the unfair lock case where the fair flag is 0. */\n\tif (likely(atomic_try_cmpxchg_acquire(&lock->cnts, &cnts, _QW_LOCKED)))\n\t\treturn;\n\n\tqueued_write_lock_slowpath(lock);\n}\n\n/**\n * queued_read_unlock - release read lock of a queue rwlock\n * @lock : Pointer to queue rwlock structure\n */\nstatic inline void queued_read_unlock(struct qrwlock *lock)\n{\n\t/*\n\t * Atomically decrement the reader count\n\t */\n\t(void)atomic_sub_return_release(_QR_BIAS, &lock->cnts);\n}\n\n/**\n * queued_write_unlock - release write lock of a queue rwlock\n * @lock : Pointer to queue rwlock structure\n */\nstatic inline void queued_write_unlock(struct qrwlock *lock)\n{\n\tsmp_store_release(&lock->wlocked, 0);\n}\n\n/*\n * Remapping rwlock architecture specific functions to the corresponding\n * queue rwlock functions.\n */\n#define arch_read_lock(l)\tqueued_read_lock(l)\n#define arch_write_lock(l)\tqueued_write_lock(l)\n#define arch_read_trylock(l)\tqueued_read_trylock(l)\n#define arch_write_trylock(l)\tqueued_write_trylock(l)\n#define arch_read_unlock(l)\tqueued_read_unlock(l)\n#define arch_write_unlock(l)\tqueued_write_unlock(l)\n\n#endif /* __ASM_GENERIC_QRWLOCK_H */\n"
  },
  {
    "path": "t/tree/include/asm-generic/qspinlock.h",
    "content": "/* SPDX-License-Identifier: GPL-2.0-or-later */\n/*\n * Queued spinlock\n *\n * (C) Copyright 2013-2015 Hewlett-Packard Development Company, L.P.\n * (C) Copyright 2015 Hewlett-Packard Enterprise Development LP\n *\n * Authors: Waiman Long <waiman.long@hpe.com>\n */\n#ifndef __ASM_GENERIC_QSPINLOCK_H\n#define __ASM_GENERIC_QSPINLOCK_H\n\n#include <asm-generic/qspinlock_types.h>\n\n/**\n * queued_spin_is_locked - is the spinlock locked?\n * @lock: Pointer to queued spinlock structure\n * Return: 1 if it is locked, 0 otherwise\n */\nstatic __always_inline int queued_spin_is_locked(struct qspinlock *lock)\n{\n\t/*\n\t * Any !0 state indicates it is locked, even if _Q_LOCKED_VAL\n\t * isn't immediately observable.\n\t */\n\treturn atomic_read(&lock->val);\n}\n\n/**\n * queued_spin_value_unlocked - is the spinlock structure unlocked?\n * @lock: queued spinlock structure\n * Return: 1 if it is unlocked, 0 otherwise\n *\n * N.B. Whenever there are tasks waiting for the lock, it is considered\n *      locked wrt the lockref code to avoid lock stealing by the lockref\n *      code and change things underneath the lock. This also allows some\n *      optimizations to be applied without conflict with lockref.\n */\nstatic __always_inline int queued_spin_value_unlocked(struct qspinlock lock)\n{\n\treturn !atomic_read(&lock.val);\n}\n\n/**\n * queued_spin_is_contended - check if the lock is contended\n * @lock : Pointer to queued spinlock structure\n * Return: 1 if lock contended, 0 otherwise\n */\nstatic __always_inline int queued_spin_is_contended(struct qspinlock *lock)\n{\n\treturn atomic_read(&lock->val) & ~_Q_LOCKED_MASK;\n}\n/**\n * queued_spin_trylock - try to acquire the queued spinlock\n * @lock : Pointer to queued spinlock structure\n * Return: 1 if lock acquired, 0 if failed\n */\nstatic __always_inline int queued_spin_trylock(struct qspinlock *lock)\n{\n\tu32 val = atomic_read(&lock->val);\n\n\tif (unlikely(val))\n\t\treturn 0;\n\n\treturn likely(atomic_try_cmpxchg_acquire(&lock->val, &val, _Q_LOCKED_VAL));\n}\n\nextern void queued_spin_lock_slowpath(struct qspinlock *lock, u32 val);\n\n/**\n * queued_spin_lock - acquire a queued spinlock\n * @lock: Pointer to queued spinlock structure\n */\nstatic __always_inline void queued_spin_lock(struct qspinlock *lock)\n{\n\tu32 val = 0;\n\n\tif (likely(atomic_try_cmpxchg_acquire(&lock->val, &val, _Q_LOCKED_VAL)))\n\t\treturn;\n\n\tqueued_spin_lock_slowpath(lock, val);\n}\n\n#ifndef queued_spin_unlock\n/**\n * queued_spin_unlock - release a queued spinlock\n * @lock : Pointer to queued spinlock structure\n */\nstatic __always_inline void queued_spin_unlock(struct qspinlock *lock)\n{\n\t/*\n\t * unlock() needs release semantics:\n\t */\n\tsmp_store_release(&lock->locked, 0);\n}\n#endif\n\n#ifndef virt_spin_lock\nstatic __always_inline bool virt_spin_lock(struct qspinlock *lock)\n{\n\treturn false;\n}\n#endif\n\n/*\n * Remapping spinlock architecture specific functions to the corresponding\n * queued spinlock functions.\n */\n#define arch_spin_is_locked(l)\t\tqueued_spin_is_locked(l)\n#define arch_spin_is_contended(l)\tqueued_spin_is_contended(l)\n#define arch_spin_value_unlocked(l)\tqueued_spin_value_unlocked(l)\n#define arch_spin_lock(l)\t\tqueued_spin_lock(l)\n#define arch_spin_trylock(l)\t\tqueued_spin_trylock(l)\n#define arch_spin_unlock(l)\t\tqueued_spin_unlock(l)\n\n#endif /* __ASM_GENERIC_QSPINLOCK_H */\n"
  },
  {
    "path": "t/tree/include/asm-generic/qspinlock_types.h",
    "content": "/* SPDX-License-Identifier: GPL-2.0-or-later */\n/*\n * Queued spinlock\n *\n * (C) Copyright 2013-2015 Hewlett-Packard Development Company, L.P.\n *\n * Authors: Waiman Long <waiman.long@hp.com>\n */\n#ifndef __ASM_GENERIC_QSPINLOCK_TYPES_H\n#define __ASM_GENERIC_QSPINLOCK_TYPES_H\n\n/*\n * Including atomic.h with PARAVIRT on will cause compilation errors because\n * of recursive header file incluson via paravirt_types.h. So don't include\n * it if PARAVIRT is on.\n */\n#ifndef CONFIG_PARAVIRT\n#include <linux/types.h>\n#include <linux/atomic.h>\n#endif\n\ntypedef struct qspinlock {\n\tunion {\n\t\tatomic_t val;\n\n\t\t/*\n\t\t * By using the whole 2nd least significant byte for the\n\t\t * pending bit, we can allow better optimization of the lock\n\t\t * acquisition for the pending bit holder.\n\t\t */\n#ifdef __LITTLE_ENDIAN\n\t\tstruct {\n\t\t\tu8\tlocked;\n\t\t\tu8\tpending;\n\t\t};\n\t\tstruct {\n\t\t\tu16\tlocked_pending;\n\t\t\tu16\ttail;\n\t\t};\n#else\n\t\tstruct {\n\t\t\tu16\ttail;\n\t\t\tu16\tlocked_pending;\n\t\t};\n\t\tstruct {\n\t\t\tu8\treserved[2];\n\t\t\tu8\tpending;\n\t\t\tu8\tlocked;\n\t\t};\n#endif\n\t};\n} arch_spinlock_t;\n\n/*\n * Initializier\n */\n#define\t__ARCH_SPIN_LOCK_UNLOCKED\t{ { .val = ATOMIC_INIT(0) } }\n\n/*\n * Bitfields in the atomic value:\n *\n * When NR_CPUS < 16K\n *  0- 7: locked byte\n *     8: pending\n *  9-15: not used\n * 16-17: tail index\n * 18-31: tail cpu (+1)\n *\n * When NR_CPUS >= 16K\n *  0- 7: locked byte\n *     8: pending\n *  9-10: tail index\n * 11-31: tail cpu (+1)\n */\n#define\t_Q_SET_MASK(type)\t(((1U << _Q_ ## type ## _BITS) - 1)\\\n\t\t\t\t      << _Q_ ## type ## _OFFSET)\n#define _Q_LOCKED_OFFSET\t0\n#define _Q_LOCKED_BITS\t\t8\n#define _Q_LOCKED_MASK\t\t_Q_SET_MASK(LOCKED)\n\n#define _Q_PENDING_OFFSET\t(_Q_LOCKED_OFFSET + _Q_LOCKED_BITS)\n#if CONFIG_NR_CPUS < (1U << 14)\n#define _Q_PENDING_BITS\t\t8\n#else\n#define _Q_PENDING_BITS\t\t1\n#endif\n#define _Q_PENDING_MASK\t\t_Q_SET_MASK(PENDING)\n\n#define _Q_TAIL_IDX_OFFSET\t(_Q_PENDING_OFFSET + _Q_PENDING_BITS)\n#define _Q_TAIL_IDX_BITS\t2\n#define _Q_TAIL_IDX_MASK\t_Q_SET_MASK(TAIL_IDX)\n\n#define _Q_TAIL_CPU_OFFSET\t(_Q_TAIL_IDX_OFFSET + _Q_TAIL_IDX_BITS)\n#define _Q_TAIL_CPU_BITS\t(32 - _Q_TAIL_CPU_OFFSET)\n#define _Q_TAIL_CPU_MASK\t_Q_SET_MASK(TAIL_CPU)\n\n#define _Q_TAIL_OFFSET\t\t_Q_TAIL_IDX_OFFSET\n#define _Q_TAIL_MASK\t\t(_Q_TAIL_IDX_MASK | _Q_TAIL_CPU_MASK)\n\n#define _Q_LOCKED_VAL\t\t(1U << _Q_LOCKED_OFFSET)\n#define _Q_PENDING_VAL\t\t(1U << _Q_PENDING_OFFSET)\n\n#endif /* __ASM_GENERIC_QSPINLOCK_TYPES_H */\n"
  },
  {
    "path": "t/tree/include/linux/acpi.h",
    "content": "/* SPDX-License-Identifier: GPL-2.0-or-later */\n/*\n * acpi.h - ACPI Interface\n *\n * Copyright (C) 2001 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>\n */\n\n#ifndef _LINUX_ACPI_H\n#define _LINUX_ACPI_H\n\n#include <linux/errno.h>\n#include <linux/ioport.h>\t/* for struct resource */\n#include <linux/irqdomain.h>\n#include <linux/resource_ext.h>\n#include <linux/device.h>\n#include <linux/property.h>\n#include <linux/uuid.h>\n\n#ifndef _LINUX\n#define _LINUX\n#endif\n#include <acpi/acpi.h>\n\n#ifdef\tCONFIG_ACPI\n\n#include <linux/list.h>\n#include <linux/mod_devicetable.h>\n#include <linux/dynamic_debug.h>\n#include <linux/module.h>\n#include <linux/mutex.h>\n\n#include <acpi/acpi_bus.h>\n#include <acpi/acpi_drivers.h>\n#include <acpi/acpi_numa.h>\n#include <acpi/acpi_io.h>\n#include <asm/acpi.h>\n\nstatic inline acpi_handle acpi_device_handle(struct acpi_device *adev)\n{\n\treturn adev ? adev->handle : NULL;\n}\n\n#define ACPI_COMPANION(dev)\t\tto_acpi_device_node((dev)->fwnode)\n#define ACPI_COMPANION_SET(dev, adev)\tset_primary_fwnode(dev, (adev) ? \\\n\tacpi_fwnode_handle(adev) : NULL)\n#define ACPI_HANDLE(dev)\t\tacpi_device_handle(ACPI_COMPANION(dev))\n#define ACPI_HANDLE_FWNODE(fwnode)\t\\\n\t\t\t\tacpi_device_handle(to_acpi_device_node(fwnode))\n\nstatic inline struct fwnode_handle *acpi_alloc_fwnode_static(void)\n{\n\tstruct fwnode_handle *fwnode;\n\n\tfwnode = kzalloc(sizeof(struct fwnode_handle), GFP_KERNEL);\n\tif (!fwnode)\n\t\treturn NULL;\n\n\tfwnode->ops = &acpi_static_fwnode_ops;\n\n\treturn fwnode;\n}\n\nstatic inline void acpi_free_fwnode_static(struct fwnode_handle *fwnode)\n{\n\tif (WARN_ON(!is_acpi_static_node(fwnode)))\n\t\treturn;\n\n\tkfree(fwnode);\n}\n\n/**\n * ACPI_DEVICE_CLASS - macro used to describe an ACPI device with\n * the PCI-defined class-code information\n *\n * @_cls : the class, subclass, prog-if triple for this device\n * @_msk : the class mask for this device\n *\n * This macro is used to create a struct acpi_device_id that matches a\n * specific PCI class. The .id and .driver_data fields will be left\n * initialized with the default value.\n */\n#define ACPI_DEVICE_CLASS(_cls, _msk)\t.cls = (_cls), .cls_msk = (_msk),\n\nstatic inline bool has_acpi_companion(struct device *dev)\n{\n\treturn is_acpi_device_node(dev->fwnode);\n}\n\nstatic inline void acpi_preset_companion(struct device *dev,\n\t\t\t\t\t struct acpi_device *parent, u64 addr)\n{\n\tACPI_COMPANION_SET(dev, acpi_find_child_device(parent, addr, false));\n}\n\nstatic inline const char *acpi_dev_name(struct acpi_device *adev)\n{\n\treturn dev_name(&adev->dev);\n}\n\nstruct device *acpi_get_first_physical_node(struct acpi_device *adev);\n\nenum acpi_irq_model_id {\n\tACPI_IRQ_MODEL_PIC = 0,\n\tACPI_IRQ_MODEL_IOAPIC,\n\tACPI_IRQ_MODEL_IOSAPIC,\n\tACPI_IRQ_MODEL_PLATFORM,\n\tACPI_IRQ_MODEL_GIC,\n\tACPI_IRQ_MODEL_COUNT\n};\n\nextern enum acpi_irq_model_id\tacpi_irq_model;\n\nenum acpi_interrupt_id {\n\tACPI_INTERRUPT_PMI\t= 1,\n\tACPI_INTERRUPT_INIT,\n\tACPI_INTERRUPT_CPEI,\n\tACPI_INTERRUPT_COUNT\n};\n\n#define\tACPI_SPACE_MEM\t\t0\n\nenum acpi_address_range_id {\n\tACPI_ADDRESS_RANGE_MEMORY = 1,\n\tACPI_ADDRESS_RANGE_RESERVED = 2,\n\tACPI_ADDRESS_RANGE_ACPI = 3,\n\tACPI_ADDRESS_RANGE_NVS\t= 4,\n\tACPI_ADDRESS_RANGE_COUNT\n};\n\n\n/* Table Handlers */\nunion acpi_subtable_headers {\n\tstruct acpi_subtable_header common;\n\tstruct acpi_hmat_structure hmat;\n};\n\ntypedef int (*acpi_tbl_table_handler)(struct acpi_table_header *table);\n\ntypedef int (*acpi_tbl_entry_handler)(union acpi_subtable_headers *header,\n\t\t\t\t      const unsigned long end);\n\n/* Debugger support */\n\nstruct acpi_debugger_ops {\n\tint (*create_thread)(acpi_osd_exec_callback function, void *context);\n\tssize_t (*write_log)(const char *msg);\n\tssize_t (*read_cmd)(char *buffer, size_t length);\n\tint (*wait_command_ready)(bool single_step, char *buffer, size_t length);\n\tint (*notify_command_complete)(void);\n};\n\nstruct acpi_debugger {\n\tconst struct acpi_debugger_ops *ops;\n\tstruct module *owner;\n\tstruct mutex lock;\n};\n\n#ifdef CONFIG_ACPI_DEBUGGER\nint __init acpi_debugger_init(void);\nint acpi_register_debugger(struct module *owner,\n\t\t\t   const struct acpi_debugger_ops *ops);\nvoid acpi_unregister_debugger(const struct acpi_debugger_ops *ops);\nint acpi_debugger_create_thread(acpi_osd_exec_callback function, void *context);\nssize_t acpi_debugger_write_log(const char *msg);\nssize_t acpi_debugger_read_cmd(char *buffer, size_t buffer_length);\nint acpi_debugger_wait_command_ready(void);\nint acpi_debugger_notify_command_complete(void);\n#else\nstatic inline int acpi_debugger_init(void)\n{\n\treturn -ENODEV;\n}\n\nstatic inline int acpi_register_debugger(struct module *owner,\n\t\t\t\t\t const struct acpi_debugger_ops *ops)\n{\n\treturn -ENODEV;\n}\n\nstatic inline void acpi_unregister_debugger(const struct acpi_debugger_ops *ops)\n{\n}\n\nstatic inline int acpi_debugger_create_thread(acpi_osd_exec_callback function,\n\t\t\t\t\t      void *context)\n{\n\treturn -ENODEV;\n}\n\nstatic inline int acpi_debugger_write_log(const char *msg)\n{\n\treturn -ENODEV;\n}\n\nstatic inline int acpi_debugger_read_cmd(char *buffer, u32 buffer_length)\n{\n\treturn -ENODEV;\n}\n\nstatic inline int acpi_debugger_wait_command_ready(void)\n{\n\treturn -ENODEV;\n}\n\nstatic inline int acpi_debugger_notify_command_complete(void)\n{\n\treturn -ENODEV;\n}\n#endif\n\n#define BAD_MADT_ENTRY(entry, end) (\t\t\t\t\t    \\\n\t\t(!entry) || (unsigned long)entry + sizeof(*entry) > end ||  \\\n\t\t((struct acpi_subtable_header *)entry)->length < sizeof(*entry))\n\nstruct acpi_subtable_proc {\n\tint id;\n\tacpi_tbl_entry_handler handler;\n\tint count;\n};\n\nvoid __iomem *__acpi_map_table(unsigned long phys, unsigned long size);\nvoid __acpi_unmap_table(void __iomem *map, unsigned long size);\nint early_acpi_boot_init(void);\nint acpi_boot_init (void);\nvoid acpi_boot_table_init (void);\nint acpi_mps_check (void);\nint acpi_numa_init (void);\n\nint acpi_table_init (void);\nint acpi_table_parse(char *id, acpi_tbl_table_handler handler);\nint __init acpi_table_parse_entries(char *id, unsigned long table_size,\n\t\t\t      int entry_id,\n\t\t\t      acpi_tbl_entry_handler handler,\n\t\t\t      unsigned int max_entries);\nint __init acpi_table_parse_entries_array(char *id, unsigned long table_size,\n\t\t\t      struct acpi_subtable_proc *proc, int proc_num,\n\t\t\t      unsigned int max_entries);\nint acpi_table_parse_madt(enum acpi_madt_type id,\n\t\t\t  acpi_tbl_entry_handler handler,\n\t\t\t  unsigned int max_entries);\nint acpi_parse_mcfg (struct acpi_table_header *header);\nvoid acpi_table_print_madt_entry (struct acpi_subtable_header *madt);\n\n/* the following numa functions are architecture-dependent */\nvoid acpi_numa_slit_init (struct acpi_table_slit *slit);\n\n#if defined(CONFIG_X86) || defined(CONFIG_IA64)\nvoid acpi_numa_processor_affinity_init (struct acpi_srat_cpu_affinity *pa);\n#else\nstatic inline void\nacpi_numa_processor_affinity_init(struct acpi_srat_cpu_affinity *pa) { }\n#endif\n\nvoid acpi_numa_x2apic_affinity_init(struct acpi_srat_x2apic_cpu_affinity *pa);\n\n#ifdef CONFIG_ARM64\nvoid acpi_numa_gicc_affinity_init(struct acpi_srat_gicc_affinity *pa);\n#else\nstatic inline void\nacpi_numa_gicc_affinity_init(struct acpi_srat_gicc_affinity *pa) { }\n#endif\n\nint acpi_numa_memory_affinity_init (struct acpi_srat_mem_affinity *ma);\n\n#ifndef PHYS_CPUID_INVALID\ntypedef u32 phys_cpuid_t;\n#define PHYS_CPUID_INVALID (phys_cpuid_t)(-1)\n#endif\n\nstatic inline bool invalid_logical_cpuid(u32 cpuid)\n{\n\treturn (int)cpuid < 0;\n}\n\nstatic inline bool invalid_phys_cpuid(phys_cpuid_t phys_id)\n{\n\treturn phys_id == PHYS_CPUID_INVALID;\n}\n\n/* Validate the processor object's proc_id */\nbool acpi_duplicate_processor_id(int proc_id);\n\n#ifdef CONFIG_ACPI_HOTPLUG_CPU\n/* Arch dependent functions for cpu hotplug support */\nint acpi_map_cpu(acpi_handle handle, phys_cpuid_t physid, u32 acpi_id,\n\t\t int *pcpu);\nint acpi_unmap_cpu(int cpu);\n#endif /* CONFIG_ACPI_HOTPLUG_CPU */\n\n#ifdef CONFIG_ACPI_HOTPLUG_IOAPIC\nint acpi_get_ioapic_id(acpi_handle handle, u32 gsi_base, u64 *phys_addr);\n#endif\n\nint acpi_register_ioapic(acpi_handle handle, u64 phys_addr, u32 gsi_base);\nint acpi_unregister_ioapic(acpi_handle handle, u32 gsi_base);\nint acpi_ioapic_registered(acpi_handle handle, u32 gsi_base);\nvoid acpi_irq_stats_init(void);\nextern u32 acpi_irq_handled;\nextern u32 acpi_irq_not_handled;\nextern unsigned int acpi_sci_irq;\nextern bool acpi_no_s5;\n#define INVALID_ACPI_IRQ\t((unsigned)-1)\nstatic inline bool acpi_sci_irq_valid(void)\n{\n\treturn acpi_sci_irq != INVALID_ACPI_IRQ;\n}\n\nextern int sbf_port;\nextern unsigned long acpi_realmode_flags;\n\nint acpi_register_gsi (struct device *dev, u32 gsi, int triggering, int polarity);\nint acpi_gsi_to_irq (u32 gsi, unsigned int *irq);\nint acpi_isa_irq_to_gsi (unsigned isa_irq, u32 *gsi);\n\nvoid acpi_set_irq_model(enum acpi_irq_model_id model,\n\t\t\tstruct fwnode_handle *fwnode);\n\nstruct irq_domain *acpi_irq_create_hierarchy(unsigned int flags,\n\t\t\t\t\t     unsigned int size,\n\t\t\t\t\t     struct fwnode_handle *fwnode,\n\t\t\t\t\t     const struct irq_domain_ops *ops,\n\t\t\t\t\t     void *host_data);\n\n#ifdef CONFIG_X86_IO_APIC\nextern int acpi_get_override_irq(u32 gsi, int *trigger, int *polarity);\n#else\nstatic inline int acpi_get_override_irq(u32 gsi, int *trigger, int *polarity)\n{\n\treturn -1;\n}\n#endif\n/*\n * This function undoes the effect of one call to acpi_register_gsi().\n * If this matches the last registration, any IRQ resources for gsi\n * are freed.\n */\nvoid acpi_unregister_gsi (u32 gsi);\n\nstruct pci_dev;\n\nint acpi_pci_irq_enable (struct pci_dev *dev);\nvoid acpi_penalize_isa_irq(int irq, int active);\nbool acpi_isa_irq_available(int irq);\n#ifdef CONFIG_PCI\nvoid acpi_penalize_sci_irq(int irq, int trigger, int polarity);\n#else\nstatic inline void acpi_penalize_sci_irq(int irq, int trigger,\n\t\t\t\t\tint polarity)\n{\n}\n#endif\nvoid acpi_pci_irq_disable (struct pci_dev *dev);\n\nextern int ec_read(u8 addr, u8 *val);\nextern int ec_write(u8 addr, u8 val);\nextern int ec_transaction(u8 command,\n                          const u8 *wdata, unsigned wdata_len,\n                          u8 *rdata, unsigned rdata_len);\nextern acpi_handle ec_get_handle(void);\n\nextern bool acpi_is_pnp_device(struct acpi_device *);\n\n#if defined(CONFIG_ACPI_WMI) || defined(CONFIG_ACPI_WMI_MODULE)\n\ntypedef void (*wmi_notify_handler) (u32 value, void *context);\n\nextern acpi_status wmi_evaluate_method(const char *guid, u8 instance,\n\t\t\t\t\tu32 method_id,\n\t\t\t\t\tconst struct acpi_buffer *in,\n\t\t\t\t\tstruct acpi_buffer *out);\nextern acpi_status wmi_query_block(const char *guid, u8 instance,\n\t\t\t\t\tstruct acpi_buffer *out);\nextern acpi_status wmi_set_block(const char *guid, u8 instance,\n\t\t\t\t\tconst struct acpi_buffer *in);\nextern acpi_status wmi_install_notify_handler(const char *guid,\n\t\t\t\t\twmi_notify_handler handler, void *data);\nextern acpi_status wmi_remove_notify_handler(const char *guid);\nextern acpi_status wmi_get_event_data(u32 event, struct acpi_buffer *out);\nextern bool wmi_has_guid(const char *guid);\nextern char *wmi_get_acpi_device_uid(const char *guid);\n\n#endif\t/* CONFIG_ACPI_WMI */\n\n#define ACPI_VIDEO_OUTPUT_SWITCHING\t\t\t0x0001\n#define ACPI_VIDEO_DEVICE_POSTING\t\t\t0x0002\n#define ACPI_VIDEO_ROM_AVAILABLE\t\t\t0x0004\n#define ACPI_VIDEO_BACKLIGHT\t\t\t\t0x0008\n#define ACPI_VIDEO_BACKLIGHT_FORCE_VENDOR\t\t0x0010\n#define ACPI_VIDEO_BACKLIGHT_FORCE_VIDEO\t\t0x0020\n#define ACPI_VIDEO_OUTPUT_SWITCHING_FORCE_VENDOR\t0x0040\n#define ACPI_VIDEO_OUTPUT_SWITCHING_FORCE_VIDEO\t\t0x0080\n#define ACPI_VIDEO_BACKLIGHT_DMI_VENDOR\t\t\t0x0100\n#define ACPI_VIDEO_BACKLIGHT_DMI_VIDEO\t\t\t0x0200\n#define ACPI_VIDEO_OUTPUT_SWITCHING_DMI_VENDOR\t\t0x0400\n#define ACPI_VIDEO_OUTPUT_SWITCHING_DMI_VIDEO\t\t0x0800\n\nextern char acpi_video_backlight_string[];\nextern long acpi_is_video_device(acpi_handle handle);\nextern int acpi_blacklisted(void);\nextern void acpi_osi_setup(char *str);\nextern bool acpi_osi_is_win8(void);\n\n#ifdef CONFIG_ACPI_NUMA\nint acpi_map_pxm_to_online_node(int pxm);\nint acpi_map_pxm_to_node(int pxm);\nint acpi_get_node(acpi_handle handle);\n#else\nstatic inline int acpi_map_pxm_to_online_node(int pxm)\n{\n\treturn 0;\n}\nstatic inline int acpi_map_pxm_to_node(int pxm)\n{\n\treturn 0;\n}\nstatic inline int acpi_get_node(acpi_handle handle)\n{\n\treturn 0;\n}\n#endif\nextern int acpi_paddr_to_node(u64 start_addr, u64 size);\n\nextern int pnpacpi_disabled;\n\n#define PXM_INVAL\t(-1)\n\nbool acpi_dev_resource_memory(struct acpi_resource *ares, struct resource *res);\nbool acpi_dev_resource_io(struct acpi_resource *ares, struct resource *res);\nbool acpi_dev_resource_address_space(struct acpi_resource *ares,\n\t\t\t\t     struct resource_win *win);\nbool acpi_dev_resource_ext_address_space(struct acpi_resource *ares,\n\t\t\t\t\t struct resource_win *win);\nunsigned long acpi_dev_irq_flags(u8 triggering, u8 polarity, u8 shareable);\nunsigned int acpi_dev_get_irq_type(int triggering, int polarity);\nbool acpi_dev_resource_interrupt(struct acpi_resource *ares, int index,\n\t\t\t\t struct resource *res);\n\nvoid acpi_dev_free_resource_list(struct list_head *list);\nint acpi_dev_get_resources(struct acpi_device *adev, struct list_head *list,\n\t\t\t   int (*preproc)(struct acpi_resource *, void *),\n\t\t\t   void *preproc_data);\nint acpi_dev_get_dma_resources(struct acpi_device *adev,\n\t\t\t       struct list_head *list);\nint acpi_dev_filter_resource_type(struct acpi_resource *ares,\n\t\t\t\t  unsigned long types);\n\nstatic inline int acpi_dev_filter_resource_type_cb(struct acpi_resource *ares,\n\t\t\t\t\t\t   void *arg)\n{\n\treturn acpi_dev_filter_resource_type(ares, (unsigned long)arg);\n}\n\nstruct acpi_device *acpi_resource_consumer(struct resource *res);\n\nint acpi_check_resource_conflict(const struct resource *res);\n\nint acpi_check_region(resource_size_t start, resource_size_t n,\n\t\t      const char *name);\n\nacpi_status acpi_release_memory(acpi_handle handle, struct resource *res,\n\t\t\t\tu32 level);\n\nint acpi_resources_are_enforced(void);\n\n#ifdef CONFIG_HIBERNATION\nvoid __init acpi_no_s4_hw_signature(void);\n#endif\n\n#ifdef CONFIG_PM_SLEEP\nvoid __init acpi_old_suspend_ordering(void);\nvoid __init acpi_nvs_nosave(void);\nvoid __init acpi_nvs_nosave_s3(void);\nvoid __init acpi_sleep_no_blacklist(void);\n#endif /* CONFIG_PM_SLEEP */\n\nstruct acpi_osc_context {\n\tchar *uuid_str;\t\t\t/* UUID string */\n\tint rev;\n\tstruct acpi_buffer cap;\t\t/* list of DWORD capabilities */\n\tstruct acpi_buffer ret;\t\t/* free by caller if success */\n};\n\nacpi_status acpi_run_osc(acpi_handle handle, struct acpi_osc_context *context);\n\n/* Indexes into _OSC Capabilities Buffer (DWORDs 2 & 3 are device-specific) */\n#define OSC_QUERY_DWORD\t\t\t\t0\t/* DWORD 1 */\n#define OSC_SUPPORT_DWORD\t\t\t1\t/* DWORD 2 */\n#define OSC_CONTROL_DWORD\t\t\t2\t/* DWORD 3 */\n\n/* _OSC Capabilities DWORD 1: Query/Control and Error Returns (generic) */\n#define OSC_QUERY_ENABLE\t\t\t0x00000001  /* input */\n#define OSC_REQUEST_ERROR\t\t\t0x00000002  /* return */\n#define OSC_INVALID_UUID_ERROR\t\t\t0x00000004  /* return */\n#define OSC_INVALID_REVISION_ERROR\t\t0x00000008  /* return */\n#define OSC_CAPABILITIES_MASK_ERROR\t\t0x00000010  /* return */\n\n/* Platform-Wide Capabilities _OSC: Capabilities DWORD 2: Support Field */\n#define OSC_SB_PAD_SUPPORT\t\t\t0x00000001\n#define OSC_SB_PPC_OST_SUPPORT\t\t\t0x00000002\n#define OSC_SB_PR3_SUPPORT\t\t\t0x00000004\n#define OSC_SB_HOTPLUG_OST_SUPPORT\t\t0x00000008\n#define OSC_SB_APEI_SUPPORT\t\t\t0x00000010\n#define OSC_SB_CPC_SUPPORT\t\t\t0x00000020\n#define OSC_SB_CPCV2_SUPPORT\t\t\t0x00000040\n#define OSC_SB_PCLPI_SUPPORT\t\t\t0x00000080\n#define OSC_SB_OSLPI_SUPPORT\t\t\t0x00000100\n#define OSC_SB_CPC_DIVERSE_HIGH_SUPPORT\t\t0x00001000\n\nextern bool osc_sb_apei_support_acked;\nextern bool osc_pc_lpi_support_confirmed;\n\n/* PCI Host Bridge _OSC: Capabilities DWORD 2: Support Field */\n#define OSC_PCI_EXT_CONFIG_SUPPORT\t\t0x00000001\n#define OSC_PCI_ASPM_SUPPORT\t\t\t0x00000002\n#define OSC_PCI_CLOCK_PM_SUPPORT\t\t0x00000004\n#define OSC_PCI_SEGMENT_GROUPS_SUPPORT\t\t0x00000008\n#define OSC_PCI_MSI_SUPPORT\t\t\t0x00000010\n#define OSC_PCI_HPX_TYPE_3_SUPPORT\t\t0x00000100\n#define OSC_PCI_SUPPORT_MASKS\t\t\t0x0000011f\n\n/* PCI Host Bridge _OSC: Capabilities DWORD 3: Control Field */\n#define OSC_PCI_EXPRESS_NATIVE_HP_CONTROL\t0x00000001\n#define OSC_PCI_SHPC_NATIVE_HP_CONTROL\t\t0x00000002\n#define OSC_PCI_EXPRESS_PME_CONTROL\t\t0x00000004\n#define OSC_PCI_EXPRESS_AER_CONTROL\t\t0x00000008\n#define OSC_PCI_EXPRESS_CAPABILITY_CONTROL\t0x00000010\n#define OSC_PCI_EXPRESS_LTR_CONTROL\t\t0x00000020\n#define OSC_PCI_CONTROL_MASKS\t\t\t0x0000003f\n\n#define ACPI_GSB_ACCESS_ATTRIB_QUICK\t\t0x00000002\n#define ACPI_GSB_ACCESS_ATTRIB_SEND_RCV         0x00000004\n#define ACPI_GSB_ACCESS_ATTRIB_BYTE\t\t0x00000006\n#define ACPI_GSB_ACCESS_ATTRIB_WORD\t\t0x00000008\n#define ACPI_GSB_ACCESS_ATTRIB_BLOCK\t\t0x0000000A\n#define ACPI_GSB_ACCESS_ATTRIB_MULTIBYTE\t0x0000000B\n#define ACPI_GSB_ACCESS_ATTRIB_WORD_CALL\t0x0000000C\n#define ACPI_GSB_ACCESS_ATTRIB_BLOCK_CALL\t0x0000000D\n#define ACPI_GSB_ACCESS_ATTRIB_RAW_BYTES\t0x0000000E\n#define ACPI_GSB_ACCESS_ATTRIB_RAW_PROCESS\t0x0000000F\n\nextern acpi_status acpi_pci_osc_control_set(acpi_handle handle,\n\t\t\t\t\t     u32 *mask, u32 req);\n\n/* Enable _OST when all relevant hotplug operations are enabled */\n#if defined(CONFIG_ACPI_HOTPLUG_CPU) &&\t\t\t\\\n\tdefined(CONFIG_ACPI_HOTPLUG_MEMORY) &&\t\t\\\n\tdefined(CONFIG_ACPI_CONTAINER)\n#define ACPI_HOTPLUG_OST\n#endif\n\n/* _OST Source Event Code (OSPM Action) */\n#define ACPI_OST_EC_OSPM_SHUTDOWN\t\t0x100\n#define ACPI_OST_EC_OSPM_EJECT\t\t\t0x103\n#define ACPI_OST_EC_OSPM_INSERTION\t\t0x200\n\n/* _OST General Processing Status Code */\n#define ACPI_OST_SC_SUCCESS\t\t\t0x0\n#define ACPI_OST_SC_NON_SPECIFIC_FAILURE\t0x1\n#define ACPI_OST_SC_UNRECOGNIZED_NOTIFY\t\t0x2\n\n/* _OST OS Shutdown Processing (0x100) Status Code */\n#define ACPI_OST_SC_OS_SHUTDOWN_DENIED\t\t0x80\n#define ACPI_OST_SC_OS_SHUTDOWN_IN_PROGRESS\t0x81\n#define ACPI_OST_SC_OS_SHUTDOWN_COMPLETED\t0x82\n#define ACPI_OST_SC_OS_SHUTDOWN_NOT_SUPPORTED\t0x83\n\n/* _OST Ejection Request (0x3, 0x103) Status Code */\n#define ACPI_OST_SC_EJECT_NOT_SUPPORTED\t\t0x80\n#define ACPI_OST_SC_DEVICE_IN_USE\t\t0x81\n#define ACPI_OST_SC_DEVICE_BUSY\t\t\t0x82\n#define ACPI_OST_SC_EJECT_DEPENDENCY_BUSY\t0x83\n#define ACPI_OST_SC_EJECT_IN_PROGRESS\t\t0x84\n\n/* _OST Insertion Request (0x200) Status Code */\n#define ACPI_OST_SC_INSERT_IN_PROGRESS\t\t0x80\n#define ACPI_OST_SC_DRIVER_LOAD_FAILURE\t\t0x81\n#define ACPI_OST_SC_INSERT_NOT_SUPPORTED\t0x82\n\nenum acpi_predicate {\n\tall_versions,\n\tless_than_or_equal,\n\tequal,\n\tgreater_than_or_equal,\n};\n\n/* Table must be terminted by a NULL entry */\nstruct acpi_platform_list {\n\tchar\toem_id[ACPI_OEM_ID_SIZE+1];\n\tchar\toem_table_id[ACPI_OEM_TABLE_ID_SIZE+1];\n\tu32\toem_revision;\n\tchar\t*table;\n\tenum acpi_predicate pred;\n\tchar\t*reason;\n\tu32\tdata;\n};\nint acpi_match_platform_list(const struct acpi_platform_list *plat);\n\nextern void acpi_early_init(void);\nextern void acpi_subsystem_init(void);\nextern void arch_post_acpi_subsys_init(void);\n\nextern int acpi_nvs_register(__u64 start, __u64 size);\n\nextern int acpi_nvs_for_each_region(int (*func)(__u64, __u64, void *),\n\t\t\t\t    void *data);\n\nconst struct acpi_device_id *acpi_match_device(const struct acpi_device_id *ids,\n\t\t\t\t\t       const struct device *dev);\n\nconst void *acpi_device_get_match_data(const struct device *dev);\nextern bool acpi_driver_match_device(struct device *dev,\n\t\t\t\t     const struct device_driver *drv);\nint acpi_device_uevent_modalias(struct device *, struct kobj_uevent_env *);\nint acpi_device_modalias(struct device *, char *, int);\nvoid acpi_walk_dep_device_list(acpi_handle handle);\n\nstruct platform_device *acpi_create_platform_device(struct acpi_device *,\n\t\t\t\t\t\t    struct property_entry *);\n#define ACPI_PTR(_ptr)\t(_ptr)\n\nstatic inline void acpi_device_set_enumerated(struct acpi_device *adev)\n{\n\tadev->flags.visited = true;\n}\n\nstatic inline void acpi_device_clear_enumerated(struct acpi_device *adev)\n{\n\tadev->flags.visited = false;\n}\n\nenum acpi_reconfig_event  {\n\tACPI_RECONFIG_DEVICE_ADD = 0,\n\tACPI_RECONFIG_DEVICE_REMOVE,\n};\n\nint acpi_reconfig_notifier_register(struct notifier_block *nb);\nint acpi_reconfig_notifier_unregister(struct notifier_block *nb);\n\n#ifdef CONFIG_ACPI_GTDT\nint acpi_gtdt_init(struct acpi_table_header *table, int *platform_timer_count);\nint acpi_gtdt_map_ppi(int type);\nbool acpi_gtdt_c3stop(int type);\nint acpi_arch_timer_mem_init(struct arch_timer_mem *timer_mem, int *timer_count);\n#endif\n\n#ifndef ACPI_HAVE_ARCH_SET_ROOT_POINTER\nstatic inline void acpi_arch_set_root_pointer(u64 addr)\n{\n}\n#endif\n\n#ifndef ACPI_HAVE_ARCH_GET_ROOT_POINTER\nstatic inline u64 acpi_arch_get_root_pointer(void)\n{\n\treturn 0;\n}\n#endif\n\n#else\t/* !CONFIG_ACPI */\n\n#define acpi_disabled 1\n\n#define ACPI_COMPANION(dev)\t\t(NULL)\n#define ACPI_COMPANION_SET(dev, adev)\tdo { } while (0)\n#define ACPI_HANDLE(dev)\t\t(NULL)\n#define ACPI_HANDLE_FWNODE(fwnode)\t(NULL)\n#define ACPI_DEVICE_CLASS(_cls, _msk)\t.cls = (0), .cls_msk = (0),\n\nstruct fwnode_handle;\n\nstatic inline bool acpi_dev_found(const char *hid)\n{\n\treturn false;\n}\n\nstatic inline bool acpi_dev_present(const char *hid, const char *uid, s64 hrv)\n{\n\treturn false;\n}\n\nstatic inline struct acpi_device *\nacpi_dev_get_first_match_dev(const char *hid, const char *uid, s64 hrv)\n{\n\treturn NULL;\n}\n\nstatic inline void acpi_dev_put(struct acpi_device *adev) {}\n\nstatic inline bool is_acpi_node(struct fwnode_handle *fwnode)\n{\n\treturn false;\n}\n\nstatic inline bool is_acpi_device_node(struct fwnode_handle *fwnode)\n{\n\treturn false;\n}\n\nstatic inline struct acpi_device *to_acpi_device_node(struct fwnode_handle *fwnode)\n{\n\treturn NULL;\n}\n\nstatic inline bool is_acpi_data_node(struct fwnode_handle *fwnode)\n{\n\treturn false;\n}\n\nstatic inline struct acpi_data_node *to_acpi_data_node(struct fwnode_handle *fwnode)\n{\n\treturn NULL;\n}\n\nstatic inline bool acpi_data_node_match(struct fwnode_handle *fwnode,\n\t\t\t\t\tconst char *name)\n{\n\treturn false;\n}\n\nstatic inline struct fwnode_handle *acpi_fwnode_handle(struct acpi_device *adev)\n{\n\treturn NULL;\n}\n\nstatic inline bool has_acpi_companion(struct device *dev)\n{\n\treturn false;\n}\n\nstatic inline void acpi_preset_companion(struct device *dev,\n\t\t\t\t\t struct acpi_device *parent, u64 addr)\n{\n}\n\nstatic inline const char *acpi_dev_name(struct acpi_device *adev)\n{\n\treturn NULL;\n}\n\nstatic inline struct device *acpi_get_first_physical_node(struct acpi_device *adev)\n{\n\treturn NULL;\n}\n\nstatic inline void acpi_early_init(void) { }\nstatic inline void acpi_subsystem_init(void) { }\n\nstatic inline int early_acpi_boot_init(void)\n{\n\treturn 0;\n}\nstatic inline int acpi_boot_init(void)\n{\n\treturn 0;\n}\n\nstatic inline void acpi_boot_table_init(void)\n{\n\treturn;\n}\n\nstatic inline int acpi_mps_check(void)\n{\n\treturn 0;\n}\n\nstatic inline int acpi_check_resource_conflict(struct resource *res)\n{\n\treturn 0;\n}\n\nstatic inline int acpi_check_region(resource_size_t start, resource_size_t n,\n\t\t\t\t    const char *name)\n{\n\treturn 0;\n}\n\nstruct acpi_table_header;\nstatic inline int acpi_table_parse(char *id,\n\t\t\t\tint (*handler)(struct acpi_table_header *))\n{\n\treturn -ENODEV;\n}\n\nstatic inline int acpi_nvs_register(__u64 start, __u64 size)\n{\n\treturn 0;\n}\n\nstatic inline int acpi_nvs_for_each_region(int (*func)(__u64, __u64, void *),\n\t\t\t\t\t   void *data)\n{\n\treturn 0;\n}\n\nstruct acpi_device_id;\n\nstatic inline const struct acpi_device_id *acpi_match_device(\n\tconst struct acpi_device_id *ids, const struct device *dev)\n{\n\treturn NULL;\n}\n\nstatic inline const void *acpi_device_get_match_data(const struct device *dev)\n{\n\treturn NULL;\n}\n\nstatic inline bool acpi_driver_match_device(struct device *dev,\n\t\t\t\t\t    const struct device_driver *drv)\n{\n\treturn false;\n}\n\nstatic inline union acpi_object *acpi_evaluate_dsm(acpi_handle handle,\n\t\t\t\t\t\t   const guid_t *guid,\n\t\t\t\t\t\t   int rev, int func,\n\t\t\t\t\t\t   union acpi_object *argv4)\n{\n\treturn NULL;\n}\n\nstatic inline int acpi_device_uevent_modalias(struct device *dev,\n\t\t\t\tstruct kobj_uevent_env *env)\n{\n\treturn -ENODEV;\n}\n\nstatic inline int acpi_device_modalias(struct device *dev,\n\t\t\t\tchar *buf, int size)\n{\n\treturn -ENODEV;\n}\n\nstatic inline bool acpi_dma_supported(struct acpi_device *adev)\n{\n\treturn false;\n}\n\nstatic inline enum dev_dma_attr acpi_get_dma_attr(struct acpi_device *adev)\n{\n\treturn DEV_DMA_NOT_SUPPORTED;\n}\n\nstatic inline int acpi_dma_get_range(struct device *dev, u64 *dma_addr,\n\t\t\t\t     u64 *offset, u64 *size)\n{\n\treturn -ENODEV;\n}\n\nstatic inline int acpi_dma_configure(struct device *dev,\n\t\t\t\t     enum dev_dma_attr attr)\n{\n\treturn 0;\n}\n\n#define ACPI_PTR(_ptr)\t(NULL)\n\nstatic inline void acpi_device_set_enumerated(struct acpi_device *adev)\n{\n}\n\nstatic inline void acpi_device_clear_enumerated(struct acpi_device *adev)\n{\n}\n\nstatic inline int acpi_reconfig_notifier_register(struct notifier_block *nb)\n{\n\treturn -EINVAL;\n}\n\nstatic inline int acpi_reconfig_notifier_unregister(struct notifier_block *nb)\n{\n\treturn -EINVAL;\n}\n\nstatic inline struct acpi_device *acpi_resource_consumer(struct resource *res)\n{\n\treturn NULL;\n}\n\n#endif\t/* !CONFIG_ACPI */\n\n#ifdef CONFIG_ACPI_HOTPLUG_IOAPIC\nint acpi_ioapic_add(acpi_handle root);\n#else\nstatic inline int acpi_ioapic_add(acpi_handle root) { return 0; }\n#endif\n\n#ifdef CONFIG_ACPI\nvoid acpi_os_set_prepare_sleep(int (*func)(u8 sleep_state,\n\t\t\t       u32 pm1a_ctrl,  u32 pm1b_ctrl));\n\nacpi_status acpi_os_prepare_sleep(u8 sleep_state,\n\t\t\t\t  u32 pm1a_control, u32 pm1b_control);\n\nvoid acpi_os_set_prepare_extended_sleep(int (*func)(u8 sleep_state,\n\t\t\t\t        u32 val_a,  u32 val_b));\n\nacpi_status acpi_os_prepare_extended_sleep(u8 sleep_state,\n\t\t\t\t\t   u32 val_a, u32 val_b);\n\n#ifdef CONFIG_X86\nvoid arch_reserve_mem_area(acpi_physical_address addr, size_t size);\n#else\nstatic inline void arch_reserve_mem_area(acpi_physical_address addr,\n\t\t\t\t\t  size_t size)\n{\n}\n#endif /* CONFIG_X86 */\n#else\n#define acpi_os_set_prepare_sleep(func, pm1a_ctrl, pm1b_ctrl) do { } while (0)\n#endif\n\n#if defined(CONFIG_ACPI) && defined(CONFIG_PM)\nint acpi_dev_suspend(struct device *dev, bool wakeup);\nint acpi_dev_resume(struct device *dev);\nint acpi_subsys_runtime_suspend(struct device *dev);\nint acpi_subsys_runtime_resume(struct device *dev);\nint acpi_dev_pm_attach(struct device *dev, bool power_on);\n#else\nstatic inline int acpi_dev_runtime_suspend(struct device *dev) { return 0; }\nstatic inline int acpi_dev_runtime_resume(struct device *dev) { return 0; }\nstatic inline int acpi_subsys_runtime_suspend(struct device *dev) { return 0; }\nstatic inline int acpi_subsys_runtime_resume(struct device *dev) { return 0; }\nstatic inline int acpi_dev_pm_attach(struct device *dev, bool power_on)\n{\n\treturn 0;\n}\n#endif\n\n#if defined(CONFIG_ACPI) && defined(CONFIG_PM_SLEEP)\nint acpi_subsys_prepare(struct device *dev);\nvoid acpi_subsys_complete(struct device *dev);\nint acpi_subsys_suspend_late(struct device *dev);\nint acpi_subsys_suspend_noirq(struct device *dev);\nint acpi_subsys_suspend(struct device *dev);\nint acpi_subsys_freeze(struct device *dev);\nint acpi_subsys_poweroff(struct device *dev);\nvoid acpi_ec_mark_gpe_for_wake(void);\nvoid acpi_ec_set_gpe_wake_mask(u8 action);\n#else\nstatic inline int acpi_subsys_prepare(struct device *dev) { return 0; }\nstatic inline void acpi_subsys_complete(struct device *dev) {}\nstatic inline int acpi_subsys_suspend_late(struct device *dev) { return 0; }\nstatic inline int acpi_subsys_suspend_noirq(struct device *dev) { return 0; }\nstatic inline int acpi_subsys_suspend(struct device *dev) { return 0; }\nstatic inline int acpi_subsys_freeze(struct device *dev) { return 0; }\nstatic inline int acpi_subsys_poweroff(struct device *dev) { return 0; }\nstatic inline void acpi_ec_mark_gpe_for_wake(void) {}\nstatic inline void acpi_ec_set_gpe_wake_mask(u8 action) {}\n#endif\n\n#ifdef CONFIG_ACPI\n__printf(3, 4)\nvoid acpi_handle_printk(const char *level, acpi_handle handle,\n\t\t\tconst char *fmt, ...);\n#else\t/* !CONFIG_ACPI */\nstatic inline __printf(3, 4) void\nacpi_handle_printk(const char *level, void *handle, const char *fmt, ...) {}\n#endif\t/* !CONFIG_ACPI */\n\n#if defined(CONFIG_ACPI) && defined(CONFIG_DYNAMIC_DEBUG)\n__printf(3, 4)\nvoid __acpi_handle_debug(struct _ddebug *descriptor, acpi_handle handle, const char *fmt, ...);\n#endif\n\n/*\n * acpi_handle_<level>: Print message with ACPI prefix and object path\n *\n * These interfaces acquire the global namespace mutex to obtain an object\n * path.  In interrupt context, it shows the object path as <n/a>.\n */\n#define acpi_handle_emerg(handle, fmt, ...)\t\t\t\t\\\n\tacpi_handle_printk(KERN_EMERG, handle, fmt, ##__VA_ARGS__)\n#define acpi_handle_alert(handle, fmt, ...)\t\t\t\t\\\n\tacpi_handle_printk(KERN_ALERT, handle, fmt, ##__VA_ARGS__)\n#define acpi_handle_crit(handle, fmt, ...)\t\t\t\t\\\n\tacpi_handle_printk(KERN_CRIT, handle, fmt, ##__VA_ARGS__)\n#define acpi_handle_err(handle, fmt, ...)\t\t\t\t\\\n\tacpi_handle_printk(KERN_ERR, handle, fmt, ##__VA_ARGS__)\n#define acpi_handle_warn(handle, fmt, ...)\t\t\t\t\\\n\tacpi_handle_printk(KERN_WARNING, handle, fmt, ##__VA_ARGS__)\n#define acpi_handle_notice(handle, fmt, ...)\t\t\t\t\\\n\tacpi_handle_printk(KERN_NOTICE, handle, fmt, ##__VA_ARGS__)\n#define acpi_handle_info(handle, fmt, ...)\t\t\t\t\\\n\tacpi_handle_printk(KERN_INFO, handle, fmt, ##__VA_ARGS__)\n\n#if defined(DEBUG)\n#define acpi_handle_debug(handle, fmt, ...)\t\t\t\t\\\n\tacpi_handle_printk(KERN_DEBUG, handle, fmt, ##__VA_ARGS__)\n#else\n#if defined(CONFIG_DYNAMIC_DEBUG)\n#define acpi_handle_debug(handle, fmt, ...)\t\t\t\t\\\n\t_dynamic_func_call(fmt, __acpi_handle_debug,\t\t\t\\\n\t\t\t   handle, pr_fmt(fmt), ##__VA_ARGS__)\n#else\n#define acpi_handle_debug(handle, fmt, ...)\t\t\t\t\\\n({\t\t\t\t\t\t\t\t\t\\\n\tif (0)\t\t\t\t\t\t\t\t\\\n\t\tacpi_handle_printk(KERN_DEBUG, handle, fmt, ##__VA_ARGS__); \\\n\t0;\t\t\t\t\t\t\t\t\\\n})\n#endif\n#endif\n\n#if defined(CONFIG_ACPI) && defined(CONFIG_GPIOLIB)\nbool acpi_gpio_get_irq_resource(struct acpi_resource *ares,\n\t\t\t\tstruct acpi_resource_gpio **agpio);\nint acpi_dev_gpio_irq_get(struct acpi_device *adev, int index);\n#else\nstatic inline bool acpi_gpio_get_irq_resource(struct acpi_resource *ares,\n\t\t\t\t\t      struct acpi_resource_gpio **agpio)\n{\n\treturn false;\n}\nstatic inline int acpi_dev_gpio_irq_get(struct acpi_device *adev, int index)\n{\n\treturn -ENXIO;\n}\n#endif\n\n/* Device properties */\n\n#ifdef CONFIG_ACPI\nint acpi_dev_get_property(const struct acpi_device *adev, const char *name,\n\t\t\t  acpi_object_type type, const union acpi_object **obj);\nint __acpi_node_get_property_reference(const struct fwnode_handle *fwnode,\n\t\t\t\tconst char *name, size_t index, size_t num_args,\n\t\t\t\tstruct fwnode_reference_args *args);\n\nstatic inline int acpi_node_get_property_reference(\n\t\t\t\tconst struct fwnode_handle *fwnode,\n\t\t\t\tconst char *name, size_t index,\n\t\t\t\tstruct fwnode_reference_args *args)\n{\n\treturn __acpi_node_get_property_reference(fwnode, name, index,\n\t\tNR_FWNODE_REFERENCE_ARGS, args);\n}\n\nstatic inline bool acpi_dev_has_props(const struct acpi_device *adev)\n{\n\treturn !list_empty(&adev->data.properties);\n}\n\nstruct acpi_device_properties *\nacpi_data_add_props(struct acpi_device_data *data, const guid_t *guid,\n\t\t    const union acpi_object *properties);\n\nint acpi_node_prop_get(const struct fwnode_handle *fwnode, const char *propname,\n\t\t       void **valptr);\nint acpi_dev_prop_read_single(struct acpi_device *adev,\n\t\t\t      const char *propname, enum dev_prop_type proptype,\n\t\t\t      void *val);\nint acpi_node_prop_read(const struct fwnode_handle *fwnode,\n\t\t\tconst char *propname, enum dev_prop_type proptype,\n\t\t\tvoid *val, size_t nval);\nint acpi_dev_prop_read(const struct acpi_device *adev, const char *propname,\n\t\t       enum dev_prop_type proptype, void *val, size_t nval);\n\nstruct fwnode_handle *acpi_get_next_subnode(const struct fwnode_handle *fwnode,\n\t\t\t\t\t    struct fwnode_handle *child);\nstruct fwnode_handle *acpi_node_get_parent(const struct fwnode_handle *fwnode);\n\nstruct acpi_probe_entry;\ntypedef bool (*acpi_probe_entry_validate_subtbl)(struct acpi_subtable_header *,\n\t\t\t\t\t\t struct acpi_probe_entry *);\n\n#define ACPI_TABLE_ID_LEN\t5\n\n/**\n * struct acpi_probe_entry - boot-time probing entry\n * @id:\t\t\tACPI table name\n * @type:\t\tOptional subtable type to match\n *\t\t\t(if @id contains subtables)\n * @subtable_valid:\tOptional callback to check the validity of\n *\t\t\tthe subtable\n * @probe_table:\tCallback to the driver being probed when table\n *\t\t\tmatch is successful\n * @probe_subtbl:\tCallback to the driver being probed when table and\n *\t\t\tsubtable match (and optional callback is successful)\n * @driver_data:\tSideband data provided back to the driver\n */\nstruct acpi_probe_entry {\n\t__u8 id[ACPI_TABLE_ID_LEN];\n\t__u8 type;\n\tacpi_probe_entry_validate_subtbl subtable_valid;\n\tunion {\n\t\tacpi_tbl_table_handler probe_table;\n\t\tacpi_tbl_entry_handler probe_subtbl;\n\t};\n\tkernel_ulong_t driver_data;\n};\n\n#define ACPI_DECLARE_PROBE_ENTRY(table, name, table_id, subtable, valid, data, fn)\t\\\n\tstatic const struct acpi_probe_entry __acpi_probe_##name\t\\\n\t\t__used __section(__##table##_acpi_probe_table)\t\t\\\n\t\t = {\t\t\t\t\t\t\t\\\n\t\t\t.id = table_id,\t\t\t\t\t\\\n\t\t\t.type = subtable,\t\t\t\t\\\n\t\t\t.subtable_valid = valid,\t\t\t\\\n\t\t\t.probe_table = (acpi_tbl_table_handler)fn,\t\\\n\t\t\t.driver_data = data, \t\t\t\t\\\n\t\t   }\n\n#define ACPI_PROBE_TABLE(name)\t\t__##name##_acpi_probe_table\n#define ACPI_PROBE_TABLE_END(name)\t__##name##_acpi_probe_table_end\n\nint __acpi_probe_device_table(struct acpi_probe_entry *start, int nr);\n\n#define acpi_probe_device_table(t)\t\t\t\t\t\\\n\t({ \t\t\t\t\t\t\t\t\\\n\t\textern struct acpi_probe_entry ACPI_PROBE_TABLE(t),\t\\\n\t\t\t                       ACPI_PROBE_TABLE_END(t);\t\\\n\t\t__acpi_probe_device_table(&ACPI_PROBE_TABLE(t),\t\t\\\n\t\t\t\t\t  (&ACPI_PROBE_TABLE_END(t) -\t\\\n\t\t\t\t\t   &ACPI_PROBE_TABLE(t)));\t\\\n\t})\n#else\nstatic inline int acpi_dev_get_property(struct acpi_device *adev,\n\t\t\t\t\tconst char *name, acpi_object_type type,\n\t\t\t\t\tconst union acpi_object **obj)\n{\n\treturn -ENXIO;\n}\n\nstatic inline int\n__acpi_node_get_property_reference(const struct fwnode_handle *fwnode,\n\t\t\t\tconst char *name, size_t index, size_t num_args,\n\t\t\t\tstruct fwnode_reference_args *args)\n{\n\treturn -ENXIO;\n}\n\nstatic inline int\nacpi_node_get_property_reference(const struct fwnode_handle *fwnode,\n\t\t\t\t const char *name, size_t index,\n\t\t\t\t struct fwnode_reference_args *args)\n{\n\treturn -ENXIO;\n}\n\nstatic inline int acpi_node_prop_get(const struct fwnode_handle *fwnode,\n\t\t\t\t     const char *propname,\n\t\t\t\t     void **valptr)\n{\n\treturn -ENXIO;\n}\n\nstatic inline int acpi_dev_prop_get(const struct acpi_device *adev,\n\t\t\t\t    const char *propname,\n\t\t\t\t    void **valptr)\n{\n\treturn -ENXIO;\n}\n\nstatic inline int acpi_dev_prop_read_single(const struct acpi_device *adev,\n\t\t\t\t\t    const char *propname,\n\t\t\t\t\t    enum dev_prop_type proptype,\n\t\t\t\t\t    void *val)\n{\n\treturn -ENXIO;\n}\n\nstatic inline int acpi_node_prop_read(const struct fwnode_handle *fwnode,\n\t\t\t\t      const char *propname,\n\t\t\t\t      enum dev_prop_type proptype,\n\t\t\t\t      void *val, size_t nval)\n{\n\treturn -ENXIO;\n}\n\nstatic inline int acpi_dev_prop_read(const struct acpi_device *adev,\n\t\t\t\t     const char *propname,\n\t\t\t\t     enum dev_prop_type proptype,\n\t\t\t\t     void *val, size_t nval)\n{\n\treturn -ENXIO;\n}\n\nstatic inline struct fwnode_handle *\nacpi_get_next_subnode(const struct fwnode_handle *fwnode,\n\t\t      struct fwnode_handle *child)\n{\n\treturn NULL;\n}\n\nstatic inline struct fwnode_handle *\nacpi_node_get_parent(const struct fwnode_handle *fwnode)\n{\n\treturn NULL;\n}\n\nstatic inline struct fwnode_handle *\nacpi_graph_get_next_endpoint(const struct fwnode_handle *fwnode,\n\t\t\t     struct fwnode_handle *prev)\n{\n\treturn ERR_PTR(-ENXIO);\n}\n\nstatic inline int\nacpi_graph_get_remote_endpoint(const struct fwnode_handle *fwnode,\n\t\t\t       struct fwnode_handle **remote,\n\t\t\t       struct fwnode_handle **port,\n\t\t\t       struct fwnode_handle **endpoint)\n{\n\treturn -ENXIO;\n}\n\n#define ACPI_DECLARE_PROBE_ENTRY(table, name, table_id, subtable, valid, data, fn) \\\n\tstatic const void * __acpi_table_##name[]\t\t\t\\\n\t\t__attribute__((unused))\t\t\t\t\t\\\n\t\t = { (void *) table_id,\t\t\t\t\t\\\n\t\t     (void *) subtable,\t\t\t\t\t\\\n\t\t     (void *) valid,\t\t\t\t\t\\\n\t\t     (void *) fn,\t\t\t\t\t\\\n\t\t     (void *) data }\n\n#define acpi_probe_device_table(t)\t({ int __r = 0; __r;})\n#endif\n\n#ifdef CONFIG_ACPI_TABLE_UPGRADE\nvoid acpi_table_upgrade(void);\n#else\nstatic inline void acpi_table_upgrade(void) { }\n#endif\n\n#if defined(CONFIG_ACPI) && defined(CONFIG_ACPI_WATCHDOG)\nextern bool acpi_has_watchdog(void);\n#else\nstatic inline bool acpi_has_watchdog(void) { return false; }\n#endif\n\n#ifdef CONFIG_ACPI_SPCR_TABLE\nextern bool qdf2400_e44_present;\nint acpi_parse_spcr(bool enable_earlycon, bool enable_console);\n#else\nstatic inline int acpi_parse_spcr(bool enable_earlycon, bool enable_console)\n{\n\treturn 0;\n}\n#endif\n\n#if IS_ENABLED(CONFIG_ACPI_GENERIC_GSI)\nint acpi_irq_get(acpi_handle handle, unsigned int index, struct resource *res);\n#else\nstatic inline\nint acpi_irq_get(acpi_handle handle, unsigned int index, struct resource *res)\n{\n\treturn -EINVAL;\n}\n#endif\n\n#ifdef CONFIG_ACPI_LPIT\nint lpit_read_residency_count_address(u64 *address);\n#else\nstatic inline int lpit_read_residency_count_address(u64 *address)\n{\n\treturn -EINVAL;\n}\n#endif\n\n#ifdef CONFIG_ACPI_PPTT\nint acpi_pptt_cpu_is_thread(unsigned int cpu);\nint find_acpi_cpu_topology(unsigned int cpu, int level);\nint find_acpi_cpu_topology_package(unsigned int cpu);\nint find_acpi_cpu_topology_hetero_id(unsigned int cpu);\nint find_acpi_cpu_cache_topology(unsigned int cpu, int level);\n#else\nstatic inline int acpi_pptt_cpu_is_thread(unsigned int cpu)\n{\n\treturn -EINVAL;\n}\nstatic inline int find_acpi_cpu_topology(unsigned int cpu, int level)\n{\n\treturn -EINVAL;\n}\nstatic inline int find_acpi_cpu_topology_package(unsigned int cpu)\n{\n\treturn -EINVAL;\n}\nstatic inline int find_acpi_cpu_topology_hetero_id(unsigned int cpu)\n{\n\treturn -EINVAL;\n}\nstatic inline int find_acpi_cpu_cache_topology(unsigned int cpu, int level)\n{\n\treturn -EINVAL;\n}\n#endif\n\n#ifdef CONFIG_ACPI\nextern int acpi_platform_notify(struct device *dev, enum kobject_action action);\n#else\nstatic inline int\nacpi_platform_notify(struct device *dev, enum kobject_action action)\n{\n\treturn 0;\n}\n#endif\n\n#endif\t/*_LINUX_ACPI_H*/\n"
  },
  {
    "path": "t/tree/include/linux/apm_bios.h",
    "content": "/* SPDX-License-Identifier: GPL-2.0-or-later */\n/*\n * Include file for the interface to an APM BIOS\n * Copyright 1994-2001 Stephen Rothwell (sfr@canb.auug.org.au)\n */\n#ifndef _LINUX_APM_H\n#define _LINUX_APM_H\n\n#include <uapi/linux/apm_bios.h>\n\n\n#define APM_CS\t\t(GDT_ENTRY_APMBIOS_BASE * 8)\n#define APM_CS_16\t(APM_CS + 8)\n#define APM_DS\t\t(APM_CS_16 + 8)\n\n/* Results of APM Installation Check */\n#define APM_16_BIT_SUPPORT\t0x0001\n#define APM_32_BIT_SUPPORT\t0x0002\n#define APM_IDLE_SLOWS_CLOCK\t0x0004\n#define APM_BIOS_DISABLED      \t0x0008\n#define APM_BIOS_DISENGAGED     0x0010\n\n/*\n * Data for APM that is persistent across module unload/load\n */\nstruct apm_info {\n\tstruct apm_bios_info\tbios;\n\tunsigned short\t\tconnection_version;\n\tint\t\t\tget_power_status_broken;\n\tint\t\t\tget_power_status_swabinminutes;\n\tint\t\t\tallow_ints;\n\tint\t\t\tforbid_idle;\n\tint\t\t\trealmode_power_off;\n\tint\t\t\tdisabled;\n};\n\n/*\n * The APM function codes\n */\n#define\tAPM_FUNC_INST_CHECK\t0x5300\n#define\tAPM_FUNC_REAL_CONN\t0x5301\n#define\tAPM_FUNC_16BIT_CONN\t0x5302\n#define\tAPM_FUNC_32BIT_CONN\t0x5303\n#define\tAPM_FUNC_DISCONN\t0x5304\n#define\tAPM_FUNC_IDLE\t\t0x5305\n#define\tAPM_FUNC_BUSY\t\t0x5306\n#define\tAPM_FUNC_SET_STATE\t0x5307\n#define\tAPM_FUNC_ENABLE_PM\t0x5308\n#define\tAPM_FUNC_RESTORE_BIOS\t0x5309\n#define\tAPM_FUNC_GET_STATUS\t0x530a\n#define\tAPM_FUNC_GET_EVENT\t0x530b\n#define\tAPM_FUNC_GET_STATE\t0x530c\n#define\tAPM_FUNC_ENABLE_DEV_PM\t0x530d\n#define\tAPM_FUNC_VERSION\t0x530e\n#define\tAPM_FUNC_ENGAGE_PM\t0x530f\n#define\tAPM_FUNC_GET_CAP\t0x5310\n#define\tAPM_FUNC_RESUME_TIMER\t0x5311\n#define\tAPM_FUNC_RESUME_ON_RING\t0x5312\n#define\tAPM_FUNC_TIMER\t\t0x5313\n\n/*\n * Function code for APM_FUNC_RESUME_TIMER\n */\n#define\tAPM_FUNC_DISABLE_TIMER\t0\n#define\tAPM_FUNC_GET_TIMER\t1\n#define\tAPM_FUNC_SET_TIMER\t2\n\n/*\n * Function code for APM_FUNC_RESUME_ON_RING\n */\n#define\tAPM_FUNC_DISABLE_RING\t0\n#define\tAPM_FUNC_ENABLE_RING\t1\n#define\tAPM_FUNC_GET_RING\t2\n\n/*\n * Function code for APM_FUNC_TIMER_STATUS\n */\n#define\tAPM_FUNC_TIMER_DISABLE\t0\n#define\tAPM_FUNC_TIMER_ENABLE\t1\n#define\tAPM_FUNC_TIMER_GET\t2\n\n/*\n * in arch/i386/kernel/setup.c\n */\nextern struct apm_info\tapm_info;\n\n/*\n * This is the \"All Devices\" ID communicated to the BIOS\n */\n#define APM_DEVICE_BALL\t\t((apm_info.connection_version > 0x0100) ? \\\n\t\t\t\t APM_DEVICE_ALL : APM_DEVICE_OLD_ALL)\n#endif\t/* LINUX_APM_H */\n"
  },
  {
    "path": "t/tree/include/linux/assoc_array.h",
    "content": "/* SPDX-License-Identifier: GPL-2.0-or-later */\n/* Generic associative array implementation.\n *\n * See Documentation/core-api/assoc_array.rst for information.\n *\n * Copyright (C) 2013 Red Hat, Inc. All Rights Reserved.\n * Written by David Howells (dhowells@redhat.com)\n */\n\n#ifndef _LINUX_ASSOC_ARRAY_H\n#define _LINUX_ASSOC_ARRAY_H\n\n#ifdef CONFIG_ASSOCIATIVE_ARRAY\n\n#include <linux/types.h>\n\n#define ASSOC_ARRAY_KEY_CHUNK_SIZE BITS_PER_LONG /* Key data retrieved in chunks of this size */\n\n/*\n * Generic associative array.\n */\nstruct assoc_array {\n\tstruct assoc_array_ptr\t*root;\t\t/* The node at the root of the tree */\n\tunsigned long\t\tnr_leaves_on_tree;\n};\n\n/*\n * Operations on objects and index keys for use by array manipulation routines.\n */\nstruct assoc_array_ops {\n\t/* Method to get a chunk of an index key from caller-supplied data */\n\tunsigned long (*get_key_chunk)(const void *index_key, int level);\n\n\t/* Method to get a piece of an object's index key */\n\tunsigned long (*get_object_key_chunk)(const void *object, int level);\n\n\t/* Is this the object we're looking for? */\n\tbool (*compare_object)(const void *object, const void *index_key);\n\n\t/* How different is an object from an index key, to a bit position in\n\t * their keys? (or -1 if they're the same)\n\t */\n\tint (*diff_objects)(const void *object, const void *index_key);\n\n\t/* Method to free an object. */\n\tvoid (*free_object)(void *object);\n};\n\n/*\n * Access and manipulation functions.\n */\nstruct assoc_array_edit;\n\nstatic inline void assoc_array_init(struct assoc_array *array)\n{\n\tarray->root = NULL;\n\tarray->nr_leaves_on_tree = 0;\n}\n\nextern int assoc_array_iterate(const struct assoc_array *array,\n\t\t\t       int (*iterator)(const void *object,\n\t\t\t\t\t       void *iterator_data),\n\t\t\t       void *iterator_data);\nextern void *assoc_array_find(const struct assoc_array *array,\n\t\t\t      const struct assoc_array_ops *ops,\n\t\t\t      const void *index_key);\nextern void assoc_array_destroy(struct assoc_array *array,\n\t\t\t\tconst struct assoc_array_ops *ops);\nextern struct assoc_array_edit *assoc_array_insert(struct assoc_array *array,\n\t\t\t\t\t\t   const struct assoc_array_ops *ops,\n\t\t\t\t\t\t   const void *index_key,\n\t\t\t\t\t\t   void *object);\nextern void assoc_array_insert_set_object(struct assoc_array_edit *edit,\n\t\t\t\t\t  void *object);\nextern struct assoc_array_edit *assoc_array_delete(struct assoc_array *array,\n\t\t\t\t\t\t   const struct assoc_array_ops *ops,\n\t\t\t\t\t\t   const void *index_key);\nextern struct assoc_array_edit *assoc_array_clear(struct assoc_array *array,\n\t\t\t\t\t\t  const struct assoc_array_ops *ops);\nextern void assoc_array_apply_edit(struct assoc_array_edit *edit);\nextern void assoc_array_cancel_edit(struct assoc_array_edit *edit);\nextern int assoc_array_gc(struct assoc_array *array,\n\t\t\t  const struct assoc_array_ops *ops,\n\t\t\t  bool (*iterator)(void *object, void *iterator_data),\n\t\t\t  void *iterator_data);\n\n#endif /* CONFIG_ASSOCIATIVE_ARRAY */\n#endif /* _LINUX_ASSOC_ARRAY_H */\n"
  },
  {
    "path": "t/tree/include/linux/cred.h",
    "content": "/* SPDX-License-Identifier: GPL-2.0-or-later */\n/* Credentials management - see Documentation/security/credentials.rst\n *\n * Copyright (C) 2008 Red Hat, Inc. All Rights Reserved.\n * Written by David Howells (dhowells@redhat.com)\n */\n\n#ifndef _LINUX_CRED_H\n#define _LINUX_CRED_H\n\n#include <linux/capability.h>\n#include <linux/init.h>\n#include <linux/key.h>\n#include <linux/atomic.h>\n#include <linux/uidgid.h>\n#include <linux/sched.h>\n#include <linux/sched/user.h>\n\nstruct cred;\nstruct inode;\n\n/*\n * COW Supplementary groups list\n */\nstruct group_info {\n\tatomic_t\tusage;\n\tint\t\tngroups;\n\tkgid_t\t\tgid[0];\n} __randomize_layout;\n\n/**\n * get_group_info - Get a reference to a group info structure\n * @group_info: The group info to reference\n *\n * This gets a reference to a set of supplementary groups.\n *\n * If the caller is accessing a task's credentials, they must hold the RCU read\n * lock when reading.\n */\nstatic inline struct group_info *get_group_info(struct group_info *gi)\n{\n\tatomic_inc(&gi->usage);\n\treturn gi;\n}\n\n/**\n * put_group_info - Release a reference to a group info structure\n * @group_info: The group info to release\n */\n#define put_group_info(group_info)\t\t\t\\\ndo {\t\t\t\t\t\t\t\\\n\tif (atomic_dec_and_test(&(group_info)->usage))\t\\\n\t\tgroups_free(group_info);\t\t\\\n} while (0)\n\nextern struct group_info init_groups;\n#ifdef CONFIG_MULTIUSER\nextern struct group_info *groups_alloc(int);\nextern void groups_free(struct group_info *);\n\nextern int in_group_p(kgid_t);\nextern int in_egroup_p(kgid_t);\nextern int groups_search(const struct group_info *, kgid_t);\n\nextern int set_current_groups(struct group_info *);\nextern void set_groups(struct cred *, struct group_info *);\nextern bool may_setgroups(void);\nextern void groups_sort(struct group_info *);\n#else\nstatic inline void groups_free(struct group_info *group_info)\n{\n}\n\nstatic inline int in_group_p(kgid_t grp)\n{\n        return 1;\n}\nstatic inline int in_egroup_p(kgid_t grp)\n{\n        return 1;\n}\nstatic inline int groups_search(const struct group_info *group_info, kgid_t grp)\n{\n\treturn 1;\n}\n#endif\n\n/*\n * The security context of a task\n *\n * The parts of the context break down into two categories:\n *\n *  (1) The objective context of a task.  These parts are used when some other\n *\ttask is attempting to affect this one.\n *\n *  (2) The subjective context.  These details are used when the task is acting\n *\tupon another object, be that a file, a task, a key or whatever.\n *\n * Note that some members of this structure belong to both categories - the\n * LSM security pointer for instance.\n *\n * A task has two security pointers.  task->real_cred points to the objective\n * context that defines that task's actual details.  The objective part of this\n * context is used whenever that task is acted upon.\n *\n * task->cred points to the subjective context that defines the details of how\n * that task is going to act upon another object.  This may be overridden\n * temporarily to point to another security context, but normally points to the\n * same context as task->real_cred.\n */\nstruct cred {\n\tatomic_t\tusage;\n#ifdef CONFIG_DEBUG_CREDENTIALS\n\tatomic_t\tsubscribers;\t/* number of processes subscribed */\n\tvoid\t\t*put_addr;\n\tunsigned\tmagic;\n#define CRED_MAGIC\t0x43736564\n#define CRED_MAGIC_DEAD\t0x44656144\n#endif\n\tkuid_t\t\tuid;\t\t/* real UID of the task */\n\tkgid_t\t\tgid;\t\t/* real GID of the task */\n\tkuid_t\t\tsuid;\t\t/* saved UID of the task */\n\tkgid_t\t\tsgid;\t\t/* saved GID of the task */\n\tkuid_t\t\teuid;\t\t/* effective UID of the task */\n\tkgid_t\t\tegid;\t\t/* effective GID of the task */\n\tkuid_t\t\tfsuid;\t\t/* UID for VFS ops */\n\tkgid_t\t\tfsgid;\t\t/* GID for VFS ops */\n\tunsigned\tsecurebits;\t/* SUID-less security management */\n\tkernel_cap_t\tcap_inheritable; /* caps our children can inherit */\n\tkernel_cap_t\tcap_permitted;\t/* caps we're permitted */\n\tkernel_cap_t\tcap_effective;\t/* caps we can actually use */\n\tkernel_cap_t\tcap_bset;\t/* capability bounding set */\n\tkernel_cap_t\tcap_ambient;\t/* Ambient capability set */\n#ifdef CONFIG_KEYS\n\tunsigned char\tjit_keyring;\t/* default keyring to attach requested\n\t\t\t\t\t * keys to */\n\tstruct key\t*session_keyring; /* keyring inherited over fork */\n\tstruct key\t*process_keyring; /* keyring private to this process */\n\tstruct key\t*thread_keyring; /* keyring private to this thread */\n\tstruct key\t*request_key_auth; /* assumed request_key authority */\n#endif\n#ifdef CONFIG_SECURITY\n\tvoid\t\t*security;\t/* subjective LSM security */\n#endif\n\tstruct user_struct *user;\t/* real user ID subscription */\n\tstruct user_namespace *user_ns; /* user_ns the caps and keyrings are relative to. */\n\tstruct group_info *group_info;\t/* supplementary groups for euid/fsgid */\n\t/* RCU deletion */\n\tunion {\n\t\tint non_rcu;\t\t\t/* Can we skip RCU deletion? */\n\t\tstruct rcu_head\trcu;\t\t/* RCU deletion hook */\n\t};\n} __randomize_layout;\n\nextern void __put_cred(struct cred *);\nextern void exit_creds(struct task_struct *);\nextern int copy_creds(struct task_struct *, unsigned long);\nextern const struct cred *get_task_cred(struct task_struct *);\nextern struct cred *cred_alloc_blank(void);\nextern struct cred *prepare_creds(void);\nextern struct cred *prepare_exec_creds(void);\nextern int commit_creds(struct cred *);\nextern void abort_creds(struct cred *);\nextern const struct cred *override_creds(const struct cred *);\nextern void revert_creds(const struct cred *);\nextern struct cred *prepare_kernel_cred(struct task_struct *);\nextern int change_create_files_as(struct cred *, struct inode *);\nextern int set_security_override(struct cred *, u32);\nextern int set_security_override_from_ctx(struct cred *, const char *);\nextern int set_create_files_as(struct cred *, struct inode *);\nextern int cred_fscmp(const struct cred *, const struct cred *);\nextern void __init cred_init(void);\n\n/*\n * check for validity of credentials\n */\n#ifdef CONFIG_DEBUG_CREDENTIALS\nextern void __invalid_creds(const struct cred *, const char *, unsigned);\nextern void __validate_process_creds(struct task_struct *,\n\t\t\t\t     const char *, unsigned);\n\nextern bool creds_are_invalid(const struct cred *cred);\n\nstatic inline void __validate_creds(const struct cred *cred,\n\t\t\t\t    const char *file, unsigned line)\n{\n\tif (unlikely(creds_are_invalid(cred)))\n\t\t__invalid_creds(cred, file, line);\n}\n\n#define validate_creds(cred)\t\t\t\t\\\ndo {\t\t\t\t\t\t\t\\\n\t__validate_creds((cred), __FILE__, __LINE__);\t\\\n} while(0)\n\n#define validate_process_creds()\t\t\t\t\\\ndo {\t\t\t\t\t\t\t\t\\\n\t__validate_process_creds(current, __FILE__, __LINE__);\t\\\n} while(0)\n\nextern void validate_creds_for_do_exit(struct task_struct *);\n#else\nstatic inline void validate_creds(const struct cred *cred)\n{\n}\nstatic inline void validate_creds_for_do_exit(struct task_struct *tsk)\n{\n}\nstatic inline void validate_process_creds(void)\n{\n}\n#endif\n\nstatic inline bool cap_ambient_invariant_ok(const struct cred *cred)\n{\n\treturn cap_issubset(cred->cap_ambient,\n\t\t\t    cap_intersect(cred->cap_permitted,\n\t\t\t\t\t  cred->cap_inheritable));\n}\n\n/**\n * get_new_cred - Get a reference on a new set of credentials\n * @cred: The new credentials to reference\n *\n * Get a reference on the specified set of new credentials.  The caller must\n * release the reference.\n */\nstatic inline struct cred *get_new_cred(struct cred *cred)\n{\n\tatomic_inc(&cred->usage);\n\treturn cred;\n}\n\n/**\n * get_cred - Get a reference on a set of credentials\n * @cred: The credentials to reference\n *\n * Get a reference on the specified set of credentials.  The caller must\n * release the reference.  If %NULL is passed, it is returned with no action.\n *\n * This is used to deal with a committed set of credentials.  Although the\n * pointer is const, this will temporarily discard the const and increment the\n * usage count.  The purpose of this is to attempt to catch at compile time the\n * accidental alteration of a set of credentials that should be considered\n * immutable.\n */\nstatic inline const struct cred *get_cred(const struct cred *cred)\n{\n\tstruct cred *nonconst_cred = (struct cred *) cred;\n\tif (!cred)\n\t\treturn cred;\n\tvalidate_creds(cred);\n\tnonconst_cred->non_rcu = 0;\n\treturn get_new_cred(nonconst_cred);\n}\n\nstatic inline const struct cred *get_cred_rcu(const struct cred *cred)\n{\n\tstruct cred *nonconst_cred = (struct cred *) cred;\n\tif (!cred)\n\t\treturn NULL;\n\tif (!atomic_inc_not_zero(&nonconst_cred->usage))\n\t\treturn NULL;\n\tvalidate_creds(cred);\n\tnonconst_cred->non_rcu = 0;\n\treturn cred;\n}\n\n/**\n * put_cred - Release a reference to a set of credentials\n * @cred: The credentials to release\n *\n * Release a reference to a set of credentials, deleting them when the last ref\n * is released.  If %NULL is passed, nothing is done.\n *\n * This takes a const pointer to a set of credentials because the credentials\n * on task_struct are attached by const pointers to prevent accidental\n * alteration of otherwise immutable credential sets.\n */\nstatic inline void put_cred(const struct cred *_cred)\n{\n\tstruct cred *cred = (struct cred *) _cred;\n\n\tif (cred) {\n\t\tvalidate_creds(cred);\n\t\tif (atomic_dec_and_test(&(cred)->usage))\n\t\t\t__put_cred(cred);\n\t}\n}\n\n/**\n * current_cred - Access the current task's subjective credentials\n *\n * Access the subjective credentials of the current task.  RCU-safe,\n * since nobody else can modify it.\n */\n#define current_cred() \\\n\trcu_dereference_protected(current->cred, 1)\n\n/**\n * current_real_cred - Access the current task's objective credentials\n *\n * Access the objective credentials of the current task.  RCU-safe,\n * since nobody else can modify it.\n */\n#define current_real_cred() \\\n\trcu_dereference_protected(current->real_cred, 1)\n\n/**\n * __task_cred - Access a task's objective credentials\n * @task: The task to query\n *\n * Access the objective credentials of a task.  The caller must hold the RCU\n * readlock.\n *\n * The result of this function should not be passed directly to get_cred();\n * rather get_task_cred() should be used instead.\n */\n#define __task_cred(task)\t\\\n\trcu_dereference((task)->real_cred)\n\n/**\n * get_current_cred - Get the current task's subjective credentials\n *\n * Get the subjective credentials of the current task, pinning them so that\n * they can't go away.  Accessing the current task's credentials directly is\n * not permitted.\n */\n#define get_current_cred()\t\t\t\t\\\n\t(get_cred(current_cred()))\n\n/**\n * get_current_user - Get the current task's user_struct\n *\n * Get the user record of the current task, pinning it so that it can't go\n * away.\n */\n#define get_current_user()\t\t\t\t\\\n({\t\t\t\t\t\t\t\\\n\tstruct user_struct *__u;\t\t\t\\\n\tconst struct cred *__cred;\t\t\t\\\n\t__cred = current_cred();\t\t\t\\\n\t__u = get_uid(__cred->user);\t\t\t\\\n\t__u;\t\t\t\t\t\t\\\n})\n\n/**\n * get_current_groups - Get the current task's supplementary group list\n *\n * Get the supplementary group list of the current task, pinning it so that it\n * can't go away.\n */\n#define get_current_groups()\t\t\t\t\\\n({\t\t\t\t\t\t\t\\\n\tstruct group_info *__groups;\t\t\t\\\n\tconst struct cred *__cred;\t\t\t\\\n\t__cred = current_cred();\t\t\t\\\n\t__groups = get_group_info(__cred->group_info);\t\\\n\t__groups;\t\t\t\t\t\\\n})\n\n#define task_cred_xxx(task, xxx)\t\t\t\\\n({\t\t\t\t\t\t\t\\\n\t__typeof__(((struct cred *)NULL)->xxx) ___val;\t\\\n\trcu_read_lock();\t\t\t\t\\\n\t___val = __task_cred((task))->xxx;\t\t\\\n\trcu_read_unlock();\t\t\t\t\\\n\t___val;\t\t\t\t\t\t\\\n})\n\n#define task_uid(task)\t\t(task_cred_xxx((task), uid))\n#define task_euid(task)\t\t(task_cred_xxx((task), euid))\n\n#define current_cred_xxx(xxx)\t\t\t\\\n({\t\t\t\t\t\t\\\n\tcurrent_cred()->xxx;\t\t\t\\\n})\n\n#define current_uid()\t\t(current_cred_xxx(uid))\n#define current_gid()\t\t(current_cred_xxx(gid))\n#define current_euid()\t\t(current_cred_xxx(euid))\n#define current_egid()\t\t(current_cred_xxx(egid))\n#define current_suid()\t\t(current_cred_xxx(suid))\n#define current_sgid()\t\t(current_cred_xxx(sgid))\n#define current_fsuid() \t(current_cred_xxx(fsuid))\n#define current_fsgid() \t(current_cred_xxx(fsgid))\n#define current_cap()\t\t(current_cred_xxx(cap_effective))\n#define current_user()\t\t(current_cred_xxx(user))\n\nextern struct user_namespace init_user_ns;\n#ifdef CONFIG_USER_NS\n#define current_user_ns()\t(current_cred_xxx(user_ns))\n#else\nstatic inline struct user_namespace *current_user_ns(void)\n{\n\treturn &init_user_ns;\n}\n#endif\n\n\n#define current_uid_gid(_uid, _gid)\t\t\\\ndo {\t\t\t\t\t\t\\\n\tconst struct cred *__cred;\t\t\\\n\t__cred = current_cred();\t\t\\\n\t*(_uid) = __cred->uid;\t\t\t\\\n\t*(_gid) = __cred->gid;\t\t\t\\\n} while(0)\n\n#define current_euid_egid(_euid, _egid)\t\t\\\ndo {\t\t\t\t\t\t\\\n\tconst struct cred *__cred;\t\t\\\n\t__cred = current_cred();\t\t\\\n\t*(_euid) = __cred->euid;\t\t\\\n\t*(_egid) = __cred->egid;\t\t\\\n} while(0)\n\n#define current_fsuid_fsgid(_fsuid, _fsgid)\t\\\ndo {\t\t\t\t\t\t\\\n\tconst struct cred *__cred;\t\t\\\n\t__cred = current_cred();\t\t\\\n\t*(_fsuid) = __cred->fsuid;\t\t\\\n\t*(_fsgid) = __cred->fsgid;\t\t\\\n} while(0)\n\n#endif /* _LINUX_CRED_H */\n"
  },
  {
    "path": "t/tree/include/linux/i2c-smbus.h",
    "content": "/* SPDX-License-Identifier: GPL-2.0-or-later */\n/*\n * i2c-smbus.h - SMBus extensions to the I2C protocol\n *\n * Copyright (C) 2010 Jean Delvare <jdelvare@suse.de>\n */\n\n#ifndef _LINUX_I2C_SMBUS_H\n#define _LINUX_I2C_SMBUS_H\n\n#include <linux/i2c.h>\n#include <linux/spinlock.h>\n#include <linux/workqueue.h>\n\n\n/**\n * i2c_smbus_alert_setup - platform data for the smbus_alert i2c client\n * @alert_edge_triggered: whether the alert interrupt is edge (1) or level (0)\n *\t\ttriggered\n * @irq: IRQ number, if the smbus_alert driver should take care of interrupt\n *\t\thandling\n *\n * If irq is not specified, the smbus_alert driver doesn't take care of\n * interrupt handling. In that case it is up to the I2C bus driver to either\n * handle the interrupts or to poll for alerts.\n *\n * If irq is specified then it it crucial that alert_edge_triggered is\n * properly set.\n */\nstruct i2c_smbus_alert_setup {\n\tint\t\t\tirq;\n};\n\nstruct i2c_client *i2c_setup_smbus_alert(struct i2c_adapter *adapter,\n\t\t\t\t\t struct i2c_smbus_alert_setup *setup);\nint i2c_handle_smbus_alert(struct i2c_client *ara);\n\n#if IS_ENABLED(CONFIG_I2C_SMBUS) && IS_ENABLED(CONFIG_OF)\nint of_i2c_setup_smbus_alert(struct i2c_adapter *adap);\n#else\nstatic inline int of_i2c_setup_smbus_alert(struct i2c_adapter *adap)\n{\n\treturn 0;\n}\n#endif\n\n#endif /* _LINUX_I2C_SMBUS_H */\n"
  },
  {
    "path": "t/tree/include/linux/i2c.h",
    "content": "/* SPDX-License-Identifier: GPL-2.0-or-later */\n/*\n * i2c.h - definitions for the Linux i2c bus interface\n * Copyright (C) 1995-2000 Simon G. Vogl\n * Copyright (C) 2013-2019 Wolfram Sang <wsa@the-dreams.de>\n *\n * With some changes from Kyösti Mälkki <kmalkki@cc.hut.fi> and\n * Frodo Looijaard <frodol@dds.nl>\n */\n#ifndef _LINUX_I2C_H\n#define _LINUX_I2C_H\n\n#include <linux/acpi.h>\t\t/* for acpi_handle */\n#include <linux/mod_devicetable.h>\n#include <linux/device.h>\t/* for struct device */\n#include <linux/sched.h>\t/* for completion */\n#include <linux/mutex.h>\n#include <linux/rtmutex.h>\n#include <linux/irqdomain.h>\t\t/* for Host Notify IRQ */\n#include <linux/of.h>\t\t/* for struct device_node */\n#include <linux/swab.h>\t\t/* for swab16 */\n#include <uapi/linux/i2c.h>\n\nextern struct bus_type i2c_bus_type;\nextern struct device_type i2c_adapter_type;\nextern struct device_type i2c_client_type;\n\n/* --- General options ------------------------------------------------\t*/\n\nstruct i2c_msg;\nstruct i2c_algorithm;\nstruct i2c_adapter;\nstruct i2c_client;\nstruct i2c_driver;\nstruct i2c_device_identity;\nunion i2c_smbus_data;\nstruct i2c_board_info;\nenum i2c_slave_event;\ntypedef int (*i2c_slave_cb_t)(struct i2c_client *client,\n\t\t\t      enum i2c_slave_event event, u8 *val);\n\nstruct module;\nstruct property_entry;\n\n#if IS_ENABLED(CONFIG_I2C)\n/*\n * The master routines are the ones normally used to transmit data to devices\n * on a bus (or read from them). Apart from two basic transfer functions to\n * transmit one message at a time, a more complex version can be used to\n * transmit an arbitrary number of messages without interruption.\n * @count must be be less than 64k since msg.len is u16.\n */\nextern int i2c_transfer_buffer_flags(const struct i2c_client *client,\n\t\t\t\t     char *buf, int count, u16 flags);\n\n/**\n * i2c_master_recv - issue a single I2C message in master receive mode\n * @client: Handle to slave device\n * @buf: Where to store data read from slave\n * @count: How many bytes to read, must be less than 64k since msg.len is u16\n *\n * Returns negative errno, or else the number of bytes read.\n */\nstatic inline int i2c_master_recv(const struct i2c_client *client,\n\t\t\t\t  char *buf, int count)\n{\n\treturn i2c_transfer_buffer_flags(client, buf, count, I2C_M_RD);\n};\n\n/**\n * i2c_master_recv_dmasafe - issue a single I2C message in master receive mode\n *\t\t\t     using a DMA safe buffer\n * @client: Handle to slave device\n * @buf: Where to store data read from slave, must be safe to use with DMA\n * @count: How many bytes to read, must be less than 64k since msg.len is u16\n *\n * Returns negative errno, or else the number of bytes read.\n */\nstatic inline int i2c_master_recv_dmasafe(const struct i2c_client *client,\n\t\t\t\t\t  char *buf, int count)\n{\n\treturn i2c_transfer_buffer_flags(client, buf, count,\n\t\t\t\t\t I2C_M_RD | I2C_M_DMA_SAFE);\n};\n\n/**\n * i2c_master_send - issue a single I2C message in master transmit mode\n * @client: Handle to slave device\n * @buf: Data that will be written to the slave\n * @count: How many bytes to write, must be less than 64k since msg.len is u16\n *\n * Returns negative errno, or else the number of bytes written.\n */\nstatic inline int i2c_master_send(const struct i2c_client *client,\n\t\t\t\t  const char *buf, int count)\n{\n\treturn i2c_transfer_buffer_flags(client, (char *)buf, count, 0);\n};\n\n/**\n * i2c_master_send_dmasafe - issue a single I2C message in master transmit mode\n *\t\t\t     using a DMA safe buffer\n * @client: Handle to slave device\n * @buf: Data that will be written to the slave, must be safe to use with DMA\n * @count: How many bytes to write, must be less than 64k since msg.len is u16\n *\n * Returns negative errno, or else the number of bytes written.\n */\nstatic inline int i2c_master_send_dmasafe(const struct i2c_client *client,\n\t\t\t\t\t  const char *buf, int count)\n{\n\treturn i2c_transfer_buffer_flags(client, (char *)buf, count,\n\t\t\t\t\t I2C_M_DMA_SAFE);\n};\n\n/* Transfer num messages.\n */\nextern int i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs,\n\t\t\tint num);\n/* Unlocked flavor */\nextern int __i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs,\n\t\t\t  int num);\n\n/* This is the very generalized SMBus access routine. You probably do not\n   want to use this, though; one of the functions below may be much easier,\n   and probably just as fast.\n   Note that we use i2c_adapter here, because you do not need a specific\n   smbus adapter to call this function. */\ns32 i2c_smbus_xfer(struct i2c_adapter *adapter, u16 addr,\n\t\t   unsigned short flags, char read_write, u8 command,\n\t\t   int protocol, union i2c_smbus_data *data);\n\n/* Unlocked flavor */\ns32 __i2c_smbus_xfer(struct i2c_adapter *adapter, u16 addr,\n\t\t     unsigned short flags, char read_write, u8 command,\n\t\t     int protocol, union i2c_smbus_data *data);\n\n/* Now follow the 'nice' access routines. These also document the calling\n   conventions of i2c_smbus_xfer. */\n\nextern s32 i2c_smbus_read_byte(const struct i2c_client *client);\nextern s32 i2c_smbus_write_byte(const struct i2c_client *client, u8 value);\nextern s32 i2c_smbus_read_byte_data(const struct i2c_client *client,\n\t\t\t\t    u8 command);\nextern s32 i2c_smbus_write_byte_data(const struct i2c_client *client,\n\t\t\t\t     u8 command, u8 value);\nextern s32 i2c_smbus_read_word_data(const struct i2c_client *client,\n\t\t\t\t    u8 command);\nextern s32 i2c_smbus_write_word_data(const struct i2c_client *client,\n\t\t\t\t     u8 command, u16 value);\n\nstatic inline s32\ni2c_smbus_read_word_swapped(const struct i2c_client *client, u8 command)\n{\n\ts32 value = i2c_smbus_read_word_data(client, command);\n\n\treturn (value < 0) ? value : swab16(value);\n}\n\nstatic inline s32\ni2c_smbus_write_word_swapped(const struct i2c_client *client,\n\t\t\t     u8 command, u16 value)\n{\n\treturn i2c_smbus_write_word_data(client, command, swab16(value));\n}\n\n/* Returns the number of read bytes */\nextern s32 i2c_smbus_read_block_data(const struct i2c_client *client,\n\t\t\t\t     u8 command, u8 *values);\nextern s32 i2c_smbus_write_block_data(const struct i2c_client *client,\n\t\t\t\t      u8 command, u8 length, const u8 *values);\n/* Returns the number of read bytes */\nextern s32 i2c_smbus_read_i2c_block_data(const struct i2c_client *client,\n\t\t\t\t\t u8 command, u8 length, u8 *values);\nextern s32 i2c_smbus_write_i2c_block_data(const struct i2c_client *client,\n\t\t\t\t\t  u8 command, u8 length,\n\t\t\t\t\t  const u8 *values);\nextern s32\ni2c_smbus_read_i2c_block_data_or_emulated(const struct i2c_client *client,\n\t\t\t\t\t  u8 command, u8 length, u8 *values);\nint i2c_get_device_id(const struct i2c_client *client,\n\t\t      struct i2c_device_identity *id);\n#endif /* I2C */\n\n/**\n * struct i2c_device_identity - i2c client device identification\n * @manufacturer_id: 0 - 4095, database maintained by NXP\n * @part_id: 0 - 511, according to manufacturer\n * @die_revision: 0 - 7, according to manufacturer\n */\nstruct i2c_device_identity {\n\tu16 manufacturer_id;\n#define I2C_DEVICE_ID_NXP_SEMICONDUCTORS                0\n#define I2C_DEVICE_ID_NXP_SEMICONDUCTORS_1              1\n#define I2C_DEVICE_ID_NXP_SEMICONDUCTORS_2              2\n#define I2C_DEVICE_ID_NXP_SEMICONDUCTORS_3              3\n#define I2C_DEVICE_ID_RAMTRON_INTERNATIONAL             4\n#define I2C_DEVICE_ID_ANALOG_DEVICES                    5\n#define I2C_DEVICE_ID_STMICROELECTRONICS                6\n#define I2C_DEVICE_ID_ON_SEMICONDUCTOR                  7\n#define I2C_DEVICE_ID_SPRINTEK_CORPORATION              8\n#define I2C_DEVICE_ID_ESPROS_PHOTONICS_AG               9\n#define I2C_DEVICE_ID_FUJITSU_SEMICONDUCTOR            10\n#define I2C_DEVICE_ID_FLIR                             11\n#define I2C_DEVICE_ID_O2MICRO                          12\n#define I2C_DEVICE_ID_ATMEL                            13\n#define I2C_DEVICE_ID_NONE                         0xffff\n\tu16 part_id;\n\tu8 die_revision;\n};\n\nenum i2c_alert_protocol {\n\tI2C_PROTOCOL_SMBUS_ALERT,\n\tI2C_PROTOCOL_SMBUS_HOST_NOTIFY,\n};\n\n/**\n * struct i2c_driver - represent an I2C device driver\n * @class: What kind of i2c device we instantiate (for detect)\n * @probe: Callback for device binding - soon to be deprecated\n * @probe_new: New callback for device binding\n * @remove: Callback for device unbinding\n * @shutdown: Callback for device shutdown\n * @alert: Alert callback, for example for the SMBus alert protocol\n * @command: Callback for bus-wide signaling (optional)\n * @driver: Device driver model driver\n * @id_table: List of I2C devices supported by this driver\n * @detect: Callback for device detection\n * @address_list: The I2C addresses to probe (for detect)\n * @clients: List of detected clients we created (for i2c-core use only)\n * @disable_i2c_core_irq_mapping: Tell the i2c-core to not do irq-mapping\n *\n * The driver.owner field should be set to the module owner of this driver.\n * The driver.name field should be set to the name of this driver.\n *\n * For automatic device detection, both @detect and @address_list must\n * be defined. @class should also be set, otherwise only devices forced\n * with module parameters will be created. The detect function must\n * fill at least the name field of the i2c_board_info structure it is\n * handed upon successful detection, and possibly also the flags field.\n *\n * If @detect is missing, the driver will still work fine for enumerated\n * devices. Detected devices simply won't be supported. This is expected\n * for the many I2C/SMBus devices which can't be detected reliably, and\n * the ones which can always be enumerated in practice.\n *\n * The i2c_client structure which is handed to the @detect callback is\n * not a real i2c_client. It is initialized just enough so that you can\n * call i2c_smbus_read_byte_data and friends on it. Don't do anything\n * else with it. In particular, calling dev_dbg and friends on it is\n * not allowed.\n */\nstruct i2c_driver {\n\tunsigned int class;\n\n\t/* Standard driver model interfaces */\n\tint (*probe)(struct i2c_client *client, const struct i2c_device_id *id);\n\tint (*remove)(struct i2c_client *client);\n\n\t/* New driver model interface to aid the seamless removal of the\n\t * current probe()'s, more commonly unused than used second parameter.\n\t */\n\tint (*probe_new)(struct i2c_client *client);\n\n\t/* driver model interfaces that don't relate to enumeration  */\n\tvoid (*shutdown)(struct i2c_client *client);\n\n\t/* Alert callback, for example for the SMBus alert protocol.\n\t * The format and meaning of the data value depends on the protocol.\n\t * For the SMBus alert protocol, there is a single bit of data passed\n\t * as the alert response's low bit (\"event flag\").\n\t * For the SMBus Host Notify protocol, the data corresponds to the\n\t * 16-bit payload data reported by the slave device acting as master.\n\t */\n\tvoid (*alert)(struct i2c_client *client, enum i2c_alert_protocol protocol,\n\t\t      unsigned int data);\n\n\t/* a ioctl like command that can be used to perform specific functions\n\t * with the device.\n\t */\n\tint (*command)(struct i2c_client *client, unsigned int cmd, void *arg);\n\n\tstruct device_driver driver;\n\tconst struct i2c_device_id *id_table;\n\n\t/* Device detection callback for automatic device creation */\n\tint (*detect)(struct i2c_client *client, struct i2c_board_info *info);\n\tconst unsigned short *address_list;\n\tstruct list_head clients;\n\n\tbool disable_i2c_core_irq_mapping;\n};\n#define to_i2c_driver(d) container_of(d, struct i2c_driver, driver)\n\n/**\n * struct i2c_client - represent an I2C slave device\n * @flags: see I2C_CLIENT_* for possible flags\n * @addr: Address used on the I2C bus connected to the parent adapter.\n * @name: Indicates the type of the device, usually a chip name that's\n *\tgeneric enough to hide second-sourcing and compatible revisions.\n * @adapter: manages the bus segment hosting this I2C device\n * @dev: Driver model device node for the slave.\n * @irq: indicates the IRQ generated by this device (if any)\n * @detected: member of an i2c_driver.clients list or i2c-core's\n *\tuserspace_devices list\n * @slave_cb: Callback when I2C slave mode of an adapter is used. The adapter\n *\tcalls it to pass on slave events to the slave driver.\n *\n * An i2c_client identifies a single device (i.e. chip) connected to an\n * i2c bus. The behaviour exposed to Linux is defined by the driver\n * managing the device.\n */\nstruct i2c_client {\n\tunsigned short flags;\t\t/* div., see below\t\t*/\n#define I2C_CLIENT_PEC\t\t0x04\t/* Use Packet Error Checking */\n#define I2C_CLIENT_TEN\t\t0x10\t/* we have a ten bit chip address */\n\t\t\t\t\t/* Must equal I2C_M_TEN below */\n#define I2C_CLIENT_SLAVE\t0x20\t/* we are the slave */\n#define I2C_CLIENT_HOST_NOTIFY\t0x40\t/* We want to use I2C host notify */\n#define I2C_CLIENT_WAKE\t\t0x80\t/* for board_info; true iff can wake */\n#define I2C_CLIENT_SCCB\t\t0x9000\t/* Use Omnivision SCCB protocol */\n\t\t\t\t\t/* Must match I2C_M_STOP|IGNORE_NAK */\n\n\tunsigned short addr;\t\t/* chip address - NOTE: 7bit\t*/\n\t\t\t\t\t/* addresses are stored in the\t*/\n\t\t\t\t\t/* _LOWER_ 7 bits\t\t*/\n\tchar name[I2C_NAME_SIZE];\n\tstruct i2c_adapter *adapter;\t/* the adapter we sit on\t*/\n\tstruct device dev;\t\t/* the device structure\t\t*/\n\tint init_irq;\t\t\t/* irq set at initialization\t*/\n\tint irq;\t\t\t/* irq issued by device\t\t*/\n\tstruct list_head detected;\n#if IS_ENABLED(CONFIG_I2C_SLAVE)\n\ti2c_slave_cb_t slave_cb;\t/* callback for slave mode\t*/\n#endif\n};\n#define to_i2c_client(d) container_of(d, struct i2c_client, dev)\n\nextern struct i2c_client *i2c_verify_client(struct device *dev);\nextern struct i2c_adapter *i2c_verify_adapter(struct device *dev);\nextern const struct i2c_device_id *i2c_match_id(const struct i2c_device_id *id,\n\t\t\t\t\tconst struct i2c_client *client);\n\nstatic inline struct i2c_client *kobj_to_i2c_client(struct kobject *kobj)\n{\n\tstruct device * const dev = container_of(kobj, struct device, kobj);\n\treturn to_i2c_client(dev);\n}\n\nstatic inline void *i2c_get_clientdata(const struct i2c_client *dev)\n{\n\treturn dev_get_drvdata(&dev->dev);\n}\n\nstatic inline void i2c_set_clientdata(struct i2c_client *dev, void *data)\n{\n\tdev_set_drvdata(&dev->dev, data);\n}\n\n/* I2C slave support */\n\n#if IS_ENABLED(CONFIG_I2C_SLAVE)\nenum i2c_slave_event {\n\tI2C_SLAVE_READ_REQUESTED,\n\tI2C_SLAVE_WRITE_REQUESTED,\n\tI2C_SLAVE_READ_PROCESSED,\n\tI2C_SLAVE_WRITE_RECEIVED,\n\tI2C_SLAVE_STOP,\n};\n\nextern int i2c_slave_register(struct i2c_client *client, i2c_slave_cb_t slave_cb);\nextern int i2c_slave_unregister(struct i2c_client *client);\nextern bool i2c_detect_slave_mode(struct device *dev);\n\nstatic inline int i2c_slave_event(struct i2c_client *client,\n\t\t\t\t  enum i2c_slave_event event, u8 *val)\n{\n\treturn client->slave_cb(client, event, val);\n}\n#else\nstatic inline bool i2c_detect_slave_mode(struct device *dev) { return false; }\n#endif\n\n/**\n * struct i2c_board_info - template for device creation\n * @type: chip type, to initialize i2c_client.name\n * @flags: to initialize i2c_client.flags\n * @addr: stored in i2c_client.addr\n * @dev_name: Overrides the default <busnr>-<addr> dev_name if set\n * @platform_data: stored in i2c_client.dev.platform_data\n * @of_node: pointer to OpenFirmware device node\n * @fwnode: device node supplied by the platform firmware\n * @properties: additional device properties for the device\n * @resources: resources associated with the device\n * @num_resources: number of resources in the @resources array\n * @irq: stored in i2c_client.irq\n *\n * I2C doesn't actually support hardware probing, although controllers and\n * devices may be able to use I2C_SMBUS_QUICK to tell whether or not there's\n * a device at a given address.  Drivers commonly need more information than\n * that, such as chip type, configuration, associated IRQ, and so on.\n *\n * i2c_board_info is used to build tables of information listing I2C devices\n * that are present.  This information is used to grow the driver model tree.\n * For mainboards this is done statically using i2c_register_board_info();\n * bus numbers identify adapters that aren't yet available.  For add-on boards,\n * i2c_new_device() does this dynamically with the adapter already known.\n */\nstruct i2c_board_info {\n\tchar\t\ttype[I2C_NAME_SIZE];\n\tunsigned short\tflags;\n\tunsigned short\taddr;\n\tconst char\t*dev_name;\n\tvoid\t\t*platform_data;\n\tstruct device_node *of_node;\n\tstruct fwnode_handle *fwnode;\n\tconst struct property_entry *properties;\n\tconst struct resource *resources;\n\tunsigned int\tnum_resources;\n\tint\t\tirq;\n};\n\n/**\n * I2C_BOARD_INFO - macro used to list an i2c device and its address\n * @dev_type: identifies the device type\n * @dev_addr: the device's address on the bus.\n *\n * This macro initializes essential fields of a struct i2c_board_info,\n * declaring what has been provided on a particular board.  Optional\n * fields (such as associated irq, or device-specific platform_data)\n * are provided using conventional syntax.\n */\n#define I2C_BOARD_INFO(dev_type, dev_addr) \\\n\t.type = dev_type, .addr = (dev_addr)\n\n\n#if IS_ENABLED(CONFIG_I2C)\n/* Add-on boards should register/unregister their devices; e.g. a board\n * with integrated I2C, a config eeprom, sensors, and a codec that's\n * used in conjunction with the primary hardware.\n */\nextern struct i2c_client *\ni2c_new_device(struct i2c_adapter *adap, struct i2c_board_info const *info);\n\nextern struct i2c_client *\ni2c_new_client_device(struct i2c_adapter *adap, struct i2c_board_info const *info);\n\n/* If you don't know the exact address of an I2C device, use this variant\n * instead, which can probe for device presence in a list of possible\n * addresses. The \"probe\" callback function is optional. If it is provided,\n * it must return 1 on successful probe, 0 otherwise. If it is not provided,\n * a default probing method is used.\n */\nextern struct i2c_client *\ni2c_new_probed_device(struct i2c_adapter *adap,\n\t\t      struct i2c_board_info *info,\n\t\t      unsigned short const *addr_list,\n\t\t      int (*probe)(struct i2c_adapter *adap, unsigned short addr));\n\n/* Common custom probe functions */\nextern int i2c_probe_func_quick_read(struct i2c_adapter *adap, unsigned short addr);\n\n/* For devices that use several addresses, use i2c_new_dummy() to make\n * client handles for the extra addresses.\n */\nextern struct i2c_client *\ni2c_new_dummy(struct i2c_adapter *adap, u16 address);\n\nextern struct i2c_client *\ni2c_new_dummy_device(struct i2c_adapter *adapter, u16 address);\n\nextern struct i2c_client *\ndevm_i2c_new_dummy_device(struct device *dev, struct i2c_adapter *adap, u16 address);\n\nextern struct i2c_client *\ni2c_new_ancillary_device(struct i2c_client *client,\n\t\t\t\tconst char *name,\n\t\t\t\tu16 default_addr);\n\nextern void i2c_unregister_device(struct i2c_client *client);\n#endif /* I2C */\n\n/* Mainboard arch_initcall() code should register all its I2C devices.\n * This is done at arch_initcall time, before declaring any i2c adapters.\n * Modules for add-on boards must use other calls.\n */\n#ifdef CONFIG_I2C_BOARDINFO\nextern int\ni2c_register_board_info(int busnum, struct i2c_board_info const *info,\n\t\t\tunsigned n);\n#else\nstatic inline int\ni2c_register_board_info(int busnum, struct i2c_board_info const *info,\n\t\t\tunsigned n)\n{\n\treturn 0;\n}\n#endif /* I2C_BOARDINFO */\n\n/**\n * struct i2c_algorithm - represent I2C transfer method\n * @master_xfer: Issue a set of i2c transactions to the given I2C adapter\n *   defined by the msgs array, with num messages available to transfer via\n *   the adapter specified by adap.\n * @master_xfer_atomic: same as @master_xfer. Yet, only using atomic context\n *   so e.g. PMICs can be accessed very late before shutdown. Optional.\n * @smbus_xfer: Issue smbus transactions to the given I2C adapter. If this\n *   is not present, then the bus layer will try and convert the SMBus calls\n *   into I2C transfers instead.\n * @smbus_xfer_atomic: same as @smbus_xfer. Yet, only using atomic context\n *   so e.g. PMICs can be accessed very late before shutdown. Optional.\n * @functionality: Return the flags that this algorithm/adapter pair supports\n *   from the I2C_FUNC_* flags.\n * @reg_slave: Register given client to I2C slave mode of this adapter\n * @unreg_slave: Unregister given client from I2C slave mode of this adapter\n *\n * The following structs are for those who like to implement new bus drivers:\n * i2c_algorithm is the interface to a class of hardware solutions which can\n * be addressed using the same bus algorithms - i.e. bit-banging or the PCF8584\n * to name two of the most common.\n *\n * The return codes from the @master_xfer{_atomic} fields should indicate the\n * type of error code that occurred during the transfer, as documented in the\n * Kernel Documentation file Documentation/i2c/fault-codes.rst.\n */\nstruct i2c_algorithm {\n\t/*\n\t * If an adapter algorithm can't do I2C-level access, set master_xfer\n\t * to NULL. If an adapter algorithm can do SMBus access, set\n\t * smbus_xfer. If set to NULL, the SMBus protocol is simulated\n\t * using common I2C messages.\n\t *\n\t * master_xfer should return the number of messages successfully\n\t * processed, or a negative value on error\n\t */\n\tint (*master_xfer)(struct i2c_adapter *adap, struct i2c_msg *msgs,\n\t\t\t   int num);\n\tint (*master_xfer_atomic)(struct i2c_adapter *adap,\n\t\t\t\t   struct i2c_msg *msgs, int num);\n\tint (*smbus_xfer)(struct i2c_adapter *adap, u16 addr,\n\t\t\t  unsigned short flags, char read_write,\n\t\t\t  u8 command, int size, union i2c_smbus_data *data);\n\tint (*smbus_xfer_atomic)(struct i2c_adapter *adap, u16 addr,\n\t\t\t\t unsigned short flags, char read_write,\n\t\t\t\t u8 command, int size, union i2c_smbus_data *data);\n\n\t/* To determine what the adapter supports */\n\tu32 (*functionality)(struct i2c_adapter *adap);\n\n#if IS_ENABLED(CONFIG_I2C_SLAVE)\n\tint (*reg_slave)(struct i2c_client *client);\n\tint (*unreg_slave)(struct i2c_client *client);\n#endif\n};\n\n/**\n * struct i2c_lock_operations - represent I2C locking operations\n * @lock_bus: Get exclusive access to an I2C bus segment\n * @trylock_bus: Try to get exclusive access to an I2C bus segment\n * @unlock_bus: Release exclusive access to an I2C bus segment\n *\n * The main operations are wrapped by i2c_lock_bus and i2c_unlock_bus.\n */\nstruct i2c_lock_operations {\n\tvoid (*lock_bus)(struct i2c_adapter *adapter, unsigned int flags);\n\tint (*trylock_bus)(struct i2c_adapter *adapter, unsigned int flags);\n\tvoid (*unlock_bus)(struct i2c_adapter *adapter, unsigned int flags);\n};\n\n/**\n * struct i2c_timings - I2C timing information\n * @bus_freq_hz: the bus frequency in Hz\n * @scl_rise_ns: time SCL signal takes to rise in ns; t(r) in the I2C specification\n * @scl_fall_ns: time SCL signal takes to fall in ns; t(f) in the I2C specification\n * @scl_int_delay_ns: time IP core additionally needs to setup SCL in ns\n * @sda_fall_ns: time SDA signal takes to fall in ns; t(f) in the I2C specification\n * @sda_hold_ns: time IP core additionally needs to hold SDA in ns\n */\nstruct i2c_timings {\n\tu32 bus_freq_hz;\n\tu32 scl_rise_ns;\n\tu32 scl_fall_ns;\n\tu32 scl_int_delay_ns;\n\tu32 sda_fall_ns;\n\tu32 sda_hold_ns;\n};\n\n/**\n * struct i2c_bus_recovery_info - I2C bus recovery information\n * @recover_bus: Recover routine. Either pass driver's recover_bus() routine, or\n *\ti2c_generic_scl_recovery().\n * @get_scl: This gets current value of SCL line. Mandatory for generic SCL\n *      recovery. Populated internally for generic GPIO recovery.\n * @set_scl: This sets/clears the SCL line. Mandatory for generic SCL recovery.\n *      Populated internally for generic GPIO recovery.\n * @get_sda: This gets current value of SDA line. This or set_sda() is mandatory\n *\tfor generic SCL recovery. Populated internally, if sda_gpio is a valid\n *\tGPIO, for generic GPIO recovery.\n * @set_sda: This sets/clears the SDA line. This or get_sda() is mandatory for\n *\tgeneric SCL recovery. Populated internally, if sda_gpio is a valid GPIO,\n *\tfor generic GPIO recovery.\n * @get_bus_free: Returns the bus free state as seen from the IP core in case it\n *\thas a more complex internal logic than just reading SDA. Optional.\n * @prepare_recovery: This will be called before starting recovery. Platform may\n *\tconfigure padmux here for SDA/SCL line or something else they want.\n * @unprepare_recovery: This will be called after completing recovery. Platform\n *\tmay configure padmux here for SDA/SCL line or something else they want.\n * @scl_gpiod: gpiod of the SCL line. Only required for GPIO recovery.\n * @sda_gpiod: gpiod of the SDA line. Only required for GPIO recovery.\n */\nstruct i2c_bus_recovery_info {\n\tint (*recover_bus)(struct i2c_adapter *adap);\n\n\tint (*get_scl)(struct i2c_adapter *adap);\n\tvoid (*set_scl)(struct i2c_adapter *adap, int val);\n\tint (*get_sda)(struct i2c_adapter *adap);\n\tvoid (*set_sda)(struct i2c_adapter *adap, int val);\n\tint (*get_bus_free)(struct i2c_adapter *adap);\n\n\tvoid (*prepare_recovery)(struct i2c_adapter *adap);\n\tvoid (*unprepare_recovery)(struct i2c_adapter *adap);\n\n\t/* gpio recovery */\n\tstruct gpio_desc *scl_gpiod;\n\tstruct gpio_desc *sda_gpiod;\n};\n\nint i2c_recover_bus(struct i2c_adapter *adap);\n\n/* Generic recovery routines */\nint i2c_generic_scl_recovery(struct i2c_adapter *adap);\n\n/**\n * struct i2c_adapter_quirks - describe flaws of an i2c adapter\n * @flags: see I2C_AQ_* for possible flags and read below\n * @max_num_msgs: maximum number of messages per transfer\n * @max_write_len: maximum length of a write message\n * @max_read_len: maximum length of a read message\n * @max_comb_1st_msg_len: maximum length of the first msg in a combined message\n * @max_comb_2nd_msg_len: maximum length of the second msg in a combined message\n *\n * Note about combined messages: Some I2C controllers can only send one message\n * per transfer, plus something called combined message or write-then-read.\n * This is (usually) a small write message followed by a read message and\n * barely enough to access register based devices like EEPROMs. There is a flag\n * to support this mode. It implies max_num_msg = 2 and does the length checks\n * with max_comb_*_len because combined message mode usually has its own\n * limitations. Because of HW implementations, some controllers can actually do\n * write-then-anything or other variants. To support that, write-then-read has\n * been broken out into smaller bits like write-first and read-second which can\n * be combined as needed.\n */\n\nstruct i2c_adapter_quirks {\n\tu64 flags;\n\tint max_num_msgs;\n\tu16 max_write_len;\n\tu16 max_read_len;\n\tu16 max_comb_1st_msg_len;\n\tu16 max_comb_2nd_msg_len;\n};\n\n/* enforce max_num_msgs = 2 and use max_comb_*_len for length checks */\n#define I2C_AQ_COMB\t\t\tBIT(0)\n/* first combined message must be write */\n#define I2C_AQ_COMB_WRITE_FIRST\t\tBIT(1)\n/* second combined message must be read */\n#define I2C_AQ_COMB_READ_SECOND\t\tBIT(2)\n/* both combined messages must have the same target address */\n#define I2C_AQ_COMB_SAME_ADDR\t\tBIT(3)\n/* convenience macro for typical write-then read case */\n#define I2C_AQ_COMB_WRITE_THEN_READ\t(I2C_AQ_COMB | I2C_AQ_COMB_WRITE_FIRST | \\\n\t\t\t\t\t I2C_AQ_COMB_READ_SECOND | I2C_AQ_COMB_SAME_ADDR)\n/* clock stretching is not supported */\n#define I2C_AQ_NO_CLK_STRETCH\t\tBIT(4)\n/* message cannot have length of 0 */\n#define I2C_AQ_NO_ZERO_LEN_READ\t\tBIT(5)\n#define I2C_AQ_NO_ZERO_LEN_WRITE\tBIT(6)\n#define I2C_AQ_NO_ZERO_LEN\t\t(I2C_AQ_NO_ZERO_LEN_READ | I2C_AQ_NO_ZERO_LEN_WRITE)\n\n/*\n * i2c_adapter is the structure used to identify a physical i2c bus along\n * with the access algorithms necessary to access it.\n */\nstruct i2c_adapter {\n\tstruct module *owner;\n\tunsigned int class;\t\t  /* classes to allow probing for */\n\tconst struct i2c_algorithm *algo; /* the algorithm to access the bus */\n\tvoid *algo_data;\n\n\t/* data fields that are valid for all devices\t*/\n\tconst struct i2c_lock_operations *lock_ops;\n\tstruct rt_mutex bus_lock;\n\tstruct rt_mutex mux_lock;\n\n\tint timeout;\t\t\t/* in jiffies */\n\tint retries;\n\tstruct device dev;\t\t/* the adapter device */\n\tunsigned long locked_flags;\t/* owned by the I2C core */\n#define I2C_ALF_IS_SUSPENDED\t\t0\n#define I2C_ALF_SUSPEND_REPORTED\t1\n\n\tint nr;\n\tchar name[48];\n\tstruct completion dev_released;\n\n\tstruct mutex userspace_clients_lock;\n\tstruct list_head userspace_clients;\n\n\tstruct i2c_bus_recovery_info *bus_recovery_info;\n\tconst struct i2c_adapter_quirks *quirks;\n\n\tstruct irq_domain *host_notify_domain;\n};\n#define to_i2c_adapter(d) container_of(d, struct i2c_adapter, dev)\n\nstatic inline void *i2c_get_adapdata(const struct i2c_adapter *adap)\n{\n\treturn dev_get_drvdata(&adap->dev);\n}\n\nstatic inline void i2c_set_adapdata(struct i2c_adapter *adap, void *data)\n{\n\tdev_set_drvdata(&adap->dev, data);\n}\n\nstatic inline struct i2c_adapter *\ni2c_parent_is_i2c_adapter(const struct i2c_adapter *adapter)\n{\n#if IS_ENABLED(CONFIG_I2C_MUX)\n\tstruct device *parent = adapter->dev.parent;\n\n\tif (parent != NULL && parent->type == &i2c_adapter_type)\n\t\treturn to_i2c_adapter(parent);\n\telse\n#endif\n\t\treturn NULL;\n}\n\nint i2c_for_each_dev(void *data, int (*fn)(struct device *dev, void *data));\n\n/* Adapter locking functions, exported for shared pin cases */\n#define I2C_LOCK_ROOT_ADAPTER BIT(0)\n#define I2C_LOCK_SEGMENT      BIT(1)\n\n/**\n * i2c_lock_bus - Get exclusive access to an I2C bus segment\n * @adapter: Target I2C bus segment\n * @flags: I2C_LOCK_ROOT_ADAPTER locks the root i2c adapter, I2C_LOCK_SEGMENT\n *\tlocks only this branch in the adapter tree\n */\nstatic inline void\ni2c_lock_bus(struct i2c_adapter *adapter, unsigned int flags)\n{\n\tadapter->lock_ops->lock_bus(adapter, flags);\n}\n\n/**\n * i2c_trylock_bus - Try to get exclusive access to an I2C bus segment\n * @adapter: Target I2C bus segment\n * @flags: I2C_LOCK_ROOT_ADAPTER tries to locks the root i2c adapter,\n *\tI2C_LOCK_SEGMENT tries to lock only this branch in the adapter tree\n *\n * Return: true if the I2C bus segment is locked, false otherwise\n */\nstatic inline int\ni2c_trylock_bus(struct i2c_adapter *adapter, unsigned int flags)\n{\n\treturn adapter->lock_ops->trylock_bus(adapter, flags);\n}\n\n/**\n * i2c_unlock_bus - Release exclusive access to an I2C bus segment\n * @adapter: Target I2C bus segment\n * @flags: I2C_LOCK_ROOT_ADAPTER unlocks the root i2c adapter, I2C_LOCK_SEGMENT\n *\tunlocks only this branch in the adapter tree\n */\nstatic inline void\ni2c_unlock_bus(struct i2c_adapter *adapter, unsigned int flags)\n{\n\tadapter->lock_ops->unlock_bus(adapter, flags);\n}\n\n/**\n * i2c_mark_adapter_suspended - Report suspended state of the adapter to the core\n * @adap: Adapter to mark as suspended\n *\n * When using this helper to mark an adapter as suspended, the core will reject\n * further transfers to this adapter. The usage of this helper is optional but\n * recommended for devices having distinct handlers for system suspend and\n * runtime suspend. More complex devices are free to implement custom solutions\n * to reject transfers when suspended.\n */\nstatic inline void i2c_mark_adapter_suspended(struct i2c_adapter *adap)\n{\n\ti2c_lock_bus(adap, I2C_LOCK_ROOT_ADAPTER);\n\tset_bit(I2C_ALF_IS_SUSPENDED, &adap->locked_flags);\n\ti2c_unlock_bus(adap, I2C_LOCK_ROOT_ADAPTER);\n}\n\n/**\n * i2c_mark_adapter_resumed - Report resumed state of the adapter to the core\n * @adap: Adapter to mark as resumed\n *\n * When using this helper to mark an adapter as resumed, the core will allow\n * further transfers to this adapter. See also further notes to\n * @i2c_mark_adapter_suspended().\n */\nstatic inline void i2c_mark_adapter_resumed(struct i2c_adapter *adap)\n{\n\ti2c_lock_bus(adap, I2C_LOCK_ROOT_ADAPTER);\n\tclear_bit(I2C_ALF_IS_SUSPENDED, &adap->locked_flags);\n\ti2c_unlock_bus(adap, I2C_LOCK_ROOT_ADAPTER);\n}\n\n/* i2c adapter classes (bitmask) */\n#define I2C_CLASS_HWMON\t\t(1<<0)\t/* lm_sensors, ... */\n#define I2C_CLASS_DDC\t\t(1<<3)\t/* DDC bus on graphics adapters */\n#define I2C_CLASS_SPD\t\t(1<<7)\t/* Memory modules */\n/* Warn users that the adapter doesn't support classes anymore */\n#define I2C_CLASS_DEPRECATED\t(1<<8)\n\n/* Internal numbers to terminate lists */\n#define I2C_CLIENT_END\t\t0xfffeU\n\n/* Construct an I2C_CLIENT_END-terminated array of i2c addresses */\n#define I2C_ADDRS(addr, addrs...) \\\n\t((const unsigned short []){ addr, ## addrs, I2C_CLIENT_END })\n\n\n/* ----- functions exported by i2c.o */\n\n/* administration...\n */\n#if IS_ENABLED(CONFIG_I2C)\nextern int i2c_add_adapter(struct i2c_adapter *adap);\nextern void i2c_del_adapter(struct i2c_adapter *adap);\nextern int i2c_add_numbered_adapter(struct i2c_adapter *adap);\n\nextern int i2c_register_driver(struct module *owner, struct i2c_driver *driver);\nextern void i2c_del_driver(struct i2c_driver *driver);\n\n/* use a define to avoid include chaining to get THIS_MODULE */\n#define i2c_add_driver(driver) \\\n\ti2c_register_driver(THIS_MODULE, driver)\n\nextern struct i2c_client *i2c_use_client(struct i2c_client *client);\nextern void i2c_release_client(struct i2c_client *client);\n\n/* call the i2c_client->command() of all attached clients with\n * the given arguments */\nextern void i2c_clients_command(struct i2c_adapter *adap,\n\t\t\t\tunsigned int cmd, void *arg);\n\nextern struct i2c_adapter *i2c_get_adapter(int nr);\nextern void i2c_put_adapter(struct i2c_adapter *adap);\nextern unsigned int i2c_adapter_depth(struct i2c_adapter *adapter);\n\nvoid i2c_parse_fw_timings(struct device *dev, struct i2c_timings *t, bool use_defaults);\n\n/* Return the functionality mask */\nstatic inline u32 i2c_get_functionality(struct i2c_adapter *adap)\n{\n\treturn adap->algo->functionality(adap);\n}\n\n/* Return 1 if adapter supports everything we need, 0 if not. */\nstatic inline int i2c_check_functionality(struct i2c_adapter *adap, u32 func)\n{\n\treturn (func & i2c_get_functionality(adap)) == func;\n}\n\n/**\n * i2c_check_quirks() - Function for checking the quirk flags in an i2c adapter\n * @adap: i2c adapter\n * @quirks: quirk flags\n *\n * Return: true if the adapter has all the specified quirk flags, false if not\n */\nstatic inline bool i2c_check_quirks(struct i2c_adapter *adap, u64 quirks)\n{\n\tif (!adap->quirks)\n\t\treturn false;\n\treturn (adap->quirks->flags & quirks) == quirks;\n}\n\n/* Return the adapter number for a specific adapter */\nstatic inline int i2c_adapter_id(struct i2c_adapter *adap)\n{\n\treturn adap->nr;\n}\n\nstatic inline u8 i2c_8bit_addr_from_msg(const struct i2c_msg *msg)\n{\n\treturn (msg->addr << 1) | (msg->flags & I2C_M_RD ? 1 : 0);\n}\n\nu8 *i2c_get_dma_safe_msg_buf(struct i2c_msg *msg, unsigned int threshold);\nvoid i2c_put_dma_safe_msg_buf(u8 *buf, struct i2c_msg *msg, bool xferred);\n\nint i2c_handle_smbus_host_notify(struct i2c_adapter *adap, unsigned short addr);\n/**\n * module_i2c_driver() - Helper macro for registering a modular I2C driver\n * @__i2c_driver: i2c_driver struct\n *\n * Helper macro for I2C drivers which do not do anything special in module\n * init/exit. This eliminates a lot of boilerplate. Each module may only\n * use this macro once, and calling it replaces module_init() and module_exit()\n */\n#define module_i2c_driver(__i2c_driver) \\\n\tmodule_driver(__i2c_driver, i2c_add_driver, \\\n\t\t\ti2c_del_driver)\n\n/**\n * builtin_i2c_driver() - Helper macro for registering a builtin I2C driver\n * @__i2c_driver: i2c_driver struct\n *\n * Helper macro for I2C drivers which do not do anything special in their\n * init. This eliminates a lot of boilerplate. Each driver may only\n * use this macro once, and calling it replaces device_initcall().\n */\n#define builtin_i2c_driver(__i2c_driver) \\\n\tbuiltin_driver(__i2c_driver, i2c_add_driver)\n\n#endif /* I2C */\n\n#if IS_ENABLED(CONFIG_OF)\n/* must call put_device() when done with returned i2c_client device */\nextern struct i2c_client *of_find_i2c_device_by_node(struct device_node *node);\n\n/* must call put_device() when done with returned i2c_adapter device */\nextern struct i2c_adapter *of_find_i2c_adapter_by_node(struct device_node *node);\n\n/* must call i2c_put_adapter() when done with returned i2c_adapter device */\nstruct i2c_adapter *of_get_i2c_adapter_by_node(struct device_node *node);\n\nextern const struct of_device_id\n*i2c_of_match_device(const struct of_device_id *matches,\n\t\t     struct i2c_client *client);\n\nint of_i2c_get_board_info(struct device *dev, struct device_node *node,\n\t\t\t  struct i2c_board_info *info);\n\n#else\n\nstatic inline struct i2c_client *of_find_i2c_device_by_node(struct device_node *node)\n{\n\treturn NULL;\n}\n\nstatic inline struct i2c_adapter *of_find_i2c_adapter_by_node(struct device_node *node)\n{\n\treturn NULL;\n}\n\nstatic inline struct i2c_adapter *of_get_i2c_adapter_by_node(struct device_node *node)\n{\n\treturn NULL;\n}\n\nstatic inline const struct of_device_id\n*i2c_of_match_device(const struct of_device_id *matches,\n\t\t     struct i2c_client *client)\n{\n\treturn NULL;\n}\n\nstatic inline int of_i2c_get_board_info(struct device *dev,\n\t\t\t\t\tstruct device_node *node,\n\t\t\t\t\tstruct i2c_board_info *info)\n{\n\treturn -ENOTSUPP;\n}\n\n#endif /* CONFIG_OF */\n\nstruct acpi_resource;\nstruct acpi_resource_i2c_serialbus;\n\n#if IS_ENABLED(CONFIG_ACPI)\nbool i2c_acpi_get_i2c_resource(struct acpi_resource *ares,\n\t\t\t       struct acpi_resource_i2c_serialbus **i2c);\nu32 i2c_acpi_find_bus_speed(struct device *dev);\nstruct i2c_client *i2c_acpi_new_device(struct device *dev, int index,\n\t\t\t\t       struct i2c_board_info *info);\nstruct i2c_adapter *i2c_acpi_find_adapter_by_handle(acpi_handle handle);\n#else\nstatic inline bool i2c_acpi_get_i2c_resource(struct acpi_resource *ares,\n\t\t\t\t\t     struct acpi_resource_i2c_serialbus **i2c)\n{\n\treturn false;\n}\nstatic inline u32 i2c_acpi_find_bus_speed(struct device *dev)\n{\n\treturn 0;\n}\nstatic inline struct i2c_client *i2c_acpi_new_device(struct device *dev,\n\t\t\t\t\tint index, struct i2c_board_info *info)\n{\n\treturn NULL;\n}\nstatic inline struct i2c_adapter *i2c_acpi_find_adapter_by_handle(acpi_handle handle)\n{\n\treturn NULL;\n}\n#endif /* CONFIG_ACPI */\n\n#endif /* _LINUX_I2C_H */\n"
  },
  {
    "path": "t/tree/include/linux/key.h",
    "content": "/* SPDX-License-Identifier: GPL-2.0-or-later */\n/* Authentication token and access key management\n *\n * Copyright (C) 2004, 2007 Red Hat, Inc. All Rights Reserved.\n * Written by David Howells (dhowells@redhat.com)\n *\n * See Documentation/security/keys/core.rst for information on keys/keyrings.\n */\n\n#ifndef _LINUX_KEY_H\n#define _LINUX_KEY_H\n\n#include <linux/types.h>\n#include <linux/list.h>\n#include <linux/rbtree.h>\n#include <linux/rcupdate.h>\n#include <linux/sysctl.h>\n#include <linux/rwsem.h>\n#include <linux/atomic.h>\n#include <linux/assoc_array.h>\n#include <linux/refcount.h>\n#include <linux/time64.h>\n\n#ifdef __KERNEL__\n#include <linux/uidgid.h>\n\n/* key handle serial number */\ntypedef int32_t key_serial_t;\n\n/* key handle permissions mask */\ntypedef uint32_t key_perm_t;\n\nstruct key;\nstruct net;\n\n#ifdef CONFIG_KEYS\n\n#undef KEY_DEBUGGING\n\n#define KEY_POS_VIEW\t0x01000000\t/* possessor can view a key's attributes */\n#define KEY_POS_READ\t0x02000000\t/* possessor can read key payload / view keyring */\n#define KEY_POS_WRITE\t0x04000000\t/* possessor can update key payload / add link to keyring */\n#define KEY_POS_SEARCH\t0x08000000\t/* possessor can find a key in search / search a keyring */\n#define KEY_POS_LINK\t0x10000000\t/* possessor can create a link to a key/keyring */\n#define KEY_POS_SETATTR\t0x20000000\t/* possessor can set key attributes */\n#define KEY_POS_ALL\t0x3f000000\n\n#define KEY_USR_VIEW\t0x00010000\t/* user permissions... */\n#define KEY_USR_READ\t0x00020000\n#define KEY_USR_WRITE\t0x00040000\n#define KEY_USR_SEARCH\t0x00080000\n#define KEY_USR_LINK\t0x00100000\n#define KEY_USR_SETATTR\t0x00200000\n#define KEY_USR_ALL\t0x003f0000\n\n#define KEY_GRP_VIEW\t0x00000100\t/* group permissions... */\n#define KEY_GRP_READ\t0x00000200\n#define KEY_GRP_WRITE\t0x00000400\n#define KEY_GRP_SEARCH\t0x00000800\n#define KEY_GRP_LINK\t0x00001000\n#define KEY_GRP_SETATTR\t0x00002000\n#define KEY_GRP_ALL\t0x00003f00\n\n#define KEY_OTH_VIEW\t0x00000001\t/* third party permissions... */\n#define KEY_OTH_READ\t0x00000002\n#define KEY_OTH_WRITE\t0x00000004\n#define KEY_OTH_SEARCH\t0x00000008\n#define KEY_OTH_LINK\t0x00000010\n#define KEY_OTH_SETATTR\t0x00000020\n#define KEY_OTH_ALL\t0x0000003f\n\n#define KEY_PERM_UNDEF\t0xffffffff\n\nstruct seq_file;\nstruct user_struct;\nstruct signal_struct;\nstruct cred;\n\nstruct key_type;\nstruct key_owner;\nstruct key_tag;\nstruct keyring_list;\nstruct keyring_name;\n\nstruct key_tag {\n\tstruct rcu_head\t\trcu;\n\trefcount_t\t\tusage;\n\tbool\t\t\tremoved;\t/* T when subject removed */\n};\n\nstruct keyring_index_key {\n\t/* [!] If this structure is altered, the union in struct key must change too! */\n\tunsigned long\t\thash;\t\t\t/* Hash value */\n\tunion {\n\t\tstruct {\n#ifdef __LITTLE_ENDIAN /* Put desc_len at the LSB of x */\n\t\t\tu16\tdesc_len;\n\t\t\tchar\tdesc[sizeof(long) - 2];\t/* First few chars of description */\n#else\n\t\t\tchar\tdesc[sizeof(long) - 2];\t/* First few chars of description */\n\t\t\tu16\tdesc_len;\n#endif\n\t\t};\n\t\tunsigned long x;\n\t};\n\tstruct key_type\t\t*type;\n\tstruct key_tag\t\t*domain_tag;\t/* Domain of operation */\n\tconst char\t\t*description;\n};\n\nunion key_payload {\n\tvoid __rcu\t\t*rcu_data0;\n\tvoid\t\t\t*data[4];\n};\n\n/*****************************************************************************/\n/*\n * key reference with possession attribute handling\n *\n * NOTE! key_ref_t is a typedef'd pointer to a type that is not actually\n * defined. This is because we abuse the bottom bit of the reference to carry a\n * flag to indicate whether the calling process possesses that key in one of\n * its keyrings.\n *\n * the key_ref_t has been made a separate type so that the compiler can reject\n * attempts to dereference it without proper conversion.\n *\n * the three functions are used to assemble and disassemble references\n */\ntypedef struct __key_reference_with_attributes *key_ref_t;\n\nstatic inline key_ref_t make_key_ref(const struct key *key,\n\t\t\t\t     bool possession)\n{\n\treturn (key_ref_t) ((unsigned long) key | possession);\n}\n\nstatic inline struct key *key_ref_to_ptr(const key_ref_t key_ref)\n{\n\treturn (struct key *) ((unsigned long) key_ref & ~1UL);\n}\n\nstatic inline bool is_key_possessed(const key_ref_t key_ref)\n{\n\treturn (unsigned long) key_ref & 1UL;\n}\n\ntypedef int (*key_restrict_link_func_t)(struct key *dest_keyring,\n\t\t\t\t\tconst struct key_type *type,\n\t\t\t\t\tconst union key_payload *payload,\n\t\t\t\t\tstruct key *restriction_key);\n\nstruct key_restriction {\n\tkey_restrict_link_func_t check;\n\tstruct key *key;\n\tstruct key_type *keytype;\n};\n\nenum key_state {\n\tKEY_IS_UNINSTANTIATED,\n\tKEY_IS_POSITIVE,\t\t/* Positively instantiated */\n};\n\n/*****************************************************************************/\n/*\n * authentication token / access credential / keyring\n * - types of key include:\n *   - keyrings\n *   - disk encryption IDs\n *   - Kerberos TGTs and tickets\n */\nstruct key {\n\trefcount_t\t\tusage;\t\t/* number of references */\n\tkey_serial_t\t\tserial;\t\t/* key serial number */\n\tunion {\n\t\tstruct list_head graveyard_link;\n\t\tstruct rb_node\tserial_node;\n\t};\n\tstruct rw_semaphore\tsem;\t\t/* change vs change sem */\n\tstruct key_user\t\t*user;\t\t/* owner of this key */\n\tvoid\t\t\t*security;\t/* security data for this key */\n\tunion {\n\t\ttime64_t\texpiry;\t\t/* time at which key expires (or 0) */\n\t\ttime64_t\trevoked_at;\t/* time at which key was revoked */\n\t};\n\ttime64_t\t\tlast_used_at;\t/* last time used for LRU keyring discard */\n\tkuid_t\t\t\tuid;\n\tkgid_t\t\t\tgid;\n\tkey_perm_t\t\tperm;\t\t/* access permissions */\n\tunsigned short\t\tquotalen;\t/* length added to quota */\n\tunsigned short\t\tdatalen;\t/* payload data length\n\t\t\t\t\t\t * - may not match RCU dereferenced payload\n\t\t\t\t\t\t * - payload should contain own length\n\t\t\t\t\t\t */\n\tshort\t\t\tstate;\t\t/* Key state (+) or rejection error (-) */\n\n#ifdef KEY_DEBUGGING\n\tunsigned\t\tmagic;\n#define KEY_DEBUG_MAGIC\t\t0x18273645u\n#endif\n\n\tunsigned long\t\tflags;\t\t/* status flags (change with bitops) */\n#define KEY_FLAG_DEAD\t\t0\t/* set if key type has been deleted */\n#define KEY_FLAG_REVOKED\t1\t/* set if key had been revoked */\n#define KEY_FLAG_IN_QUOTA\t2\t/* set if key consumes quota */\n#define KEY_FLAG_USER_CONSTRUCT\t3\t/* set if key is being constructed in userspace */\n#define KEY_FLAG_ROOT_CAN_CLEAR\t4\t/* set if key can be cleared by root without permission */\n#define KEY_FLAG_INVALIDATED\t5\t/* set if key has been invalidated */\n#define KEY_FLAG_BUILTIN\t6\t/* set if key is built in to the kernel */\n#define KEY_FLAG_ROOT_CAN_INVAL\t7\t/* set if key can be invalidated by root without permission */\n#define KEY_FLAG_KEEP\t\t8\t/* set if key should not be removed */\n#define KEY_FLAG_UID_KEYRING\t9\t/* set if key is a user or user session keyring */\n\n\t/* the key type and key description string\n\t * - the desc is used to match a key against search criteria\n\t * - it should be a printable string\n\t * - eg: for krb5 AFS, this might be \"afs@REDHAT.COM\"\n\t */\n\tunion {\n\t\tstruct keyring_index_key index_key;\n\t\tstruct {\n\t\t\tunsigned long\thash;\n\t\t\tunsigned long\tlen_desc;\n\t\t\tstruct key_type\t*type;\t\t/* type of key */\n\t\t\tstruct key_tag\t*domain_tag;\t/* Domain of operation */\n\t\t\tchar\t\t*description;\n\t\t};\n\t};\n\n\t/* key data\n\t * - this is used to hold the data actually used in cryptography or\n\t *   whatever\n\t */\n\tunion {\n\t\tunion key_payload payload;\n\t\tstruct {\n\t\t\t/* Keyring bits */\n\t\t\tstruct list_head name_link;\n\t\t\tstruct assoc_array keys;\n\t\t};\n\t};\n\n\t/* This is set on a keyring to restrict the addition of a link to a key\n\t * to it.  If this structure isn't provided then it is assumed that the\n\t * keyring is open to any addition.  It is ignored for non-keyring\n\t * keys. Only set this value using keyring_restrict(), keyring_alloc(),\n\t * or key_alloc().\n\t *\n\t * This is intended for use with rings of trusted keys whereby addition\n\t * to the keyring needs to be controlled.  KEY_ALLOC_BYPASS_RESTRICTION\n\t * overrides this, allowing the kernel to add extra keys without\n\t * restriction.\n\t */\n\tstruct key_restriction *restrict_link;\n};\n\nextern struct key *key_alloc(struct key_type *type,\n\t\t\t     const char *desc,\n\t\t\t     kuid_t uid, kgid_t gid,\n\t\t\t     const struct cred *cred,\n\t\t\t     key_perm_t perm,\n\t\t\t     unsigned long flags,\n\t\t\t     struct key_restriction *restrict_link);\n\n\n#define KEY_ALLOC_IN_QUOTA\t\t0x0000\t/* add to quota, reject if would overrun */\n#define KEY_ALLOC_QUOTA_OVERRUN\t\t0x0001\t/* add to quota, permit even if overrun */\n#define KEY_ALLOC_NOT_IN_QUOTA\t\t0x0002\t/* not in quota */\n#define KEY_ALLOC_BUILT_IN\t\t0x0004\t/* Key is built into kernel */\n#define KEY_ALLOC_BYPASS_RESTRICTION\t0x0008\t/* Override the check on restricted keyrings */\n#define KEY_ALLOC_UID_KEYRING\t\t0x0010\t/* allocating a user or user session keyring */\n\nextern void key_revoke(struct key *key);\nextern void key_invalidate(struct key *key);\nextern void key_put(struct key *key);\nextern bool key_put_tag(struct key_tag *tag);\nextern void key_remove_domain(struct key_tag *domain_tag);\n\nstatic inline struct key *__key_get(struct key *key)\n{\n\trefcount_inc(&key->usage);\n\treturn key;\n}\n\nstatic inline struct key *key_get(struct key *key)\n{\n\treturn key ? __key_get(key) : key;\n}\n\nstatic inline void key_ref_put(key_ref_t key_ref)\n{\n\tkey_put(key_ref_to_ptr(key_ref));\n}\n\nextern struct key *request_key_tag(struct key_type *type,\n\t\t\t\t   const char *description,\n\t\t\t\t   struct key_tag *domain_tag,\n\t\t\t\t   const char *callout_info);\n\nextern struct key *request_key_rcu(struct key_type *type,\n\t\t\t\t   const char *description,\n\t\t\t\t   struct key_tag *domain_tag);\n\nextern struct key *request_key_with_auxdata(struct key_type *type,\n\t\t\t\t\t    const char *description,\n\t\t\t\t\t    struct key_tag *domain_tag,\n\t\t\t\t\t    const void *callout_info,\n\t\t\t\t\t    size_t callout_len,\n\t\t\t\t\t    void *aux);\n\n/**\n * request_key - Request a key and wait for construction\n * @type: Type of key.\n * @description: The searchable description of the key.\n * @callout_info: The data to pass to the instantiation upcall (or NULL).\n *\n * As for request_key_tag(), but with the default global domain tag.\n */\nstatic inline struct key *request_key(struct key_type *type,\n\t\t\t\t      const char *description,\n\t\t\t\t      const char *callout_info)\n{\n\treturn request_key_tag(type, description, NULL, callout_info);\n}\n\n#ifdef CONFIG_NET\n/**\n * request_key_net - Request a key for a net namespace and wait for construction\n * @type: Type of key.\n * @description: The searchable description of the key.\n * @net: The network namespace that is the key's domain of operation.\n * @callout_info: The data to pass to the instantiation upcall (or NULL).\n *\n * As for request_key() except that it does not add the returned key to a\n * keyring if found, new keys are always allocated in the user's quota, the\n * callout_info must be a NUL-terminated string and no auxiliary data can be\n * passed.  Only keys that operate the specified network namespace are used.\n *\n * Furthermore, it then works as wait_for_key_construction() to wait for the\n * completion of keys undergoing construction with a non-interruptible wait.\n */\n#define request_key_net(type, description, net, callout_info) \\\n\trequest_key_tag(type, description, net->key_domain, callout_info);\n\n/**\n * request_key_net_rcu - Request a key for a net namespace under RCU conditions\n * @type: Type of key.\n * @description: The searchable description of the key.\n * @net: The network namespace that is the key's domain of operation.\n *\n * As for request_key_rcu() except that only keys that operate the specified\n * network namespace are used.\n */\n#define request_key_net_rcu(type, description, net) \\\n\trequest_key_rcu(type, description, net->key_domain);\n#endif /* CONFIG_NET */\n\nextern int wait_for_key_construction(struct key *key, bool intr);\n\nextern int key_validate(const struct key *key);\n\nextern key_ref_t key_create_or_update(key_ref_t keyring,\n\t\t\t\t      const char *type,\n\t\t\t\t      const char *description,\n\t\t\t\t      const void *payload,\n\t\t\t\t      size_t plen,\n\t\t\t\t      key_perm_t perm,\n\t\t\t\t      unsigned long flags);\n\nextern int key_update(key_ref_t key,\n\t\t      const void *payload,\n\t\t      size_t plen);\n\nextern int key_link(struct key *keyring,\n\t\t    struct key *key);\n\nextern int key_move(struct key *key,\n\t\t    struct key *from_keyring,\n\t\t    struct key *to_keyring,\n\t\t    unsigned int flags);\n\nextern int key_unlink(struct key *keyring,\n\t\t      struct key *key);\n\nextern struct key *keyring_alloc(const char *description, kuid_t uid, kgid_t gid,\n\t\t\t\t const struct cred *cred,\n\t\t\t\t key_perm_t perm,\n\t\t\t\t unsigned long flags,\n\t\t\t\t struct key_restriction *restrict_link,\n\t\t\t\t struct key *dest);\n\nextern int restrict_link_reject(struct key *keyring,\n\t\t\t\tconst struct key_type *type,\n\t\t\t\tconst union key_payload *payload,\n\t\t\t\tstruct key *restriction_key);\n\nextern int keyring_clear(struct key *keyring);\n\nextern key_ref_t keyring_search(key_ref_t keyring,\n\t\t\t\tstruct key_type *type,\n\t\t\t\tconst char *description,\n\t\t\t\tbool recurse);\n\nextern int keyring_add_key(struct key *keyring,\n\t\t\t   struct key *key);\n\nextern int keyring_restrict(key_ref_t keyring, const char *type,\n\t\t\t    const char *restriction);\n\nextern struct key *key_lookup(key_serial_t id);\n\nstatic inline key_serial_t key_serial(const struct key *key)\n{\n\treturn key ? key->serial : 0;\n}\n\nextern void key_set_timeout(struct key *, unsigned);\n\nextern key_ref_t lookup_user_key(key_serial_t id, unsigned long flags,\n\t\t\t\t key_perm_t perm);\nextern void key_free_user_ns(struct user_namespace *);\n\n/*\n * The permissions required on a key that we're looking up.\n */\n#define\tKEY_NEED_VIEW\t0x01\t/* Require permission to view attributes */\n#define\tKEY_NEED_READ\t0x02\t/* Require permission to read content */\n#define\tKEY_NEED_WRITE\t0x04\t/* Require permission to update / modify */\n#define\tKEY_NEED_SEARCH\t0x08\t/* Require permission to search (keyring) or find (key) */\n#define\tKEY_NEED_LINK\t0x10\t/* Require permission to link */\n#define\tKEY_NEED_SETATTR 0x20\t/* Require permission to change attributes */\n#define\tKEY_NEED_ALL\t0x3f\t/* All the above permissions */\n\nstatic inline short key_read_state(const struct key *key)\n{\n\t/* Barrier versus mark_key_instantiated(). */\n\treturn smp_load_acquire(&key->state);\n}\n\n/**\n * key_is_positive - Determine if a key has been positively instantiated\n * @key: The key to check.\n *\n * Return true if the specified key has been positively instantiated, false\n * otherwise.\n */\nstatic inline bool key_is_positive(const struct key *key)\n{\n\treturn key_read_state(key) == KEY_IS_POSITIVE;\n}\n\nstatic inline bool key_is_negative(const struct key *key)\n{\n\treturn key_read_state(key) < 0;\n}\n\n#define dereference_key_rcu(KEY)\t\t\t\t\t\\\n\t(rcu_dereference((KEY)->payload.rcu_data0))\n\n#define dereference_key_locked(KEY)\t\t\t\t\t\\\n\t(rcu_dereference_protected((KEY)->payload.rcu_data0,\t\t\\\n\t\t\t\t   rwsem_is_locked(&((struct key *)(KEY))->sem)))\n\n#define rcu_assign_keypointer(KEY, PAYLOAD)\t\t\t\t\\\ndo {\t\t\t\t\t\t\t\t\t\\\n\trcu_assign_pointer((KEY)->payload.rcu_data0, (PAYLOAD));\t\\\n} while (0)\n\n#ifdef CONFIG_SYSCTL\nextern struct ctl_table key_sysctls[];\n#endif\n/*\n * the userspace interface\n */\nextern int install_thread_keyring_to_cred(struct cred *cred);\nextern void key_fsuid_changed(struct cred *new_cred);\nextern void key_fsgid_changed(struct cred *new_cred);\nextern void key_init(void);\n\n#else /* CONFIG_KEYS */\n\n#define key_validate(k)\t\t\t0\n#define key_serial(k)\t\t\t0\n#define key_get(k) \t\t\t({ NULL; })\n#define key_revoke(k)\t\t\tdo { } while(0)\n#define key_invalidate(k)\t\tdo { } while(0)\n#define key_put(k)\t\t\tdo { } while(0)\n#define key_ref_put(k)\t\t\tdo { } while(0)\n#define make_key_ref(k, p)\t\tNULL\n#define key_ref_to_ptr(k)\t\tNULL\n#define is_key_possessed(k)\t\t0\n#define key_fsuid_changed(c)\t\tdo { } while(0)\n#define key_fsgid_changed(c)\t\tdo { } while(0)\n#define key_init()\t\t\tdo { } while(0)\n#define key_free_user_ns(ns)\t\tdo { } while(0)\n#define key_remove_domain(d)\t\tdo { } while(0)\n\n#endif /* CONFIG_KEYS */\n#endif /* __KERNEL__ */\n#endif /* _LINUX_KEY_H */\n"
  },
  {
    "path": "t/tree/include/linux/kmod.h",
    "content": "/* SPDX-License-Identifier: GPL-2.0-or-later */\n#ifndef __LINUX_KMOD_H__\n#define __LINUX_KMOD_H__\n\n/*\n *\tinclude/linux/kmod.h\n */\n\n#include <linux/umh.h>\n#include <linux/gfp.h>\n#include <linux/stddef.h>\n#include <linux/errno.h>\n#include <linux/compiler.h>\n#include <linux/workqueue.h>\n#include <linux/sysctl.h>\n\n#define KMOD_PATH_LEN 256\n\n#ifdef CONFIG_MODULES\nextern char modprobe_path[]; /* for sysctl */\n/* modprobe exit status on success, -ve on error.  Return value\n * usually useless though. */\nextern __printf(2, 3)\nint __request_module(bool wait, const char *name, ...);\n#define request_module(mod...) __request_module(true, mod)\n#define request_module_nowait(mod...) __request_module(false, mod)\n#define try_then_request_module(x, mod...) \\\n\t((x) ?: (__request_module(true, mod), (x)))\n#else\nstatic inline int request_module(const char *name, ...) { return -ENOSYS; }\nstatic inline int request_module_nowait(const char *name, ...) { return -ENOSYS; }\n#define try_then_request_module(x, mod...) (x)\n#endif\n\n#endif /* __LINUX_KMOD_H__ */\n"
  },
  {
    "path": "t/tree/include/linux/log2.h",
    "content": "/* SPDX-License-Identifier: GPL-2.0-or-later */\n/* Integer base 2 logarithm calculation\n *\n * Copyright (C) 2006 Red Hat, Inc. All Rights Reserved.\n * Written by David Howells (dhowells@redhat.com)\n */\n\n#ifndef _LINUX_LOG2_H\n#define _LINUX_LOG2_H\n\n#include <linux/types.h>\n#include <linux/bitops.h>\n\n/*\n * non-constant log of base 2 calculators\n * - the arch may override these in asm/bitops.h if they can be implemented\n *   more efficiently than using fls() and fls64()\n * - the arch is not required to handle n==0 if implementing the fallback\n */\n#ifndef CONFIG_ARCH_HAS_ILOG2_U32\nstatic inline __attribute__((const))\nint __ilog2_u32(u32 n)\n{\n\treturn fls(n) - 1;\n}\n#endif\n\n#ifndef CONFIG_ARCH_HAS_ILOG2_U64\nstatic inline __attribute__((const))\nint __ilog2_u64(u64 n)\n{\n\treturn fls64(n) - 1;\n}\n#endif\n\n/**\n * is_power_of_2() - check if a value is a power of two\n * @n: the value to check\n *\n * Determine whether some value is a power of two, where zero is\n * *not* considered a power of two.\n * Return: true if @n is a power of 2, otherwise false.\n */\nstatic inline __attribute__((const))\nbool is_power_of_2(unsigned long n)\n{\n\treturn (n != 0 && ((n & (n - 1)) == 0));\n}\n\n/**\n * __roundup_pow_of_two() - round up to nearest power of two\n * @n: value to round up\n */\nstatic inline __attribute__((const))\nunsigned long __roundup_pow_of_two(unsigned long n)\n{\n\treturn 1UL << fls_long(n - 1);\n}\n\n/**\n * __rounddown_pow_of_two() - round down to nearest power of two\n * @n: value to round down\n */\nstatic inline __attribute__((const))\nunsigned long __rounddown_pow_of_two(unsigned long n)\n{\n\treturn 1UL << (fls_long(n) - 1);\n}\n\n/**\n * const_ilog2 - log base 2 of 32-bit or a 64-bit constant unsigned value\n * @n: parameter\n *\n * Use this where sparse expects a true constant expression, e.g. for array\n * indices.\n */\n#define const_ilog2(n)\t\t\t\t\\\n(\t\t\t\t\t\t\\\n\t__builtin_constant_p(n) ? (\t\t\\\n\t\t(n) < 2 ? 0 :\t\t\t\\\n\t\t(n) & (1ULL << 63) ? 63 :\t\\\n\t\t(n) & (1ULL << 62) ? 62 :\t\\\n\t\t(n) & (1ULL << 61) ? 61 :\t\\\n\t\t(n) & (1ULL << 60) ? 60 :\t\\\n\t\t(n) & (1ULL << 59) ? 59 :\t\\\n\t\t(n) & (1ULL << 58) ? 58 :\t\\\n\t\t(n) & (1ULL << 57) ? 57 :\t\\\n\t\t(n) & (1ULL << 56) ? 56 :\t\\\n\t\t(n) & (1ULL << 55) ? 55 :\t\\\n\t\t(n) & (1ULL << 54) ? 54 :\t\\\n\t\t(n) & (1ULL << 53) ? 53 :\t\\\n\t\t(n) & (1ULL << 52) ? 52 :\t\\\n\t\t(n) & (1ULL << 51) ? 51 :\t\\\n\t\t(n) & (1ULL << 50) ? 50 :\t\\\n\t\t(n) & (1ULL << 49) ? 49 :\t\\\n\t\t(n) & (1ULL << 48) ? 48 :\t\\\n\t\t(n) & (1ULL << 47) ? 47 :\t\\\n\t\t(n) & (1ULL << 46) ? 46 :\t\\\n\t\t(n) & (1ULL << 45) ? 45 :\t\\\n\t\t(n) & (1ULL << 44) ? 44 :\t\\\n\t\t(n) & (1ULL << 43) ? 43 :\t\\\n\t\t(n) & (1ULL << 42) ? 42 :\t\\\n\t\t(n) & (1ULL << 41) ? 41 :\t\\\n\t\t(n) & (1ULL << 40) ? 40 :\t\\\n\t\t(n) & (1ULL << 39) ? 39 :\t\\\n\t\t(n) & (1ULL << 38) ? 38 :\t\\\n\t\t(n) & (1ULL << 37) ? 37 :\t\\\n\t\t(n) & (1ULL << 36) ? 36 :\t\\\n\t\t(n) & (1ULL << 35) ? 35 :\t\\\n\t\t(n) & (1ULL << 34) ? 34 :\t\\\n\t\t(n) & (1ULL << 33) ? 33 :\t\\\n\t\t(n) & (1ULL << 32) ? 32 :\t\\\n\t\t(n) & (1ULL << 31) ? 31 :\t\\\n\t\t(n) & (1ULL << 30) ? 30 :\t\\\n\t\t(n) & (1ULL << 29) ? 29 :\t\\\n\t\t(n) & (1ULL << 28) ? 28 :\t\\\n\t\t(n) & (1ULL << 27) ? 27 :\t\\\n\t\t(n) & (1ULL << 26) ? 26 :\t\\\n\t\t(n) & (1ULL << 25) ? 25 :\t\\\n\t\t(n) & (1ULL << 24) ? 24 :\t\\\n\t\t(n) & (1ULL << 23) ? 23 :\t\\\n\t\t(n) & (1ULL << 22) ? 22 :\t\\\n\t\t(n) & (1ULL << 21) ? 21 :\t\\\n\t\t(n) & (1ULL << 20) ? 20 :\t\\\n\t\t(n) & (1ULL << 19) ? 19 :\t\\\n\t\t(n) & (1ULL << 18) ? 18 :\t\\\n\t\t(n) & (1ULL << 17) ? 17 :\t\\\n\t\t(n) & (1ULL << 16) ? 16 :\t\\\n\t\t(n) & (1ULL << 15) ? 15 :\t\\\n\t\t(n) & (1ULL << 14) ? 14 :\t\\\n\t\t(n) & (1ULL << 13) ? 13 :\t\\\n\t\t(n) & (1ULL << 12) ? 12 :\t\\\n\t\t(n) & (1ULL << 11) ? 11 :\t\\\n\t\t(n) & (1ULL << 10) ? 10 :\t\\\n\t\t(n) & (1ULL <<  9) ?  9 :\t\\\n\t\t(n) & (1ULL <<  8) ?  8 :\t\\\n\t\t(n) & (1ULL <<  7) ?  7 :\t\\\n\t\t(n) & (1ULL <<  6) ?  6 :\t\\\n\t\t(n) & (1ULL <<  5) ?  5 :\t\\\n\t\t(n) & (1ULL <<  4) ?  4 :\t\\\n\t\t(n) & (1ULL <<  3) ?  3 :\t\\\n\t\t(n) & (1ULL <<  2) ?  2 :\t\\\n\t\t1) :\t\t\t\t\\\n\t-1)\n\n/**\n * ilog2 - log base 2 of 32-bit or a 64-bit unsigned value\n * @n: parameter\n *\n * constant-capable log of base 2 calculation\n * - this can be used to initialise global variables from constant data, hence\n * the massive ternary operator construction\n *\n * selects the appropriately-sized optimised version depending on sizeof(n)\n */\n#define ilog2(n) \\\n( \\\n\t__builtin_constant_p(n) ?\t\\\n\tconst_ilog2(n) :\t\t\\\n\t(sizeof(n) <= 4) ?\t\t\\\n\t__ilog2_u32(n) :\t\t\\\n\t__ilog2_u64(n)\t\t\t\\\n )\n\n/**\n * roundup_pow_of_two - round the given value up to nearest power of two\n * @n: parameter\n *\n * round the given value up to the nearest power of two\n * - the result is undefined when n == 0\n * - this can be used to initialise global variables from constant data\n */\n#define roundup_pow_of_two(n)\t\t\t\\\n(\t\t\t\t\t\t\\\n\t__builtin_constant_p(n) ? (\t\t\\\n\t\t(n == 1) ? 1 :\t\t\t\\\n\t\t(1UL << (ilog2((n) - 1) + 1))\t\\\n\t\t\t\t   ) :\t\t\\\n\t__roundup_pow_of_two(n)\t\t\t\\\n )\n\n/**\n * rounddown_pow_of_two - round the given value down to nearest power of two\n * @n: parameter\n *\n * round the given value down to the nearest power of two\n * - the result is undefined when n == 0\n * - this can be used to initialise global variables from constant data\n */\n#define rounddown_pow_of_two(n)\t\t\t\\\n(\t\t\t\t\t\t\\\n\t__builtin_constant_p(n) ? (\t\t\\\n\t\t(1UL << ilog2(n))) :\t\t\\\n\t__rounddown_pow_of_two(n)\t\t\\\n )\n\nstatic inline __attribute_const__\nint __order_base_2(unsigned long n)\n{\n\treturn n > 1 ? ilog2(n - 1) + 1 : 0;\n}\n\n/**\n * order_base_2 - calculate the (rounded up) base 2 order of the argument\n * @n: parameter\n *\n * The first few values calculated by this routine:\n *  ob2(0) = 0\n *  ob2(1) = 0\n *  ob2(2) = 1\n *  ob2(3) = 2\n *  ob2(4) = 2\n *  ob2(5) = 3\n *  ... and so on.\n */\n#define order_base_2(n)\t\t\t\t\\\n(\t\t\t\t\t\t\\\n\t__builtin_constant_p(n) ? (\t\t\\\n\t\t((n) == 0 || (n) == 1) ? 0 :\t\\\n\t\tilog2((n) - 1) + 1) :\t\t\\\n\t__order_base_2(n)\t\t\t\\\n)\n\nstatic inline __attribute__((const))\nint __bits_per(unsigned long n)\n{\n\tif (n < 2)\n\t\treturn 1;\n\tif (is_power_of_2(n))\n\t\treturn order_base_2(n) + 1;\n\treturn order_base_2(n);\n}\n\n/**\n * bits_per - calculate the number of bits required for the argument\n * @n: parameter\n *\n * This is constant-capable and can be used for compile time\n * initializations, e.g bitfields.\n *\n * The first few values calculated by this routine:\n * bf(0) = 1\n * bf(1) = 1\n * bf(2) = 2\n * bf(3) = 2\n * bf(4) = 3\n * ... and so on.\n */\n#define bits_per(n)\t\t\t\t\\\n(\t\t\t\t\t\t\\\n\t__builtin_constant_p(n) ? (\t\t\\\n\t\t((n) == 0 || (n) == 1)\t\t\\\n\t\t\t? 1 : ilog2(n) + 1\t\\\n\t) :\t\t\t\t\t\\\n\t__bits_per(n)\t\t\t\t\\\n)\n#endif /* _LINUX_LOG2_H */\n"
  },
  {
    "path": "t/tree/include/linux/logic_pio.h",
    "content": "// SPDX-License-Identifier: GPL-2.0+\n/*\n * Copyright (C) 2017 HiSilicon Limited, All Rights Reserved.\n * Author: Gabriele Paoloni <gabriele.paoloni@huawei.com>\n * Author: Zhichang Yuan <yuanzhichang@hisilicon.com>\n */\n\n#ifndef __LINUX_LOGIC_PIO_H\n#define __LINUX_LOGIC_PIO_H\n\n#include <linux/fwnode.h>\n\nenum {\n\tLOGIC_PIO_INDIRECT,\t\t/* Indirect IO flag */\n\tLOGIC_PIO_CPU_MMIO,\t\t/* Memory-mapped IO flag */\n};\n\nstruct logic_pio_hwaddr {\n\tstruct list_head list;\n\tstruct fwnode_handle *fwnode;\n\tresource_size_t hw_start;\n\tresource_size_t io_start;\n\tresource_size_t size; /* range size populated */\n\tunsigned long flags;\n\n\tvoid *hostdata;\n\tconst struct logic_pio_host_ops *ops;\n};\n\nstruct logic_pio_host_ops {\n\tu32 (*in)(void *hostdata, unsigned long addr, size_t dwidth);\n\tvoid (*out)(void *hostdata, unsigned long addr, u32 val,\n\t\t    size_t dwidth);\n\tu32 (*ins)(void *hostdata, unsigned long addr, void *buffer,\n\t\t   size_t dwidth, unsigned int count);\n\tvoid (*outs)(void *hostdata, unsigned long addr, const void *buffer,\n\t\t     size_t dwidth, unsigned int count);\n};\n\n#ifdef CONFIG_INDIRECT_PIO\nu8 logic_inb(unsigned long addr);\nvoid logic_outb(u8 value, unsigned long addr);\nvoid logic_outw(u16 value, unsigned long addr);\nvoid logic_outl(u32 value, unsigned long addr);\nu16 logic_inw(unsigned long addr);\nu32 logic_inl(unsigned long addr);\nvoid logic_outb(u8 value, unsigned long addr);\nvoid logic_outw(u16 value, unsigned long addr);\nvoid logic_outl(u32 value, unsigned long addr);\nvoid logic_insb(unsigned long addr, void *buffer, unsigned int count);\nvoid logic_insl(unsigned long addr, void *buffer, unsigned int count);\nvoid logic_insw(unsigned long addr, void *buffer, unsigned int count);\nvoid logic_outsb(unsigned long addr, const void *buffer, unsigned int count);\nvoid logic_outsw(unsigned long addr, const void *buffer, unsigned int count);\nvoid logic_outsl(unsigned long addr, const void *buffer, unsigned int count);\n\n#ifndef inb\n#define inb logic_inb\n#endif\n\n#ifndef inw\n#define inw logic_inw\n#endif\n\n#ifndef inl\n#define inl logic_inl\n#endif\n\n#ifndef outb\n#define outb logic_outb\n#endif\n\n#ifndef outw\n#define outw logic_outw\n#endif\n\n#ifndef outl\n#define outl logic_outl\n#endif\n\n#ifndef insb\n#define insb logic_insb\n#endif\n\n#ifndef insw\n#define insw logic_insw\n#endif\n\n#ifndef insl\n#define insl logic_insl\n#endif\n\n#ifndef outsb\n#define outsb logic_outsb\n#endif\n\n#ifndef outsw\n#define outsw logic_outsw\n#endif\n\n#ifndef outsl\n#define outsl logic_outsl\n#endif\n\n/*\n * We reserve 0x4000 bytes for Indirect IO as so far this library is only\n * used by the HiSilicon LPC Host. If needed, we can reserve a wider IO\n * area by redefining the macro below.\n */\n#define PIO_INDIRECT_SIZE 0x4000\n#define MMIO_UPPER_LIMIT (IO_SPACE_LIMIT - PIO_INDIRECT_SIZE)\n#else\n#define MMIO_UPPER_LIMIT IO_SPACE_LIMIT\n#endif /* CONFIG_INDIRECT_PIO */\n\nstruct logic_pio_hwaddr *find_io_range_by_fwnode(struct fwnode_handle *fwnode);\nunsigned long logic_pio_trans_hwaddr(struct fwnode_handle *fwnode,\n\t\t\tresource_size_t hw_addr, resource_size_t size);\nint logic_pio_register_range(struct logic_pio_hwaddr *newrange);\nvoid logic_pio_unregister_range(struct logic_pio_hwaddr *range);\nresource_size_t logic_pio_to_hwaddr(unsigned long pio);\nunsigned long logic_pio_trans_cpuaddr(resource_size_t hw_addr);\n\n#endif /* __LINUX_LOGIC_PIO_H */\n"
  },
  {
    "path": "t/tree/include/linux/memblock.h",
    "content": "/* SPDX-License-Identifier: GPL-2.0-or-later */\n#ifndef _LINUX_MEMBLOCK_H\n#define _LINUX_MEMBLOCK_H\n#ifdef __KERNEL__\n\n/*\n * Logical memory blocks.\n *\n * Copyright (C) 2001 Peter Bergner, IBM Corp.\n */\n\n#include <linux/init.h>\n#include <linux/mm.h>\n#include <asm/dma.h>\n\nextern unsigned long max_low_pfn;\nextern unsigned long min_low_pfn;\n\n/*\n * highest page\n */\nextern unsigned long max_pfn;\n/*\n * highest possible page\n */\nextern unsigned long long max_possible_pfn;\n\n/**\n * enum memblock_flags - definition of memory region attributes\n * @MEMBLOCK_NONE: no special request\n * @MEMBLOCK_HOTPLUG: hotpluggable region\n * @MEMBLOCK_MIRROR: mirrored region\n * @MEMBLOCK_NOMAP: don't add to kernel direct mapping\n */\nenum memblock_flags {\n\tMEMBLOCK_NONE\t\t= 0x0,\t/* No special request */\n\tMEMBLOCK_HOTPLUG\t= 0x1,\t/* hotpluggable region */\n\tMEMBLOCK_MIRROR\t\t= 0x2,\t/* mirrored region */\n\tMEMBLOCK_NOMAP\t\t= 0x4,\t/* don't add to kernel direct mapping */\n};\n\n/**\n * struct memblock_region - represents a memory region\n * @base: physical address of the region\n * @size: size of the region\n * @flags: memory region attributes\n * @nid: NUMA node id\n */\nstruct memblock_region {\n\tphys_addr_t base;\n\tphys_addr_t size;\n\tenum memblock_flags flags;\n#ifdef CONFIG_HAVE_MEMBLOCK_NODE_MAP\n\tint nid;\n#endif\n};\n\n/**\n * struct memblock_type - collection of memory regions of certain type\n * @cnt: number of regions\n * @max: size of the allocated array\n * @total_size: size of all regions\n * @regions: array of regions\n * @name: the memory type symbolic name\n */\nstruct memblock_type {\n\tunsigned long cnt;\n\tunsigned long max;\n\tphys_addr_t total_size;\n\tstruct memblock_region *regions;\n\tchar *name;\n};\n\n/**\n * struct memblock - memblock allocator metadata\n * @bottom_up: is bottom up direction?\n * @current_limit: physical address of the current allocation limit\n * @memory: usabe memory regions\n * @reserved: reserved memory regions\n * @physmem: all physical memory\n */\nstruct memblock {\n\tbool bottom_up;  /* is bottom up direction? */\n\tphys_addr_t current_limit;\n\tstruct memblock_type memory;\n\tstruct memblock_type reserved;\n#ifdef CONFIG_HAVE_MEMBLOCK_PHYS_MAP\n\tstruct memblock_type physmem;\n#endif\n};\n\nextern struct memblock memblock;\nextern int memblock_debug;\n\n#ifndef CONFIG_ARCH_KEEP_MEMBLOCK\n#define __init_memblock __meminit\n#define __initdata_memblock __meminitdata\nvoid memblock_discard(void);\n#else\n#define __init_memblock\n#define __initdata_memblock\nstatic inline void memblock_discard(void) {}\n#endif\n\n#define memblock_dbg(fmt, ...) \\\n\tif (memblock_debug) printk(KERN_INFO pr_fmt(fmt), ##__VA_ARGS__)\n\nphys_addr_t memblock_find_in_range(phys_addr_t start, phys_addr_t end,\n\t\t\t\t   phys_addr_t size, phys_addr_t align);\nvoid memblock_allow_resize(void);\nint memblock_add_node(phys_addr_t base, phys_addr_t size, int nid);\nint memblock_add(phys_addr_t base, phys_addr_t size);\nint memblock_remove(phys_addr_t base, phys_addr_t size);\nint memblock_free(phys_addr_t base, phys_addr_t size);\nint memblock_reserve(phys_addr_t base, phys_addr_t size);\n#ifdef CONFIG_HAVE_MEMBLOCK_PHYS_MAP\nint memblock_physmem_add(phys_addr_t base, phys_addr_t size);\n#endif\nvoid memblock_trim_memory(phys_addr_t align);\nbool memblock_overlaps_region(struct memblock_type *type,\n\t\t\t      phys_addr_t base, phys_addr_t size);\nint memblock_mark_hotplug(phys_addr_t base, phys_addr_t size);\nint memblock_clear_hotplug(phys_addr_t base, phys_addr_t size);\nint memblock_mark_mirror(phys_addr_t base, phys_addr_t size);\nint memblock_mark_nomap(phys_addr_t base, phys_addr_t size);\nint memblock_clear_nomap(phys_addr_t base, phys_addr_t size);\n\nunsigned long memblock_free_all(void);\nvoid reset_node_managed_pages(pg_data_t *pgdat);\nvoid reset_all_zones_managed_pages(void);\n\n/* Low level functions */\nvoid __next_mem_range(u64 *idx, int nid, enum memblock_flags flags,\n\t\t      struct memblock_type *type_a,\n\t\t      struct memblock_type *type_b, phys_addr_t *out_start,\n\t\t      phys_addr_t *out_end, int *out_nid);\n\nvoid __next_mem_range_rev(u64 *idx, int nid, enum memblock_flags flags,\n\t\t\t  struct memblock_type *type_a,\n\t\t\t  struct memblock_type *type_b, phys_addr_t *out_start,\n\t\t\t  phys_addr_t *out_end, int *out_nid);\n\nvoid __next_reserved_mem_region(u64 *idx, phys_addr_t *out_start,\n\t\t\t\tphys_addr_t *out_end);\n\nvoid __memblock_free_late(phys_addr_t base, phys_addr_t size);\n\n/**\n * for_each_mem_range - iterate through memblock areas from type_a and not\n * included in type_b. Or just type_a if type_b is NULL.\n * @i: u64 used as loop variable\n * @type_a: ptr to memblock_type to iterate\n * @type_b: ptr to memblock_type which excludes from the iteration\n * @nid: node selector, %NUMA_NO_NODE for all nodes\n * @flags: pick from blocks based on memory attributes\n * @p_start: ptr to phys_addr_t for start address of the range, can be %NULL\n * @p_end: ptr to phys_addr_t for end address of the range, can be %NULL\n * @p_nid: ptr to int for nid of the range, can be %NULL\n */\n#define for_each_mem_range(i, type_a, type_b, nid, flags,\t\t\\\n\t\t\t   p_start, p_end, p_nid)\t\t\t\\\n\tfor (i = 0, __next_mem_range(&i, nid, flags, type_a, type_b,\t\\\n\t\t\t\t     p_start, p_end, p_nid);\t\t\\\n\t     i != (u64)ULLONG_MAX;\t\t\t\t\t\\\n\t     __next_mem_range(&i, nid, flags, type_a, type_b,\t\t\\\n\t\t\t      p_start, p_end, p_nid))\n\n/**\n * for_each_mem_range_rev - reverse iterate through memblock areas from\n * type_a and not included in type_b. Or just type_a if type_b is NULL.\n * @i: u64 used as loop variable\n * @type_a: ptr to memblock_type to iterate\n * @type_b: ptr to memblock_type which excludes from the iteration\n * @nid: node selector, %NUMA_NO_NODE for all nodes\n * @flags: pick from blocks based on memory attributes\n * @p_start: ptr to phys_addr_t for start address of the range, can be %NULL\n * @p_end: ptr to phys_addr_t for end address of the range, can be %NULL\n * @p_nid: ptr to int for nid of the range, can be %NULL\n */\n#define for_each_mem_range_rev(i, type_a, type_b, nid, flags,\t\t\\\n\t\t\t       p_start, p_end, p_nid)\t\t\t\\\n\tfor (i = (u64)ULLONG_MAX,\t\t\t\t\t\\\n\t\t     __next_mem_range_rev(&i, nid, flags, type_a, type_b,\\\n\t\t\t\t\t  p_start, p_end, p_nid);\t\\\n\t     i != (u64)ULLONG_MAX;\t\t\t\t\t\\\n\t     __next_mem_range_rev(&i, nid, flags, type_a, type_b,\t\\\n\t\t\t\t  p_start, p_end, p_nid))\n\n/**\n * for_each_reserved_mem_region - iterate over all reserved memblock areas\n * @i: u64 used as loop variable\n * @p_start: ptr to phys_addr_t for start address of the range, can be %NULL\n * @p_end: ptr to phys_addr_t for end address of the range, can be %NULL\n *\n * Walks over reserved areas of memblock. Available as soon as memblock\n * is initialized.\n */\n#define for_each_reserved_mem_region(i, p_start, p_end)\t\t\t\\\n\tfor (i = 0UL, __next_reserved_mem_region(&i, p_start, p_end);\t\\\n\t     i != (u64)ULLONG_MAX;\t\t\t\t\t\\\n\t     __next_reserved_mem_region(&i, p_start, p_end))\n\nstatic inline bool memblock_is_hotpluggable(struct memblock_region *m)\n{\n\treturn m->flags & MEMBLOCK_HOTPLUG;\n}\n\nstatic inline bool memblock_is_mirror(struct memblock_region *m)\n{\n\treturn m->flags & MEMBLOCK_MIRROR;\n}\n\nstatic inline bool memblock_is_nomap(struct memblock_region *m)\n{\n\treturn m->flags & MEMBLOCK_NOMAP;\n}\n\n#ifdef CONFIG_HAVE_MEMBLOCK_NODE_MAP\nint memblock_search_pfn_nid(unsigned long pfn, unsigned long *start_pfn,\n\t\t\t    unsigned long  *end_pfn);\nvoid __next_mem_pfn_range(int *idx, int nid, unsigned long *out_start_pfn,\n\t\t\t  unsigned long *out_end_pfn, int *out_nid);\n\n/**\n * for_each_mem_pfn_range - early memory pfn range iterator\n * @i: an integer used as loop variable\n * @nid: node selector, %MAX_NUMNODES for all nodes\n * @p_start: ptr to ulong for start pfn of the range, can be %NULL\n * @p_end: ptr to ulong for end pfn of the range, can be %NULL\n * @p_nid: ptr to int for nid of the range, can be %NULL\n *\n * Walks over configured memory ranges.\n */\n#define for_each_mem_pfn_range(i, nid, p_start, p_end, p_nid)\t\t\\\n\tfor (i = -1, __next_mem_pfn_range(&i, nid, p_start, p_end, p_nid); \\\n\t     i >= 0; __next_mem_pfn_range(&i, nid, p_start, p_end, p_nid))\n#endif /* CONFIG_HAVE_MEMBLOCK_NODE_MAP */\n\n#ifdef CONFIG_DEFERRED_STRUCT_PAGE_INIT\nvoid __next_mem_pfn_range_in_zone(u64 *idx, struct zone *zone,\n\t\t\t\t  unsigned long *out_spfn,\n\t\t\t\t  unsigned long *out_epfn);\n/**\n * for_each_free_mem_range_in_zone - iterate through zone specific free\n * memblock areas\n * @i: u64 used as loop variable\n * @zone: zone in which all of the memory blocks reside\n * @p_start: ptr to phys_addr_t for start address of the range, can be %NULL\n * @p_end: ptr to phys_addr_t for end address of the range, can be %NULL\n *\n * Walks over free (memory && !reserved) areas of memblock in a specific\n * zone. Available once memblock and an empty zone is initialized. The main\n * assumption is that the zone start, end, and pgdat have been associated.\n * This way we can use the zone to determine NUMA node, and if a given part\n * of the memblock is valid for the zone.\n */\n#define for_each_free_mem_pfn_range_in_zone(i, zone, p_start, p_end)\t\\\n\tfor (i = 0,\t\t\t\t\t\t\t\\\n\t     __next_mem_pfn_range_in_zone(&i, zone, p_start, p_end);\t\\\n\t     i != U64_MAX;\t\t\t\t\t\\\n\t     __next_mem_pfn_range_in_zone(&i, zone, p_start, p_end))\n\n/**\n * for_each_free_mem_range_in_zone_from - iterate through zone specific\n * free memblock areas from a given point\n * @i: u64 used as loop variable\n * @zone: zone in which all of the memory blocks reside\n * @p_start: ptr to phys_addr_t for start address of the range, can be %NULL\n * @p_end: ptr to phys_addr_t for end address of the range, can be %NULL\n *\n * Walks over free (memory && !reserved) areas of memblock in a specific\n * zone, continuing from current position. Available as soon as memblock is\n * initialized.\n */\n#define for_each_free_mem_pfn_range_in_zone_from(i, zone, p_start, p_end) \\\n\tfor (; i != U64_MAX;\t\t\t\t\t  \\\n\t     __next_mem_pfn_range_in_zone(&i, zone, p_start, p_end))\n#endif /* CONFIG_DEFERRED_STRUCT_PAGE_INIT */\n\n/**\n * for_each_free_mem_range - iterate through free memblock areas\n * @i: u64 used as loop variable\n * @nid: node selector, %NUMA_NO_NODE for all nodes\n * @flags: pick from blocks based on memory attributes\n * @p_start: ptr to phys_addr_t for start address of the range, can be %NULL\n * @p_end: ptr to phys_addr_t for end address of the range, can be %NULL\n * @p_nid: ptr to int for nid of the range, can be %NULL\n *\n * Walks over free (memory && !reserved) areas of memblock.  Available as\n * soon as memblock is initialized.\n */\n#define for_each_free_mem_range(i, nid, flags, p_start, p_end, p_nid)\t\\\n\tfor_each_mem_range(i, &memblock.memory, &memblock.reserved,\t\\\n\t\t\t   nid, flags, p_start, p_end, p_nid)\n\n/**\n * for_each_free_mem_range_reverse - rev-iterate through free memblock areas\n * @i: u64 used as loop variable\n * @nid: node selector, %NUMA_NO_NODE for all nodes\n * @flags: pick from blocks based on memory attributes\n * @p_start: ptr to phys_addr_t for start address of the range, can be %NULL\n * @p_end: ptr to phys_addr_t for end address of the range, can be %NULL\n * @p_nid: ptr to int for nid of the range, can be %NULL\n *\n * Walks over free (memory && !reserved) areas of memblock in reverse\n * order.  Available as soon as memblock is initialized.\n */\n#define for_each_free_mem_range_reverse(i, nid, flags, p_start, p_end,\t\\\n\t\t\t\t\tp_nid)\t\t\t\t\\\n\tfor_each_mem_range_rev(i, &memblock.memory, &memblock.reserved,\t\\\n\t\t\t       nid, flags, p_start, p_end, p_nid)\n\n#ifdef CONFIG_HAVE_MEMBLOCK_NODE_MAP\nint memblock_set_node(phys_addr_t base, phys_addr_t size,\n\t\t      struct memblock_type *type, int nid);\n\nstatic inline void memblock_set_region_node(struct memblock_region *r, int nid)\n{\n\tr->nid = nid;\n}\n\nstatic inline int memblock_get_region_node(const struct memblock_region *r)\n{\n\treturn r->nid;\n}\n#else\nstatic inline void memblock_set_region_node(struct memblock_region *r, int nid)\n{\n}\n\nstatic inline int memblock_get_region_node(const struct memblock_region *r)\n{\n\treturn 0;\n}\n#endif /* CONFIG_HAVE_MEMBLOCK_NODE_MAP */\n\n/* Flags for memblock allocation APIs */\n#define MEMBLOCK_ALLOC_ANYWHERE\t(~(phys_addr_t)0)\n#define MEMBLOCK_ALLOC_ACCESSIBLE\t0\n#define MEMBLOCK_ALLOC_KASAN\t\t1\n\n/* We are using top down, so it is safe to use 0 here */\n#define MEMBLOCK_LOW_LIMIT 0\n\n#ifndef ARCH_LOW_ADDRESS_LIMIT\n#define ARCH_LOW_ADDRESS_LIMIT  0xffffffffUL\n#endif\n\nphys_addr_t memblock_phys_alloc_range(phys_addr_t size, phys_addr_t align,\n\t\t\t\t      phys_addr_t start, phys_addr_t end);\nphys_addr_t memblock_phys_alloc_try_nid(phys_addr_t size, phys_addr_t align, int nid);\n\nstatic inline phys_addr_t memblock_phys_alloc(phys_addr_t size,\n\t\t\t\t\t      phys_addr_t align)\n{\n\treturn memblock_phys_alloc_range(size, align, 0,\n\t\t\t\t\t MEMBLOCK_ALLOC_ACCESSIBLE);\n}\n\nvoid *memblock_alloc_exact_nid_raw(phys_addr_t size, phys_addr_t align,\n\t\t\t\t phys_addr_t min_addr, phys_addr_t max_addr,\n\t\t\t\t int nid);\nvoid *memblock_alloc_try_nid_raw(phys_addr_t size, phys_addr_t align,\n\t\t\t\t phys_addr_t min_addr, phys_addr_t max_addr,\n\t\t\t\t int nid);\nvoid *memblock_alloc_try_nid(phys_addr_t size, phys_addr_t align,\n\t\t\t     phys_addr_t min_addr, phys_addr_t max_addr,\n\t\t\t     int nid);\n\nstatic inline void * __init memblock_alloc(phys_addr_t size,  phys_addr_t align)\n{\n\treturn memblock_alloc_try_nid(size, align, MEMBLOCK_LOW_LIMIT,\n\t\t\t\t      MEMBLOCK_ALLOC_ACCESSIBLE, NUMA_NO_NODE);\n}\n\nstatic inline void * __init memblock_alloc_raw(phys_addr_t size,\n\t\t\t\t\t       phys_addr_t align)\n{\n\treturn memblock_alloc_try_nid_raw(size, align, MEMBLOCK_LOW_LIMIT,\n\t\t\t\t\t  MEMBLOCK_ALLOC_ACCESSIBLE,\n\t\t\t\t\t  NUMA_NO_NODE);\n}\n\nstatic inline void * __init memblock_alloc_from(phys_addr_t size,\n\t\t\t\t\t\tphys_addr_t align,\n\t\t\t\t\t\tphys_addr_t min_addr)\n{\n\treturn memblock_alloc_try_nid(size, align, min_addr,\n\t\t\t\t      MEMBLOCK_ALLOC_ACCESSIBLE, NUMA_NO_NODE);\n}\n\nstatic inline void * __init memblock_alloc_low(phys_addr_t size,\n\t\t\t\t\t       phys_addr_t align)\n{\n\treturn memblock_alloc_try_nid(size, align, MEMBLOCK_LOW_LIMIT,\n\t\t\t\t      ARCH_LOW_ADDRESS_LIMIT, NUMA_NO_NODE);\n}\n\nstatic inline void * __init memblock_alloc_node(phys_addr_t size,\n\t\t\t\t\t\tphys_addr_t align, int nid)\n{\n\treturn memblock_alloc_try_nid(size, align, MEMBLOCK_LOW_LIMIT,\n\t\t\t\t      MEMBLOCK_ALLOC_ACCESSIBLE, nid);\n}\n\nstatic inline void __init memblock_free_early(phys_addr_t base,\n\t\t\t\t\t      phys_addr_t size)\n{\n\tmemblock_free(base, size);\n}\n\nstatic inline void __init memblock_free_early_nid(phys_addr_t base,\n\t\t\t\t\t\t  phys_addr_t size, int nid)\n{\n\tmemblock_free(base, size);\n}\n\nstatic inline void __init memblock_free_late(phys_addr_t base, phys_addr_t size)\n{\n\t__memblock_free_late(base, size);\n}\n\n/*\n * Set the allocation direction to bottom-up or top-down.\n */\nstatic inline void __init memblock_set_bottom_up(bool enable)\n{\n\tmemblock.bottom_up = enable;\n}\n\n/*\n * Check if the allocation direction is bottom-up or not.\n * if this is true, that said, memblock will allocate memory\n * in bottom-up direction.\n */\nstatic inline bool memblock_bottom_up(void)\n{\n\treturn memblock.bottom_up;\n}\n\nphys_addr_t memblock_phys_mem_size(void);\nphys_addr_t memblock_reserved_size(void);\nphys_addr_t memblock_mem_size(unsigned long limit_pfn);\nphys_addr_t memblock_start_of_DRAM(void);\nphys_addr_t memblock_end_of_DRAM(void);\nvoid memblock_enforce_memory_limit(phys_addr_t memory_limit);\nvoid memblock_cap_memory_range(phys_addr_t base, phys_addr_t size);\nvoid memblock_mem_limit_remove_map(phys_addr_t limit);\nbool memblock_is_memory(phys_addr_t addr);\nbool memblock_is_map_memory(phys_addr_t addr);\nbool memblock_is_region_memory(phys_addr_t base, phys_addr_t size);\nbool memblock_is_reserved(phys_addr_t addr);\nbool memblock_is_region_reserved(phys_addr_t base, phys_addr_t size);\n\nextern void __memblock_dump_all(void);\n\nstatic inline void memblock_dump_all(void)\n{\n\tif (memblock_debug)\n\t\t__memblock_dump_all();\n}\n\n/**\n * memblock_set_current_limit - Set the current allocation limit to allow\n *                         limiting allocations to what is currently\n *                         accessible during boot\n * @limit: New limit value (physical address)\n */\nvoid memblock_set_current_limit(phys_addr_t limit);\n\n\nphys_addr_t memblock_get_current_limit(void);\n\n/*\n * pfn conversion functions\n *\n * While the memory MEMBLOCKs should always be page aligned, the reserved\n * MEMBLOCKs may not be. This accessor attempt to provide a very clear\n * idea of what they return for such non aligned MEMBLOCKs.\n */\n\n/**\n * memblock_region_memory_base_pfn - get the lowest pfn of the memory region\n * @reg: memblock_region structure\n *\n * Return: the lowest pfn intersecting with the memory region\n */\nstatic inline unsigned long memblock_region_memory_base_pfn(const struct memblock_region *reg)\n{\n\treturn PFN_UP(reg->base);\n}\n\n/**\n * memblock_region_memory_end_pfn - get the end pfn of the memory region\n * @reg: memblock_region structure\n *\n * Return: the end_pfn of the reserved region\n */\nstatic inline unsigned long memblock_region_memory_end_pfn(const struct memblock_region *reg)\n{\n\treturn PFN_DOWN(reg->base + reg->size);\n}\n\n/**\n * memblock_region_reserved_base_pfn - get the lowest pfn of the reserved region\n * @reg: memblock_region structure\n *\n * Return: the lowest pfn intersecting with the reserved region\n */\nstatic inline unsigned long memblock_region_reserved_base_pfn(const struct memblock_region *reg)\n{\n\treturn PFN_DOWN(reg->base);\n}\n\n/**\n * memblock_region_reserved_end_pfn - get the end pfn of the reserved region\n * @reg: memblock_region structure\n *\n * Return: the end_pfn of the reserved region\n */\nstatic inline unsigned long memblock_region_reserved_end_pfn(const struct memblock_region *reg)\n{\n\treturn PFN_UP(reg->base + reg->size);\n}\n\n#define for_each_memblock(memblock_type, region)\t\t\t\t\t\\\n\tfor (region = memblock.memblock_type.regions;\t\t\t\t\t\\\n\t     region < (memblock.memblock_type.regions + memblock.memblock_type.cnt);\t\\\n\t     region++)\n\n#define for_each_memblock_type(i, memblock_type, rgn)\t\t\t\\\n\tfor (i = 0, rgn = &memblock_type->regions[0];\t\t\t\\\n\t     i < memblock_type->cnt;\t\t\t\t\t\\\n\t     i++, rgn = &memblock_type->regions[i])\n\nextern void *alloc_large_system_hash(const char *tablename,\n\t\t\t\t     unsigned long bucketsize,\n\t\t\t\t     unsigned long numentries,\n\t\t\t\t     int scale,\n\t\t\t\t     int flags,\n\t\t\t\t     unsigned int *_hash_shift,\n\t\t\t\t     unsigned int *_hash_mask,\n\t\t\t\t     unsigned long low_limit,\n\t\t\t\t     unsigned long high_limit);\n\n#define HASH_EARLY\t0x00000001\t/* Allocating during early boot? */\n#define HASH_SMALL\t0x00000002\t/* sub-page allocation allowed, min\n\t\t\t\t\t * shift passed via *_hash_shift */\n#define HASH_ZERO\t0x00000004\t/* Zero allocated hash table */\n\n/* Only NUMA needs hash distribution. 64bit NUMA architectures have\n * sufficient vmalloc space.\n */\n#ifdef CONFIG_NUMA\n#define HASHDIST_DEFAULT IS_ENABLED(CONFIG_64BIT)\nextern int hashdist;\t\t/* Distribute hashes across NUMA nodes? */\n#else\n#define hashdist (0)\n#endif\n\n#ifdef CONFIG_MEMTEST\nextern void early_memtest(phys_addr_t start, phys_addr_t end);\n#else\nstatic inline void early_memtest(phys_addr_t start, phys_addr_t end)\n{\n}\n#endif\n\n#endif /* __KERNEL__ */\n\n#endif /* _LINUX_MEMBLOCK_H */\n"
  },
  {
    "path": "t/tree/include/linux/of.h",
    "content": "/* SPDX-License-Identifier: GPL-2.0+ */\n#ifndef _LINUX_OF_H\n#define _LINUX_OF_H\n/*\n * Definitions for talking to the Open Firmware PROM on\n * Power Macintosh and other computers.\n *\n * Copyright (C) 1996-2005 Paul Mackerras.\n *\n * Updates for PPC64 by Peter Bergner & David Engebretsen, IBM Corp.\n * Updates for SPARC64 by David S. Miller\n * Derived from PowerPC and Sparc prom.h files by Stephen Rothwell, IBM Corp.\n */\n#include <linux/types.h>\n#include <linux/bitops.h>\n#include <linux/errno.h>\n#include <linux/kobject.h>\n#include <linux/mod_devicetable.h>\n#include <linux/spinlock.h>\n#include <linux/topology.h>\n#include <linux/notifier.h>\n#include <linux/property.h>\n#include <linux/list.h>\n\n#include <asm/byteorder.h>\n#include <asm/errno.h>\n\ntypedef u32 phandle;\ntypedef u32 ihandle;\n\nstruct property {\n\tchar\t*name;\n\tint\tlength;\n\tvoid\t*value;\n\tstruct property *next;\n#if defined(CONFIG_OF_DYNAMIC) || defined(CONFIG_SPARC)\n\tunsigned long _flags;\n#endif\n#if defined(CONFIG_OF_PROMTREE)\n\tunsigned int unique_id;\n#endif\n#if defined(CONFIG_OF_KOBJ)\n\tstruct bin_attribute attr;\n#endif\n};\n\n#if defined(CONFIG_SPARC)\nstruct of_irq_controller;\n#endif\n\nstruct device_node {\n\tconst char *name;\n\tphandle phandle;\n\tconst char *full_name;\n\tstruct fwnode_handle fwnode;\n\n\tstruct\tproperty *properties;\n\tstruct\tproperty *deadprops;\t/* removed properties */\n\tstruct\tdevice_node *parent;\n\tstruct\tdevice_node *child;\n\tstruct\tdevice_node *sibling;\n#if defined(CONFIG_OF_KOBJ)\n\tstruct\tkobject kobj;\n#endif\n\tunsigned long _flags;\n\tvoid\t*data;\n#if defined(CONFIG_SPARC)\n\tunsigned int unique_id;\n\tstruct of_irq_controller *irq_trans;\n#endif\n};\n\n#define MAX_PHANDLE_ARGS 16\nstruct of_phandle_args {\n\tstruct device_node *np;\n\tint args_count;\n\tuint32_t args[MAX_PHANDLE_ARGS];\n};\n\nstruct of_phandle_iterator {\n\t/* Common iterator information */\n\tconst char *cells_name;\n\tint cell_count;\n\tconst struct device_node *parent;\n\n\t/* List size information */\n\tconst __be32 *list_end;\n\tconst __be32 *phandle_end;\n\n\t/* Current position state */\n\tconst __be32 *cur;\n\tuint32_t cur_count;\n\tphandle phandle;\n\tstruct device_node *node;\n};\n\nstruct of_reconfig_data {\n\tstruct device_node\t*dn;\n\tstruct property\t\t*prop;\n\tstruct property\t\t*old_prop;\n};\n\n/* initialize a node */\nextern struct kobj_type of_node_ktype;\nextern const struct fwnode_operations of_fwnode_ops;\nstatic inline void of_node_init(struct device_node *node)\n{\n#if defined(CONFIG_OF_KOBJ)\n\tkobject_init(&node->kobj, &of_node_ktype);\n#endif\n\tnode->fwnode.ops = &of_fwnode_ops;\n}\n\n#if defined(CONFIG_OF_KOBJ)\n#define of_node_kobj(n) (&(n)->kobj)\n#else\n#define of_node_kobj(n) NULL\n#endif\n\n#ifdef CONFIG_OF_DYNAMIC\nextern struct device_node *of_node_get(struct device_node *node);\nextern void of_node_put(struct device_node *node);\n#else /* CONFIG_OF_DYNAMIC */\n/* Dummy ref counting routines - to be implemented later */\nstatic inline struct device_node *of_node_get(struct device_node *node)\n{\n\treturn node;\n}\nstatic inline void of_node_put(struct device_node *node) { }\n#endif /* !CONFIG_OF_DYNAMIC */\n\n/* Pointer for first entry in chain of all nodes. */\nextern struct device_node *of_root;\nextern struct device_node *of_chosen;\nextern struct device_node *of_aliases;\nextern struct device_node *of_stdout;\nextern raw_spinlock_t devtree_lock;\n\n/*\n * struct device_node flag descriptions\n * (need to be visible even when !CONFIG_OF)\n */\n#define OF_DYNAMIC\t\t1 /* (and properties) allocated via kmalloc */\n#define OF_DETACHED\t\t2 /* detached from the device tree */\n#define OF_POPULATED\t\t3 /* device already created */\n#define OF_POPULATED_BUS\t4 /* platform bus created for children */\n#define OF_OVERLAY\t\t5 /* allocated for an overlay */\n#define OF_OVERLAY_FREE_CSET\t6 /* in overlay cset being freed */\n\n#define OF_BAD_ADDR\t((u64)-1)\n\n#ifdef CONFIG_OF\nvoid of_core_init(void);\n\nstatic inline bool is_of_node(const struct fwnode_handle *fwnode)\n{\n\treturn !IS_ERR_OR_NULL(fwnode) && fwnode->ops == &of_fwnode_ops;\n}\n\n#define to_of_node(__fwnode)\t\t\t\t\t\t\\\n\t({\t\t\t\t\t\t\t\t\\\n\t\ttypeof(__fwnode) __to_of_node_fwnode = (__fwnode);\t\\\n\t\t\t\t\t\t\t\t\t\\\n\t\tis_of_node(__to_of_node_fwnode) ?\t\t\t\\\n\t\t\tcontainer_of(__to_of_node_fwnode,\t\t\\\n\t\t\t\t     struct device_node, fwnode) :\t\\\n\t\t\tNULL;\t\t\t\t\t\t\\\n\t})\n\n#define of_fwnode_handle(node)\t\t\t\t\t\t\\\n\t({\t\t\t\t\t\t\t\t\\\n\t\ttypeof(node) __of_fwnode_handle_node = (node);\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\t\t__of_fwnode_handle_node ?\t\t\t\t\\\n\t\t\t&__of_fwnode_handle_node->fwnode : NULL;\t\\\n\t})\n\nstatic inline bool of_have_populated_dt(void)\n{\n\treturn of_root != NULL;\n}\n\nstatic inline bool of_node_is_root(const struct device_node *node)\n{\n\treturn node && (node->parent == NULL);\n}\n\nstatic inline int of_node_check_flag(struct device_node *n, unsigned long flag)\n{\n\treturn test_bit(flag, &n->_flags);\n}\n\nstatic inline int of_node_test_and_set_flag(struct device_node *n,\n\t\t\t\t\t    unsigned long flag)\n{\n\treturn test_and_set_bit(flag, &n->_flags);\n}\n\nstatic inline void of_node_set_flag(struct device_node *n, unsigned long flag)\n{\n\tset_bit(flag, &n->_flags);\n}\n\nstatic inline void of_node_clear_flag(struct device_node *n, unsigned long flag)\n{\n\tclear_bit(flag, &n->_flags);\n}\n\n#if defined(CONFIG_OF_DYNAMIC) || defined(CONFIG_SPARC)\nstatic inline int of_property_check_flag(struct property *p, unsigned long flag)\n{\n\treturn test_bit(flag, &p->_flags);\n}\n\nstatic inline void of_property_set_flag(struct property *p, unsigned long flag)\n{\n\tset_bit(flag, &p->_flags);\n}\n\nstatic inline void of_property_clear_flag(struct property *p, unsigned long flag)\n{\n\tclear_bit(flag, &p->_flags);\n}\n#endif\n\nextern struct device_node *__of_find_all_nodes(struct device_node *prev);\nextern struct device_node *of_find_all_nodes(struct device_node *prev);\n\n/*\n * OF address retrieval & translation\n */\n\n/* Helper to read a big number; size is in cells (not bytes) */\nstatic inline u64 of_read_number(const __be32 *cell, int size)\n{\n\tu64 r = 0;\n\tfor (; size--; cell++)\n\t\tr = (r << 32) | be32_to_cpu(*cell);\n\treturn r;\n}\n\n/* Like of_read_number, but we want an unsigned long result */\nstatic inline unsigned long of_read_ulong(const __be32 *cell, int size)\n{\n\t/* toss away upper bits if unsigned long is smaller than u64 */\n\treturn of_read_number(cell, size);\n}\n\n#if defined(CONFIG_SPARC)\n#include <asm/prom.h>\n#endif\n\n#define OF_IS_DYNAMIC(x) test_bit(OF_DYNAMIC, &x->_flags)\n#define OF_MARK_DYNAMIC(x) set_bit(OF_DYNAMIC, &x->_flags)\n\nextern bool of_node_name_eq(const struct device_node *np, const char *name);\nextern bool of_node_name_prefix(const struct device_node *np, const char *prefix);\n\nstatic inline const char *of_node_full_name(const struct device_node *np)\n{\n\treturn np ? np->full_name : \"<no-node>\";\n}\n\n#define for_each_of_allnodes_from(from, dn) \\\n\tfor (dn = __of_find_all_nodes(from); dn; dn = __of_find_all_nodes(dn))\n#define for_each_of_allnodes(dn) for_each_of_allnodes_from(NULL, dn)\nextern struct device_node *of_find_node_by_name(struct device_node *from,\n\tconst char *name);\nextern struct device_node *of_find_node_by_type(struct device_node *from,\n\tconst char *type);\nextern struct device_node *of_find_compatible_node(struct device_node *from,\n\tconst char *type, const char *compat);\nextern struct device_node *of_find_matching_node_and_match(\n\tstruct device_node *from,\n\tconst struct of_device_id *matches,\n\tconst struct of_device_id **match);\n\nextern struct device_node *of_find_node_opts_by_path(const char *path,\n\tconst char **opts);\nstatic inline struct device_node *of_find_node_by_path(const char *path)\n{\n\treturn of_find_node_opts_by_path(path, NULL);\n}\n\nextern struct device_node *of_find_node_by_phandle(phandle handle);\nextern struct device_node *of_get_parent(const struct device_node *node);\nextern struct device_node *of_get_next_parent(struct device_node *node);\nextern struct device_node *of_get_next_child(const struct device_node *node,\n\t\t\t\t\t     struct device_node *prev);\nextern struct device_node *of_get_next_available_child(\n\tconst struct device_node *node, struct device_node *prev);\n\nextern struct device_node *of_get_compatible_child(const struct device_node *parent,\n\t\t\t\t\tconst char *compatible);\nextern struct device_node *of_get_child_by_name(const struct device_node *node,\n\t\t\t\t\tconst char *name);\n\n/* cache lookup */\nextern struct device_node *of_find_next_cache_node(const struct device_node *);\nextern int of_find_last_cache_level(unsigned int cpu);\nextern struct device_node *of_find_node_with_property(\n\tstruct device_node *from, const char *prop_name);\n\nextern struct property *of_find_property(const struct device_node *np,\n\t\t\t\t\t const char *name,\n\t\t\t\t\t int *lenp);\nextern int of_property_count_elems_of_size(const struct device_node *np,\n\t\t\t\tconst char *propname, int elem_size);\nextern int of_property_read_u32_index(const struct device_node *np,\n\t\t\t\t       const char *propname,\n\t\t\t\t       u32 index, u32 *out_value);\nextern int of_property_read_u64_index(const struct device_node *np,\n\t\t\t\t       const char *propname,\n\t\t\t\t       u32 index, u64 *out_value);\nextern int of_property_read_variable_u8_array(const struct device_node *np,\n\t\t\t\t\tconst char *propname, u8 *out_values,\n\t\t\t\t\tsize_t sz_min, size_t sz_max);\nextern int of_property_read_variable_u16_array(const struct device_node *np,\n\t\t\t\t\tconst char *propname, u16 *out_values,\n\t\t\t\t\tsize_t sz_min, size_t sz_max);\nextern int of_property_read_variable_u32_array(const struct device_node *np,\n\t\t\t\t\tconst char *propname,\n\t\t\t\t\tu32 *out_values,\n\t\t\t\t\tsize_t sz_min,\n\t\t\t\t\tsize_t sz_max);\nextern int of_property_read_u64(const struct device_node *np,\n\t\t\t\tconst char *propname, u64 *out_value);\nextern int of_property_read_variable_u64_array(const struct device_node *np,\n\t\t\t\t\tconst char *propname,\n\t\t\t\t\tu64 *out_values,\n\t\t\t\t\tsize_t sz_min,\n\t\t\t\t\tsize_t sz_max);\n\nextern int of_property_read_string(const struct device_node *np,\n\t\t\t\t   const char *propname,\n\t\t\t\t   const char **out_string);\nextern int of_property_match_string(const struct device_node *np,\n\t\t\t\t    const char *propname,\n\t\t\t\t    const char *string);\nextern int of_property_read_string_helper(const struct device_node *np,\n\t\t\t\t\t      const char *propname,\n\t\t\t\t\t      const char **out_strs, size_t sz, int index);\nextern int of_device_is_compatible(const struct device_node *device,\n\t\t\t\t   const char *);\nextern int of_device_compatible_match(struct device_node *device,\n\t\t\t\t      const char *const *compat);\nextern bool of_device_is_available(const struct device_node *device);\nextern bool of_device_is_big_endian(const struct device_node *device);\nextern const void *of_get_property(const struct device_node *node,\n\t\t\t\tconst char *name,\n\t\t\t\tint *lenp);\nextern struct device_node *of_get_cpu_node(int cpu, unsigned int *thread);\nextern struct device_node *of_get_next_cpu_node(struct device_node *prev);\n\n#define for_each_property_of_node(dn, pp) \\\n\tfor (pp = dn->properties; pp != NULL; pp = pp->next)\n\nextern int of_n_addr_cells(struct device_node *np);\nextern int of_n_size_cells(struct device_node *np);\nextern const struct of_device_id *of_match_node(\n\tconst struct of_device_id *matches, const struct device_node *node);\nextern int of_modalias_node(struct device_node *node, char *modalias, int len);\nextern void of_print_phandle_args(const char *msg, const struct of_phandle_args *args);\nextern struct device_node *of_parse_phandle(const struct device_node *np,\n\t\t\t\t\t    const char *phandle_name,\n\t\t\t\t\t    int index);\nextern int of_parse_phandle_with_args(const struct device_node *np,\n\tconst char *list_name, const char *cells_name, int index,\n\tstruct of_phandle_args *out_args);\nextern int of_parse_phandle_with_args_map(const struct device_node *np,\n\tconst char *list_name, const char *stem_name, int index,\n\tstruct of_phandle_args *out_args);\nextern int of_parse_phandle_with_fixed_args(const struct device_node *np,\n\tconst char *list_name, int cells_count, int index,\n\tstruct of_phandle_args *out_args);\nextern int of_count_phandle_with_args(const struct device_node *np,\n\tconst char *list_name, const char *cells_name);\n\n/* phandle iterator functions */\nextern int of_phandle_iterator_init(struct of_phandle_iterator *it,\n\t\t\t\t    const struct device_node *np,\n\t\t\t\t    const char *list_name,\n\t\t\t\t    const char *cells_name,\n\t\t\t\t    int cell_count);\n\nextern int of_phandle_iterator_next(struct of_phandle_iterator *it);\nextern int of_phandle_iterator_args(struct of_phandle_iterator *it,\n\t\t\t\t    uint32_t *args,\n\t\t\t\t    int size);\n\nextern void of_alias_scan(void * (*dt_alloc)(u64 size, u64 align));\nextern int of_alias_get_id(struct device_node *np, const char *stem);\nextern int of_alias_get_highest_id(const char *stem);\nextern int of_alias_get_alias_list(const struct of_device_id *matches,\n\t\t\t\t   const char *stem, unsigned long *bitmap,\n\t\t\t\t   unsigned int nbits);\n\nextern int of_machine_is_compatible(const char *compat);\n\nextern int of_add_property(struct device_node *np, struct property *prop);\nextern int of_remove_property(struct device_node *np, struct property *prop);\nextern int of_update_property(struct device_node *np, struct property *newprop);\n\n/* For updating the device tree at runtime */\n#define OF_RECONFIG_ATTACH_NODE\t\t0x0001\n#define OF_RECONFIG_DETACH_NODE\t\t0x0002\n#define OF_RECONFIG_ADD_PROPERTY\t0x0003\n#define OF_RECONFIG_REMOVE_PROPERTY\t0x0004\n#define OF_RECONFIG_UPDATE_PROPERTY\t0x0005\n\nextern int of_attach_node(struct device_node *);\nextern int of_detach_node(struct device_node *);\n\n#define of_match_ptr(_ptr)\t(_ptr)\n\n/**\n * of_property_read_u8_array - Find and read an array of u8 from a property.\n *\n * @np:\t\tdevice node from which the property value is to be read.\n * @propname:\tname of the property to be searched.\n * @out_values:\tpointer to return value, modified only if return value is 0.\n * @sz:\t\tnumber of array elements to read\n *\n * Search for a property in a device node and read 8-bit value(s) from\n * it. Returns 0 on success, -EINVAL if the property does not exist,\n * -ENODATA if property does not have a value, and -EOVERFLOW if the\n * property data isn't large enough.\n *\n * dts entry of array should be like:\n *\tproperty = /bits/ 8 <0x50 0x60 0x70>;\n *\n * The out_values is modified only if a valid u8 value can be decoded.\n */\nstatic inline int of_property_read_u8_array(const struct device_node *np,\n\t\t\t\t\t    const char *propname,\n\t\t\t\t\t    u8 *out_values, size_t sz)\n{\n\tint ret = of_property_read_variable_u8_array(np, propname, out_values,\n\t\t\t\t\t\t     sz, 0);\n\tif (ret >= 0)\n\t\treturn 0;\n\telse\n\t\treturn ret;\n}\n\n/**\n * of_property_read_u16_array - Find and read an array of u16 from a property.\n *\n * @np:\t\tdevice node from which the property value is to be read.\n * @propname:\tname of the property to be searched.\n * @out_values:\tpointer to return value, modified only if return value is 0.\n * @sz:\t\tnumber of array elements to read\n *\n * Search for a property in a device node and read 16-bit value(s) from\n * it. Returns 0 on success, -EINVAL if the property does not exist,\n * -ENODATA if property does not have a value, and -EOVERFLOW if the\n * property data isn't large enough.\n *\n * dts entry of array should be like:\n *\tproperty = /bits/ 16 <0x5000 0x6000 0x7000>;\n *\n * The out_values is modified only if a valid u16 value can be decoded.\n */\nstatic inline int of_property_read_u16_array(const struct device_node *np,\n\t\t\t\t\t     const char *propname,\n\t\t\t\t\t     u16 *out_values, size_t sz)\n{\n\tint ret = of_property_read_variable_u16_array(np, propname, out_values,\n\t\t\t\t\t\t      sz, 0);\n\tif (ret >= 0)\n\t\treturn 0;\n\telse\n\t\treturn ret;\n}\n\n/**\n * of_property_read_u32_array - Find and read an array of 32 bit integers\n * from a property.\n *\n * @np:\t\tdevice node from which the property value is to be read.\n * @propname:\tname of the property to be searched.\n * @out_values:\tpointer to return value, modified only if return value is 0.\n * @sz:\t\tnumber of array elements to read\n *\n * Search for a property in a device node and read 32-bit value(s) from\n * it. Returns 0 on success, -EINVAL if the property does not exist,\n * -ENODATA if property does not have a value, and -EOVERFLOW if the\n * property data isn't large enough.\n *\n * The out_values is modified only if a valid u32 value can be decoded.\n */\nstatic inline int of_property_read_u32_array(const struct device_node *np,\n\t\t\t\t\t     const char *propname,\n\t\t\t\t\t     u32 *out_values, size_t sz)\n{\n\tint ret = of_property_read_variable_u32_array(np, propname, out_values,\n\t\t\t\t\t\t      sz, 0);\n\tif (ret >= 0)\n\t\treturn 0;\n\telse\n\t\treturn ret;\n}\n\n/**\n * of_property_read_u64_array - Find and read an array of 64 bit integers\n * from a property.\n *\n * @np:\t\tdevice node from which the property value is to be read.\n * @propname:\tname of the property to be searched.\n * @out_values:\tpointer to return value, modified only if return value is 0.\n * @sz:\t\tnumber of array elements to read\n *\n * Search for a property in a device node and read 64-bit value(s) from\n * it. Returns 0 on success, -EINVAL if the property does not exist,\n * -ENODATA if property does not have a value, and -EOVERFLOW if the\n * property data isn't large enough.\n *\n * The out_values is modified only if a valid u64 value can be decoded.\n */\nstatic inline int of_property_read_u64_array(const struct device_node *np,\n\t\t\t\t\t     const char *propname,\n\t\t\t\t\t     u64 *out_values, size_t sz)\n{\n\tint ret = of_property_read_variable_u64_array(np, propname, out_values,\n\t\t\t\t\t\t      sz, 0);\n\tif (ret >= 0)\n\t\treturn 0;\n\telse\n\t\treturn ret;\n}\n\n/*\n * struct property *prop;\n * const __be32 *p;\n * u32 u;\n *\n * of_property_for_each_u32(np, \"propname\", prop, p, u)\n *         printk(\"U32 value: %x\\n\", u);\n */\nconst __be32 *of_prop_next_u32(struct property *prop, const __be32 *cur,\n\t\t\t       u32 *pu);\n/*\n * struct property *prop;\n * const char *s;\n *\n * of_property_for_each_string(np, \"propname\", prop, s)\n *         printk(\"String value: %s\\n\", s);\n */\nconst char *of_prop_next_string(struct property *prop, const char *cur);\n\nbool of_console_check(struct device_node *dn, char *name, int index);\n\nextern int of_cpu_node_to_id(struct device_node *np);\n\nint of_map_rid(struct device_node *np, u32 rid,\n\t       const char *map_name, const char *map_mask_name,\n\t       struct device_node **target, u32 *id_out);\n\n#else /* CONFIG_OF */\n\nstatic inline void of_core_init(void)\n{\n}\n\nstatic inline bool is_of_node(const struct fwnode_handle *fwnode)\n{\n\treturn false;\n}\n\nstatic inline struct device_node *to_of_node(const struct fwnode_handle *fwnode)\n{\n\treturn NULL;\n}\n\nstatic inline bool of_node_name_eq(const struct device_node *np, const char *name)\n{\n\treturn false;\n}\n\nstatic inline bool of_node_name_prefix(const struct device_node *np, const char *prefix)\n{\n\treturn false;\n}\n\nstatic inline const char* of_node_full_name(const struct device_node *np)\n{\n\treturn \"<no-node>\";\n}\n\nstatic inline struct device_node *of_find_node_by_name(struct device_node *from,\n\tconst char *name)\n{\n\treturn NULL;\n}\n\nstatic inline struct device_node *of_find_node_by_type(struct device_node *from,\n\tconst char *type)\n{\n\treturn NULL;\n}\n\nstatic inline struct device_node *of_find_matching_node_and_match(\n\tstruct device_node *from,\n\tconst struct of_device_id *matches,\n\tconst struct of_device_id **match)\n{\n\treturn NULL;\n}\n\nstatic inline struct device_node *of_find_node_by_path(const char *path)\n{\n\treturn NULL;\n}\n\nstatic inline struct device_node *of_find_node_opts_by_path(const char *path,\n\tconst char **opts)\n{\n\treturn NULL;\n}\n\nstatic inline struct device_node *of_find_node_by_phandle(phandle handle)\n{\n\treturn NULL;\n}\n\nstatic inline struct device_node *of_get_parent(const struct device_node *node)\n{\n\treturn NULL;\n}\n\nstatic inline struct device_node *of_get_next_child(\n\tconst struct device_node *node, struct device_node *prev)\n{\n\treturn NULL;\n}\n\nstatic inline struct device_node *of_get_next_available_child(\n\tconst struct device_node *node, struct device_node *prev)\n{\n\treturn NULL;\n}\n\nstatic inline struct device_node *of_find_node_with_property(\n\tstruct device_node *from, const char *prop_name)\n{\n\treturn NULL;\n}\n\n#define of_fwnode_handle(node) NULL\n\nstatic inline bool of_have_populated_dt(void)\n{\n\treturn false;\n}\n\nstatic inline struct device_node *of_get_compatible_child(const struct device_node *parent,\n\t\t\t\t\tconst char *compatible)\n{\n\treturn NULL;\n}\n\nstatic inline struct device_node *of_get_child_by_name(\n\t\t\t\t\tconst struct device_node *node,\n\t\t\t\t\tconst char *name)\n{\n\treturn NULL;\n}\n\nstatic inline int of_device_is_compatible(const struct device_node *device,\n\t\t\t\t\t  const char *name)\n{\n\treturn 0;\n}\n\nstatic inline  int of_device_compatible_match(struct device_node *device,\n\t\t\t\t\t      const char *const *compat)\n{\n\treturn 0;\n}\n\nstatic inline bool of_device_is_available(const struct device_node *device)\n{\n\treturn false;\n}\n\nstatic inline bool of_device_is_big_endian(const struct device_node *device)\n{\n\treturn false;\n}\n\nstatic inline struct property *of_find_property(const struct device_node *np,\n\t\t\t\t\t\tconst char *name,\n\t\t\t\t\t\tint *lenp)\n{\n\treturn NULL;\n}\n\nstatic inline struct device_node *of_find_compatible_node(\n\t\t\t\t\t\tstruct device_node *from,\n\t\t\t\t\t\tconst char *type,\n\t\t\t\t\t\tconst char *compat)\n{\n\treturn NULL;\n}\n\nstatic inline int of_property_count_elems_of_size(const struct device_node *np,\n\t\t\tconst char *propname, int elem_size)\n{\n\treturn -ENOSYS;\n}\n\nstatic inline int of_property_read_u8_array(const struct device_node *np,\n\t\t\tconst char *propname, u8 *out_values, size_t sz)\n{\n\treturn -ENOSYS;\n}\n\nstatic inline int of_property_read_u16_array(const struct device_node *np,\n\t\t\tconst char *propname, u16 *out_values, size_t sz)\n{\n\treturn -ENOSYS;\n}\n\nstatic inline int of_property_read_u32_array(const struct device_node *np,\n\t\t\t\t\t     const char *propname,\n\t\t\t\t\t     u32 *out_values, size_t sz)\n{\n\treturn -ENOSYS;\n}\n\nstatic inline int of_property_read_u64_array(const struct device_node *np,\n\t\t\t\t\t     const char *propname,\n\t\t\t\t\t     u64 *out_values, size_t sz)\n{\n\treturn -ENOSYS;\n}\n\nstatic inline int of_property_read_u32_index(const struct device_node *np,\n\t\t\tconst char *propname, u32 index, u32 *out_value)\n{\n\treturn -ENOSYS;\n}\n\nstatic inline int of_property_read_u64_index(const struct device_node *np,\n\t\t\tconst char *propname, u32 index, u64 *out_value)\n{\n\treturn -ENOSYS;\n}\n\nstatic inline const void *of_get_property(const struct device_node *node,\n\t\t\t\tconst char *name,\n\t\t\t\tint *lenp)\n{\n\treturn NULL;\n}\n\nstatic inline struct device_node *of_get_cpu_node(int cpu,\n\t\t\t\t\tunsigned int *thread)\n{\n\treturn NULL;\n}\n\nstatic inline struct device_node *of_get_next_cpu_node(struct device_node *prev)\n{\n\treturn NULL;\n}\n\nstatic inline int of_n_addr_cells(struct device_node *np)\n{\n\treturn 0;\n\n}\nstatic inline int of_n_size_cells(struct device_node *np)\n{\n\treturn 0;\n}\n\nstatic inline int of_property_read_variable_u8_array(const struct device_node *np,\n\t\t\t\t\tconst char *propname, u8 *out_values,\n\t\t\t\t\tsize_t sz_min, size_t sz_max)\n{\n\treturn -ENOSYS;\n}\n\nstatic inline int of_property_read_variable_u16_array(const struct device_node *np,\n\t\t\t\t\tconst char *propname, u16 *out_values,\n\t\t\t\t\tsize_t sz_min, size_t sz_max)\n{\n\treturn -ENOSYS;\n}\n\nstatic inline int of_property_read_variable_u32_array(const struct device_node *np,\n\t\t\t\t\tconst char *propname,\n\t\t\t\t\tu32 *out_values,\n\t\t\t\t\tsize_t sz_min,\n\t\t\t\t\tsize_t sz_max)\n{\n\treturn -ENOSYS;\n}\n\nstatic inline int of_property_read_u64(const struct device_node *np,\n\t\t\t\t       const char *propname, u64 *out_value)\n{\n\treturn -ENOSYS;\n}\n\nstatic inline int of_property_read_variable_u64_array(const struct device_node *np,\n\t\t\t\t\tconst char *propname,\n\t\t\t\t\tu64 *out_values,\n\t\t\t\t\tsize_t sz_min,\n\t\t\t\t\tsize_t sz_max)\n{\n\treturn -ENOSYS;\n}\n\nstatic inline int of_property_read_string(const struct device_node *np,\n\t\t\t\t\t  const char *propname,\n\t\t\t\t\t  const char **out_string)\n{\n\treturn -ENOSYS;\n}\n\nstatic inline int of_property_match_string(const struct device_node *np,\n\t\t\t\t\t   const char *propname,\n\t\t\t\t\t   const char *string)\n{\n\treturn -ENOSYS;\n}\n\nstatic inline int of_property_read_string_helper(const struct device_node *np,\n\t\t\t\t\t\t const char *propname,\n\t\t\t\t\t\t const char **out_strs, size_t sz, int index)\n{\n\treturn -ENOSYS;\n}\n\nstatic inline struct device_node *of_parse_phandle(const struct device_node *np,\n\t\t\t\t\t\t   const char *phandle_name,\n\t\t\t\t\t\t   int index)\n{\n\treturn NULL;\n}\n\nstatic inline int of_parse_phandle_with_args(const struct device_node *np,\n\t\t\t\t\t     const char *list_name,\n\t\t\t\t\t     const char *cells_name,\n\t\t\t\t\t     int index,\n\t\t\t\t\t     struct of_phandle_args *out_args)\n{\n\treturn -ENOSYS;\n}\n\nstatic inline int of_parse_phandle_with_args_map(const struct device_node *np,\n\t\t\t\t\t\t const char *list_name,\n\t\t\t\t\t\t const char *stem_name,\n\t\t\t\t\t\t int index,\n\t\t\t\t\t\t struct of_phandle_args *out_args)\n{\n\treturn -ENOSYS;\n}\n\nstatic inline int of_parse_phandle_with_fixed_args(const struct device_node *np,\n\tconst char *list_name, int cells_count, int index,\n\tstruct of_phandle_args *out_args)\n{\n\treturn -ENOSYS;\n}\n\nstatic inline int of_count_phandle_with_args(struct device_node *np,\n\t\t\t\t\t     const char *list_name,\n\t\t\t\t\t     const char *cells_name)\n{\n\treturn -ENOSYS;\n}\n\nstatic inline int of_phandle_iterator_init(struct of_phandle_iterator *it,\n\t\t\t\t\t   const struct device_node *np,\n\t\t\t\t\t   const char *list_name,\n\t\t\t\t\t   const char *cells_name,\n\t\t\t\t\t   int cell_count)\n{\n\treturn -ENOSYS;\n}\n\nstatic inline int of_phandle_iterator_next(struct of_phandle_iterator *it)\n{\n\treturn -ENOSYS;\n}\n\nstatic inline int of_phandle_iterator_args(struct of_phandle_iterator *it,\n\t\t\t\t\t   uint32_t *args,\n\t\t\t\t\t   int size)\n{\n\treturn 0;\n}\n\nstatic inline int of_alias_get_id(struct device_node *np, const char *stem)\n{\n\treturn -ENOSYS;\n}\n\nstatic inline int of_alias_get_highest_id(const char *stem)\n{\n\treturn -ENOSYS;\n}\n\nstatic inline int of_alias_get_alias_list(const struct of_device_id *matches,\n\t\t\t\t\t  const char *stem, unsigned long *bitmap,\n\t\t\t\t\t  unsigned int nbits)\n{\n\treturn -ENOSYS;\n}\n\nstatic inline int of_machine_is_compatible(const char *compat)\n{\n\treturn 0;\n}\n\nstatic inline bool of_console_check(const struct device_node *dn, const char *name, int index)\n{\n\treturn false;\n}\n\nstatic inline const __be32 *of_prop_next_u32(struct property *prop,\n\t\tconst __be32 *cur, u32 *pu)\n{\n\treturn NULL;\n}\n\nstatic inline const char *of_prop_next_string(struct property *prop,\n\t\tconst char *cur)\n{\n\treturn NULL;\n}\n\nstatic inline int of_node_check_flag(struct device_node *n, unsigned long flag)\n{\n\treturn 0;\n}\n\nstatic inline int of_node_test_and_set_flag(struct device_node *n,\n\t\t\t\t\t    unsigned long flag)\n{\n\treturn 0;\n}\n\nstatic inline void of_node_set_flag(struct device_node *n, unsigned long flag)\n{\n}\n\nstatic inline void of_node_clear_flag(struct device_node *n, unsigned long flag)\n{\n}\n\nstatic inline int of_property_check_flag(struct property *p, unsigned long flag)\n{\n\treturn 0;\n}\n\nstatic inline void of_property_set_flag(struct property *p, unsigned long flag)\n{\n}\n\nstatic inline void of_property_clear_flag(struct property *p, unsigned long flag)\n{\n}\n\nstatic inline int of_cpu_node_to_id(struct device_node *np)\n{\n\treturn -ENODEV;\n}\n\nstatic inline int of_map_rid(struct device_node *np, u32 rid,\n\t\t\t     const char *map_name, const char *map_mask_name,\n\t\t\t     struct device_node **target, u32 *id_out)\n{\n\treturn -EINVAL;\n}\n\n#define of_match_ptr(_ptr)\tNULL\n#define of_match_node(_matches, _node)\tNULL\n#endif /* CONFIG_OF */\n\n/* Default string compare functions, Allow arch asm/prom.h to override */\n#if !defined(of_compat_cmp)\n#define of_compat_cmp(s1, s2, l)\tstrcasecmp((s1), (s2))\n#define of_prop_cmp(s1, s2)\t\tstrcmp((s1), (s2))\n#define of_node_cmp(s1, s2)\t\tstrcasecmp((s1), (s2))\n#endif\n\nstatic inline int of_prop_val_eq(struct property *p1, struct property *p2)\n{\n\treturn p1->length == p2->length &&\n\t       !memcmp(p1->value, p2->value, (size_t)p1->length);\n}\n\n#if defined(CONFIG_OF) && defined(CONFIG_NUMA)\nextern int of_node_to_nid(struct device_node *np);\n#else\nstatic inline int of_node_to_nid(struct device_node *device)\n{\n\treturn NUMA_NO_NODE;\n}\n#endif\n\n#ifdef CONFIG_OF_NUMA\nextern int of_numa_init(void);\n#else\nstatic inline int of_numa_init(void)\n{\n\treturn -ENOSYS;\n}\n#endif\n\nstatic inline struct device_node *of_find_matching_node(\n\tstruct device_node *from,\n\tconst struct of_device_id *matches)\n{\n\treturn of_find_matching_node_and_match(from, matches, NULL);\n}\n\nstatic inline const char *of_node_get_device_type(const struct device_node *np)\n{\n\treturn of_get_property(np, \"device_type\", NULL);\n}\n\nstatic inline bool of_node_is_type(const struct device_node *np, const char *type)\n{\n\tconst char *match = of_node_get_device_type(np);\n\n\treturn np && match && type && !strcmp(match, type);\n}\n\n/**\n * of_property_count_u8_elems - Count the number of u8 elements in a property\n *\n * @np:\t\tdevice node from which the property value is to be read.\n * @propname:\tname of the property to be searched.\n *\n * Search for a property in a device node and count the number of u8 elements\n * in it. Returns number of elements on sucess, -EINVAL if the property does\n * not exist or its length does not match a multiple of u8 and -ENODATA if the\n * property does not have a value.\n */\nstatic inline int of_property_count_u8_elems(const struct device_node *np,\n\t\t\t\tconst char *propname)\n{\n\treturn of_property_count_elems_of_size(np, propname, sizeof(u8));\n}\n\n/**\n * of_property_count_u16_elems - Count the number of u16 elements in a property\n *\n * @np:\t\tdevice node from which the property value is to be read.\n * @propname:\tname of the property to be searched.\n *\n * Search for a property in a device node and count the number of u16 elements\n * in it. Returns number of elements on sucess, -EINVAL if the property does\n * not exist or its length does not match a multiple of u16 and -ENODATA if the\n * property does not have a value.\n */\nstatic inline int of_property_count_u16_elems(const struct device_node *np,\n\t\t\t\tconst char *propname)\n{\n\treturn of_property_count_elems_of_size(np, propname, sizeof(u16));\n}\n\n/**\n * of_property_count_u32_elems - Count the number of u32 elements in a property\n *\n * @np:\t\tdevice node from which the property value is to be read.\n * @propname:\tname of the property to be searched.\n *\n * Search for a property in a device node and count the number of u32 elements\n * in it. Returns number of elements on sucess, -EINVAL if the property does\n * not exist or its length does not match a multiple of u32 and -ENODATA if the\n * property does not have a value.\n */\nstatic inline int of_property_count_u32_elems(const struct device_node *np,\n\t\t\t\tconst char *propname)\n{\n\treturn of_property_count_elems_of_size(np, propname, sizeof(u32));\n}\n\n/**\n * of_property_count_u64_elems - Count the number of u64 elements in a property\n *\n * @np:\t\tdevice node from which the property value is to be read.\n * @propname:\tname of the property to be searched.\n *\n * Search for a property in a device node and count the number of u64 elements\n * in it. Returns number of elements on sucess, -EINVAL if the property does\n * not exist or its length does not match a multiple of u64 and -ENODATA if the\n * property does not have a value.\n */\nstatic inline int of_property_count_u64_elems(const struct device_node *np,\n\t\t\t\tconst char *propname)\n{\n\treturn of_property_count_elems_of_size(np, propname, sizeof(u64));\n}\n\n/**\n * of_property_read_string_array() - Read an array of strings from a multiple\n * strings property.\n * @np:\t\tdevice node from which the property value is to be read.\n * @propname:\tname of the property to be searched.\n * @out_strs:\toutput array of string pointers.\n * @sz:\t\tnumber of array elements to read.\n *\n * Search for a property in a device tree node and retrieve a list of\n * terminated string values (pointer to data, not a copy) in that property.\n *\n * If @out_strs is NULL, the number of strings in the property is returned.\n */\nstatic inline int of_property_read_string_array(const struct device_node *np,\n\t\t\t\t\t\tconst char *propname, const char **out_strs,\n\t\t\t\t\t\tsize_t sz)\n{\n\treturn of_property_read_string_helper(np, propname, out_strs, sz, 0);\n}\n\n/**\n * of_property_count_strings() - Find and return the number of strings from a\n * multiple strings property.\n * @np:\t\tdevice node from which the property value is to be read.\n * @propname:\tname of the property to be searched.\n *\n * Search for a property in a device tree node and retrieve the number of null\n * terminated string contain in it. Returns the number of strings on\n * success, -EINVAL if the property does not exist, -ENODATA if property\n * does not have a value, and -EILSEQ if the string is not null-terminated\n * within the length of the property data.\n */\nstatic inline int of_property_count_strings(const struct device_node *np,\n\t\t\t\t\t    const char *propname)\n{\n\treturn of_property_read_string_helper(np, propname, NULL, 0, 0);\n}\n\n/**\n * of_property_read_string_index() - Find and read a string from a multiple\n * strings property.\n * @np:\t\tdevice node from which the property value is to be read.\n * @propname:\tname of the property to be searched.\n * @index:\tindex of the string in the list of strings\n * @out_string:\tpointer to null terminated return string, modified only if\n *\t\treturn value is 0.\n *\n * Search for a property in a device tree node and retrieve a null\n * terminated string value (pointer to data, not a copy) in the list of strings\n * contained in that property.\n * Returns 0 on success, -EINVAL if the property does not exist, -ENODATA if\n * property does not have a value, and -EILSEQ if the string is not\n * null-terminated within the length of the property data.\n *\n * The out_string pointer is modified only if a valid string can be decoded.\n */\nstatic inline int of_property_read_string_index(const struct device_node *np,\n\t\t\t\t\t\tconst char *propname,\n\t\t\t\t\t\tint index, const char **output)\n{\n\tint rc = of_property_read_string_helper(np, propname, output, 1, index);\n\treturn rc < 0 ? rc : 0;\n}\n\n/**\n * of_property_read_bool - Find a property\n * @np:\t\tdevice node from which the property value is to be read.\n * @propname:\tname of the property to be searched.\n *\n * Search for a property in a device node.\n * Returns true if the property exists false otherwise.\n */\nstatic inline bool of_property_read_bool(const struct device_node *np,\n\t\t\t\t\t const char *propname)\n{\n\tstruct property *prop = of_find_property(np, propname, NULL);\n\n\treturn prop ? true : false;\n}\n\nstatic inline int of_property_read_u8(const struct device_node *np,\n\t\t\t\t       const char *propname,\n\t\t\t\t       u8 *out_value)\n{\n\treturn of_property_read_u8_array(np, propname, out_value, 1);\n}\n\nstatic inline int of_property_read_u16(const struct device_node *np,\n\t\t\t\t       const char *propname,\n\t\t\t\t       u16 *out_value)\n{\n\treturn of_property_read_u16_array(np, propname, out_value, 1);\n}\n\nstatic inline int of_property_read_u32(const struct device_node *np,\n\t\t\t\t       const char *propname,\n\t\t\t\t       u32 *out_value)\n{\n\treturn of_property_read_u32_array(np, propname, out_value, 1);\n}\n\nstatic inline int of_property_read_s32(const struct device_node *np,\n\t\t\t\t       const char *propname,\n\t\t\t\t       s32 *out_value)\n{\n\treturn of_property_read_u32(np, propname, (u32*) out_value);\n}\n\n#define of_for_each_phandle(it, err, np, ln, cn, cc)\t\t\t\\\n\tfor (of_phandle_iterator_init((it), (np), (ln), (cn), (cc)),\t\\\n\t     err = of_phandle_iterator_next(it);\t\t\t\\\n\t     err == 0;\t\t\t\t\t\t\t\\\n\t     err = of_phandle_iterator_next(it))\n\n#define of_property_for_each_u32(np, propname, prop, p, u)\t\\\n\tfor (prop = of_find_property(np, propname, NULL),\t\\\n\t\tp = of_prop_next_u32(prop, NULL, &u);\t\t\\\n\t\tp;\t\t\t\t\t\t\\\n\t\tp = of_prop_next_u32(prop, p, &u))\n\n#define of_property_for_each_string(np, propname, prop, s)\t\\\n\tfor (prop = of_find_property(np, propname, NULL),\t\\\n\t\ts = of_prop_next_string(prop, NULL);\t\t\\\n\t\ts;\t\t\t\t\t\t\\\n\t\ts = of_prop_next_string(prop, s))\n\n#define for_each_node_by_name(dn, name) \\\n\tfor (dn = of_find_node_by_name(NULL, name); dn; \\\n\t     dn = of_find_node_by_name(dn, name))\n#define for_each_node_by_type(dn, type) \\\n\tfor (dn = of_find_node_by_type(NULL, type); dn; \\\n\t     dn = of_find_node_by_type(dn, type))\n#define for_each_compatible_node(dn, type, compatible) \\\n\tfor (dn = of_find_compatible_node(NULL, type, compatible); dn; \\\n\t     dn = of_find_compatible_node(dn, type, compatible))\n#define for_each_matching_node(dn, matches) \\\n\tfor (dn = of_find_matching_node(NULL, matches); dn; \\\n\t     dn = of_find_matching_node(dn, matches))\n#define for_each_matching_node_and_match(dn, matches, match) \\\n\tfor (dn = of_find_matching_node_and_match(NULL, matches, match); \\\n\t     dn; dn = of_find_matching_node_and_match(dn, matches, match))\n\n#define for_each_child_of_node(parent, child) \\\n\tfor (child = of_get_next_child(parent, NULL); child != NULL; \\\n\t     child = of_get_next_child(parent, child))\n#define for_each_available_child_of_node(parent, child) \\\n\tfor (child = of_get_next_available_child(parent, NULL); child != NULL; \\\n\t     child = of_get_next_available_child(parent, child))\n\n#define for_each_of_cpu_node(cpu) \\\n\tfor (cpu = of_get_next_cpu_node(NULL); cpu != NULL; \\\n\t     cpu = of_get_next_cpu_node(cpu))\n\n#define for_each_node_with_property(dn, prop_name) \\\n\tfor (dn = of_find_node_with_property(NULL, prop_name); dn; \\\n\t     dn = of_find_node_with_property(dn, prop_name))\n\nstatic inline int of_get_child_count(const struct device_node *np)\n{\n\tstruct device_node *child;\n\tint num = 0;\n\n\tfor_each_child_of_node(np, child)\n\t\tnum++;\n\n\treturn num;\n}\n\nstatic inline int of_get_available_child_count(const struct device_node *np)\n{\n\tstruct device_node *child;\n\tint num = 0;\n\n\tfor_each_available_child_of_node(np, child)\n\t\tnum++;\n\n\treturn num;\n}\n\n#if defined(CONFIG_OF) && !defined(MODULE)\n#define _OF_DECLARE(table, name, compat, fn, fn_type)\t\t\t\\\n\tstatic const struct of_device_id __of_table_##name\t\t\\\n\t\t__used __section(__##table##_of_table)\t\t\t\\\n\t\t = { .compatible = compat,\t\t\t\t\\\n\t\t     .data = (fn == (fn_type)NULL) ? fn : fn  }\n#else\n#define _OF_DECLARE(table, name, compat, fn, fn_type)\t\t\t\\\n\tstatic const struct of_device_id __of_table_##name\t\t\\\n\t\t__attribute__((unused))\t\t\t\t\t\\\n\t\t = { .compatible = compat,\t\t\t\t\\\n\t\t     .data = (fn == (fn_type)NULL) ? fn : fn }\n#endif\n\ntypedef int (*of_init_fn_2)(struct device_node *, struct device_node *);\ntypedef int (*of_init_fn_1_ret)(struct device_node *);\ntypedef void (*of_init_fn_1)(struct device_node *);\n\n#define OF_DECLARE_1(table, name, compat, fn) \\\n\t\t_OF_DECLARE(table, name, compat, fn, of_init_fn_1)\n#define OF_DECLARE_1_RET(table, name, compat, fn) \\\n\t\t_OF_DECLARE(table, name, compat, fn, of_init_fn_1_ret)\n#define OF_DECLARE_2(table, name, compat, fn) \\\n\t\t_OF_DECLARE(table, name, compat, fn, of_init_fn_2)\n\n/**\n * struct of_changeset_entry\t- Holds a changeset entry\n *\n * @node:\tlist_head for the log list\n * @action:\tnotifier action\n * @np:\t\tpointer to the device node affected\n * @prop:\tpointer to the property affected\n * @old_prop:\thold a pointer to the original property\n *\n * Every modification of the device tree during a changeset\n * is held in a list of of_changeset_entry structures.\n * That way we can recover from a partial application, or we can\n * revert the changeset\n */\nstruct of_changeset_entry {\n\tstruct list_head node;\n\tunsigned long action;\n\tstruct device_node *np;\n\tstruct property *prop;\n\tstruct property *old_prop;\n};\n\n/**\n * struct of_changeset - changeset tracker structure\n *\n * @entries:\tlist_head for the changeset entries\n *\n * changesets are a convenient way to apply bulk changes to the\n * live tree. In case of an error, changes are rolled-back.\n * changesets live on after initial application, and if not\n * destroyed after use, they can be reverted in one single call.\n */\nstruct of_changeset {\n\tstruct list_head entries;\n};\n\nenum of_reconfig_change {\n\tOF_RECONFIG_NO_CHANGE = 0,\n\tOF_RECONFIG_CHANGE_ADD,\n\tOF_RECONFIG_CHANGE_REMOVE,\n};\n\n#ifdef CONFIG_OF_DYNAMIC\nextern int of_reconfig_notifier_register(struct notifier_block *);\nextern int of_reconfig_notifier_unregister(struct notifier_block *);\nextern int of_reconfig_notify(unsigned long, struct of_reconfig_data *rd);\nextern int of_reconfig_get_state_change(unsigned long action,\n\t\t\t\t\tstruct of_reconfig_data *arg);\n\nextern void of_changeset_init(struct of_changeset *ocs);\nextern void of_changeset_destroy(struct of_changeset *ocs);\nextern int of_changeset_apply(struct of_changeset *ocs);\nextern int of_changeset_revert(struct of_changeset *ocs);\nextern int of_changeset_action(struct of_changeset *ocs,\n\t\tunsigned long action, struct device_node *np,\n\t\tstruct property *prop);\n\nstatic inline int of_changeset_attach_node(struct of_changeset *ocs,\n\t\tstruct device_node *np)\n{\n\treturn of_changeset_action(ocs, OF_RECONFIG_ATTACH_NODE, np, NULL);\n}\n\nstatic inline int of_changeset_detach_node(struct of_changeset *ocs,\n\t\tstruct device_node *np)\n{\n\treturn of_changeset_action(ocs, OF_RECONFIG_DETACH_NODE, np, NULL);\n}\n\nstatic inline int of_changeset_add_property(struct of_changeset *ocs,\n\t\tstruct device_node *np, struct property *prop)\n{\n\treturn of_changeset_action(ocs, OF_RECONFIG_ADD_PROPERTY, np, prop);\n}\n\nstatic inline int of_changeset_remove_property(struct of_changeset *ocs,\n\t\tstruct device_node *np, struct property *prop)\n{\n\treturn of_changeset_action(ocs, OF_RECONFIG_REMOVE_PROPERTY, np, prop);\n}\n\nstatic inline int of_changeset_update_property(struct of_changeset *ocs,\n\t\tstruct device_node *np, struct property *prop)\n{\n\treturn of_changeset_action(ocs, OF_RECONFIG_UPDATE_PROPERTY, np, prop);\n}\n#else /* CONFIG_OF_DYNAMIC */\nstatic inline int of_reconfig_notifier_register(struct notifier_block *nb)\n{\n\treturn -EINVAL;\n}\nstatic inline int of_reconfig_notifier_unregister(struct notifier_block *nb)\n{\n\treturn -EINVAL;\n}\nstatic inline int of_reconfig_notify(unsigned long action,\n\t\t\t\t     struct of_reconfig_data *arg)\n{\n\treturn -EINVAL;\n}\nstatic inline int of_reconfig_get_state_change(unsigned long action,\n\t\t\t\t\t\tstruct of_reconfig_data *arg)\n{\n\treturn -EINVAL;\n}\n#endif /* CONFIG_OF_DYNAMIC */\n\n/**\n * of_device_is_system_power_controller - Tells if system-power-controller is found for device_node\n * @np: Pointer to the given device_node\n *\n * return true if present false otherwise\n */\nstatic inline bool of_device_is_system_power_controller(const struct device_node *np)\n{\n\treturn of_property_read_bool(np, \"system-power-controller\");\n}\n\n/**\n * Overlay support\n */\n\nenum of_overlay_notify_action {\n\tOF_OVERLAY_PRE_APPLY = 0,\n\tOF_OVERLAY_POST_APPLY,\n\tOF_OVERLAY_PRE_REMOVE,\n\tOF_OVERLAY_POST_REMOVE,\n};\n\nstruct of_overlay_notify_data {\n\tstruct device_node *overlay;\n\tstruct device_node *target;\n};\n\n#ifdef CONFIG_OF_OVERLAY\n\nint of_overlay_fdt_apply(const void *overlay_fdt, u32 overlay_fdt_size,\n\t\t\t int *ovcs_id);\nint of_overlay_remove(int *ovcs_id);\nint of_overlay_remove_all(void);\n\nint of_overlay_notifier_register(struct notifier_block *nb);\nint of_overlay_notifier_unregister(struct notifier_block *nb);\n\n#else\n\nstatic inline int of_overlay_fdt_apply(void *overlay_fdt, u32 overlay_fdt_size,\n\t\t\t\t       int *ovcs_id)\n{\n\treturn -ENOTSUPP;\n}\n\nstatic inline int of_overlay_remove(int *ovcs_id)\n{\n\treturn -ENOTSUPP;\n}\n\nstatic inline int of_overlay_remove_all(void)\n{\n\treturn -ENOTSUPP;\n}\n\nstatic inline int of_overlay_notifier_register(struct notifier_block *nb)\n{\n\treturn 0;\n}\n\nstatic inline int of_overlay_notifier_unregister(struct notifier_block *nb)\n{\n\treturn 0;\n}\n\n#endif\n\n#endif /* _LINUX_OF_H */\n"
  },
  {
    "path": "t/tree/include/linux/of_platform.h",
    "content": "/* SPDX-License-Identifier: GPL-2.0+ */\n#ifndef _LINUX_OF_PLATFORM_H\n#define _LINUX_OF_PLATFORM_H\n/*\n *    Copyright (C) 2006 Benjamin Herrenschmidt, IBM Corp.\n *\t\t\t <benh@kernel.crashing.org>\n */\n\n#include <linux/device.h>\n#include <linux/mod_devicetable.h>\n#include <linux/pm.h>\n#include <linux/of_device.h>\n#include <linux/platform_device.h>\n\n/**\n * struct of_dev_auxdata - lookup table entry for device names & platform_data\n * @compatible: compatible value of node to match against node\n * @phys_addr: Start address of registers to match against node\n * @name: Name to assign for matching nodes\n * @platform_data: platform_data to assign for matching nodes\n *\n * This lookup table allows the caller of of_platform_populate() to override\n * the names of devices when creating devices from the device tree.  The table\n * should be terminated with an empty entry.  It also allows the platform_data\n * pointer to be set.\n *\n * The reason for this functionality is that some Linux infrastructure uses\n * the device name to look up a specific device, but the Linux-specific names\n * are not encoded into the device tree, so the kernel needs to provide specific\n * values.\n *\n * Note: Using an auxdata lookup table should be considered a last resort when\n * converting a platform to use the DT.  Normally the automatically generated\n * device name will not matter, and drivers should obtain data from the device\n * node instead of from an anonymous platform_data pointer.\n */\nstruct of_dev_auxdata {\n\tchar *compatible;\n\tresource_size_t phys_addr;\n\tchar *name;\n\tvoid *platform_data;\n};\n\n/* Macro to simplify populating a lookup table */\n#define OF_DEV_AUXDATA(_compat,_phys,_name,_pdata) \\\n\t{ .compatible = _compat, .phys_addr = _phys, .name = _name, \\\n\t  .platform_data = _pdata }\n\nextern const struct of_device_id of_default_bus_match_table[];\n\n/* Platform drivers register/unregister */\nextern struct platform_device *of_device_alloc(struct device_node *np,\n\t\t\t\t\t const char *bus_id,\n\t\t\t\t\t struct device *parent);\n#ifdef CONFIG_OF\nextern struct platform_device *of_find_device_by_node(struct device_node *np);\n#else\nstatic inline struct platform_device *of_find_device_by_node(struct device_node *np)\n{\n\treturn NULL;\n}\n#endif\n\n/* Platform devices and busses creation */\nextern struct platform_device *of_platform_device_create(struct device_node *np,\n\t\t\t\t\t\t   const char *bus_id,\n\t\t\t\t\t\t   struct device *parent);\n\nextern int of_platform_device_destroy(struct device *dev, void *data);\nextern int of_platform_bus_probe(struct device_node *root,\n\t\t\t\t const struct of_device_id *matches,\n\t\t\t\t struct device *parent);\n#ifdef CONFIG_OF_ADDRESS\nextern int of_platform_populate(struct device_node *root,\n\t\t\t\tconst struct of_device_id *matches,\n\t\t\t\tconst struct of_dev_auxdata *lookup,\n\t\t\t\tstruct device *parent);\nextern int of_platform_default_populate(struct device_node *root,\n\t\t\t\t\tconst struct of_dev_auxdata *lookup,\n\t\t\t\t\tstruct device *parent);\nextern void of_platform_depopulate(struct device *parent);\n\nextern int devm_of_platform_populate(struct device *dev);\n\nextern void devm_of_platform_depopulate(struct device *dev);\n#else\nstatic inline int of_platform_populate(struct device_node *root,\n\t\t\t\t\tconst struct of_device_id *matches,\n\t\t\t\t\tconst struct of_dev_auxdata *lookup,\n\t\t\t\t\tstruct device *parent)\n{\n\treturn -ENODEV;\n}\nstatic inline int of_platform_default_populate(struct device_node *root,\n\t\t\t\t\t       const struct of_dev_auxdata *lookup,\n\t\t\t\t\t       struct device *parent)\n{\n\treturn -ENODEV;\n}\nstatic inline void of_platform_depopulate(struct device *parent) { }\n\nstatic inline int devm_of_platform_populate(struct device *dev)\n{\n\treturn -ENODEV;\n}\n\nstatic inline void devm_of_platform_depopulate(struct device *dev) { }\n#endif\n\n#if defined(CONFIG_OF_DYNAMIC) && defined(CONFIG_OF_ADDRESS)\nextern void of_platform_register_reconfig_notifier(void);\n#else\nstatic inline void of_platform_register_reconfig_notifier(void) { }\n#endif\n\n#endif\t/* _LINUX_OF_PLATFORM_H */\n"
  },
  {
    "path": "t/tree/include/linux/plist.h",
    "content": "/* SPDX-License-Identifier: GPL-2.0-or-later */\n/*\n * Descending-priority-sorted double-linked list\n *\n * (C) 2002-2003 Intel Corp\n * Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com>.\n *\n * 2001-2005 (c) MontaVista Software, Inc.\n * Daniel Walker <dwalker@mvista.com>\n *\n * (C) 2005 Thomas Gleixner <tglx@linutronix.de>\n *\n * Simplifications of the original code by\n * Oleg Nesterov <oleg@tv-sign.ru>\n *\n * Based on simple lists (include/linux/list.h).\n *\n * This is a priority-sorted list of nodes; each node has a\n * priority from INT_MIN (highest) to INT_MAX (lowest).\n *\n * Addition is O(K), removal is O(1), change of priority of a node is\n * O(K) and K is the number of RT priority levels used in the system.\n * (1 <= K <= 99)\n *\n * This list is really a list of lists:\n *\n *  - The tier 1 list is the prio_list, different priority nodes.\n *\n *  - The tier 2 list is the node_list, serialized nodes.\n *\n * Simple ASCII art explanation:\n *\n * pl:prio_list (only for plist_node)\n * nl:node_list\n *   HEAD|             NODE(S)\n *       |\n *       ||------------------------------------|\n *       ||->|pl|<->|pl|<--------------->|pl|<-|\n *       |   |10|   |21|   |21|   |21|   |40|   (prio)\n *       |   |  |   |  |   |  |   |  |   |  |\n *       |   |  |   |  |   |  |   |  |   |  |\n * |->|nl|<->|nl|<->|nl|<->|nl|<->|nl|<->|nl|<-|\n * |-------------------------------------------|\n *\n * The nodes on the prio_list list are sorted by priority to simplify\n * the insertion of new nodes. There are no nodes with duplicate\n * priorites on the list.\n *\n * The nodes on the node_list are ordered by priority and can contain\n * entries which have the same priority. Those entries are ordered\n * FIFO\n *\n * Addition means: look for the prio_list node in the prio_list\n * for the priority of the node and insert it before the node_list\n * entry of the next prio_list node. If it is the first node of\n * that priority, add it to the prio_list in the right position and\n * insert it into the serialized node_list list\n *\n * Removal means remove it from the node_list and remove it from\n * the prio_list if the node_list list_head is non empty. In case\n * of removal from the prio_list it must be checked whether other\n * entries of the same priority are on the list or not. If there\n * is another entry of the same priority then this entry has to\n * replace the removed entry on the prio_list. If the entry which\n * is removed is the only entry of this priority then a simple\n * remove from both list is sufficient.\n *\n * INT_MIN is the highest priority, 0 is the medium highest, INT_MAX\n * is lowest priority.\n *\n * No locking is done, up to the caller.\n */\n#ifndef _LINUX_PLIST_H_\n#define _LINUX_PLIST_H_\n\n#include <linux/kernel.h>\n#include <linux/list.h>\n\nstruct plist_head {\n\tstruct list_head node_list;\n};\n\nstruct plist_node {\n\tint\t\t\tprio;\n\tstruct list_head\tprio_list;\n\tstruct list_head\tnode_list;\n};\n\n/**\n * PLIST_HEAD_INIT - static struct plist_head initializer\n * @head:\tstruct plist_head variable name\n */\n#define PLIST_HEAD_INIT(head)\t\t\t\t\\\n{\t\t\t\t\t\t\t\\\n\t.node_list = LIST_HEAD_INIT((head).node_list)\t\\\n}\n\n/**\n * PLIST_HEAD - declare and init plist_head\n * @head:\tname for struct plist_head variable\n */\n#define PLIST_HEAD(head) \\\n\tstruct plist_head head = PLIST_HEAD_INIT(head)\n\n/**\n * PLIST_NODE_INIT - static struct plist_node initializer\n * @node:\tstruct plist_node variable name\n * @__prio:\tinitial node priority\n */\n#define PLIST_NODE_INIT(node, __prio)\t\t\t\\\n{\t\t\t\t\t\t\t\\\n\t.prio  = (__prio),\t\t\t\t\\\n\t.prio_list = LIST_HEAD_INIT((node).prio_list),\t\\\n\t.node_list = LIST_HEAD_INIT((node).node_list),\t\\\n}\n\n/**\n * plist_head_init - dynamic struct plist_head initializer\n * @head:\t&struct plist_head pointer\n */\nstatic inline void\nplist_head_init(struct plist_head *head)\n{\n\tINIT_LIST_HEAD(&head->node_list);\n}\n\n/**\n * plist_node_init - Dynamic struct plist_node initializer\n * @node:\t&struct plist_node pointer\n * @prio:\tinitial node priority\n */\nstatic inline void plist_node_init(struct plist_node *node, int prio)\n{\n\tnode->prio = prio;\n\tINIT_LIST_HEAD(&node->prio_list);\n\tINIT_LIST_HEAD(&node->node_list);\n}\n\nextern void plist_add(struct plist_node *node, struct plist_head *head);\nextern void plist_del(struct plist_node *node, struct plist_head *head);\n\nextern void plist_requeue(struct plist_node *node, struct plist_head *head);\n\n/**\n * plist_for_each - iterate over the plist\n * @pos:\tthe type * to use as a loop counter\n * @head:\tthe head for your list\n */\n#define plist_for_each(pos, head)\t\\\n\t list_for_each_entry(pos, &(head)->node_list, node_list)\n\n/**\n * plist_for_each_continue - continue iteration over the plist\n * @pos:\tthe type * to use as a loop cursor\n * @head:\tthe head for your list\n *\n * Continue to iterate over plist, continuing after the current position.\n */\n#define plist_for_each_continue(pos, head)\t\\\n\t list_for_each_entry_continue(pos, &(head)->node_list, node_list)\n\n/**\n * plist_for_each_safe - iterate safely over a plist of given type\n * @pos:\tthe type * to use as a loop counter\n * @n:\tanother type * to use as temporary storage\n * @head:\tthe head for your list\n *\n * Iterate over a plist of given type, safe against removal of list entry.\n */\n#define plist_for_each_safe(pos, n, head)\t\\\n\t list_for_each_entry_safe(pos, n, &(head)->node_list, node_list)\n\n/**\n * plist_for_each_entry\t- iterate over list of given type\n * @pos:\tthe type * to use as a loop counter\n * @head:\tthe head for your list\n * @mem:\tthe name of the list_head within the struct\n */\n#define plist_for_each_entry(pos, head, mem)\t\\\n\t list_for_each_entry(pos, &(head)->node_list, mem.node_list)\n\n/**\n * plist_for_each_entry_continue - continue iteration over list of given type\n * @pos:\tthe type * to use as a loop cursor\n * @head:\tthe head for your list\n * @m:\t\tthe name of the list_head within the struct\n *\n * Continue to iterate over list of given type, continuing after\n * the current position.\n */\n#define plist_for_each_entry_continue(pos, head, m)\t\\\n\tlist_for_each_entry_continue(pos, &(head)->node_list, m.node_list)\n\n/**\n * plist_for_each_entry_safe - iterate safely over list of given type\n * @pos:\tthe type * to use as a loop counter\n * @n:\t\tanother type * to use as temporary storage\n * @head:\tthe head for your list\n * @m:\t\tthe name of the list_head within the struct\n *\n * Iterate over list of given type, safe against removal of list entry.\n */\n#define plist_for_each_entry_safe(pos, n, head, m)\t\\\n\tlist_for_each_entry_safe(pos, n, &(head)->node_list, m.node_list)\n\n/**\n * plist_head_empty - return !0 if a plist_head is empty\n * @head:\t&struct plist_head pointer\n */\nstatic inline int plist_head_empty(const struct plist_head *head)\n{\n\treturn list_empty(&head->node_list);\n}\n\n/**\n * plist_node_empty - return !0 if plist_node is not on a list\n * @node:\t&struct plist_node pointer\n */\nstatic inline int plist_node_empty(const struct plist_node *node)\n{\n\treturn list_empty(&node->node_list);\n}\n\n/* All functions below assume the plist_head is not empty. */\n\n/**\n * plist_first_entry - get the struct for the first entry\n * @head:\tthe &struct plist_head pointer\n * @type:\tthe type of the struct this is embedded in\n * @member:\tthe name of the list_head within the struct\n */\n#ifdef CONFIG_DEBUG_PLIST\n# define plist_first_entry(head, type, member)\t\\\n({ \\\n\tWARN_ON(plist_head_empty(head)); \\\n\tcontainer_of(plist_first(head), type, member); \\\n})\n#else\n# define plist_first_entry(head, type, member)\t\\\n\tcontainer_of(plist_first(head), type, member)\n#endif\n\n/**\n * plist_last_entry - get the struct for the last entry\n * @head:\tthe &struct plist_head pointer\n * @type:\tthe type of the struct this is embedded in\n * @member:\tthe name of the list_head within the struct\n */\n#ifdef CONFIG_DEBUG_PLIST\n# define plist_last_entry(head, type, member)\t\\\n({ \\\n\tWARN_ON(plist_head_empty(head)); \\\n\tcontainer_of(plist_last(head), type, member); \\\n})\n#else\n# define plist_last_entry(head, type, member)\t\\\n\tcontainer_of(plist_last(head), type, member)\n#endif\n\n/**\n * plist_next - get the next entry in list\n * @pos:\tthe type * to cursor\n */\n#define plist_next(pos) \\\n\tlist_next_entry(pos, node_list)\n\n/**\n * plist_prev - get the prev entry in list\n * @pos:\tthe type * to cursor\n */\n#define plist_prev(pos) \\\n\tlist_prev_entry(pos, node_list)\n\n/**\n * plist_first - return the first node (and thus, highest priority)\n * @head:\tthe &struct plist_head pointer\n *\n * Assumes the plist is _not_ empty.\n */\nstatic inline struct plist_node *plist_first(const struct plist_head *head)\n{\n\treturn list_entry(head->node_list.next,\n\t\t\t  struct plist_node, node_list);\n}\n\n/**\n * plist_last - return the last node (and thus, lowest priority)\n * @head:\tthe &struct plist_head pointer\n *\n * Assumes the plist is _not_ empty.\n */\nstatic inline struct plist_node *plist_last(const struct plist_head *head)\n{\n\treturn list_entry(head->node_list.prev,\n\t\t\t  struct plist_node, node_list);\n}\n\n#endif\n"
  },
  {
    "path": "t/tree/include/linux/pm.h",
    "content": "/* SPDX-License-Identifier: GPL-2.0-or-later */\n/*\n *  pm.h - Power management interface\n *\n *  Copyright (C) 2000 Andrew Henroid\n */\n\n#ifndef _LINUX_PM_H\n#define _LINUX_PM_H\n\n#include <linux/list.h>\n#include <linux/workqueue.h>\n#include <linux/spinlock.h>\n#include <linux/wait.h>\n#include <linux/timer.h>\n#include <linux/hrtimer.h>\n#include <linux/completion.h>\n\n/*\n * Callbacks for platform drivers to implement.\n */\nextern void (*pm_power_off)(void);\nextern void (*pm_power_off_prepare)(void);\n\nstruct device; /* we have a circular dep with device.h */\n#ifdef CONFIG_VT_CONSOLE_SLEEP\nextern void pm_vt_switch_required(struct device *dev, bool required);\nextern void pm_vt_switch_unregister(struct device *dev);\n#else\nstatic inline void pm_vt_switch_required(struct device *dev, bool required)\n{\n}\nstatic inline void pm_vt_switch_unregister(struct device *dev)\n{\n}\n#endif /* CONFIG_VT_CONSOLE_SLEEP */\n\n/*\n * Device power management\n */\n\nstruct device;\n\n#ifdef CONFIG_PM\nextern const char power_group_name[];\t\t/* = \"power\" */\n#else\n#define power_group_name\tNULL\n#endif\n\ntypedef struct pm_message {\n\tint event;\n} pm_message_t;\n\n/**\n * struct dev_pm_ops - device PM callbacks.\n *\n * @prepare: The principal role of this callback is to prevent new children of\n *\tthe device from being registered after it has returned (the driver's\n *\tsubsystem and generally the rest of the kernel is supposed to prevent\n *\tnew calls to the probe method from being made too once @prepare() has\n *\tsucceeded).  If @prepare() detects a situation it cannot handle (e.g.\n *\tregistration of a child already in progress), it may return -EAGAIN, so\n *\tthat the PM core can execute it once again (e.g. after a new child has\n *\tbeen registered) to recover from the race condition.\n *\tThis method is executed for all kinds of suspend transitions and is\n *\tfollowed by one of the suspend callbacks: @suspend(), @freeze(), or\n *\t@poweroff().  If the transition is a suspend to memory or standby (that\n *\tis, not related to hibernation), the return value of @prepare() may be\n *\tused to indicate to the PM core to leave the device in runtime suspend\n *\tif applicable.  Namely, if @prepare() returns a positive number, the PM\n *\tcore will understand that as a declaration that the device appears to be\n *\truntime-suspended and it may be left in that state during the entire\n *\ttransition and during the subsequent resume if all of its descendants\n *\tare left in runtime suspend too.  If that happens, @complete() will be\n *\texecuted directly after @prepare() and it must ensure the proper\n *\tfunctioning of the device after the system resume.\n *\tThe PM core executes subsystem-level @prepare() for all devices before\n *\tstarting to invoke suspend callbacks for any of them, so generally\n *\tdevices may be assumed to be functional or to respond to runtime resume\n *\trequests while @prepare() is being executed.  However, device drivers\n *\tmay NOT assume anything about the availability of user space at that\n *\ttime and it is NOT valid to request firmware from within @prepare()\n *\t(it's too late to do that).  It also is NOT valid to allocate\n *\tsubstantial amounts of memory from @prepare() in the GFP_KERNEL mode.\n *\t[To work around these limitations, drivers may register suspend and\n *\thibernation notifiers to be executed before the freezing of tasks.]\n *\n * @complete: Undo the changes made by @prepare().  This method is executed for\n *\tall kinds of resume transitions, following one of the resume callbacks:\n *\t@resume(), @thaw(), @restore().  Also called if the state transition\n *\tfails before the driver's suspend callback: @suspend(), @freeze() or\n *\t@poweroff(), can be executed (e.g. if the suspend callback fails for one\n *\tof the other devices that the PM core has unsuccessfully attempted to\n *\tsuspend earlier).\n *\tThe PM core executes subsystem-level @complete() after it has executed\n *\tthe appropriate resume callbacks for all devices.  If the corresponding\n *\t@prepare() at the beginning of the suspend transition returned a\n *\tpositive number and the device was left in runtime suspend (without\n *\texecuting any suspend and resume callbacks for it), @complete() will be\n *\tthe only callback executed for the device during resume.  In that case,\n *\t@complete() must be prepared to do whatever is necessary to ensure the\n *\tproper functioning of the device after the system resume.  To this end,\n *\t@complete() can check the power.direct_complete flag of the device to\n *\tlearn whether (unset) or not (set) the previous suspend and resume\n *\tcallbacks have been executed for it.\n *\n * @suspend: Executed before putting the system into a sleep state in which the\n *\tcontents of main memory are preserved.  The exact action to perform\n *\tdepends on the device's subsystem (PM domain, device type, class or bus\n *\ttype), but generally the device must be quiescent after subsystem-level\n *\t@suspend() has returned, so that it doesn't do any I/O or DMA.\n *\tSubsystem-level @suspend() is executed for all devices after invoking\n *\tsubsystem-level @prepare() for all of them.\n *\n * @suspend_late: Continue operations started by @suspend().  For a number of\n *\tdevices @suspend_late() may point to the same callback routine as the\n *\truntime suspend callback.\n *\n * @resume: Executed after waking the system up from a sleep state in which the\n *\tcontents of main memory were preserved.  The exact action to perform\n *\tdepends on the device's subsystem, but generally the driver is expected\n *\tto start working again, responding to hardware events and software\n *\trequests (the device itself may be left in a low-power state, waiting\n *\tfor a runtime resume to occur).  The state of the device at the time its\n *\tdriver's @resume() callback is run depends on the platform and subsystem\n *\tthe device belongs to.  On most platforms, there are no restrictions on\n *\tavailability of resources like clocks during @resume().\n *\tSubsystem-level @resume() is executed for all devices after invoking\n *\tsubsystem-level @resume_noirq() for all of them.\n *\n * @resume_early: Prepare to execute @resume().  For a number of devices\n *\t@resume_early() may point to the same callback routine as the runtime\n *\tresume callback.\n *\n * @freeze: Hibernation-specific, executed before creating a hibernation image.\n *\tAnalogous to @suspend(), but it should not enable the device to signal\n *\twakeup events or change its power state.  The majority of subsystems\n *\t(with the notable exception of the PCI bus type) expect the driver-level\n *\t@freeze() to save the device settings in memory to be used by @restore()\n *\tduring the subsequent resume from hibernation.\n *\tSubsystem-level @freeze() is executed for all devices after invoking\n *\tsubsystem-level @prepare() for all of them.\n *\n * @freeze_late: Continue operations started by @freeze().  Analogous to\n *\t@suspend_late(), but it should not enable the device to signal wakeup\n *\tevents or change its power state.\n *\n * @thaw: Hibernation-specific, executed after creating a hibernation image OR\n *\tif the creation of an image has failed.  Also executed after a failing\n *\tattempt to restore the contents of main memory from such an image.\n *\tUndo the changes made by the preceding @freeze(), so the device can be\n *\toperated in the same way as immediately before the call to @freeze().\n *\tSubsystem-level @thaw() is executed for all devices after invoking\n *\tsubsystem-level @thaw_noirq() for all of them.  It also may be executed\n *\tdirectly after @freeze() in case of a transition error.\n *\n * @thaw_early: Prepare to execute @thaw().  Undo the changes made by the\n *\tpreceding @freeze_late().\n *\n * @poweroff: Hibernation-specific, executed after saving a hibernation image.\n *\tAnalogous to @suspend(), but it need not save the device's settings in\n *\tmemory.\n *\tSubsystem-level @poweroff() is executed for all devices after invoking\n *\tsubsystem-level @prepare() for all of them.\n *\n * @poweroff_late: Continue operations started by @poweroff().  Analogous to\n *\t@suspend_late(), but it need not save the device's settings in memory.\n *\n * @restore: Hibernation-specific, executed after restoring the contents of main\n *\tmemory from a hibernation image, analogous to @resume().\n *\n * @restore_early: Prepare to execute @restore(), analogous to @resume_early().\n *\n * @suspend_noirq: Complete the actions started by @suspend().  Carry out any\n *\tadditional operations required for suspending the device that might be\n *\tracing with its driver's interrupt handler, which is guaranteed not to\n *\trun while @suspend_noirq() is being executed.\n *\tIt generally is expected that the device will be in a low-power state\n *\t(appropriate for the target system sleep state) after subsystem-level\n *\t@suspend_noirq() has returned successfully.  If the device can generate\n *\tsystem wakeup signals and is enabled to wake up the system, it should be\n *\tconfigured to do so at that time.  However, depending on the platform\n *\tand device's subsystem, @suspend() or @suspend_late() may be allowed to\n *\tput the device into the low-power state and configure it to generate\n *\twakeup signals, in which case it generally is not necessary to define\n *\t@suspend_noirq().\n *\n * @resume_noirq: Prepare for the execution of @resume() by carrying out any\n *\toperations required for resuming the device that might be racing with\n *\tits driver's interrupt handler, which is guaranteed not to run while\n *\t@resume_noirq() is being executed.\n *\n * @freeze_noirq: Complete the actions started by @freeze().  Carry out any\n *\tadditional operations required for freezing the device that might be\n *\tracing with its driver's interrupt handler, which is guaranteed not to\n *\trun while @freeze_noirq() is being executed.\n *\tThe power state of the device should not be changed by either @freeze(),\n *\tor @freeze_late(), or @freeze_noirq() and it should not be configured to\n *\tsignal system wakeup by any of these callbacks.\n *\n * @thaw_noirq: Prepare for the execution of @thaw() by carrying out any\n *\toperations required for thawing the device that might be racing with its\n *\tdriver's interrupt handler, which is guaranteed not to run while\n *\t@thaw_noirq() is being executed.\n *\n * @poweroff_noirq: Complete the actions started by @poweroff().  Analogous to\n *\t@suspend_noirq(), but it need not save the device's settings in memory.\n *\n * @restore_noirq: Prepare for the execution of @restore() by carrying out any\n *\toperations required for thawing the device that might be racing with its\n *\tdriver's interrupt handler, which is guaranteed not to run while\n *\t@restore_noirq() is being executed.  Analogous to @resume_noirq().\n *\n * @runtime_suspend: Prepare the device for a condition in which it won't be\n *\table to communicate with the CPU(s) and RAM due to power management.\n *\tThis need not mean that the device should be put into a low-power state.\n *\tFor example, if the device is behind a link which is about to be turned\n *\toff, the device may remain at full power.  If the device does go to low\n *\tpower and is capable of generating runtime wakeup events, remote wakeup\n *\t(i.e., a hardware mechanism allowing the device to request a change of\n *\tits power state via an interrupt) should be enabled for it.\n *\n * @runtime_resume: Put the device into the fully active state in response to a\n *\twakeup event generated by hardware or at the request of software.  If\n *\tnecessary, put the device into the full-power state and restore its\n *\tregisters, so that it is fully operational.\n *\n * @runtime_idle: Device appears to be inactive and it might be put into a\n *\tlow-power state if all of the necessary conditions are satisfied.\n *\tCheck these conditions, and return 0 if it's appropriate to let the PM\n *\tcore queue a suspend request for the device.\n *\n * Several device power state transitions are externally visible, affecting\n * the state of pending I/O queues and (for drivers that touch hardware)\n * interrupts, wakeups, DMA, and other hardware state.  There may also be\n * internal transitions to various low-power modes which are transparent\n * to the rest of the driver stack (such as a driver that's ON gating off\n * clocks which are not in active use).\n *\n * The externally visible transitions are handled with the help of callbacks\n * included in this structure in such a way that, typically, two levels of\n * callbacks are involved.  First, the PM core executes callbacks provided by PM\n * domains, device types, classes and bus types.  They are the subsystem-level\n * callbacks expected to execute callbacks provided by device drivers, although\n * they may choose not to do that.  If the driver callbacks are executed, they\n * have to collaborate with the subsystem-level callbacks to achieve the goals\n * appropriate for the given system transition, given transition phase and the\n * subsystem the device belongs to.\n *\n * All of the above callbacks, except for @complete(), return error codes.\n * However, the error codes returned by @resume(), @thaw(), @restore(),\n * @resume_noirq(), @thaw_noirq(), and @restore_noirq(), do not cause the PM\n * core to abort the resume transition during which they are returned.  The\n * error codes returned in those cases are only printed to the system logs for\n * debugging purposes.  Still, it is recommended that drivers only return error\n * codes from their resume methods in case of an unrecoverable failure (i.e.\n * when the device being handled refuses to resume and becomes unusable) to\n * allow the PM core to be modified in the future, so that it can avoid\n * attempting to handle devices that failed to resume and their children.\n *\n * It is allowed to unregister devices while the above callbacks are being\n * executed.  However, a callback routine MUST NOT try to unregister the device\n * it was called for, although it may unregister children of that device (for\n * example, if it detects that a child was unplugged while the system was\n * asleep).\n *\n * There also are callbacks related to runtime power management of devices.\n * Again, as a rule these callbacks are executed by the PM core for subsystems\n * (PM domains, device types, classes and bus types) and the subsystem-level\n * callbacks are expected to invoke the driver callbacks.  Moreover, the exact\n * actions to be performed by a device driver's callbacks generally depend on\n * the platform and subsystem the device belongs to.\n *\n * Refer to Documentation/power/runtime_pm.rst for more information about the\n * role of the @runtime_suspend(), @runtime_resume() and @runtime_idle()\n * callbacks in device runtime power management.\n */\nstruct dev_pm_ops {\n\tint (*prepare)(struct device *dev);\n\tvoid (*complete)(struct device *dev);\n\tint (*suspend)(struct device *dev);\n\tint (*resume)(struct device *dev);\n\tint (*freeze)(struct device *dev);\n\tint (*thaw)(struct device *dev);\n\tint (*poweroff)(struct device *dev);\n\tint (*restore)(struct device *dev);\n\tint (*suspend_late)(struct device *dev);\n\tint (*resume_early)(struct device *dev);\n\tint (*freeze_late)(struct device *dev);\n\tint (*thaw_early)(struct device *dev);\n\tint (*poweroff_late)(struct device *dev);\n\tint (*restore_early)(struct device *dev);\n\tint (*suspend_noirq)(struct device *dev);\n\tint (*resume_noirq)(struct device *dev);\n\tint (*freeze_noirq)(struct device *dev);\n\tint (*thaw_noirq)(struct device *dev);\n\tint (*poweroff_noirq)(struct device *dev);\n\tint (*restore_noirq)(struct device *dev);\n\tint (*runtime_suspend)(struct device *dev);\n\tint (*runtime_resume)(struct device *dev);\n\tint (*runtime_idle)(struct device *dev);\n};\n\n#ifdef CONFIG_PM_SLEEP\n#define SET_SYSTEM_SLEEP_PM_OPS(suspend_fn, resume_fn) \\\n\t.suspend = suspend_fn, \\\n\t.resume = resume_fn, \\\n\t.freeze = suspend_fn, \\\n\t.thaw = resume_fn, \\\n\t.poweroff = suspend_fn, \\\n\t.restore = resume_fn,\n#else\n#define SET_SYSTEM_SLEEP_PM_OPS(suspend_fn, resume_fn)\n#endif\n\n#ifdef CONFIG_PM_SLEEP\n#define SET_LATE_SYSTEM_SLEEP_PM_OPS(suspend_fn, resume_fn) \\\n\t.suspend_late = suspend_fn, \\\n\t.resume_early = resume_fn, \\\n\t.freeze_late = suspend_fn, \\\n\t.thaw_early = resume_fn, \\\n\t.poweroff_late = suspend_fn, \\\n\t.restore_early = resume_fn,\n#else\n#define SET_LATE_SYSTEM_SLEEP_PM_OPS(suspend_fn, resume_fn)\n#endif\n\n#ifdef CONFIG_PM_SLEEP\n#define SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(suspend_fn, resume_fn) \\\n\t.suspend_noirq = suspend_fn, \\\n\t.resume_noirq = resume_fn, \\\n\t.freeze_noirq = suspend_fn, \\\n\t.thaw_noirq = resume_fn, \\\n\t.poweroff_noirq = suspend_fn, \\\n\t.restore_noirq = resume_fn,\n#else\n#define SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(suspend_fn, resume_fn)\n#endif\n\n#ifdef CONFIG_PM\n#define SET_RUNTIME_PM_OPS(suspend_fn, resume_fn, idle_fn) \\\n\t.runtime_suspend = suspend_fn, \\\n\t.runtime_resume = resume_fn, \\\n\t.runtime_idle = idle_fn,\n#else\n#define SET_RUNTIME_PM_OPS(suspend_fn, resume_fn, idle_fn)\n#endif\n\n/*\n * Use this if you want to use the same suspend and resume callbacks for suspend\n * to RAM and hibernation.\n */\n#define SIMPLE_DEV_PM_OPS(name, suspend_fn, resume_fn) \\\nconst struct dev_pm_ops name = { \\\n\tSET_SYSTEM_SLEEP_PM_OPS(suspend_fn, resume_fn) \\\n}\n\n/*\n * Use this for defining a set of PM operations to be used in all situations\n * (system suspend, hibernation or runtime PM).\n * NOTE: In general, system suspend callbacks, .suspend() and .resume(), should\n * be different from the corresponding runtime PM callbacks, .runtime_suspend(),\n * and .runtime_resume(), because .runtime_suspend() always works on an already\n * quiescent device, while .suspend() should assume that the device may be doing\n * something when it is called (it should ensure that the device will be\n * quiescent after it has returned).  Therefore it's better to point the \"late\"\n * suspend and \"early\" resume callback pointers, .suspend_late() and\n * .resume_early(), to the same routines as .runtime_suspend() and\n * .runtime_resume(), respectively (and analogously for hibernation).\n */\n#define UNIVERSAL_DEV_PM_OPS(name, suspend_fn, resume_fn, idle_fn) \\\nconst struct dev_pm_ops name = { \\\n\tSET_SYSTEM_SLEEP_PM_OPS(suspend_fn, resume_fn) \\\n\tSET_RUNTIME_PM_OPS(suspend_fn, resume_fn, idle_fn) \\\n}\n\n/*\n * PM_EVENT_ messages\n *\n * The following PM_EVENT_ messages are defined for the internal use of the PM\n * core, in order to provide a mechanism allowing the high level suspend and\n * hibernation code to convey the necessary information to the device PM core\n * code:\n *\n * ON\t\tNo transition.\n *\n * FREEZE\tSystem is going to hibernate, call ->prepare() and ->freeze()\n *\t\tfor all devices.\n *\n * SUSPEND\tSystem is going to suspend, call ->prepare() and ->suspend()\n *\t\tfor all devices.\n *\n * HIBERNATE\tHibernation image has been saved, call ->prepare() and\n *\t\t->poweroff() for all devices.\n *\n * QUIESCE\tContents of main memory are going to be restored from a (loaded)\n *\t\thibernation image, call ->prepare() and ->freeze() for all\n *\t\tdevices.\n *\n * RESUME\tSystem is resuming, call ->resume() and ->complete() for all\n *\t\tdevices.\n *\n * THAW\t\tHibernation image has been created, call ->thaw() and\n *\t\t->complete() for all devices.\n *\n * RESTORE\tContents of main memory have been restored from a hibernation\n *\t\timage, call ->restore() and ->complete() for all devices.\n *\n * RECOVER\tCreation of a hibernation image or restoration of the main\n *\t\tmemory contents from a hibernation image has failed, call\n *\t\t->thaw() and ->complete() for all devices.\n *\n * The following PM_EVENT_ messages are defined for internal use by\n * kernel subsystems.  They are never issued by the PM core.\n *\n * USER_SUSPEND\t\tManual selective suspend was issued by userspace.\n *\n * USER_RESUME\t\tManual selective resume was issued by userspace.\n *\n * REMOTE_WAKEUP\tRemote-wakeup request was received from the device.\n *\n * AUTO_SUSPEND\t\tAutomatic (device idle) runtime suspend was\n *\t\t\tinitiated by the subsystem.\n *\n * AUTO_RESUME\t\tAutomatic (device needed) runtime resume was\n *\t\t\trequested by a driver.\n */\n\n#define PM_EVENT_INVALID\t(-1)\n#define PM_EVENT_ON\t\t0x0000\n#define PM_EVENT_FREEZE\t\t0x0001\n#define PM_EVENT_SUSPEND\t0x0002\n#define PM_EVENT_HIBERNATE\t0x0004\n#define PM_EVENT_QUIESCE\t0x0008\n#define PM_EVENT_RESUME\t\t0x0010\n#define PM_EVENT_THAW\t\t0x0020\n#define PM_EVENT_RESTORE\t0x0040\n#define PM_EVENT_RECOVER\t0x0080\n#define PM_EVENT_USER\t\t0x0100\n#define PM_EVENT_REMOTE\t\t0x0200\n#define PM_EVENT_AUTO\t\t0x0400\n\n#define PM_EVENT_SLEEP\t\t(PM_EVENT_SUSPEND | PM_EVENT_HIBERNATE)\n#define PM_EVENT_USER_SUSPEND\t(PM_EVENT_USER | PM_EVENT_SUSPEND)\n#define PM_EVENT_USER_RESUME\t(PM_EVENT_USER | PM_EVENT_RESUME)\n#define PM_EVENT_REMOTE_RESUME\t(PM_EVENT_REMOTE | PM_EVENT_RESUME)\n#define PM_EVENT_AUTO_SUSPEND\t(PM_EVENT_AUTO | PM_EVENT_SUSPEND)\n#define PM_EVENT_AUTO_RESUME\t(PM_EVENT_AUTO | PM_EVENT_RESUME)\n\n#define PMSG_INVALID\t((struct pm_message){ .event = PM_EVENT_INVALID, })\n#define PMSG_ON\t\t((struct pm_message){ .event = PM_EVENT_ON, })\n#define PMSG_FREEZE\t((struct pm_message){ .event = PM_EVENT_FREEZE, })\n#define PMSG_QUIESCE\t((struct pm_message){ .event = PM_EVENT_QUIESCE, })\n#define PMSG_SUSPEND\t((struct pm_message){ .event = PM_EVENT_SUSPEND, })\n#define PMSG_HIBERNATE\t((struct pm_message){ .event = PM_EVENT_HIBERNATE, })\n#define PMSG_RESUME\t((struct pm_message){ .event = PM_EVENT_RESUME, })\n#define PMSG_THAW\t((struct pm_message){ .event = PM_EVENT_THAW, })\n#define PMSG_RESTORE\t((struct pm_message){ .event = PM_EVENT_RESTORE, })\n#define PMSG_RECOVER\t((struct pm_message){ .event = PM_EVENT_RECOVER, })\n#define PMSG_USER_SUSPEND\t((struct pm_message) \\\n\t\t\t\t\t{ .event = PM_EVENT_USER_SUSPEND, })\n#define PMSG_USER_RESUME\t((struct pm_message) \\\n\t\t\t\t\t{ .event = PM_EVENT_USER_RESUME, })\n#define PMSG_REMOTE_RESUME\t((struct pm_message) \\\n\t\t\t\t\t{ .event = PM_EVENT_REMOTE_RESUME, })\n#define PMSG_AUTO_SUSPEND\t((struct pm_message) \\\n\t\t\t\t\t{ .event = PM_EVENT_AUTO_SUSPEND, })\n#define PMSG_AUTO_RESUME\t((struct pm_message) \\\n\t\t\t\t\t{ .event = PM_EVENT_AUTO_RESUME, })\n\n#define PMSG_IS_AUTO(msg)\t(((msg).event & PM_EVENT_AUTO) != 0)\n\n/*\n * Device run-time power management status.\n *\n * These status labels are used internally by the PM core to indicate the\n * current status of a device with respect to the PM core operations.  They do\n * not reflect the actual power state of the device or its status as seen by the\n * driver.\n *\n * RPM_ACTIVE\t\tDevice is fully operational.  Indicates that the device\n *\t\t\tbus type's ->runtime_resume() callback has completed\n *\t\t\tsuccessfully.\n *\n * RPM_SUSPENDED\tDevice bus type's ->runtime_suspend() callback has\n *\t\t\tcompleted successfully.  The device is regarded as\n *\t\t\tsuspended.\n *\n * RPM_RESUMING\t\tDevice bus type's ->runtime_resume() callback is being\n *\t\t\texecuted.\n *\n * RPM_SUSPENDING\tDevice bus type's ->runtime_suspend() callback is being\n *\t\t\texecuted.\n */\n\nenum rpm_status {\n\tRPM_ACTIVE = 0,\n\tRPM_RESUMING,\n\tRPM_SUSPENDED,\n\tRPM_SUSPENDING,\n};\n\n/*\n * Device run-time power management request types.\n *\n * RPM_REQ_NONE\t\tDo nothing.\n *\n * RPM_REQ_IDLE\t\tRun the device bus type's ->runtime_idle() callback\n *\n * RPM_REQ_SUSPEND\tRun the device bus type's ->runtime_suspend() callback\n *\n * RPM_REQ_AUTOSUSPEND\tSame as RPM_REQ_SUSPEND, but not until the device has\n *\t\t\tbeen inactive for as long as power.autosuspend_delay\n *\n * RPM_REQ_RESUME\tRun the device bus type's ->runtime_resume() callback\n */\n\nenum rpm_request {\n\tRPM_REQ_NONE = 0,\n\tRPM_REQ_IDLE,\n\tRPM_REQ_SUSPEND,\n\tRPM_REQ_AUTOSUSPEND,\n\tRPM_REQ_RESUME,\n};\n\nstruct wakeup_source;\nstruct wake_irq;\nstruct pm_domain_data;\n\nstruct pm_subsys_data {\n\tspinlock_t lock;\n\tunsigned int refcount;\n#ifdef CONFIG_PM_CLK\n\tstruct list_head clock_list;\n#endif\n#ifdef CONFIG_PM_GENERIC_DOMAINS\n\tstruct pm_domain_data *domain_data;\n#endif\n};\n\n/*\n * Driver flags to control system suspend/resume behavior.\n *\n * These flags can be set by device drivers at the probe time.  They need not be\n * cleared by the drivers as the driver core will take care of that.\n *\n * NEVER_SKIP: Do not skip all system suspend/resume callbacks for the device.\n * SMART_PREPARE: Check the return value of the driver's ->prepare callback.\n * SMART_SUSPEND: No need to resume the device from runtime suspend.\n * LEAVE_SUSPENDED: Avoid resuming the device during system resume if possible.\n *\n * Setting SMART_PREPARE instructs bus types and PM domains which may want\n * system suspend/resume callbacks to be skipped for the device to return 0 from\n * their ->prepare callbacks if the driver's ->prepare callback returns 0 (in\n * other words, the system suspend/resume callbacks can only be skipped for the\n * device if its driver doesn't object against that).  This flag has no effect\n * if NEVER_SKIP is set.\n *\n * Setting SMART_SUSPEND instructs bus types and PM domains which may want to\n * runtime resume the device upfront during system suspend that doing so is not\n * necessary from the driver's perspective.  It also may cause them to skip\n * invocations of the ->suspend_late and ->suspend_noirq callbacks provided by\n * the driver if they decide to leave the device in runtime suspend.\n *\n * Setting LEAVE_SUSPENDED informs the PM core and middle-layer code that the\n * driver prefers the device to be left in suspend after system resume.\n */\n#define DPM_FLAG_NEVER_SKIP\t\tBIT(0)\n#define DPM_FLAG_SMART_PREPARE\t\tBIT(1)\n#define DPM_FLAG_SMART_SUSPEND\t\tBIT(2)\n#define DPM_FLAG_LEAVE_SUSPENDED\tBIT(3)\n\nstruct dev_pm_info {\n\tpm_message_t\t\tpower_state;\n\tunsigned int\t\tcan_wakeup:1;\n\tunsigned int\t\tasync_suspend:1;\n\tbool\t\t\tin_dpm_list:1;\t/* Owned by the PM core */\n\tbool\t\t\tis_prepared:1;\t/* Owned by the PM core */\n\tbool\t\t\tis_suspended:1;\t/* Ditto */\n\tbool\t\t\tis_noirq_suspended:1;\n\tbool\t\t\tis_late_suspended:1;\n\tbool\t\t\tno_pm:1;\n\tbool\t\t\tearly_init:1;\t/* Owned by the PM core */\n\tbool\t\t\tdirect_complete:1;\t/* Owned by the PM core */\n\tu32\t\t\tdriver_flags;\n\tspinlock_t\t\tlock;\n#ifdef CONFIG_PM_SLEEP\n\tstruct list_head\tentry;\n\tstruct completion\tcompletion;\n\tstruct wakeup_source\t*wakeup;\n\tbool\t\t\twakeup_path:1;\n\tbool\t\t\tsyscore:1;\n\tbool\t\t\tno_pm_callbacks:1;\t/* Owned by the PM core */\n\tunsigned int\t\tmust_resume:1;\t/* Owned by the PM core */\n\tunsigned int\t\tmay_skip_resume:1;\t/* Set by subsystems */\n#else\n\tunsigned int\t\tshould_wakeup:1;\n#endif\n#ifdef CONFIG_PM\n\tstruct hrtimer\t\tsuspend_timer;\n\tunsigned long\t\ttimer_expires;\n\tstruct work_struct\twork;\n\twait_queue_head_t\twait_queue;\n\tstruct wake_irq\t\t*wakeirq;\n\tatomic_t\t\tusage_count;\n\tatomic_t\t\tchild_count;\n\tunsigned int\t\tdisable_depth:3;\n\tunsigned int\t\tidle_notification:1;\n\tunsigned int\t\trequest_pending:1;\n\tunsigned int\t\tdeferred_resume:1;\n\tunsigned int\t\truntime_auto:1;\n\tbool\t\t\tignore_children:1;\n\tunsigned int\t\tno_callbacks:1;\n\tunsigned int\t\tirq_safe:1;\n\tunsigned int\t\tuse_autosuspend:1;\n\tunsigned int\t\ttimer_autosuspends:1;\n\tunsigned int\t\tmemalloc_noio:1;\n\tunsigned int\t\tlinks_count;\n\tenum rpm_request\trequest;\n\tenum rpm_status\t\truntime_status;\n\tint\t\t\truntime_error;\n\tint\t\t\tautosuspend_delay;\n\tu64\t\t\tlast_busy;\n\tu64\t\t\tactive_time;\n\tu64\t\t\tsuspended_time;\n\tu64\t\t\taccounting_timestamp;\n#endif\n\tstruct pm_subsys_data\t*subsys_data;  /* Owned by the subsystem. */\n\tvoid (*set_latency_tolerance)(struct device *, s32);\n\tstruct dev_pm_qos\t*qos;\n};\n\nextern int dev_pm_get_subsys_data(struct device *dev);\nextern void dev_pm_put_subsys_data(struct device *dev);\n\n/**\n * struct dev_pm_domain - power management domain representation.\n *\n * @ops: Power management operations associated with this domain.\n * @detach: Called when removing a device from the domain.\n * @activate: Called before executing probe routines for bus types and drivers.\n * @sync: Called after successful driver probe.\n * @dismiss: Called after unsuccessful driver probe and after driver removal.\n *\n * Power domains provide callbacks that are executed during system suspend,\n * hibernation, system resume and during runtime PM transitions instead of\n * subsystem-level and driver-level callbacks.\n */\nstruct dev_pm_domain {\n\tstruct dev_pm_ops\tops;\n\tvoid (*detach)(struct device *dev, bool power_off);\n\tint (*activate)(struct device *dev);\n\tvoid (*sync)(struct device *dev);\n\tvoid (*dismiss)(struct device *dev);\n};\n\n/*\n * The PM_EVENT_ messages are also used by drivers implementing the legacy\n * suspend framework, based on the ->suspend() and ->resume() callbacks common\n * for suspend and hibernation transitions, according to the rules below.\n */\n\n/* Necessary, because several drivers use PM_EVENT_PRETHAW */\n#define PM_EVENT_PRETHAW PM_EVENT_QUIESCE\n\n/*\n * One transition is triggered by resume(), after a suspend() call; the\n * message is implicit:\n *\n * ON\t\tDriver starts working again, responding to hardware events\n *\t\tand software requests.  The hardware may have gone through\n *\t\ta power-off reset, or it may have maintained state from the\n *\t\tprevious suspend() which the driver will rely on while\n *\t\tresuming.  On most platforms, there are no restrictions on\n *\t\tavailability of resources like clocks during resume().\n *\n * Other transitions are triggered by messages sent using suspend().  All\n * these transitions quiesce the driver, so that I/O queues are inactive.\n * That commonly entails turning off IRQs and DMA; there may be rules\n * about how to quiesce that are specific to the bus or the device's type.\n * (For example, network drivers mark the link state.)  Other details may\n * differ according to the message:\n *\n * SUSPEND\tQuiesce, enter a low power device state appropriate for\n *\t\tthe upcoming system state (such as PCI_D3hot), and enable\n *\t\twakeup events as appropriate.\n *\n * HIBERNATE\tEnter a low power device state appropriate for the hibernation\n *\t\tstate (eg. ACPI S4) and enable wakeup events as appropriate.\n *\n * FREEZE\tQuiesce operations so that a consistent image can be saved;\n *\t\tbut do NOT otherwise enter a low power device state, and do\n *\t\tNOT emit system wakeup events.\n *\n * PRETHAW\tQuiesce as if for FREEZE; additionally, prepare for restoring\n *\t\tthe system from a snapshot taken after an earlier FREEZE.\n *\t\tSome drivers will need to reset their hardware state instead\n *\t\tof preserving it, to ensure that it's never mistaken for the\n *\t\tstate which that earlier snapshot had set up.\n *\n * A minimally power-aware driver treats all messages as SUSPEND, fully\n * reinitializes its device during resume() -- whether or not it was reset\n * during the suspend/resume cycle -- and can't issue wakeup events.\n *\n * More power-aware drivers may also use low power states at runtime as\n * well as during system sleep states like PM_SUSPEND_STANDBY.  They may\n * be able to use wakeup events to exit from runtime low-power states,\n * or from system low-power states such as standby or suspend-to-RAM.\n */\n\n#ifdef CONFIG_PM_SLEEP\nextern void device_pm_lock(void);\nextern void dpm_resume_start(pm_message_t state);\nextern void dpm_resume_end(pm_message_t state);\nextern void dpm_resume_noirq(pm_message_t state);\nextern void dpm_resume_early(pm_message_t state);\nextern void dpm_resume(pm_message_t state);\nextern void dpm_complete(pm_message_t state);\n\nextern void device_pm_unlock(void);\nextern int dpm_suspend_end(pm_message_t state);\nextern int dpm_suspend_start(pm_message_t state);\nextern int dpm_suspend_noirq(pm_message_t state);\nextern int dpm_suspend_late(pm_message_t state);\nextern int dpm_suspend(pm_message_t state);\nextern int dpm_prepare(pm_message_t state);\n\nextern void __suspend_report_result(const char *function, void *fn, int ret);\n\n#define suspend_report_result(fn, ret)\t\t\t\t\t\\\n\tdo {\t\t\t\t\t\t\t\t\\\n\t\t__suspend_report_result(__func__, fn, ret);\t\t\\\n\t} while (0)\n\nextern int device_pm_wait_for_dev(struct device *sub, struct device *dev);\nextern void dpm_for_each_dev(void *data, void (*fn)(struct device *, void *));\n\nextern int pm_generic_prepare(struct device *dev);\nextern int pm_generic_suspend_late(struct device *dev);\nextern int pm_generic_suspend_noirq(struct device *dev);\nextern int pm_generic_suspend(struct device *dev);\nextern int pm_generic_resume_early(struct device *dev);\nextern int pm_generic_resume_noirq(struct device *dev);\nextern int pm_generic_resume(struct device *dev);\nextern int pm_generic_freeze_noirq(struct device *dev);\nextern int pm_generic_freeze_late(struct device *dev);\nextern int pm_generic_freeze(struct device *dev);\nextern int pm_generic_thaw_noirq(struct device *dev);\nextern int pm_generic_thaw_early(struct device *dev);\nextern int pm_generic_thaw(struct device *dev);\nextern int pm_generic_restore_noirq(struct device *dev);\nextern int pm_generic_restore_early(struct device *dev);\nextern int pm_generic_restore(struct device *dev);\nextern int pm_generic_poweroff_noirq(struct device *dev);\nextern int pm_generic_poweroff_late(struct device *dev);\nextern int pm_generic_poweroff(struct device *dev);\nextern void pm_generic_complete(struct device *dev);\n\nextern bool dev_pm_may_skip_resume(struct device *dev);\nextern bool dev_pm_smart_suspend_and_suspended(struct device *dev);\n\n#else /* !CONFIG_PM_SLEEP */\n\n#define device_pm_lock() do {} while (0)\n#define device_pm_unlock() do {} while (0)\n\nstatic inline int dpm_suspend_start(pm_message_t state)\n{\n\treturn 0;\n}\n\n#define suspend_report_result(fn, ret)\t\tdo {} while (0)\n\nstatic inline int device_pm_wait_for_dev(struct device *a, struct device *b)\n{\n\treturn 0;\n}\n\nstatic inline void dpm_for_each_dev(void *data, void (*fn)(struct device *, void *))\n{\n}\n\n#define pm_generic_prepare\t\tNULL\n#define pm_generic_suspend_late\t\tNULL\n#define pm_generic_suspend_noirq\tNULL\n#define pm_generic_suspend\t\tNULL\n#define pm_generic_resume_early\t\tNULL\n#define pm_generic_resume_noirq\t\tNULL\n#define pm_generic_resume\t\tNULL\n#define pm_generic_freeze_noirq\t\tNULL\n#define pm_generic_freeze_late\t\tNULL\n#define pm_generic_freeze\t\tNULL\n#define pm_generic_thaw_noirq\t\tNULL\n#define pm_generic_thaw_early\t\tNULL\n#define pm_generic_thaw\t\t\tNULL\n#define pm_generic_restore_noirq\tNULL\n#define pm_generic_restore_early\tNULL\n#define pm_generic_restore\t\tNULL\n#define pm_generic_poweroff_noirq\tNULL\n#define pm_generic_poweroff_late\tNULL\n#define pm_generic_poweroff\t\tNULL\n#define pm_generic_complete\t\tNULL\n#endif /* !CONFIG_PM_SLEEP */\n\n/* How to reorder dpm_list after device_move() */\nenum dpm_order {\n\tDPM_ORDER_NONE,\n\tDPM_ORDER_DEV_AFTER_PARENT,\n\tDPM_ORDER_PARENT_BEFORE_DEV,\n\tDPM_ORDER_DEV_LAST,\n};\n\n#endif /* _LINUX_PM_H */\n"
  },
  {
    "path": "t/tree/include/linux/pm_wakeup.h",
    "content": "/* SPDX-License-Identifier: GPL-2.0-or-later */\n/*\n *  pm_wakeup.h - Power management wakeup interface\n *\n *  Copyright (C) 2008 Alan Stern\n *  Copyright (C) 2010 Rafael J. Wysocki, Novell Inc.\n */\n\n#ifndef _LINUX_PM_WAKEUP_H\n#define _LINUX_PM_WAKEUP_H\n\n#ifndef _DEVICE_H_\n# error \"please don't include this file directly\"\n#endif\n\n#include <linux/types.h>\n\nstruct wake_irq;\n\n/**\n * struct wakeup_source - Representation of wakeup sources\n *\n * @name: Name of the wakeup source\n * @id: Wakeup source id\n * @entry: Wakeup source list entry\n * @lock: Wakeup source lock\n * @wakeirq: Optional device specific wakeirq\n * @timer: Wakeup timer list\n * @timer_expires: Wakeup timer expiration\n * @total_time: Total time this wakeup source has been active.\n * @max_time: Maximum time this wakeup source has been continuously active.\n * @last_time: Monotonic clock when the wakeup source's was touched last time.\n * @prevent_sleep_time: Total time this source has been preventing autosleep.\n * @event_count: Number of signaled wakeup events.\n * @active_count: Number of times the wakeup source was activated.\n * @relax_count: Number of times the wakeup source was deactivated.\n * @expire_count: Number of times the wakeup source's timeout has expired.\n * @wakeup_count: Number of times the wakeup source might abort suspend.\n * @dev: Struct device for sysfs statistics about the wakeup source.\n * @active: Status of the wakeup source.\n * @autosleep_enabled: Autosleep is active, so update @prevent_sleep_time.\n */\nstruct wakeup_source {\n\tconst char \t\t*name;\n\tint\t\t\tid;\n\tstruct list_head\tentry;\n\tspinlock_t\t\tlock;\n\tstruct wake_irq\t\t*wakeirq;\n\tstruct timer_list\ttimer;\n\tunsigned long\t\ttimer_expires;\n\tktime_t total_time;\n\tktime_t max_time;\n\tktime_t last_time;\n\tktime_t start_prevent_time;\n\tktime_t prevent_sleep_time;\n\tunsigned long\t\tevent_count;\n\tunsigned long\t\tactive_count;\n\tunsigned long\t\trelax_count;\n\tunsigned long\t\texpire_count;\n\tunsigned long\t\twakeup_count;\n\tstruct device\t\t*dev;\n\tbool\t\t\tactive:1;\n\tbool\t\t\tautosleep_enabled:1;\n};\n\n#ifdef CONFIG_PM_SLEEP\n\n/*\n * Changes to device_may_wakeup take effect on the next pm state change.\n */\n\nstatic inline bool device_can_wakeup(struct device *dev)\n{\n\treturn dev->power.can_wakeup;\n}\n\nstatic inline bool device_may_wakeup(struct device *dev)\n{\n\treturn dev->power.can_wakeup && !!dev->power.wakeup;\n}\n\nstatic inline void device_set_wakeup_path(struct device *dev)\n{\n\tdev->power.wakeup_path = true;\n}\n\n/* drivers/base/power/wakeup.c */\nextern struct wakeup_source *wakeup_source_create(const char *name);\nextern void wakeup_source_destroy(struct wakeup_source *ws);\nextern void wakeup_source_add(struct wakeup_source *ws);\nextern void wakeup_source_remove(struct wakeup_source *ws);\nextern struct wakeup_source *wakeup_source_register(struct device *dev,\n\t\t\t\t\t\t    const char *name);\nextern void wakeup_source_unregister(struct wakeup_source *ws);\nextern int device_wakeup_enable(struct device *dev);\nextern int device_wakeup_disable(struct device *dev);\nextern void device_set_wakeup_capable(struct device *dev, bool capable);\nextern int device_init_wakeup(struct device *dev, bool val);\nextern int device_set_wakeup_enable(struct device *dev, bool enable);\nextern void __pm_stay_awake(struct wakeup_source *ws);\nextern void pm_stay_awake(struct device *dev);\nextern void __pm_relax(struct wakeup_source *ws);\nextern void pm_relax(struct device *dev);\nextern void pm_wakeup_ws_event(struct wakeup_source *ws, unsigned int msec, bool hard);\nextern void pm_wakeup_dev_event(struct device *dev, unsigned int msec, bool hard);\n\n#else /* !CONFIG_PM_SLEEP */\n\nstatic inline void device_set_wakeup_capable(struct device *dev, bool capable)\n{\n\tdev->power.can_wakeup = capable;\n}\n\nstatic inline bool device_can_wakeup(struct device *dev)\n{\n\treturn dev->power.can_wakeup;\n}\n\nstatic inline struct wakeup_source *wakeup_source_create(const char *name)\n{\n\treturn NULL;\n}\n\nstatic inline void wakeup_source_destroy(struct wakeup_source *ws) {}\n\nstatic inline void wakeup_source_add(struct wakeup_source *ws) {}\n\nstatic inline void wakeup_source_remove(struct wakeup_source *ws) {}\n\nstatic inline struct wakeup_source *wakeup_source_register(struct device *dev,\n\t\t\t\t\t\t\t   const char *name)\n{\n\treturn NULL;\n}\n\nstatic inline void wakeup_source_unregister(struct wakeup_source *ws) {}\n\nstatic inline int device_wakeup_enable(struct device *dev)\n{\n\tdev->power.should_wakeup = true;\n\treturn 0;\n}\n\nstatic inline int device_wakeup_disable(struct device *dev)\n{\n\tdev->power.should_wakeup = false;\n\treturn 0;\n}\n\nstatic inline int device_set_wakeup_enable(struct device *dev, bool enable)\n{\n\tdev->power.should_wakeup = enable;\n\treturn 0;\n}\n\nstatic inline int device_init_wakeup(struct device *dev, bool val)\n{\n\tdevice_set_wakeup_capable(dev, val);\n\tdevice_set_wakeup_enable(dev, val);\n\treturn 0;\n}\n\nstatic inline bool device_may_wakeup(struct device *dev)\n{\n\treturn dev->power.can_wakeup && dev->power.should_wakeup;\n}\n\nstatic inline void device_set_wakeup_path(struct device *dev) {}\n\nstatic inline void __pm_stay_awake(struct wakeup_source *ws) {}\n\nstatic inline void pm_stay_awake(struct device *dev) {}\n\nstatic inline void __pm_relax(struct wakeup_source *ws) {}\n\nstatic inline void pm_relax(struct device *dev) {}\n\nstatic inline void pm_wakeup_ws_event(struct wakeup_source *ws,\n\t\t\t\t      unsigned int msec, bool hard) {}\n\nstatic inline void pm_wakeup_dev_event(struct device *dev, unsigned int msec,\n\t\t\t\t       bool hard) {}\n\n#endif /* !CONFIG_PM_SLEEP */\n\nstatic inline void __pm_wakeup_event(struct wakeup_source *ws, unsigned int msec)\n{\n\treturn pm_wakeup_ws_event(ws, msec, false);\n}\n\nstatic inline void pm_wakeup_event(struct device *dev, unsigned int msec)\n{\n\treturn pm_wakeup_dev_event(dev, msec, false);\n}\n\nstatic inline void pm_wakeup_hard_event(struct device *dev)\n{\n\treturn pm_wakeup_dev_event(dev, 0, true);\n}\n\n#endif /* _LINUX_PM_WAKEUP_H */\n"
  },
  {
    "path": "t/tree/include/linux/radix-tree.h",
    "content": "/* SPDX-License-Identifier: GPL-2.0-or-later */\n/*\n * Copyright (C) 2001 Momchil Velikov\n * Portions Copyright (C) 2001 Christoph Hellwig\n * Copyright (C) 2006 Nick Piggin\n * Copyright (C) 2012 Konstantin Khlebnikov\n */\n#ifndef _LINUX_RADIX_TREE_H\n#define _LINUX_RADIX_TREE_H\n\n#include <linux/bitops.h>\n#include <linux/kernel.h>\n#include <linux/list.h>\n#include <linux/preempt.h>\n#include <linux/rcupdate.h>\n#include <linux/spinlock.h>\n#include <linux/types.h>\n#include <linux/xarray.h>\n\n/* Keep unconverted code working */\n#define radix_tree_root\t\txarray\n#define radix_tree_node\t\txa_node\n\n/*\n * The bottom two bits of the slot determine how the remaining bits in the\n * slot are interpreted:\n *\n * 00 - data pointer\n * 10 - internal entry\n * x1 - value entry\n *\n * The internal entry may be a pointer to the next level in the tree, a\n * sibling entry, or an indicator that the entry in this slot has been moved\n * to another location in the tree and the lookup should be restarted.  While\n * NULL fits the 'data pointer' pattern, it means that there is no entry in\n * the tree for this index (no matter what level of the tree it is found at).\n * This means that storing a NULL entry in the tree is the same as deleting\n * the entry from the tree.\n */\n#define RADIX_TREE_ENTRY_MASK\t\t3UL\n#define RADIX_TREE_INTERNAL_NODE\t2UL\n\nstatic inline bool radix_tree_is_internal_node(void *ptr)\n{\n\treturn ((unsigned long)ptr & RADIX_TREE_ENTRY_MASK) ==\n\t\t\t\tRADIX_TREE_INTERNAL_NODE;\n}\n\n/*** radix-tree API starts here ***/\n\n#define RADIX_TREE_MAP_SHIFT\tXA_CHUNK_SHIFT\n#define RADIX_TREE_MAP_SIZE\t(1UL << RADIX_TREE_MAP_SHIFT)\n#define RADIX_TREE_MAP_MASK\t(RADIX_TREE_MAP_SIZE-1)\n\n#define RADIX_TREE_MAX_TAGS\tXA_MAX_MARKS\n#define RADIX_TREE_TAG_LONGS\tXA_MARK_LONGS\n\n#define RADIX_TREE_INDEX_BITS  (8 /* CHAR_BIT */ * sizeof(unsigned long))\n#define RADIX_TREE_MAX_PATH (DIV_ROUND_UP(RADIX_TREE_INDEX_BITS, \\\n\t\t\t\t\t  RADIX_TREE_MAP_SHIFT))\n\n/* The IDR tag is stored in the low bits of xa_flags */\n#define ROOT_IS_IDR\t((__force gfp_t)4)\n/* The top bits of xa_flags are used to store the root tags */\n#define ROOT_TAG_SHIFT\t(__GFP_BITS_SHIFT)\n\n#define RADIX_TREE_INIT(name, mask)\tXARRAY_INIT(name, mask)\n\n#define RADIX_TREE(name, mask) \\\n\tstruct radix_tree_root name = RADIX_TREE_INIT(name, mask)\n\n#define INIT_RADIX_TREE(root, mask) xa_init_flags(root, mask)\n\nstatic inline bool radix_tree_empty(const struct radix_tree_root *root)\n{\n\treturn root->xa_head == NULL;\n}\n\n/**\n * struct radix_tree_iter - radix tree iterator state\n *\n * @index:\tindex of current slot\n * @next_index:\tone beyond the last index for this chunk\n * @tags:\tbit-mask for tag-iterating\n * @node:\tnode that contains current slot\n *\n * This radix tree iterator works in terms of \"chunks\" of slots.  A chunk is a\n * subinterval of slots contained within one radix tree leaf node.  It is\n * described by a pointer to its first slot and a struct radix_tree_iter\n * which holds the chunk's position in the tree and its size.  For tagged\n * iteration radix_tree_iter also holds the slots' bit-mask for one chosen\n * radix tree tag.\n */\nstruct radix_tree_iter {\n\tunsigned long\tindex;\n\tunsigned long\tnext_index;\n\tunsigned long\ttags;\n\tstruct radix_tree_node *node;\n};\n\n/**\n * Radix-tree synchronization\n *\n * The radix-tree API requires that users provide all synchronisation (with\n * specific exceptions, noted below).\n *\n * Synchronization of access to the data items being stored in the tree, and\n * management of their lifetimes must be completely managed by API users.\n *\n * For API usage, in general,\n * - any function _modifying_ the tree or tags (inserting or deleting\n *   items, setting or clearing tags) must exclude other modifications, and\n *   exclude any functions reading the tree.\n * - any function _reading_ the tree or tags (looking up items or tags,\n *   gang lookups) must exclude modifications to the tree, but may occur\n *   concurrently with other readers.\n *\n * The notable exceptions to this rule are the following functions:\n * __radix_tree_lookup\n * radix_tree_lookup\n * radix_tree_lookup_slot\n * radix_tree_tag_get\n * radix_tree_gang_lookup\n * radix_tree_gang_lookup_tag\n * radix_tree_gang_lookup_tag_slot\n * radix_tree_tagged\n *\n * The first 7 functions are able to be called locklessly, using RCU. The\n * caller must ensure calls to these functions are made within rcu_read_lock()\n * regions. Other readers (lock-free or otherwise) and modifications may be\n * running concurrently.\n *\n * It is still required that the caller manage the synchronization and lifetimes\n * of the items. So if RCU lock-free lookups are used, typically this would mean\n * that the items have their own locks, or are amenable to lock-free access; and\n * that the items are freed by RCU (or only freed after having been deleted from\n * the radix tree *and* a synchronize_rcu() grace period).\n *\n * (Note, rcu_assign_pointer and rcu_dereference are not needed to control\n * access to data items when inserting into or looking up from the radix tree)\n *\n * Note that the value returned by radix_tree_tag_get() may not be relied upon\n * if only the RCU read lock is held.  Functions to set/clear tags and to\n * delete nodes running concurrently with it may affect its result such that\n * two consecutive reads in the same locked section may return different\n * values.  If reliability is required, modification functions must also be\n * excluded from concurrency.\n *\n * radix_tree_tagged is able to be called without locking or RCU.\n */\n\n/**\n * radix_tree_deref_slot - dereference a slot\n * @slot: slot pointer, returned by radix_tree_lookup_slot\n *\n * For use with radix_tree_lookup_slot().  Caller must hold tree at least read\n * locked across slot lookup and dereference. Not required if write lock is\n * held (ie. items cannot be concurrently inserted).\n *\n * radix_tree_deref_retry must be used to confirm validity of the pointer if\n * only the read lock is held.\n *\n * Return: entry stored in that slot.\n */\nstatic inline void *radix_tree_deref_slot(void __rcu **slot)\n{\n\treturn rcu_dereference(*slot);\n}\n\n/**\n * radix_tree_deref_slot_protected - dereference a slot with tree lock held\n * @slot: slot pointer, returned by radix_tree_lookup_slot\n *\n * Similar to radix_tree_deref_slot.  The caller does not hold the RCU read\n * lock but it must hold the tree lock to prevent parallel updates.\n *\n * Return: entry stored in that slot.\n */\nstatic inline void *radix_tree_deref_slot_protected(void __rcu **slot,\n\t\t\t\t\t\t\tspinlock_t *treelock)\n{\n\treturn rcu_dereference_protected(*slot, lockdep_is_held(treelock));\n}\n\n/**\n * radix_tree_deref_retry\t- check radix_tree_deref_slot\n * @arg:\tpointer returned by radix_tree_deref_slot\n * Returns:\t0 if retry is not required, otherwise retry is required\n *\n * radix_tree_deref_retry must be used with radix_tree_deref_slot.\n */\nstatic inline int radix_tree_deref_retry(void *arg)\n{\n\treturn unlikely(radix_tree_is_internal_node(arg));\n}\n\n/**\n * radix_tree_exception\t- radix_tree_deref_slot returned either exception?\n * @arg:\tvalue returned by radix_tree_deref_slot\n * Returns:\t0 if well-aligned pointer, non-0 if either kind of exception.\n */\nstatic inline int radix_tree_exception(void *arg)\n{\n\treturn unlikely((unsigned long)arg & RADIX_TREE_ENTRY_MASK);\n}\n\nint radix_tree_insert(struct radix_tree_root *, unsigned long index,\n\t\t\tvoid *);\nvoid *__radix_tree_lookup(const struct radix_tree_root *, unsigned long index,\n\t\t\t  struct radix_tree_node **nodep, void __rcu ***slotp);\nvoid *radix_tree_lookup(const struct radix_tree_root *, unsigned long);\nvoid __rcu **radix_tree_lookup_slot(const struct radix_tree_root *,\n\t\t\t\t\tunsigned long index);\nvoid __radix_tree_replace(struct radix_tree_root *, struct radix_tree_node *,\n\t\t\t  void __rcu **slot, void *entry);\nvoid radix_tree_iter_replace(struct radix_tree_root *,\n\t\tconst struct radix_tree_iter *, void __rcu **slot, void *entry);\nvoid radix_tree_replace_slot(struct radix_tree_root *,\n\t\t\t     void __rcu **slot, void *entry);\nvoid radix_tree_iter_delete(struct radix_tree_root *,\n\t\t\tstruct radix_tree_iter *iter, void __rcu **slot);\nvoid *radix_tree_delete_item(struct radix_tree_root *, unsigned long, void *);\nvoid *radix_tree_delete(struct radix_tree_root *, unsigned long);\nunsigned int radix_tree_gang_lookup(const struct radix_tree_root *,\n\t\t\tvoid **results, unsigned long first_index,\n\t\t\tunsigned int max_items);\nint radix_tree_preload(gfp_t gfp_mask);\nint radix_tree_maybe_preload(gfp_t gfp_mask);\nvoid radix_tree_init(void);\nvoid *radix_tree_tag_set(struct radix_tree_root *,\n\t\t\tunsigned long index, unsigned int tag);\nvoid *radix_tree_tag_clear(struct radix_tree_root *,\n\t\t\tunsigned long index, unsigned int tag);\nint radix_tree_tag_get(const struct radix_tree_root *,\n\t\t\tunsigned long index, unsigned int tag);\nvoid radix_tree_iter_tag_clear(struct radix_tree_root *,\n\t\tconst struct radix_tree_iter *iter, unsigned int tag);\nunsigned int radix_tree_gang_lookup_tag(const struct radix_tree_root *,\n\t\tvoid **results, unsigned long first_index,\n\t\tunsigned int max_items, unsigned int tag);\nunsigned int radix_tree_gang_lookup_tag_slot(const struct radix_tree_root *,\n\t\tvoid __rcu ***results, unsigned long first_index,\n\t\tunsigned int max_items, unsigned int tag);\nint radix_tree_tagged(const struct radix_tree_root *, unsigned int tag);\n\nstatic inline void radix_tree_preload_end(void)\n{\n\tpreempt_enable();\n}\n\nvoid __rcu **idr_get_free(struct radix_tree_root *root,\n\t\t\t      struct radix_tree_iter *iter, gfp_t gfp,\n\t\t\t      unsigned long max);\n\nenum {\n\tRADIX_TREE_ITER_TAG_MASK = 0x0f,\t/* tag index in lower nybble */\n\tRADIX_TREE_ITER_TAGGED   = 0x10,\t/* lookup tagged slots */\n\tRADIX_TREE_ITER_CONTIG   = 0x20,\t/* stop at first hole */\n};\n\n/**\n * radix_tree_iter_init - initialize radix tree iterator\n *\n * @iter:\tpointer to iterator state\n * @start:\titeration starting index\n * Returns:\tNULL\n */\nstatic __always_inline void __rcu **\nradix_tree_iter_init(struct radix_tree_iter *iter, unsigned long start)\n{\n\t/*\n\t * Leave iter->tags uninitialized. radix_tree_next_chunk() will fill it\n\t * in the case of a successful tagged chunk lookup.  If the lookup was\n\t * unsuccessful or non-tagged then nobody cares about ->tags.\n\t *\n\t * Set index to zero to bypass next_index overflow protection.\n\t * See the comment in radix_tree_next_chunk() for details.\n\t */\n\titer->index = 0;\n\titer->next_index = start;\n\treturn NULL;\n}\n\n/**\n * radix_tree_next_chunk - find next chunk of slots for iteration\n *\n * @root:\tradix tree root\n * @iter:\titerator state\n * @flags:\tRADIX_TREE_ITER_* flags and tag index\n * Returns:\tpointer to chunk first slot, or NULL if there no more left\n *\n * This function looks up the next chunk in the radix tree starting from\n * @iter->next_index.  It returns a pointer to the chunk's first slot.\n * Also it fills @iter with data about chunk: position in the tree (index),\n * its end (next_index), and constructs a bit mask for tagged iterating (tags).\n */\nvoid __rcu **radix_tree_next_chunk(const struct radix_tree_root *,\n\t\t\t     struct radix_tree_iter *iter, unsigned flags);\n\n/**\n * radix_tree_iter_lookup - look up an index in the radix tree\n * @root: radix tree root\n * @iter: iterator state\n * @index: key to look up\n *\n * If @index is present in the radix tree, this function returns the slot\n * containing it and updates @iter to describe the entry.  If @index is not\n * present, it returns NULL.\n */\nstatic inline void __rcu **\nradix_tree_iter_lookup(const struct radix_tree_root *root,\n\t\t\tstruct radix_tree_iter *iter, unsigned long index)\n{\n\tradix_tree_iter_init(iter, index);\n\treturn radix_tree_next_chunk(root, iter, RADIX_TREE_ITER_CONTIG);\n}\n\n/**\n * radix_tree_iter_retry - retry this chunk of the iteration\n * @iter:\titerator state\n *\n * If we iterate over a tree protected only by the RCU lock, a race\n * against deletion or creation may result in seeing a slot for which\n * radix_tree_deref_retry() returns true.  If so, call this function\n * and continue the iteration.\n */\nstatic inline __must_check\nvoid __rcu **radix_tree_iter_retry(struct radix_tree_iter *iter)\n{\n\titer->next_index = iter->index;\n\titer->tags = 0;\n\treturn NULL;\n}\n\nstatic inline unsigned long\n__radix_tree_iter_add(struct radix_tree_iter *iter, unsigned long slots)\n{\n\treturn iter->index + slots;\n}\n\n/**\n * radix_tree_iter_resume - resume iterating when the chunk may be invalid\n * @slot: pointer to current slot\n * @iter: iterator state\n * Returns: New slot pointer\n *\n * If the iterator needs to release then reacquire a lock, the chunk may\n * have been invalidated by an insertion or deletion.  Call this function\n * before releasing the lock to continue the iteration from the next index.\n */\nvoid __rcu **__must_check radix_tree_iter_resume(void __rcu **slot,\n\t\t\t\t\tstruct radix_tree_iter *iter);\n\n/**\n * radix_tree_chunk_size - get current chunk size\n *\n * @iter:\tpointer to radix tree iterator\n * Returns:\tcurrent chunk size\n */\nstatic __always_inline long\nradix_tree_chunk_size(struct radix_tree_iter *iter)\n{\n\treturn iter->next_index - iter->index;\n}\n\n/**\n * radix_tree_next_slot - find next slot in chunk\n *\n * @slot:\tpointer to current slot\n * @iter:\tpointer to interator state\n * @flags:\tRADIX_TREE_ITER_*, should be constant\n * Returns:\tpointer to next slot, or NULL if there no more left\n *\n * This function updates @iter->index in the case of a successful lookup.\n * For tagged lookup it also eats @iter->tags.\n *\n * There are several cases where 'slot' can be passed in as NULL to this\n * function.  These cases result from the use of radix_tree_iter_resume() or\n * radix_tree_iter_retry().  In these cases we don't end up dereferencing\n * 'slot' because either:\n * a) we are doing tagged iteration and iter->tags has been set to 0, or\n * b) we are doing non-tagged iteration, and iter->index and iter->next_index\n *    have been set up so that radix_tree_chunk_size() returns 1 or 0.\n */\nstatic __always_inline void __rcu **radix_tree_next_slot(void __rcu **slot,\n\t\t\t\tstruct radix_tree_iter *iter, unsigned flags)\n{\n\tif (flags & RADIX_TREE_ITER_TAGGED) {\n\t\titer->tags >>= 1;\n\t\tif (unlikely(!iter->tags))\n\t\t\treturn NULL;\n\t\tif (likely(iter->tags & 1ul)) {\n\t\t\titer->index = __radix_tree_iter_add(iter, 1);\n\t\t\tslot++;\n\t\t\tgoto found;\n\t\t}\n\t\tif (!(flags & RADIX_TREE_ITER_CONTIG)) {\n\t\t\tunsigned offset = __ffs(iter->tags);\n\n\t\t\titer->tags >>= offset++;\n\t\t\titer->index = __radix_tree_iter_add(iter, offset);\n\t\t\tslot += offset;\n\t\t\tgoto found;\n\t\t}\n\t} else {\n\t\tlong count = radix_tree_chunk_size(iter);\n\n\t\twhile (--count > 0) {\n\t\t\tslot++;\n\t\t\titer->index = __radix_tree_iter_add(iter, 1);\n\n\t\t\tif (likely(*slot))\n\t\t\t\tgoto found;\n\t\t\tif (flags & RADIX_TREE_ITER_CONTIG) {\n\t\t\t\t/* forbid switching to the next chunk */\n\t\t\t\titer->next_index = 0;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\treturn NULL;\n\n found:\n\treturn slot;\n}\n\n/**\n * radix_tree_for_each_slot - iterate over non-empty slots\n *\n * @slot:\tthe void** variable for pointer to slot\n * @root:\tthe struct radix_tree_root pointer\n * @iter:\tthe struct radix_tree_iter pointer\n * @start:\titeration starting index\n *\n * @slot points to radix tree slot, @iter->index contains its index.\n */\n#define radix_tree_for_each_slot(slot, root, iter, start)\t\t\\\n\tfor (slot = radix_tree_iter_init(iter, start) ;\t\t\t\\\n\t     slot || (slot = radix_tree_next_chunk(root, iter, 0)) ;\t\\\n\t     slot = radix_tree_next_slot(slot, iter, 0))\n\n/**\n * radix_tree_for_each_tagged - iterate over tagged slots\n *\n * @slot:\tthe void** variable for pointer to slot\n * @root:\tthe struct radix_tree_root pointer\n * @iter:\tthe struct radix_tree_iter pointer\n * @start:\titeration starting index\n * @tag:\ttag index\n *\n * @slot points to radix tree slot, @iter->index contains its index.\n */\n#define radix_tree_for_each_tagged(slot, root, iter, start, tag)\t\\\n\tfor (slot = radix_tree_iter_init(iter, start) ;\t\t\t\\\n\t     slot || (slot = radix_tree_next_chunk(root, iter,\t\t\\\n\t\t\t      RADIX_TREE_ITER_TAGGED | tag)) ;\t\t\\\n\t     slot = radix_tree_next_slot(slot, iter,\t\t\t\\\n\t\t\t\tRADIX_TREE_ITER_TAGGED | tag))\n\n#endif /* _LINUX_RADIX_TREE_H */\n"
  },
  {
    "path": "t/tree/include/linux/rbtree.h",
    "content": "/* SPDX-License-Identifier: GPL-2.0-or-later */\n/*\n  Red Black Trees\n  (C) 1999  Andrea Arcangeli <andrea@suse.de>\n  \n\n  linux/include/linux/rbtree.h\n\n  To use rbtrees you'll have to implement your own insert and search cores.\n  This will avoid us to use callbacks and to drop drammatically performances.\n  I know it's not the cleaner way,  but in C (not in C++) to get\n  performances and genericity...\n\n  See Documentation/rbtree.txt for documentation and samples.\n*/\n\n#ifndef\t_LINUX_RBTREE_H\n#define\t_LINUX_RBTREE_H\n\n#include <linux/kernel.h>\n#include <linux/stddef.h>\n#include <linux/rcupdate.h>\n\nstruct rb_node {\n\tunsigned long  __rb_parent_color;\n\tstruct rb_node *rb_right;\n\tstruct rb_node *rb_left;\n} __attribute__((aligned(sizeof(long))));\n    /* The alignment might seem pointless, but allegedly CRIS needs it */\n\nstruct rb_root {\n\tstruct rb_node *rb_node;\n};\n\n#define rb_parent(r)   ((struct rb_node *)((r)->__rb_parent_color & ~3))\n\n#define RB_ROOT\t(struct rb_root) { NULL, }\n#define\trb_entry(ptr, type, member) container_of(ptr, type, member)\n\n#define RB_EMPTY_ROOT(root)  (READ_ONCE((root)->rb_node) == NULL)\n\n/* 'empty' nodes are nodes that are known not to be inserted in an rbtree */\n#define RB_EMPTY_NODE(node)  \\\n\t((node)->__rb_parent_color == (unsigned long)(node))\n#define RB_CLEAR_NODE(node)  \\\n\t((node)->__rb_parent_color = (unsigned long)(node))\n\n\nextern void rb_insert_color(struct rb_node *, struct rb_root *);\nextern void rb_erase(struct rb_node *, struct rb_root *);\n\n\n/* Find logical next and previous nodes in a tree */\nextern struct rb_node *rb_next(const struct rb_node *);\nextern struct rb_node *rb_prev(const struct rb_node *);\nextern struct rb_node *rb_first(const struct rb_root *);\nextern struct rb_node *rb_last(const struct rb_root *);\n\n/* Postorder iteration - always visit the parent after its children */\nextern struct rb_node *rb_first_postorder(const struct rb_root *);\nextern struct rb_node *rb_next_postorder(const struct rb_node *);\n\n/* Fast replacement of a single node without remove/rebalance/add/rebalance */\nextern void rb_replace_node(struct rb_node *victim, struct rb_node *new,\n\t\t\t    struct rb_root *root);\nextern void rb_replace_node_rcu(struct rb_node *victim, struct rb_node *new,\n\t\t\t\tstruct rb_root *root);\n\nstatic inline void rb_link_node(struct rb_node *node, struct rb_node *parent,\n\t\t\t\tstruct rb_node **rb_link)\n{\n\tnode->__rb_parent_color = (unsigned long)parent;\n\tnode->rb_left = node->rb_right = NULL;\n\n\t*rb_link = node;\n}\n\nstatic inline void rb_link_node_rcu(struct rb_node *node, struct rb_node *parent,\n\t\t\t\t    struct rb_node **rb_link)\n{\n\tnode->__rb_parent_color = (unsigned long)parent;\n\tnode->rb_left = node->rb_right = NULL;\n\n\trcu_assign_pointer(*rb_link, node);\n}\n\n#define rb_entry_safe(ptr, type, member) \\\n\t({ typeof(ptr) ____ptr = (ptr); \\\n\t   ____ptr ? rb_entry(____ptr, type, member) : NULL; \\\n\t})\n\n/**\n * rbtree_postorder_for_each_entry_safe - iterate in post-order over rb_root of\n * given type allowing the backing memory of @pos to be invalidated\n *\n * @pos:\tthe 'type *' to use as a loop cursor.\n * @n:\t\tanother 'type *' to use as temporary storage\n * @root:\t'rb_root *' of the rbtree.\n * @field:\tthe name of the rb_node field within 'type'.\n *\n * rbtree_postorder_for_each_entry_safe() provides a similar guarantee as\n * list_for_each_entry_safe() and allows the iteration to continue independent\n * of changes to @pos by the body of the loop.\n *\n * Note, however, that it cannot handle other modifications that re-order the\n * rbtree it is iterating over. This includes calling rb_erase() on @pos, as\n * rb_erase() may rebalance the tree, causing us to miss some nodes.\n */\n#define rbtree_postorder_for_each_entry_safe(pos, n, root, field) \\\n\tfor (pos = rb_entry_safe(rb_first_postorder(root), typeof(*pos), field); \\\n\t     pos && ({ n = rb_entry_safe(rb_next_postorder(&pos->field), \\\n\t\t\ttypeof(*pos), field); 1; }); \\\n\t     pos = n)\n\n/*\n * Leftmost-cached rbtrees.\n *\n * We do not cache the rightmost node based on footprint\n * size vs number of potential users that could benefit\n * from O(1) rb_last(). Just not worth it, users that want\n * this feature can always implement the logic explicitly.\n * Furthermore, users that want to cache both pointers may\n * find it a bit asymmetric, but that's ok.\n */\nstruct rb_root_cached {\n\tstruct rb_root rb_root;\n\tstruct rb_node *rb_leftmost;\n};\n\n#define RB_ROOT_CACHED (struct rb_root_cached) { {NULL, }, NULL }\n\n/* Same as rb_first(), but O(1) */\n#define rb_first_cached(root) (root)->rb_leftmost\n\nstatic inline void rb_insert_color_cached(struct rb_node *node,\n\t\t\t\t\t  struct rb_root_cached *root,\n\t\t\t\t\t  bool leftmost)\n{\n\tif (leftmost)\n\t\troot->rb_leftmost = node;\n\trb_insert_color(node, &root->rb_root);\n}\n\nstatic inline void rb_erase_cached(struct rb_node *node,\n\t\t\t\t   struct rb_root_cached *root)\n{\n\tif (root->rb_leftmost == node)\n\t\troot->rb_leftmost = rb_next(node);\n\trb_erase(node, &root->rb_root);\n}\n\nstatic inline void rb_replace_node_cached(struct rb_node *victim,\n\t\t\t\t\t  struct rb_node *new,\n\t\t\t\t\t  struct rb_root_cached *root)\n{\n\tif (root->rb_leftmost == victim)\n\t\troot->rb_leftmost = new;\n\trb_replace_node(victim, new, &root->rb_root);\n}\n\n#endif\t/* _LINUX_RBTREE_H */\n"
  },
  {
    "path": "t/tree/include/linux/rcu_node_tree.h",
    "content": "/* SPDX-License-Identifier: GPL-2.0+ */\n/*\n * RCU node combining tree definitions.  These are used to compute\n * global attributes while avoiding common-case global contention.  A key\n * property that these computations rely on is a tournament-style approach\n * where only one of the tasks contending a lower level in the tree need\n * advance to the next higher level.  If properly configured, this allows\n * unlimited scalability while maintaining a constant level of contention\n * on the root node.\n *\n * This seemingly RCU-private file must be available to SRCU users\n * because the size of the TREE SRCU srcu_struct structure depends\n * on these definitions.\n *\n * Copyright IBM Corporation, 2017\n *\n * Author: Paul E. McKenney <paulmck@linux.ibm.com>\n */\n\n#ifndef __LINUX_RCU_NODE_TREE_H\n#define __LINUX_RCU_NODE_TREE_H\n\n/*\n * Define shape of hierarchy based on NR_CPUS, CONFIG_RCU_FANOUT, and\n * CONFIG_RCU_FANOUT_LEAF.\n * In theory, it should be possible to add more levels straightforwardly.\n * In practice, this did work well going from three levels to four.\n * Of course, your mileage may vary.\n */\n\n#ifdef CONFIG_RCU_FANOUT\n#define RCU_FANOUT CONFIG_RCU_FANOUT\n#else /* #ifdef CONFIG_RCU_FANOUT */\n# ifdef CONFIG_64BIT\n# define RCU_FANOUT 64\n# else\n# define RCU_FANOUT 32\n# endif\n#endif /* #else #ifdef CONFIG_RCU_FANOUT */\n\n#ifdef CONFIG_RCU_FANOUT_LEAF\n#define RCU_FANOUT_LEAF CONFIG_RCU_FANOUT_LEAF\n#else /* #ifdef CONFIG_RCU_FANOUT_LEAF */\n#define RCU_FANOUT_LEAF 16\n#endif /* #else #ifdef CONFIG_RCU_FANOUT_LEAF */\n\n#define RCU_FANOUT_1\t      (RCU_FANOUT_LEAF)\n#define RCU_FANOUT_2\t      (RCU_FANOUT_1 * RCU_FANOUT)\n#define RCU_FANOUT_3\t      (RCU_FANOUT_2 * RCU_FANOUT)\n#define RCU_FANOUT_4\t      (RCU_FANOUT_3 * RCU_FANOUT)\n\n#if NR_CPUS <= RCU_FANOUT_1\n#  define RCU_NUM_LVLS\t      1\n#  define NUM_RCU_LVL_0\t      1\n#  define NUM_RCU_NODES\t      NUM_RCU_LVL_0\n#  define NUM_RCU_LVL_INIT    { NUM_RCU_LVL_0 }\n#  define RCU_NODE_NAME_INIT  { \"rcu_node_0\" }\n#  define RCU_FQS_NAME_INIT   { \"rcu_node_fqs_0\" }\n#elif NR_CPUS <= RCU_FANOUT_2\n#  define RCU_NUM_LVLS\t      2\n#  define NUM_RCU_LVL_0\t      1\n#  define NUM_RCU_LVL_1\t      DIV_ROUND_UP(NR_CPUS, RCU_FANOUT_1)\n#  define NUM_RCU_NODES\t      (NUM_RCU_LVL_0 + NUM_RCU_LVL_1)\n#  define NUM_RCU_LVL_INIT    { NUM_RCU_LVL_0, NUM_RCU_LVL_1 }\n#  define RCU_NODE_NAME_INIT  { \"rcu_node_0\", \"rcu_node_1\" }\n#  define RCU_FQS_NAME_INIT   { \"rcu_node_fqs_0\", \"rcu_node_fqs_1\" }\n#elif NR_CPUS <= RCU_FANOUT_3\n#  define RCU_NUM_LVLS\t      3\n#  define NUM_RCU_LVL_0\t      1\n#  define NUM_RCU_LVL_1\t      DIV_ROUND_UP(NR_CPUS, RCU_FANOUT_2)\n#  define NUM_RCU_LVL_2\t      DIV_ROUND_UP(NR_CPUS, RCU_FANOUT_1)\n#  define NUM_RCU_NODES\t      (NUM_RCU_LVL_0 + NUM_RCU_LVL_1 + NUM_RCU_LVL_2)\n#  define NUM_RCU_LVL_INIT    { NUM_RCU_LVL_0, NUM_RCU_LVL_1, NUM_RCU_LVL_2 }\n#  define RCU_NODE_NAME_INIT  { \"rcu_node_0\", \"rcu_node_1\", \"rcu_node_2\" }\n#  define RCU_FQS_NAME_INIT   { \"rcu_node_fqs_0\", \"rcu_node_fqs_1\", \"rcu_node_fqs_2\" }\n#elif NR_CPUS <= RCU_FANOUT_4\n#  define RCU_NUM_LVLS\t      4\n#  define NUM_RCU_LVL_0\t      1\n#  define NUM_RCU_LVL_1\t      DIV_ROUND_UP(NR_CPUS, RCU_FANOUT_3)\n#  define NUM_RCU_LVL_2\t      DIV_ROUND_UP(NR_CPUS, RCU_FANOUT_2)\n#  define NUM_RCU_LVL_3\t      DIV_ROUND_UP(NR_CPUS, RCU_FANOUT_1)\n#  define NUM_RCU_NODES\t      (NUM_RCU_LVL_0 + NUM_RCU_LVL_1 + NUM_RCU_LVL_2 + NUM_RCU_LVL_3)\n#  define NUM_RCU_LVL_INIT    { NUM_RCU_LVL_0, NUM_RCU_LVL_1, NUM_RCU_LVL_2, NUM_RCU_LVL_3 }\n#  define RCU_NODE_NAME_INIT  { \"rcu_node_0\", \"rcu_node_1\", \"rcu_node_2\", \"rcu_node_3\" }\n#  define RCU_FQS_NAME_INIT   { \"rcu_node_fqs_0\", \"rcu_node_fqs_1\", \"rcu_node_fqs_2\", \"rcu_node_fqs_3\" }\n#else\n# error \"CONFIG_RCU_FANOUT insufficient for NR_CPUS\"\n#endif /* #if (NR_CPUS) <= RCU_FANOUT_1 */\n\n#endif /* __LINUX_RCU_NODE_TREE_H */\n"
  },
  {
    "path": "t/tree/include/linux/rcu_segcblist.h",
    "content": "/* SPDX-License-Identifier: GPL-2.0+ */\n/*\n * RCU segmented callback lists\n *\n * This seemingly RCU-private file must be available to SRCU users\n * because the size of the TREE SRCU srcu_struct structure depends\n * on these definitions.\n *\n * Copyright IBM Corporation, 2017\n *\n * Authors: Paul E. McKenney <paulmck@linux.net.ibm.com>\n */\n\n#ifndef __INCLUDE_LINUX_RCU_SEGCBLIST_H\n#define __INCLUDE_LINUX_RCU_SEGCBLIST_H\n\n#include <linux/types.h>\n#include <linux/atomic.h>\n\n/* Simple unsegmented callback lists. */\nstruct rcu_cblist {\n\tstruct rcu_head *head;\n\tstruct rcu_head **tail;\n\tlong len;\n\tlong len_lazy;\n};\n\n#define RCU_CBLIST_INITIALIZER(n) { .head = NULL, .tail = &n.head }\n\n/* Complicated segmented callback lists.  ;-) */\n\n/*\n * Index values for segments in rcu_segcblist structure.\n *\n * The segments are as follows:\n *\n * [head, *tails[RCU_DONE_TAIL]):\n *\tCallbacks whose grace period has elapsed, and thus can be invoked.\n * [*tails[RCU_DONE_TAIL], *tails[RCU_WAIT_TAIL]):\n *\tCallbacks waiting for the current GP from the current CPU's viewpoint.\n * [*tails[RCU_WAIT_TAIL], *tails[RCU_NEXT_READY_TAIL]):\n *\tCallbacks that arrived before the next GP started, again from\n *\tthe current CPU's viewpoint.  These can be handled by the next GP.\n * [*tails[RCU_NEXT_READY_TAIL], *tails[RCU_NEXT_TAIL]):\n *\tCallbacks that might have arrived after the next GP started.\n *\tThere is some uncertainty as to when a given GP starts and\n *\tends, but a CPU knows the exact times if it is the one starting\n *\tor ending the GP.  Other CPUs know that the previous GP ends\n *\tbefore the next one starts.\n *\n * Note that RCU_WAIT_TAIL cannot be empty unless RCU_NEXT_READY_TAIL is also\n * empty.\n *\n * The ->gp_seq[] array contains the grace-period number at which the\n * corresponding segment of callbacks will be ready to invoke.  A given\n * element of this array is meaningful only when the corresponding segment\n * is non-empty, and it is never valid for RCU_DONE_TAIL (whose callbacks\n * are already ready to invoke) or for RCU_NEXT_TAIL (whose callbacks have\n * not yet been assigned a grace-period number).\n */\n#define RCU_DONE_TAIL\t\t0\t/* Also RCU_WAIT head. */\n#define RCU_WAIT_TAIL\t\t1\t/* Also RCU_NEXT_READY head. */\n#define RCU_NEXT_READY_TAIL\t2\t/* Also RCU_NEXT head. */\n#define RCU_NEXT_TAIL\t\t3\n#define RCU_CBLIST_NSEGS\t4\n\nstruct rcu_segcblist {\n\tstruct rcu_head *head;\n\tstruct rcu_head **tails[RCU_CBLIST_NSEGS];\n\tunsigned long gp_seq[RCU_CBLIST_NSEGS];\n#ifdef CONFIG_RCU_NOCB_CPU\n\tatomic_long_t len;\n#else\n\tlong len;\n#endif\n\tlong len_lazy;\n\tu8 enabled;\n\tu8 offloaded;\n};\n\n#define RCU_SEGCBLIST_INITIALIZER(n) \\\n{ \\\n\t.head = NULL, \\\n\t.tails[RCU_DONE_TAIL] = &n.head, \\\n\t.tails[RCU_WAIT_TAIL] = &n.head, \\\n\t.tails[RCU_NEXT_READY_TAIL] = &n.head, \\\n\t.tails[RCU_NEXT_TAIL] = &n.head, \\\n}\n\n#endif /* __INCLUDE_LINUX_RCU_SEGCBLIST_H */\n"
  },
  {
    "path": "t/tree/include/linux/rcu_sync.h",
    "content": "/* SPDX-License-Identifier: GPL-2.0+ */\n/*\n * RCU-based infrastructure for lightweight reader-writer locking\n *\n * Copyright (c) 2015, Red Hat, Inc.\n *\n * Author: Oleg Nesterov <oleg@redhat.com>\n */\n\n#ifndef _LINUX_RCU_SYNC_H_\n#define _LINUX_RCU_SYNC_H_\n\n#include <linux/wait.h>\n#include <linux/rcupdate.h>\n\n/* Structure to mediate between updaters and fastpath-using readers.  */\nstruct rcu_sync {\n\tint\t\t\tgp_state;\n\tint\t\t\tgp_count;\n\twait_queue_head_t\tgp_wait;\n\n\tstruct rcu_head\t\tcb_head;\n};\n\n/**\n * rcu_sync_is_idle() - Are readers permitted to use their fastpaths?\n * @rsp: Pointer to rcu_sync structure to use for synchronization\n *\n * Returns true if readers are permitted to use their fastpaths.  Must be\n * invoked within some flavor of RCU read-side critical section.\n */\nstatic inline bool rcu_sync_is_idle(struct rcu_sync *rsp)\n{\n\tRCU_LOCKDEP_WARN(!rcu_read_lock_any_held(),\n\t\t\t \"suspicious rcu_sync_is_idle() usage\");\n\treturn !READ_ONCE(rsp->gp_state); /* GP_IDLE */\n}\n\nextern void rcu_sync_init(struct rcu_sync *);\nextern void rcu_sync_enter_start(struct rcu_sync *);\nextern void rcu_sync_enter(struct rcu_sync *);\nextern void rcu_sync_exit(struct rcu_sync *);\nextern void rcu_sync_dtor(struct rcu_sync *);\n\n#define __RCU_SYNC_INITIALIZER(name) {\t\t\t\t\t\\\n\t\t.gp_state = 0,\t\t\t\t\t\t\\\n\t\t.gp_count = 0,\t\t\t\t\t\t\\\n\t\t.gp_wait = __WAIT_QUEUE_HEAD_INITIALIZER(name.gp_wait),\t\\\n\t}\n\n#define\tDEFINE_RCU_SYNC(name)\t\\\n\tstruct rcu_sync name = __RCU_SYNC_INITIALIZER(name)\n\n#endif /* _LINUX_RCU_SYNC_H_ */\n"
  },
  {
    "path": "t/tree/include/linux/rcupdate.h",
    "content": "/* SPDX-License-Identifier: GPL-2.0+ */\n/*\n * Read-Copy Update mechanism for mutual exclusion\n *\n * Copyright IBM Corporation, 2001\n *\n * Author: Dipankar Sarma <dipankar@in.ibm.com>\n *\n * Based on the original work by Paul McKenney <paulmck@vnet.ibm.com>\n * and inputs from Rusty Russell, Andrea Arcangeli and Andi Kleen.\n * Papers:\n * http://www.rdrop.com/users/paulmck/paper/rclockpdcsproof.pdf\n * http://lse.sourceforge.net/locking/rclock_OLS.2001.05.01c.sc.pdf (OLS2001)\n *\n * For detailed explanation of Read-Copy Update mechanism see -\n *\t\thttp://lse.sourceforge.net/locking/rcupdate.html\n *\n */\n\n#ifndef __LINUX_RCUPDATE_H\n#define __LINUX_RCUPDATE_H\n\n#include <linux/types.h>\n#include <linux/compiler.h>\n#include <linux/atomic.h>\n#include <linux/irqflags.h>\n#include <linux/preempt.h>\n#include <linux/bottom_half.h>\n#include <linux/lockdep.h>\n#include <asm/processor.h>\n#include <linux/cpumask.h>\n\n#define ULONG_CMP_GE(a, b)\t(ULONG_MAX / 2 >= (a) - (b))\n#define ULONG_CMP_LT(a, b)\t(ULONG_MAX / 2 < (a) - (b))\n#define ulong2long(a)\t\t(*(long *)(&(a)))\n\n/* Exported common interfaces */\nvoid call_rcu(struct rcu_head *head, rcu_callback_t func);\nvoid rcu_barrier_tasks(void);\nvoid synchronize_rcu(void);\n\n#ifdef CONFIG_PREEMPT_RCU\n\nvoid __rcu_read_lock(void);\nvoid __rcu_read_unlock(void);\n\n/*\n * Defined as a macro as it is a very low level header included from\n * areas that don't even know about current.  This gives the rcu_read_lock()\n * nesting depth, but makes sense only if CONFIG_PREEMPT_RCU -- in other\n * types of kernel builds, the rcu_read_lock() nesting depth is unknowable.\n */\n#define rcu_preempt_depth() (current->rcu_read_lock_nesting)\n\n#else /* #ifdef CONFIG_PREEMPT_RCU */\n\nstatic inline void __rcu_read_lock(void)\n{\n\tpreempt_disable();\n}\n\nstatic inline void __rcu_read_unlock(void)\n{\n\tpreempt_enable();\n}\n\nstatic inline int rcu_preempt_depth(void)\n{\n\treturn 0;\n}\n\n#endif /* #else #ifdef CONFIG_PREEMPT_RCU */\n\n/* Internal to kernel */\nvoid rcu_init(void);\nextern int rcu_scheduler_active __read_mostly;\nvoid rcu_sched_clock_irq(int user);\nvoid rcu_report_dead(unsigned int cpu);\nvoid rcutree_migrate_callbacks(int cpu);\n\n#ifdef CONFIG_RCU_STALL_COMMON\nvoid rcu_sysrq_start(void);\nvoid rcu_sysrq_end(void);\n#else /* #ifdef CONFIG_RCU_STALL_COMMON */\nstatic inline void rcu_sysrq_start(void) { }\nstatic inline void rcu_sysrq_end(void) { }\n#endif /* #else #ifdef CONFIG_RCU_STALL_COMMON */\n\n#ifdef CONFIG_NO_HZ_FULL\nvoid rcu_user_enter(void);\nvoid rcu_user_exit(void);\n#else\nstatic inline void rcu_user_enter(void) { }\nstatic inline void rcu_user_exit(void) { }\n#endif /* CONFIG_NO_HZ_FULL */\n\n#ifdef CONFIG_RCU_NOCB_CPU\nvoid rcu_init_nohz(void);\n#else /* #ifdef CONFIG_RCU_NOCB_CPU */\nstatic inline void rcu_init_nohz(void) { }\n#endif /* #else #ifdef CONFIG_RCU_NOCB_CPU */\n\n/**\n * RCU_NONIDLE - Indicate idle-loop code that needs RCU readers\n * @a: Code that RCU needs to pay attention to.\n *\n * RCU read-side critical sections are forbidden in the inner idle loop,\n * that is, between the rcu_idle_enter() and the rcu_idle_exit() -- RCU\n * will happily ignore any such read-side critical sections.  However,\n * things like powertop need tracepoints in the inner idle loop.\n *\n * This macro provides the way out:  RCU_NONIDLE(do_something_with_RCU())\n * will tell RCU that it needs to pay attention, invoke its argument\n * (in this example, calling the do_something_with_RCU() function),\n * and then tell RCU to go back to ignoring this CPU.  It is permissible\n * to nest RCU_NONIDLE() wrappers, but not indefinitely (but the limit is\n * on the order of a million or so, even on 32-bit systems).  It is\n * not legal to block within RCU_NONIDLE(), nor is it permissible to\n * transfer control either into or out of RCU_NONIDLE()'s statement.\n */\n#define RCU_NONIDLE(a) \\\n\tdo { \\\n\t\trcu_irq_enter_irqson(); \\\n\t\tdo { a; } while (0); \\\n\t\trcu_irq_exit_irqson(); \\\n\t} while (0)\n\n/*\n * Note a quasi-voluntary context switch for RCU-tasks's benefit.\n * This is a macro rather than an inline function to avoid #include hell.\n */\n#ifdef CONFIG_TASKS_RCU\n#define rcu_tasks_qs(t) \\\n\tdo { \\\n\t\tif (READ_ONCE((t)->rcu_tasks_holdout)) \\\n\t\t\tWRITE_ONCE((t)->rcu_tasks_holdout, false); \\\n\t} while (0)\n#define rcu_note_voluntary_context_switch(t) rcu_tasks_qs(t)\nvoid call_rcu_tasks(struct rcu_head *head, rcu_callback_t func);\nvoid synchronize_rcu_tasks(void);\nvoid exit_tasks_rcu_start(void);\nvoid exit_tasks_rcu_finish(void);\n#else /* #ifdef CONFIG_TASKS_RCU */\n#define rcu_tasks_qs(t)\tdo { } while (0)\n#define rcu_note_voluntary_context_switch(t) do { } while (0)\n#define call_rcu_tasks call_rcu\n#define synchronize_rcu_tasks synchronize_rcu\nstatic inline void exit_tasks_rcu_start(void) { }\nstatic inline void exit_tasks_rcu_finish(void) { }\n#endif /* #else #ifdef CONFIG_TASKS_RCU */\n\n/**\n * cond_resched_tasks_rcu_qs - Report potential quiescent states to RCU\n *\n * This macro resembles cond_resched(), except that it is defined to\n * report potential quiescent states to RCU-tasks even if the cond_resched()\n * machinery were to be shut off, as some advocate for PREEMPT kernels.\n */\n#define cond_resched_tasks_rcu_qs() \\\ndo { \\\n\trcu_tasks_qs(current); \\\n\tcond_resched(); \\\n} while (0)\n\n/*\n * Infrastructure to implement the synchronize_() primitives in\n * TREE_RCU and rcu_barrier_() primitives in TINY_RCU.\n */\n\n#if defined(CONFIG_TREE_RCU) || defined(CONFIG_PREEMPT_RCU)\n#include <linux/rcutree.h>\n#elif defined(CONFIG_TINY_RCU)\n#include <linux/rcutiny.h>\n#else\n#error \"Unknown RCU implementation specified to kernel configuration\"\n#endif\n\n/*\n * The init_rcu_head_on_stack() and destroy_rcu_head_on_stack() calls\n * are needed for dynamic initialization and destruction of rcu_head\n * on the stack, and init_rcu_head()/destroy_rcu_head() are needed for\n * dynamic initialization and destruction of statically allocated rcu_head\n * structures.  However, rcu_head structures allocated dynamically in the\n * heap don't need any initialization.\n */\n#ifdef CONFIG_DEBUG_OBJECTS_RCU_HEAD\nvoid init_rcu_head(struct rcu_head *head);\nvoid destroy_rcu_head(struct rcu_head *head);\nvoid init_rcu_head_on_stack(struct rcu_head *head);\nvoid destroy_rcu_head_on_stack(struct rcu_head *head);\n#else /* !CONFIG_DEBUG_OBJECTS_RCU_HEAD */\nstatic inline void init_rcu_head(struct rcu_head *head) { }\nstatic inline void destroy_rcu_head(struct rcu_head *head) { }\nstatic inline void init_rcu_head_on_stack(struct rcu_head *head) { }\nstatic inline void destroy_rcu_head_on_stack(struct rcu_head *head) { }\n#endif\t/* #else !CONFIG_DEBUG_OBJECTS_RCU_HEAD */\n\n#if defined(CONFIG_HOTPLUG_CPU) && defined(CONFIG_PROVE_RCU)\nbool rcu_lockdep_current_cpu_online(void);\n#else /* #if defined(CONFIG_HOTPLUG_CPU) && defined(CONFIG_PROVE_RCU) */\nstatic inline bool rcu_lockdep_current_cpu_online(void) { return true; }\n#endif /* #else #if defined(CONFIG_HOTPLUG_CPU) && defined(CONFIG_PROVE_RCU) */\n\n#ifdef CONFIG_DEBUG_LOCK_ALLOC\n\nstatic inline void rcu_lock_acquire(struct lockdep_map *map)\n{\n\tlock_acquire(map, 0, 0, 2, 0, NULL, _THIS_IP_);\n}\n\nstatic inline void rcu_lock_release(struct lockdep_map *map)\n{\n\tlock_release(map, 1, _THIS_IP_);\n}\n\nextern struct lockdep_map rcu_lock_map;\nextern struct lockdep_map rcu_bh_lock_map;\nextern struct lockdep_map rcu_sched_lock_map;\nextern struct lockdep_map rcu_callback_map;\nint debug_lockdep_rcu_enabled(void);\nint rcu_read_lock_held(void);\nint rcu_read_lock_bh_held(void);\nint rcu_read_lock_sched_held(void);\nint rcu_read_lock_any_held(void);\n\n#else /* #ifdef CONFIG_DEBUG_LOCK_ALLOC */\n\n# define rcu_lock_acquire(a)\t\tdo { } while (0)\n# define rcu_lock_release(a)\t\tdo { } while (0)\n\nstatic inline int rcu_read_lock_held(void)\n{\n\treturn 1;\n}\n\nstatic inline int rcu_read_lock_bh_held(void)\n{\n\treturn 1;\n}\n\nstatic inline int rcu_read_lock_sched_held(void)\n{\n\treturn !preemptible();\n}\n\nstatic inline int rcu_read_lock_any_held(void)\n{\n\treturn !preemptible();\n}\n\n#endif /* #else #ifdef CONFIG_DEBUG_LOCK_ALLOC */\n\n#ifdef CONFIG_PROVE_RCU\n\n/**\n * RCU_LOCKDEP_WARN - emit lockdep splat if specified condition is met\n * @c: condition to check\n * @s: informative message\n */\n#define RCU_LOCKDEP_WARN(c, s)\t\t\t\t\t\t\\\n\tdo {\t\t\t\t\t\t\t\t\\\n\t\tstatic bool __section(.data.unlikely) __warned;\t\t\\\n\t\tif (debug_lockdep_rcu_enabled() && !__warned && (c)) {\t\\\n\t\t\t__warned = true;\t\t\t\t\\\n\t\t\tlockdep_rcu_suspicious(__FILE__, __LINE__, s);\t\\\n\t\t}\t\t\t\t\t\t\t\\\n\t} while (0)\n\n#if defined(CONFIG_PROVE_RCU) && !defined(CONFIG_PREEMPT_RCU)\nstatic inline void rcu_preempt_sleep_check(void)\n{\n\tRCU_LOCKDEP_WARN(lock_is_held(&rcu_lock_map),\n\t\t\t \"Illegal context switch in RCU read-side critical section\");\n}\n#else /* #ifdef CONFIG_PROVE_RCU */\nstatic inline void rcu_preempt_sleep_check(void) { }\n#endif /* #else #ifdef CONFIG_PROVE_RCU */\n\n#define rcu_sleep_check()\t\t\t\t\t\t\\\n\tdo {\t\t\t\t\t\t\t\t\\\n\t\trcu_preempt_sleep_check();\t\t\t\t\\\n\t\tRCU_LOCKDEP_WARN(lock_is_held(&rcu_bh_lock_map),\t\\\n\t\t\t\t \"Illegal context switch in RCU-bh read-side critical section\"); \\\n\t\tRCU_LOCKDEP_WARN(lock_is_held(&rcu_sched_lock_map),\t\\\n\t\t\t\t \"Illegal context switch in RCU-sched read-side critical section\"); \\\n\t} while (0)\n\n#else /* #ifdef CONFIG_PROVE_RCU */\n\n#define RCU_LOCKDEP_WARN(c, s) do { } while (0)\n#define rcu_sleep_check() do { } while (0)\n\n#endif /* #else #ifdef CONFIG_PROVE_RCU */\n\n/*\n * Helper functions for rcu_dereference_check(), rcu_dereference_protected()\n * and rcu_assign_pointer().  Some of these could be folded into their\n * callers, but they are left separate in order to ease introduction of\n * multiple pointers markings to match different RCU implementations\n * (e.g., __srcu), should this make sense in the future.\n */\n\n#ifdef __CHECKER__\n#define rcu_check_sparse(p, space) \\\n\t((void)(((typeof(*p) space *)p) == p))\n#else /* #ifdef __CHECKER__ */\n#define rcu_check_sparse(p, space)\n#endif /* #else #ifdef __CHECKER__ */\n\n#define __rcu_access_pointer(p, space) \\\n({ \\\n\ttypeof(*p) *_________p1 = (typeof(*p) *__force)READ_ONCE(p); \\\n\trcu_check_sparse(p, space); \\\n\t((typeof(*p) __force __kernel *)(_________p1)); \\\n})\n#define __rcu_dereference_check(p, c, space) \\\n({ \\\n\t/* Dependency order vs. p above. */ \\\n\ttypeof(*p) *________p1 = (typeof(*p) *__force)READ_ONCE(p); \\\n\tRCU_LOCKDEP_WARN(!(c), \"suspicious rcu_dereference_check() usage\"); \\\n\trcu_check_sparse(p, space); \\\n\t((typeof(*p) __force __kernel *)(________p1)); \\\n})\n#define __rcu_dereference_protected(p, c, space) \\\n({ \\\n\tRCU_LOCKDEP_WARN(!(c), \"suspicious rcu_dereference_protected() usage\"); \\\n\trcu_check_sparse(p, space); \\\n\t((typeof(*p) __force __kernel *)(p)); \\\n})\n#define rcu_dereference_raw(p) \\\n({ \\\n\t/* Dependency order vs. p above. */ \\\n\ttypeof(p) ________p1 = READ_ONCE(p); \\\n\t((typeof(*p) __force __kernel *)(________p1)); \\\n})\n\n/**\n * RCU_INITIALIZER() - statically initialize an RCU-protected global variable\n * @v: The value to statically initialize with.\n */\n#define RCU_INITIALIZER(v) (typeof(*(v)) __force __rcu *)(v)\n\n/**\n * rcu_assign_pointer() - assign to RCU-protected pointer\n * @p: pointer to assign to\n * @v: value to assign (publish)\n *\n * Assigns the specified value to the specified RCU-protected\n * pointer, ensuring that any concurrent RCU readers will see\n * any prior initialization.\n *\n * Inserts memory barriers on architectures that require them\n * (which is most of them), and also prevents the compiler from\n * reordering the code that initializes the structure after the pointer\n * assignment.  More importantly, this call documents which pointers\n * will be dereferenced by RCU read-side code.\n *\n * In some special cases, you may use RCU_INIT_POINTER() instead\n * of rcu_assign_pointer().  RCU_INIT_POINTER() is a bit faster due\n * to the fact that it does not constrain either the CPU or the compiler.\n * That said, using RCU_INIT_POINTER() when you should have used\n * rcu_assign_pointer() is a very bad thing that results in\n * impossible-to-diagnose memory corruption.  So please be careful.\n * See the RCU_INIT_POINTER() comment header for details.\n *\n * Note that rcu_assign_pointer() evaluates each of its arguments only\n * once, appearances notwithstanding.  One of the \"extra\" evaluations\n * is in typeof() and the other visible only to sparse (__CHECKER__),\n * neither of which actually execute the argument.  As with most cpp\n * macros, this execute-arguments-only-once property is important, so\n * please be careful when making changes to rcu_assign_pointer() and the\n * other macros that it invokes.\n */\n#define rcu_assign_pointer(p, v)\t\t\t\t\t      \\\ndo {\t\t\t\t\t\t\t\t\t      \\\n\tuintptr_t _r_a_p__v = (uintptr_t)(v);\t\t\t\t      \\\n\trcu_check_sparse(p, __rcu);\t\t\t\t\t      \\\n\t\t\t\t\t\t\t\t\t      \\\n\tif (__builtin_constant_p(v) && (_r_a_p__v) == (uintptr_t)NULL)\t      \\\n\t\tWRITE_ONCE((p), (typeof(p))(_r_a_p__v));\t\t      \\\n\telse\t\t\t\t\t\t\t\t      \\\n\t\tsmp_store_release(&p, RCU_INITIALIZER((typeof(p))_r_a_p__v)); \\\n} while (0)\n\n/**\n * rcu_swap_protected() - swap an RCU and a regular pointer\n * @rcu_ptr: RCU pointer\n * @ptr: regular pointer\n * @c: the conditions under which the dereference will take place\n *\n * Perform swap(@rcu_ptr, @ptr) where @rcu_ptr is an RCU-annotated pointer and\n * @c is the argument that is passed to the rcu_dereference_protected() call\n * used to read that pointer.\n */\n#define rcu_swap_protected(rcu_ptr, ptr, c) do {\t\t\t\\\n\ttypeof(ptr) __tmp = rcu_dereference_protected((rcu_ptr), (c));\t\\\n\trcu_assign_pointer((rcu_ptr), (ptr));\t\t\t\t\\\n\t(ptr) = __tmp;\t\t\t\t\t\t\t\\\n} while (0)\n\n/**\n * rcu_access_pointer() - fetch RCU pointer with no dereferencing\n * @p: The pointer to read\n *\n * Return the value of the specified RCU-protected pointer, but omit the\n * lockdep checks for being in an RCU read-side critical section.  This is\n * useful when the value of this pointer is accessed, but the pointer is\n * not dereferenced, for example, when testing an RCU-protected pointer\n * against NULL.  Although rcu_access_pointer() may also be used in cases\n * where update-side locks prevent the value of the pointer from changing,\n * you should instead use rcu_dereference_protected() for this use case.\n *\n * It is also permissible to use rcu_access_pointer() when read-side\n * access to the pointer was removed at least one grace period ago, as\n * is the case in the context of the RCU callback that is freeing up\n * the data, or after a synchronize_rcu() returns.  This can be useful\n * when tearing down multi-linked structures after a grace period\n * has elapsed.\n */\n#define rcu_access_pointer(p) __rcu_access_pointer((p), __rcu)\n\n/**\n * rcu_dereference_check() - rcu_dereference with debug checking\n * @p: The pointer to read, prior to dereferencing\n * @c: The conditions under which the dereference will take place\n *\n * Do an rcu_dereference(), but check that the conditions under which the\n * dereference will take place are correct.  Typically the conditions\n * indicate the various locking conditions that should be held at that\n * point.  The check should return true if the conditions are satisfied.\n * An implicit check for being in an RCU read-side critical section\n * (rcu_read_lock()) is included.\n *\n * For example:\n *\n *\tbar = rcu_dereference_check(foo->bar, lockdep_is_held(&foo->lock));\n *\n * could be used to indicate to lockdep that foo->bar may only be dereferenced\n * if either rcu_read_lock() is held, or that the lock required to replace\n * the bar struct at foo->bar is held.\n *\n * Note that the list of conditions may also include indications of when a lock\n * need not be held, for example during initialisation or destruction of the\n * target struct:\n *\n *\tbar = rcu_dereference_check(foo->bar, lockdep_is_held(&foo->lock) ||\n *\t\t\t\t\t      atomic_read(&foo->usage) == 0);\n *\n * Inserts memory barriers on architectures that require them\n * (currently only the Alpha), prevents the compiler from refetching\n * (and from merging fetches), and, more importantly, documents exactly\n * which pointers are protected by RCU and checks that the pointer is\n * annotated as __rcu.\n */\n#define rcu_dereference_check(p, c) \\\n\t__rcu_dereference_check((p), (c) || rcu_read_lock_held(), __rcu)\n\n/**\n * rcu_dereference_bh_check() - rcu_dereference_bh with debug checking\n * @p: The pointer to read, prior to dereferencing\n * @c: The conditions under which the dereference will take place\n *\n * This is the RCU-bh counterpart to rcu_dereference_check().\n */\n#define rcu_dereference_bh_check(p, c) \\\n\t__rcu_dereference_check((p), (c) || rcu_read_lock_bh_held(), __rcu)\n\n/**\n * rcu_dereference_sched_check() - rcu_dereference_sched with debug checking\n * @p: The pointer to read, prior to dereferencing\n * @c: The conditions under which the dereference will take place\n *\n * This is the RCU-sched counterpart to rcu_dereference_check().\n */\n#define rcu_dereference_sched_check(p, c) \\\n\t__rcu_dereference_check((p), (c) || rcu_read_lock_sched_held(), \\\n\t\t\t\t__rcu)\n\n/*\n * The tracing infrastructure traces RCU (we want that), but unfortunately\n * some of the RCU checks causes tracing to lock up the system.\n *\n * The no-tracing version of rcu_dereference_raw() must not call\n * rcu_read_lock_held().\n */\n#define rcu_dereference_raw_check(p) __rcu_dereference_check((p), 1, __rcu)\n\n/**\n * rcu_dereference_protected() - fetch RCU pointer when updates prevented\n * @p: The pointer to read, prior to dereferencing\n * @c: The conditions under which the dereference will take place\n *\n * Return the value of the specified RCU-protected pointer, but omit\n * the READ_ONCE().  This is useful in cases where update-side locks\n * prevent the value of the pointer from changing.  Please note that this\n * primitive does *not* prevent the compiler from repeating this reference\n * or combining it with other references, so it should not be used without\n * protection of appropriate locks.\n *\n * This function is only for update-side use.  Using this function\n * when protected only by rcu_read_lock() will result in infrequent\n * but very ugly failures.\n */\n#define rcu_dereference_protected(p, c) \\\n\t__rcu_dereference_protected((p), (c), __rcu)\n\n\n/**\n * rcu_dereference() - fetch RCU-protected pointer for dereferencing\n * @p: The pointer to read, prior to dereferencing\n *\n * This is a simple wrapper around rcu_dereference_check().\n */\n#define rcu_dereference(p) rcu_dereference_check(p, 0)\n\n/**\n * rcu_dereference_bh() - fetch an RCU-bh-protected pointer for dereferencing\n * @p: The pointer to read, prior to dereferencing\n *\n * Makes rcu_dereference_check() do the dirty work.\n */\n#define rcu_dereference_bh(p) rcu_dereference_bh_check(p, 0)\n\n/**\n * rcu_dereference_sched() - fetch RCU-sched-protected pointer for dereferencing\n * @p: The pointer to read, prior to dereferencing\n *\n * Makes rcu_dereference_check() do the dirty work.\n */\n#define rcu_dereference_sched(p) rcu_dereference_sched_check(p, 0)\n\n/**\n * rcu_pointer_handoff() - Hand off a pointer from RCU to other mechanism\n * @p: The pointer to hand off\n *\n * This is simply an identity function, but it documents where a pointer\n * is handed off from RCU to some other synchronization mechanism, for\n * example, reference counting or locking.  In C11, it would map to\n * kill_dependency().  It could be used as follows::\n *\n *\trcu_read_lock();\n *\tp = rcu_dereference(gp);\n *\tlong_lived = is_long_lived(p);\n *\tif (long_lived) {\n *\t\tif (!atomic_inc_not_zero(p->refcnt))\n *\t\t\tlong_lived = false;\n *\t\telse\n *\t\t\tp = rcu_pointer_handoff(p);\n *\t}\n *\trcu_read_unlock();\n */\n#define rcu_pointer_handoff(p) (p)\n\n/**\n * rcu_read_lock() - mark the beginning of an RCU read-side critical section\n *\n * When synchronize_rcu() is invoked on one CPU while other CPUs\n * are within RCU read-side critical sections, then the\n * synchronize_rcu() is guaranteed to block until after all the other\n * CPUs exit their critical sections.  Similarly, if call_rcu() is invoked\n * on one CPU while other CPUs are within RCU read-side critical\n * sections, invocation of the corresponding RCU callback is deferred\n * until after the all the other CPUs exit their critical sections.\n *\n * Note, however, that RCU callbacks are permitted to run concurrently\n * with new RCU read-side critical sections.  One way that this can happen\n * is via the following sequence of events: (1) CPU 0 enters an RCU\n * read-side critical section, (2) CPU 1 invokes call_rcu() to register\n * an RCU callback, (3) CPU 0 exits the RCU read-side critical section,\n * (4) CPU 2 enters a RCU read-side critical section, (5) the RCU\n * callback is invoked.  This is legal, because the RCU read-side critical\n * section that was running concurrently with the call_rcu() (and which\n * therefore might be referencing something that the corresponding RCU\n * callback would free up) has completed before the corresponding\n * RCU callback is invoked.\n *\n * RCU read-side critical sections may be nested.  Any deferred actions\n * will be deferred until the outermost RCU read-side critical section\n * completes.\n *\n * You can avoid reading and understanding the next paragraph by\n * following this rule: don't put anything in an rcu_read_lock() RCU\n * read-side critical section that would block in a !PREEMPT kernel.\n * But if you want the full story, read on!\n *\n * In non-preemptible RCU implementations (TREE_RCU and TINY_RCU),\n * it is illegal to block while in an RCU read-side critical section.\n * In preemptible RCU implementations (PREEMPT_RCU) in CONFIG_PREEMPTION\n * kernel builds, RCU read-side critical sections may be preempted,\n * but explicit blocking is illegal.  Finally, in preemptible RCU\n * implementations in real-time (with -rt patchset) kernel builds, RCU\n * read-side critical sections may be preempted and they may also block, but\n * only when acquiring spinlocks that are subject to priority inheritance.\n */\nstatic __always_inline void rcu_read_lock(void)\n{\n\t__rcu_read_lock();\n\t__acquire(RCU);\n\trcu_lock_acquire(&rcu_lock_map);\n\tRCU_LOCKDEP_WARN(!rcu_is_watching(),\n\t\t\t \"rcu_read_lock() used illegally while idle\");\n}\n\n/*\n * So where is rcu_write_lock()?  It does not exist, as there is no\n * way for writers to lock out RCU readers.  This is a feature, not\n * a bug -- this property is what provides RCU's performance benefits.\n * Of course, writers must coordinate with each other.  The normal\n * spinlock primitives work well for this, but any other technique may be\n * used as well.  RCU does not care how the writers keep out of each\n * others' way, as long as they do so.\n */\n\n/**\n * rcu_read_unlock() - marks the end of an RCU read-side critical section.\n *\n * In most situations, rcu_read_unlock() is immune from deadlock.\n * However, in kernels built with CONFIG_RCU_BOOST, rcu_read_unlock()\n * is responsible for deboosting, which it does via rt_mutex_unlock().\n * Unfortunately, this function acquires the scheduler's runqueue and\n * priority-inheritance spinlocks.  This means that deadlock could result\n * if the caller of rcu_read_unlock() already holds one of these locks or\n * any lock that is ever acquired while holding them.\n *\n * That said, RCU readers are never priority boosted unless they were\n * preempted.  Therefore, one way to avoid deadlock is to make sure\n * that preemption never happens within any RCU read-side critical\n * section whose outermost rcu_read_unlock() is called with one of\n * rt_mutex_unlock()'s locks held.  Such preemption can be avoided in\n * a number of ways, for example, by invoking preempt_disable() before\n * critical section's outermost rcu_read_lock().\n *\n * Given that the set of locks acquired by rt_mutex_unlock() might change\n * at any time, a somewhat more future-proofed approach is to make sure\n * that that preemption never happens within any RCU read-side critical\n * section whose outermost rcu_read_unlock() is called with irqs disabled.\n * This approach relies on the fact that rt_mutex_unlock() currently only\n * acquires irq-disabled locks.\n *\n * The second of these two approaches is best in most situations,\n * however, the first approach can also be useful, at least to those\n * developers willing to keep abreast of the set of locks acquired by\n * rt_mutex_unlock().\n *\n * See rcu_read_lock() for more information.\n */\nstatic inline void rcu_read_unlock(void)\n{\n\tRCU_LOCKDEP_WARN(!rcu_is_watching(),\n\t\t\t \"rcu_read_unlock() used illegally while idle\");\n\t__release(RCU);\n\t__rcu_read_unlock();\n\trcu_lock_release(&rcu_lock_map); /* Keep acq info for rls diags. */\n}\n\n/**\n * rcu_read_lock_bh() - mark the beginning of an RCU-bh critical section\n *\n * This is equivalent of rcu_read_lock(), but also disables softirqs.\n * Note that anything else that disables softirqs can also serve as\n * an RCU read-side critical section.\n *\n * Note that rcu_read_lock_bh() and the matching rcu_read_unlock_bh()\n * must occur in the same context, for example, it is illegal to invoke\n * rcu_read_unlock_bh() from one task if the matching rcu_read_lock_bh()\n * was invoked from some other task.\n */\nstatic inline void rcu_read_lock_bh(void)\n{\n\tlocal_bh_disable();\n\t__acquire(RCU_BH);\n\trcu_lock_acquire(&rcu_bh_lock_map);\n\tRCU_LOCKDEP_WARN(!rcu_is_watching(),\n\t\t\t \"rcu_read_lock_bh() used illegally while idle\");\n}\n\n/*\n * rcu_read_unlock_bh - marks the end of a softirq-only RCU critical section\n *\n * See rcu_read_lock_bh() for more information.\n */\nstatic inline void rcu_read_unlock_bh(void)\n{\n\tRCU_LOCKDEP_WARN(!rcu_is_watching(),\n\t\t\t \"rcu_read_unlock_bh() used illegally while idle\");\n\trcu_lock_release(&rcu_bh_lock_map);\n\t__release(RCU_BH);\n\tlocal_bh_enable();\n}\n\n/**\n * rcu_read_lock_sched() - mark the beginning of a RCU-sched critical section\n *\n * This is equivalent of rcu_read_lock(), but disables preemption.\n * Read-side critical sections can also be introduced by anything else\n * that disables preemption, including local_irq_disable() and friends.\n *\n * Note that rcu_read_lock_sched() and the matching rcu_read_unlock_sched()\n * must occur in the same context, for example, it is illegal to invoke\n * rcu_read_unlock_sched() from process context if the matching\n * rcu_read_lock_sched() was invoked from an NMI handler.\n */\nstatic inline void rcu_read_lock_sched(void)\n{\n\tpreempt_disable();\n\t__acquire(RCU_SCHED);\n\trcu_lock_acquire(&rcu_sched_lock_map);\n\tRCU_LOCKDEP_WARN(!rcu_is_watching(),\n\t\t\t \"rcu_read_lock_sched() used illegally while idle\");\n}\n\n/* Used by lockdep and tracing: cannot be traced, cannot call lockdep. */\nstatic inline notrace void rcu_read_lock_sched_notrace(void)\n{\n\tpreempt_disable_notrace();\n\t__acquire(RCU_SCHED);\n}\n\n/*\n * rcu_read_unlock_sched - marks the end of a RCU-classic critical section\n *\n * See rcu_read_lock_sched for more information.\n */\nstatic inline void rcu_read_unlock_sched(void)\n{\n\tRCU_LOCKDEP_WARN(!rcu_is_watching(),\n\t\t\t \"rcu_read_unlock_sched() used illegally while idle\");\n\trcu_lock_release(&rcu_sched_lock_map);\n\t__release(RCU_SCHED);\n\tpreempt_enable();\n}\n\n/* Used by lockdep and tracing: cannot be traced, cannot call lockdep. */\nstatic inline notrace void rcu_read_unlock_sched_notrace(void)\n{\n\t__release(RCU_SCHED);\n\tpreempt_enable_notrace();\n}\n\n/**\n * RCU_INIT_POINTER() - initialize an RCU protected pointer\n * @p: The pointer to be initialized.\n * @v: The value to initialized the pointer to.\n *\n * Initialize an RCU-protected pointer in special cases where readers\n * do not need ordering constraints on the CPU or the compiler.  These\n * special cases are:\n *\n * 1.\tThis use of RCU_INIT_POINTER() is NULLing out the pointer *or*\n * 2.\tThe caller has taken whatever steps are required to prevent\n *\tRCU readers from concurrently accessing this pointer *or*\n * 3.\tThe referenced data structure has already been exposed to\n *\treaders either at compile time or via rcu_assign_pointer() *and*\n *\n *\ta.\tYou have not made *any* reader-visible changes to\n *\t\tthis structure since then *or*\n *\tb.\tIt is OK for readers accessing this structure from its\n *\t\tnew location to see the old state of the structure.  (For\n *\t\texample, the changes were to statistical counters or to\n *\t\tother state where exact synchronization is not required.)\n *\n * Failure to follow these rules governing use of RCU_INIT_POINTER() will\n * result in impossible-to-diagnose memory corruption.  As in the structures\n * will look OK in crash dumps, but any concurrent RCU readers might\n * see pre-initialized values of the referenced data structure.  So\n * please be very careful how you use RCU_INIT_POINTER()!!!\n *\n * If you are creating an RCU-protected linked structure that is accessed\n * by a single external-to-structure RCU-protected pointer, then you may\n * use RCU_INIT_POINTER() to initialize the internal RCU-protected\n * pointers, but you must use rcu_assign_pointer() to initialize the\n * external-to-structure pointer *after* you have completely initialized\n * the reader-accessible portions of the linked structure.\n *\n * Note that unlike rcu_assign_pointer(), RCU_INIT_POINTER() provides no\n * ordering guarantees for either the CPU or the compiler.\n */\n#define RCU_INIT_POINTER(p, v) \\\n\tdo { \\\n\t\trcu_check_sparse(p, __rcu); \\\n\t\tWRITE_ONCE(p, RCU_INITIALIZER(v)); \\\n\t} while (0)\n\n/**\n * RCU_POINTER_INITIALIZER() - statically initialize an RCU protected pointer\n * @p: The pointer to be initialized.\n * @v: The value to initialized the pointer to.\n *\n * GCC-style initialization for an RCU-protected pointer in a structure field.\n */\n#define RCU_POINTER_INITIALIZER(p, v) \\\n\t\t.p = RCU_INITIALIZER(v)\n\n/*\n * Does the specified offset indicate that the corresponding rcu_head\n * structure can be handled by kfree_rcu()?\n */\n#define __is_kfree_rcu_offset(offset) ((offset) < 4096)\n\n/*\n * Helper macro for kfree_rcu() to prevent argument-expansion eyestrain.\n */\n#define __kfree_rcu(head, offset) \\\n\tdo { \\\n\t\tBUILD_BUG_ON(!__is_kfree_rcu_offset(offset)); \\\n\t\tkfree_call_rcu(head, (rcu_callback_t)(unsigned long)(offset)); \\\n\t} while (0)\n\n/**\n * kfree_rcu() - kfree an object after a grace period.\n * @ptr:\tpointer to kfree\n * @rhf:\tthe name of the struct rcu_head within the type of @ptr.\n *\n * Many rcu callbacks functions just call kfree() on the base structure.\n * These functions are trivial, but their size adds up, and furthermore\n * when they are used in a kernel module, that module must invoke the\n * high-latency rcu_barrier() function at module-unload time.\n *\n * The kfree_rcu() function handles this issue.  Rather than encoding a\n * function address in the embedded rcu_head structure, kfree_rcu() instead\n * encodes the offset of the rcu_head structure within the base structure.\n * Because the functions are not allowed in the low-order 4096 bytes of\n * kernel virtual memory, offsets up to 4095 bytes can be accommodated.\n * If the offset is larger than 4095 bytes, a compile-time error will\n * be generated in __kfree_rcu().  If this error is triggered, you can\n * either fall back to use of call_rcu() or rearrange the structure to\n * position the rcu_head structure into the first 4096 bytes.\n *\n * Note that the allowable offset might decrease in the future, for example,\n * to allow something like kmem_cache_free_rcu().\n *\n * The BUILD_BUG_ON check must not involve any function calls, hence the\n * checks are done in macros here.\n */\n#define kfree_rcu(ptr, rhf)\t\t\t\t\t\t\\\ndo {\t\t\t\t\t\t\t\t\t\\\n\ttypeof (ptr) ___p = (ptr);\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\\\n\tif (___p)\t\t\t\t\t\t\t\\\n\t\t__kfree_rcu(&((___p)->rhf), offsetof(typeof(*(ptr)), rhf)); \\\n} while (0)\n\n/*\n * Place this after a lock-acquisition primitive to guarantee that\n * an UNLOCK+LOCK pair acts as a full barrier.  This guarantee applies\n * if the UNLOCK and LOCK are executed by the same CPU or if the\n * UNLOCK and LOCK operate on the same lock variable.\n */\n#ifdef CONFIG_ARCH_WEAK_RELEASE_ACQUIRE\n#define smp_mb__after_unlock_lock()\tsmp_mb()  /* Full ordering for lock. */\n#else /* #ifdef CONFIG_ARCH_WEAK_RELEASE_ACQUIRE */\n#define smp_mb__after_unlock_lock()\tdo { } while (0)\n#endif /* #else #ifdef CONFIG_ARCH_WEAK_RELEASE_ACQUIRE */\n\n\n/* Has the specified rcu_head structure been handed to call_rcu()? */\n\n/**\n * rcu_head_init - Initialize rcu_head for rcu_head_after_call_rcu()\n * @rhp: The rcu_head structure to initialize.\n *\n * If you intend to invoke rcu_head_after_call_rcu() to test whether a\n * given rcu_head structure has already been passed to call_rcu(), then\n * you must also invoke this rcu_head_init() function on it just after\n * allocating that structure.  Calls to this function must not race with\n * calls to call_rcu(), rcu_head_after_call_rcu(), or callback invocation.\n */\nstatic inline void rcu_head_init(struct rcu_head *rhp)\n{\n\trhp->func = (rcu_callback_t)~0L;\n}\n\n/**\n * rcu_head_after_call_rcu - Has this rcu_head been passed to call_rcu()?\n * @rhp: The rcu_head structure to test.\n * @f: The function passed to call_rcu() along with @rhp.\n *\n * Returns @true if the @rhp has been passed to call_rcu() with @func,\n * and @false otherwise.  Emits a warning in any other case, including\n * the case where @rhp has already been invoked after a grace period.\n * Calls to this function must not race with callback invocation.  One way\n * to avoid such races is to enclose the call to rcu_head_after_call_rcu()\n * in an RCU read-side critical section that includes a read-side fetch\n * of the pointer to the structure containing @rhp.\n */\nstatic inline bool\nrcu_head_after_call_rcu(struct rcu_head *rhp, rcu_callback_t f)\n{\n\trcu_callback_t func = READ_ONCE(rhp->func);\n\n\tif (func == f)\n\t\treturn true;\n\tWARN_ON_ONCE(func != (rcu_callback_t)~0L);\n\treturn false;\n}\n\n#endif /* __LINUX_RCUPDATE_H */\n"
  },
  {
    "path": "t/tree/include/linux/rcutree.h",
    "content": "/* SPDX-License-Identifier: GPL-2.0+ */\n/*\n * Read-Copy Update mechanism for mutual exclusion (tree-based version)\n *\n * Copyright IBM Corporation, 2008\n *\n * Author: Dipankar Sarma <dipankar@in.ibm.com>\n *\t   Paul E. McKenney <paulmck@linux.ibm.com> Hierarchical algorithm\n *\n * Based on the original work by Paul McKenney <paulmck@linux.ibm.com>\n * and inputs from Rusty Russell, Andrea Arcangeli and Andi Kleen.\n *\n * For detailed explanation of Read-Copy Update mechanism see -\n *\tDocumentation/RCU\n */\n\n#ifndef __LINUX_RCUTREE_H\n#define __LINUX_RCUTREE_H\n\nvoid rcu_softirq_qs(void);\nvoid rcu_note_context_switch(bool preempt);\nint rcu_needs_cpu(u64 basem, u64 *nextevt);\nvoid rcu_cpu_stall_reset(void);\n\n/*\n * Note a virtualization-based context switch.  This is simply a\n * wrapper around rcu_note_context_switch(), which allows TINY_RCU\n * to save a few bytes. The caller must have disabled interrupts.\n */\nstatic inline void rcu_virt_note_context_switch(int cpu)\n{\n\trcu_note_context_switch(false);\n}\n\nvoid synchronize_rcu_expedited(void);\nvoid kfree_call_rcu(struct rcu_head *head, rcu_callback_t func);\n\nvoid rcu_barrier(void);\nbool rcu_eqs_special_set(int cpu);\nunsigned long get_state_synchronize_rcu(void);\nvoid cond_synchronize_rcu(unsigned long oldstate);\n\nvoid rcu_idle_enter(void);\nvoid rcu_idle_exit(void);\nvoid rcu_irq_enter(void);\nvoid rcu_irq_exit(void);\nvoid rcu_irq_enter_irqson(void);\nvoid rcu_irq_exit_irqson(void);\n\nvoid exit_rcu(void);\n\nvoid rcu_scheduler_starting(void);\nextern int rcu_scheduler_active __read_mostly;\nvoid rcu_end_inkernel_boot(void);\nbool rcu_is_watching(void);\n#ifndef CONFIG_PREEMPTION\nvoid rcu_all_qs(void);\n#endif\n\n/* RCUtree hotplug events */\nint rcutree_prepare_cpu(unsigned int cpu);\nint rcutree_online_cpu(unsigned int cpu);\nint rcutree_offline_cpu(unsigned int cpu);\nint rcutree_dead_cpu(unsigned int cpu);\nint rcutree_dying_cpu(unsigned int cpu);\nvoid rcu_cpu_starting(unsigned int cpu);\n\n#endif /* __LINUX_RCUTREE_H */\n"
  },
  {
    "path": "t/tree/include/linux/srcu.h",
    "content": "/* SPDX-License-Identifier: GPL-2.0+ */\n/*\n * Sleepable Read-Copy Update mechanism for mutual exclusion\n *\n * Copyright (C) IBM Corporation, 2006\n * Copyright (C) Fujitsu, 2012\n *\n * Author: Paul McKenney <paulmck@linux.ibm.com>\n *\t   Lai Jiangshan <laijs@cn.fujitsu.com>\n *\n * For detailed explanation of Read-Copy Update mechanism see -\n *\t\tDocumentation/RCU/ *.txt\n *\n */\n\n#ifndef _LINUX_SRCU_H\n#define _LINUX_SRCU_H\n\n#include <linux/mutex.h>\n#include <linux/rcupdate.h>\n#include <linux/workqueue.h>\n#include <linux/rcu_segcblist.h>\n\nstruct srcu_struct;\n\n#ifdef CONFIG_DEBUG_LOCK_ALLOC\n\nint __init_srcu_struct(struct srcu_struct *ssp, const char *name,\n\t\t       struct lock_class_key *key);\n\n#define init_srcu_struct(ssp) \\\n({ \\\n\tstatic struct lock_class_key __srcu_key; \\\n\t\\\n\t__init_srcu_struct((ssp), #ssp, &__srcu_key); \\\n})\n\n#define __SRCU_DEP_MAP_INIT(srcu_name)\t.dep_map = { .name = #srcu_name },\n#else /* #ifdef CONFIG_DEBUG_LOCK_ALLOC */\n\nint init_srcu_struct(struct srcu_struct *ssp);\n\n#define __SRCU_DEP_MAP_INIT(srcu_name)\n#endif /* #else #ifdef CONFIG_DEBUG_LOCK_ALLOC */\n\n#ifdef CONFIG_TINY_SRCU\n#include <linux/srcutiny.h>\n#elif defined(CONFIG_TREE_SRCU)\n#include <linux/srcutree.h>\n#elif defined(CONFIG_SRCU)\n#error \"Unknown SRCU implementation specified to kernel configuration\"\n#else\n/* Dummy definition for things like notifiers.  Actual use gets link error. */\nstruct srcu_struct { };\n#endif\n\nvoid call_srcu(struct srcu_struct *ssp, struct rcu_head *head,\n\t\tvoid (*func)(struct rcu_head *head));\nvoid cleanup_srcu_struct(struct srcu_struct *ssp);\nint __srcu_read_lock(struct srcu_struct *ssp) __acquires(ssp);\nvoid __srcu_read_unlock(struct srcu_struct *ssp, int idx) __releases(ssp);\nvoid synchronize_srcu(struct srcu_struct *ssp);\n\n#ifdef CONFIG_DEBUG_LOCK_ALLOC\n\n/**\n * srcu_read_lock_held - might we be in SRCU read-side critical section?\n * @ssp: The srcu_struct structure to check\n *\n * If CONFIG_DEBUG_LOCK_ALLOC is selected, returns nonzero iff in an SRCU\n * read-side critical section.  In absence of CONFIG_DEBUG_LOCK_ALLOC,\n * this assumes we are in an SRCU read-side critical section unless it can\n * prove otherwise.\n *\n * Checks debug_lockdep_rcu_enabled() to prevent false positives during boot\n * and while lockdep is disabled.\n *\n * Note that SRCU is based on its own statemachine and it doesn't\n * relies on normal RCU, it can be called from the CPU which\n * is in the idle loop from an RCU point of view or offline.\n */\nstatic inline int srcu_read_lock_held(const struct srcu_struct *ssp)\n{\n\tif (!debug_lockdep_rcu_enabled())\n\t\treturn 1;\n\treturn lock_is_held(&ssp->dep_map);\n}\n\n#else /* #ifdef CONFIG_DEBUG_LOCK_ALLOC */\n\nstatic inline int srcu_read_lock_held(const struct srcu_struct *ssp)\n{\n\treturn 1;\n}\n\n#endif /* #else #ifdef CONFIG_DEBUG_LOCK_ALLOC */\n\n/**\n * srcu_dereference_check - fetch SRCU-protected pointer for later dereferencing\n * @p: the pointer to fetch and protect for later dereferencing\n * @ssp: pointer to the srcu_struct, which is used to check that we\n *\treally are in an SRCU read-side critical section.\n * @c: condition to check for update-side use\n *\n * If PROVE_RCU is enabled, invoking this outside of an RCU read-side\n * critical section will result in an RCU-lockdep splat, unless @c evaluates\n * to 1.  The @c argument will normally be a logical expression containing\n * lockdep_is_held() calls.\n */\n#define srcu_dereference_check(p, ssp, c) \\\n\t__rcu_dereference_check((p), (c) || srcu_read_lock_held(ssp), __rcu)\n\n/**\n * srcu_dereference - fetch SRCU-protected pointer for later dereferencing\n * @p: the pointer to fetch and protect for later dereferencing\n * @ssp: pointer to the srcu_struct, which is used to check that we\n *\treally are in an SRCU read-side critical section.\n *\n * Makes rcu_dereference_check() do the dirty work.  If PROVE_RCU\n * is enabled, invoking this outside of an RCU read-side critical\n * section will result in an RCU-lockdep splat.\n */\n#define srcu_dereference(p, ssp) srcu_dereference_check((p), (ssp), 0)\n\n/**\n * srcu_dereference_notrace - no tracing and no lockdep calls from here\n * @p: the pointer to fetch and protect for later dereferencing\n * @ssp: pointer to the srcu_struct, which is used to check that we\n *\treally are in an SRCU read-side critical section.\n */\n#define srcu_dereference_notrace(p, ssp) srcu_dereference_check((p), (ssp), 1)\n\n/**\n * srcu_read_lock - register a new reader for an SRCU-protected structure.\n * @ssp: srcu_struct in which to register the new reader.\n *\n * Enter an SRCU read-side critical section.  Note that SRCU read-side\n * critical sections may be nested.  However, it is illegal to\n * call anything that waits on an SRCU grace period for the same\n * srcu_struct, whether directly or indirectly.  Please note that\n * one way to indirectly wait on an SRCU grace period is to acquire\n * a mutex that is held elsewhere while calling synchronize_srcu() or\n * synchronize_srcu_expedited().\n *\n * Note that srcu_read_lock() and the matching srcu_read_unlock() must\n * occur in the same context, for example, it is illegal to invoke\n * srcu_read_unlock() in an irq handler if the matching srcu_read_lock()\n * was invoked in process context.\n */\nstatic inline int srcu_read_lock(struct srcu_struct *ssp) __acquires(ssp)\n{\n\tint retval;\n\n\tretval = __srcu_read_lock(ssp);\n\trcu_lock_acquire(&(ssp)->dep_map);\n\treturn retval;\n}\n\n/* Used by tracing, cannot be traced and cannot invoke lockdep. */\nstatic inline notrace int\nsrcu_read_lock_notrace(struct srcu_struct *ssp) __acquires(ssp)\n{\n\tint retval;\n\n\tretval = __srcu_read_lock(ssp);\n\treturn retval;\n}\n\n/**\n * srcu_read_unlock - unregister a old reader from an SRCU-protected structure.\n * @ssp: srcu_struct in which to unregister the old reader.\n * @idx: return value from corresponding srcu_read_lock().\n *\n * Exit an SRCU read-side critical section.\n */\nstatic inline void srcu_read_unlock(struct srcu_struct *ssp, int idx)\n\t__releases(ssp)\n{\n\tWARN_ON_ONCE(idx & ~0x1);\n\trcu_lock_release(&(ssp)->dep_map);\n\t__srcu_read_unlock(ssp, idx);\n}\n\n/* Used by tracing, cannot be traced and cannot call lockdep. */\nstatic inline notrace void\nsrcu_read_unlock_notrace(struct srcu_struct *ssp, int idx) __releases(ssp)\n{\n\t__srcu_read_unlock(ssp, idx);\n}\n\n/**\n * smp_mb__after_srcu_read_unlock - ensure full ordering after srcu_read_unlock\n *\n * Converts the preceding srcu_read_unlock into a two-way memory barrier.\n *\n * Call this after srcu_read_unlock, to guarantee that all memory operations\n * that occur after smp_mb__after_srcu_read_unlock will appear to happen after\n * the preceding srcu_read_unlock.\n */\nstatic inline void smp_mb__after_srcu_read_unlock(void)\n{\n\t/* __srcu_read_unlock has smp_mb() internally so nothing to do here. */\n}\n\n#endif\n"
  },
  {
    "path": "t/tree/include/linux/srcutree.h",
    "content": "/* SPDX-License-Identifier: GPL-2.0+ */\n/*\n * Sleepable Read-Copy Update mechanism for mutual exclusion,\n *\ttree variant.\n *\n * Copyright (C) IBM Corporation, 2017\n *\n * Author: Paul McKenney <paulmck@linux.ibm.com>\n */\n\n#ifndef _LINUX_SRCU_TREE_H\n#define _LINUX_SRCU_TREE_H\n\n#include <linux/rcu_node_tree.h>\n#include <linux/completion.h>\n\nstruct srcu_node;\nstruct srcu_struct;\n\n/*\n * Per-CPU structure feeding into leaf srcu_node, similar in function\n * to rcu_node.\n */\nstruct srcu_data {\n\t/* Read-side state. */\n\tunsigned long srcu_lock_count[2];\t/* Locks per CPU. */\n\tunsigned long srcu_unlock_count[2];\t/* Unlocks per CPU. */\n\n\t/* Update-side state. */\n\tspinlock_t __private lock ____cacheline_internodealigned_in_smp;\n\tstruct rcu_segcblist srcu_cblist;\t/* List of callbacks.*/\n\tunsigned long srcu_gp_seq_needed;\t/* Furthest future GP needed. */\n\tunsigned long srcu_gp_seq_needed_exp;\t/* Furthest future exp GP. */\n\tbool srcu_cblist_invoking;\t\t/* Invoking these CBs? */\n\tstruct timer_list delay_work;\t\t/* Delay for CB invoking */\n\tstruct work_struct work;\t\t/* Context for CB invoking. */\n\tstruct rcu_head srcu_barrier_head;\t/* For srcu_barrier() use. */\n\tstruct srcu_node *mynode;\t\t/* Leaf srcu_node. */\n\tunsigned long grpmask;\t\t\t/* Mask for leaf srcu_node */\n\t\t\t\t\t\t/*  ->srcu_data_have_cbs[]. */\n\tint cpu;\n\tstruct srcu_struct *ssp;\n};\n\n/*\n * Node in SRCU combining tree, similar in function to rcu_data.\n */\nstruct srcu_node {\n\tspinlock_t __private lock;\n\tunsigned long srcu_have_cbs[4];\t\t/* GP seq for children */\n\t\t\t\t\t\t/*  having CBs, but only */\n\t\t\t\t\t\t/*  is > ->srcu_gq_seq. */\n\tunsigned long srcu_data_have_cbs[4];\t/* Which srcu_data structs */\n\t\t\t\t\t\t/*  have CBs for given GP? */\n\tunsigned long srcu_gp_seq_needed_exp;\t/* Furthest future exp GP. */\n\tstruct srcu_node *srcu_parent;\t\t/* Next up in tree. */\n\tint grplo;\t\t\t\t/* Least CPU for node. */\n\tint grphi;\t\t\t\t/* Biggest CPU for node. */\n};\n\n/*\n * Per-SRCU-domain structure, similar in function to rcu_state.\n */\nstruct srcu_struct {\n\tstruct srcu_node node[NUM_RCU_NODES];\t/* Combining tree. */\n\tstruct srcu_node *level[RCU_NUM_LVLS + 1];\n\t\t\t\t\t\t/* First node at each level. */\n\tstruct mutex srcu_cb_mutex;\t\t/* Serialize CB preparation. */\n\tspinlock_t __private lock;\t\t/* Protect counters */\n\tstruct mutex srcu_gp_mutex;\t\t/* Serialize GP work. */\n\tunsigned int srcu_idx;\t\t\t/* Current rdr array element. */\n\tunsigned long srcu_gp_seq;\t\t/* Grace-period seq #. */\n\tunsigned long srcu_gp_seq_needed;\t/* Latest gp_seq needed. */\n\tunsigned long srcu_gp_seq_needed_exp;\t/* Furthest future exp GP. */\n\tunsigned long srcu_last_gp_end;\t\t/* Last GP end timestamp (ns) */\n\tstruct srcu_data __percpu *sda;\t\t/* Per-CPU srcu_data array. */\n\tunsigned long srcu_barrier_seq;\t\t/* srcu_barrier seq #. */\n\tstruct mutex srcu_barrier_mutex;\t/* Serialize barrier ops. */\n\tstruct completion srcu_barrier_completion;\n\t\t\t\t\t\t/* Awaken barrier rq at end. */\n\tatomic_t srcu_barrier_cpu_cnt;\t\t/* # CPUs not yet posting a */\n\t\t\t\t\t\t/*  callback for the barrier */\n\t\t\t\t\t\t/*  operation. */\n\tstruct delayed_work work;\n#ifdef CONFIG_DEBUG_LOCK_ALLOC\n\tstruct lockdep_map dep_map;\n#endif /* #ifdef CONFIG_DEBUG_LOCK_ALLOC */\n};\n\n/* Values for state variable (bottom bits of ->srcu_gp_seq). */\n#define SRCU_STATE_IDLE\t\t0\n#define SRCU_STATE_SCAN1\t1\n#define SRCU_STATE_SCAN2\t2\n\n#define __SRCU_STRUCT_INIT(name, pcpu_name)\t\t\t\t\\\n{\t\t\t\t\t\t\t\t\t\\\n\t.sda = &pcpu_name,\t\t\t\t\t\t\\\n\t.lock = __SPIN_LOCK_UNLOCKED(name.lock),\t\t\t\\\n\t.srcu_gp_seq_needed = -1UL,\t\t\t\t\t\\\n\t.work = __DELAYED_WORK_INITIALIZER(name.work, NULL, 0),\t\t\\\n\t__SRCU_DEP_MAP_INIT(name)\t\t\t\t\t\\\n}\n\n/*\n * Define and initialize a srcu struct at build time.\n * Do -not- call init_srcu_struct() nor cleanup_srcu_struct() on it.\n *\n * Note that although DEFINE_STATIC_SRCU() hides the name from other\n * files, the per-CPU variable rules nevertheless require that the\n * chosen name be globally unique.  These rules also prohibit use of\n * DEFINE_STATIC_SRCU() within a function.  If these rules are too\n * restrictive, declare the srcu_struct manually.  For example, in\n * each file:\n *\n *\tstatic struct srcu_struct my_srcu;\n *\n * Then, before the first use of each my_srcu, manually initialize it:\n *\n *\tinit_srcu_struct(&my_srcu);\n *\n * See include/linux/percpu-defs.h for the rules on per-CPU variables.\n */\n#ifdef MODULE\n# define __DEFINE_SRCU(name, is_static)\t\t\t\t\t\\\n\tis_static struct srcu_struct name;\t\t\t\t\\\n\tstruct srcu_struct * const __srcu_struct_##name\t\t\t\\\n\t\t__section(\"___srcu_struct_ptrs\") = &name\n#else\n# define __DEFINE_SRCU(name, is_static)\t\t\t\t\t\\\n\tstatic DEFINE_PER_CPU(struct srcu_data, name##_srcu_data);\t\\\n\tis_static struct srcu_struct name =\t\t\t\t\\\n\t\t__SRCU_STRUCT_INIT(name, name##_srcu_data)\n#endif\n#define DEFINE_SRCU(name)\t\t__DEFINE_SRCU(name, /* not static */)\n#define DEFINE_STATIC_SRCU(name)\t__DEFINE_SRCU(name, static)\n\nvoid synchronize_srcu_expedited(struct srcu_struct *ssp);\nvoid srcu_barrier(struct srcu_struct *ssp);\nvoid srcu_torture_stats_print(struct srcu_struct *ssp, char *tt, char *tf);\n\n#endif\n"
  },
  {
    "path": "t/tree/include/linux/stackdepot.h",
    "content": "/* SPDX-License-Identifier: GPL-2.0-or-later */\n/*\n * A generic stack depot implementation\n *\n * Author: Alexander Potapenko <glider@google.com>\n * Copyright (C) 2016 Google, Inc.\n *\n * Based on code by Dmitry Chernenkov.\n */\n\n#ifndef _LINUX_STACKDEPOT_H\n#define _LINUX_STACKDEPOT_H\n\ntypedef u32 depot_stack_handle_t;\n\ndepot_stack_handle_t stack_depot_save(unsigned long *entries,\n\t\t\t\t      unsigned int nr_entries, gfp_t gfp_flags);\n\nunsigned int stack_depot_fetch(depot_stack_handle_t handle,\n\t\t\t       unsigned long **entries);\n\n#endif\n"
  },
  {
    "path": "t/tree/include/linux/uprobes.h",
    "content": "/* SPDX-License-Identifier: GPL-2.0-or-later */\n#ifndef _LINUX_UPROBES_H\n#define _LINUX_UPROBES_H\n/*\n * User-space Probes (UProbes)\n *\n * Copyright (C) IBM Corporation, 2008-2012\n * Authors:\n *\tSrikar Dronamraju\n *\tJim Keniston\n * Copyright (C) 2011-2012 Red Hat, Inc., Peter Zijlstra\n */\n\n#include <linux/errno.h>\n#include <linux/rbtree.h>\n#include <linux/types.h>\n#include <linux/wait.h>\n\nstruct vm_area_struct;\nstruct mm_struct;\nstruct inode;\nstruct notifier_block;\nstruct page;\n\n#define UPROBE_HANDLER_REMOVE\t\t1\n#define UPROBE_HANDLER_MASK\t\t1\n\n#define MAX_URETPROBE_DEPTH\t\t64\n\nenum uprobe_filter_ctx {\n\tUPROBE_FILTER_REGISTER,\n\tUPROBE_FILTER_UNREGISTER,\n\tUPROBE_FILTER_MMAP,\n};\n\nstruct uprobe_consumer {\n\tint (*handler)(struct uprobe_consumer *self, struct pt_regs *regs);\n\tint (*ret_handler)(struct uprobe_consumer *self,\n\t\t\t\tunsigned long func,\n\t\t\t\tstruct pt_regs *regs);\n\tbool (*filter)(struct uprobe_consumer *self,\n\t\t\t\tenum uprobe_filter_ctx ctx,\n\t\t\t\tstruct mm_struct *mm);\n\n\tstruct uprobe_consumer *next;\n};\n\n#ifdef CONFIG_UPROBES\n#include <asm/uprobes.h>\n\nenum uprobe_task_state {\n\tUTASK_RUNNING,\n\tUTASK_SSTEP,\n\tUTASK_SSTEP_ACK,\n\tUTASK_SSTEP_TRAPPED,\n};\n\n/*\n * uprobe_task: Metadata of a task while it singlesteps.\n */\nstruct uprobe_task {\n\tenum uprobe_task_state\t\tstate;\n\n\tunion {\n\t\tstruct {\n\t\t\tstruct arch_uprobe_task\tautask;\n\t\t\tunsigned long\t\tvaddr;\n\t\t};\n\n\t\tstruct {\n\t\t\tstruct callback_head\tdup_xol_work;\n\t\t\tunsigned long\t\tdup_xol_addr;\n\t\t};\n\t};\n\n\tstruct uprobe\t\t\t*active_uprobe;\n\tunsigned long\t\t\txol_vaddr;\n\n\tstruct return_instance\t\t*return_instances;\n\tunsigned int\t\t\tdepth;\n};\n\nstruct return_instance {\n\tstruct uprobe\t\t*uprobe;\n\tunsigned long\t\tfunc;\n\tunsigned long\t\tstack;\t\t/* stack pointer */\n\tunsigned long\t\torig_ret_vaddr; /* original return address */\n\tbool\t\t\tchained;\t/* true, if instance is nested */\n\n\tstruct return_instance\t*next;\t\t/* keep as stack */\n};\n\nenum rp_check {\n\tRP_CHECK_CALL,\n\tRP_CHECK_CHAIN_CALL,\n\tRP_CHECK_RET,\n};\n\nstruct xol_area;\n\nstruct uprobes_state {\n\tstruct xol_area\t\t*xol_area;\n};\n\nextern void __init uprobes_init(void);\nextern int set_swbp(struct arch_uprobe *aup, struct mm_struct *mm, unsigned long vaddr);\nextern int set_orig_insn(struct arch_uprobe *aup, struct mm_struct *mm, unsigned long vaddr);\nextern bool is_swbp_insn(uprobe_opcode_t *insn);\nextern bool is_trap_insn(uprobe_opcode_t *insn);\nextern unsigned long uprobe_get_swbp_addr(struct pt_regs *regs);\nextern unsigned long uprobe_get_trap_addr(struct pt_regs *regs);\nextern int uprobe_write_opcode(struct arch_uprobe *auprobe, struct mm_struct *mm, unsigned long vaddr, uprobe_opcode_t);\nextern int uprobe_register(struct inode *inode, loff_t offset, struct uprobe_consumer *uc);\nextern int uprobe_register_refctr(struct inode *inode, loff_t offset, loff_t ref_ctr_offset, struct uprobe_consumer *uc);\nextern int uprobe_apply(struct inode *inode, loff_t offset, struct uprobe_consumer *uc, bool);\nextern void uprobe_unregister(struct inode *inode, loff_t offset, struct uprobe_consumer *uc);\nextern int uprobe_mmap(struct vm_area_struct *vma);\nextern void uprobe_munmap(struct vm_area_struct *vma, unsigned long start, unsigned long end);\nextern void uprobe_start_dup_mmap(void);\nextern void uprobe_end_dup_mmap(void);\nextern void uprobe_dup_mmap(struct mm_struct *oldmm, struct mm_struct *newmm);\nextern void uprobe_free_utask(struct task_struct *t);\nextern void uprobe_copy_process(struct task_struct *t, unsigned long flags);\nextern int uprobe_post_sstep_notifier(struct pt_regs *regs);\nextern int uprobe_pre_sstep_notifier(struct pt_regs *regs);\nextern void uprobe_notify_resume(struct pt_regs *regs);\nextern bool uprobe_deny_signal(void);\nextern bool arch_uprobe_skip_sstep(struct arch_uprobe *aup, struct pt_regs *regs);\nextern void uprobe_clear_state(struct mm_struct *mm);\nextern int  arch_uprobe_analyze_insn(struct arch_uprobe *aup, struct mm_struct *mm, unsigned long addr);\nextern int  arch_uprobe_pre_xol(struct arch_uprobe *aup, struct pt_regs *regs);\nextern int  arch_uprobe_post_xol(struct arch_uprobe *aup, struct pt_regs *regs);\nextern bool arch_uprobe_xol_was_trapped(struct task_struct *tsk);\nextern int  arch_uprobe_exception_notify(struct notifier_block *self, unsigned long val, void *data);\nextern void arch_uprobe_abort_xol(struct arch_uprobe *aup, struct pt_regs *regs);\nextern unsigned long arch_uretprobe_hijack_return_addr(unsigned long trampoline_vaddr, struct pt_regs *regs);\nextern bool arch_uretprobe_is_alive(struct return_instance *ret, enum rp_check ctx, struct pt_regs *regs);\nextern bool arch_uprobe_ignore(struct arch_uprobe *aup, struct pt_regs *regs);\nextern void arch_uprobe_copy_ixol(struct page *page, unsigned long vaddr,\n\t\t\t\t\t void *src, unsigned long len);\n#else /* !CONFIG_UPROBES */\nstruct uprobes_state {\n};\n\nstatic inline void uprobes_init(void)\n{\n}\n\n#define uprobe_get_trap_addr(regs)\tinstruction_pointer(regs)\n\nstatic inline int\nuprobe_register(struct inode *inode, loff_t offset, struct uprobe_consumer *uc)\n{\n\treturn -ENOSYS;\n}\nstatic inline int uprobe_register_refctr(struct inode *inode, loff_t offset, loff_t ref_ctr_offset, struct uprobe_consumer *uc)\n{\n\treturn -ENOSYS;\n}\nstatic inline int\nuprobe_apply(struct inode *inode, loff_t offset, struct uprobe_consumer *uc, bool add)\n{\n\treturn -ENOSYS;\n}\nstatic inline void\nuprobe_unregister(struct inode *inode, loff_t offset, struct uprobe_consumer *uc)\n{\n}\nstatic inline int uprobe_mmap(struct vm_area_struct *vma)\n{\n\treturn 0;\n}\nstatic inline void\nuprobe_munmap(struct vm_area_struct *vma, unsigned long start, unsigned long end)\n{\n}\nstatic inline void uprobe_start_dup_mmap(void)\n{\n}\nstatic inline void uprobe_end_dup_mmap(void)\n{\n}\nstatic inline void\nuprobe_dup_mmap(struct mm_struct *oldmm, struct mm_struct *newmm)\n{\n}\nstatic inline void uprobe_notify_resume(struct pt_regs *regs)\n{\n}\nstatic inline bool uprobe_deny_signal(void)\n{\n\treturn false;\n}\nstatic inline void uprobe_free_utask(struct task_struct *t)\n{\n}\nstatic inline void uprobe_copy_process(struct task_struct *t, unsigned long flags)\n{\n}\nstatic inline void uprobe_clear_state(struct mm_struct *mm)\n{\n}\n#endif /* !CONFIG_UPROBES */\n#endif\t/* _LINUX_UPROBES_H */\n"
  },
  {
    "path": "t/tree/include/linux/xarray.h",
    "content": "/* SPDX-License-Identifier: GPL-2.0+ */\n#ifndef _LINUX_XARRAY_H\n#define _LINUX_XARRAY_H\n/*\n * eXtensible Arrays\n * Copyright (c) 2017 Microsoft Corporation\n * Author: Matthew Wilcox <willy@infradead.org>\n *\n * See Documentation/core-api/xarray.rst for how to use the XArray.\n */\n\n#include <linux/bug.h>\n#include <linux/compiler.h>\n#include <linux/gfp.h>\n#include <linux/kconfig.h>\n#include <linux/kernel.h>\n#include <linux/rcupdate.h>\n#include <linux/spinlock.h>\n#include <linux/types.h>\n\n/*\n * The bottom two bits of the entry determine how the XArray interprets\n * the contents:\n *\n * 00: Pointer entry\n * 10: Internal entry\n * x1: Value entry or tagged pointer\n *\n * Attempting to store internal entries in the XArray is a bug.\n *\n * Most internal entries are pointers to the next node in the tree.\n * The following internal entries have a special meaning:\n *\n * 0-62: Sibling entries\n * 256: Zero entry\n * 257: Retry entry\n *\n * Errors are also represented as internal entries, but use the negative\n * space (-4094 to -2).  They're never stored in the slots array; only\n * returned by the normal API.\n */\n\n#define BITS_PER_XA_VALUE\t(BITS_PER_LONG - 1)\n\n/**\n * xa_mk_value() - Create an XArray entry from an integer.\n * @v: Value to store in XArray.\n *\n * Context: Any context.\n * Return: An entry suitable for storing in the XArray.\n */\nstatic inline void *xa_mk_value(unsigned long v)\n{\n\tWARN_ON((long)v < 0);\n\treturn (void *)((v << 1) | 1);\n}\n\n/**\n * xa_to_value() - Get value stored in an XArray entry.\n * @entry: XArray entry.\n *\n * Context: Any context.\n * Return: The value stored in the XArray entry.\n */\nstatic inline unsigned long xa_to_value(const void *entry)\n{\n\treturn (unsigned long)entry >> 1;\n}\n\n/**\n * xa_is_value() - Determine if an entry is a value.\n * @entry: XArray entry.\n *\n * Context: Any context.\n * Return: True if the entry is a value, false if it is a pointer.\n */\nstatic inline bool xa_is_value(const void *entry)\n{\n\treturn (unsigned long)entry & 1;\n}\n\n/**\n * xa_tag_pointer() - Create an XArray entry for a tagged pointer.\n * @p: Plain pointer.\n * @tag: Tag value (0, 1 or 3).\n *\n * If the user of the XArray prefers, they can tag their pointers instead\n * of storing value entries.  Three tags are available (0, 1 and 3).\n * These are distinct from the xa_mark_t as they are not replicated up\n * through the array and cannot be searched for.\n *\n * Context: Any context.\n * Return: An XArray entry.\n */\nstatic inline void *xa_tag_pointer(void *p, unsigned long tag)\n{\n\treturn (void *)((unsigned long)p | tag);\n}\n\n/**\n * xa_untag_pointer() - Turn an XArray entry into a plain pointer.\n * @entry: XArray entry.\n *\n * If you have stored a tagged pointer in the XArray, call this function\n * to get the untagged version of the pointer.\n *\n * Context: Any context.\n * Return: A pointer.\n */\nstatic inline void *xa_untag_pointer(void *entry)\n{\n\treturn (void *)((unsigned long)entry & ~3UL);\n}\n\n/**\n * xa_pointer_tag() - Get the tag stored in an XArray entry.\n * @entry: XArray entry.\n *\n * If you have stored a tagged pointer in the XArray, call this function\n * to get the tag of that pointer.\n *\n * Context: Any context.\n * Return: A tag.\n */\nstatic inline unsigned int xa_pointer_tag(void *entry)\n{\n\treturn (unsigned long)entry & 3UL;\n}\n\n/*\n * xa_mk_internal() - Create an internal entry.\n * @v: Value to turn into an internal entry.\n *\n * Internal entries are used for a number of purposes.  Entries 0-255 are\n * used for sibling entries (only 0-62 are used by the current code).  256\n * is used for the retry entry.  257 is used for the reserved / zero entry.\n * Negative internal entries are used to represent errnos.  Node pointers\n * are also tagged as internal entries in some situations.\n *\n * Context: Any context.\n * Return: An XArray internal entry corresponding to this value.\n */\nstatic inline void *xa_mk_internal(unsigned long v)\n{\n\treturn (void *)((v << 2) | 2);\n}\n\n/*\n * xa_to_internal() - Extract the value from an internal entry.\n * @entry: XArray entry.\n *\n * Context: Any context.\n * Return: The value which was stored in the internal entry.\n */\nstatic inline unsigned long xa_to_internal(const void *entry)\n{\n\treturn (unsigned long)entry >> 2;\n}\n\n/*\n * xa_is_internal() - Is the entry an internal entry?\n * @entry: XArray entry.\n *\n * Context: Any context.\n * Return: %true if the entry is an internal entry.\n */\nstatic inline bool xa_is_internal(const void *entry)\n{\n\treturn ((unsigned long)entry & 3) == 2;\n}\n\n#define XA_ZERO_ENTRY\t\txa_mk_internal(257)\n\n/**\n * xa_is_zero() - Is the entry a zero entry?\n * @entry: Entry retrieved from the XArray\n *\n * The normal API will return NULL as the contents of a slot containing\n * a zero entry.  You can only see zero entries by using the advanced API.\n *\n * Return: %true if the entry is a zero entry.\n */\nstatic inline bool xa_is_zero(const void *entry)\n{\n\treturn unlikely(entry == XA_ZERO_ENTRY);\n}\n\n/**\n * xa_is_err() - Report whether an XArray operation returned an error\n * @entry: Result from calling an XArray function\n *\n * If an XArray operation cannot complete an operation, it will return\n * a special value indicating an error.  This function tells you\n * whether an error occurred; xa_err() tells you which error occurred.\n *\n * Context: Any context.\n * Return: %true if the entry indicates an error.\n */\nstatic inline bool xa_is_err(const void *entry)\n{\n\treturn unlikely(xa_is_internal(entry) &&\n\t\t\tentry >= xa_mk_internal(-MAX_ERRNO));\n}\n\n/**\n * xa_err() - Turn an XArray result into an errno.\n * @entry: Result from calling an XArray function.\n *\n * If an XArray operation cannot complete an operation, it will return\n * a special pointer value which encodes an errno.  This function extracts\n * the errno from the pointer value, or returns 0 if the pointer does not\n * represent an errno.\n *\n * Context: Any context.\n * Return: A negative errno or 0.\n */\nstatic inline int xa_err(void *entry)\n{\n\t/* xa_to_internal() would not do sign extension. */\n\tif (xa_is_err(entry))\n\t\treturn (long)entry >> 2;\n\treturn 0;\n}\n\n/**\n * struct xa_limit - Represents a range of IDs.\n * @min: The lowest ID to allocate (inclusive).\n * @max: The maximum ID to allocate (inclusive).\n *\n * This structure is used either directly or via the XA_LIMIT() macro\n * to communicate the range of IDs that are valid for allocation.\n * Two common ranges are predefined for you:\n * * xa_limit_32b\t- [0 - UINT_MAX]\n * * xa_limit_31b\t- [0 - INT_MAX]\n */\nstruct xa_limit {\n\tu32 max;\n\tu32 min;\n};\n\n#define XA_LIMIT(_min, _max) (struct xa_limit) { .min = _min, .max = _max }\n\n#define xa_limit_32b\tXA_LIMIT(0, UINT_MAX)\n#define xa_limit_31b\tXA_LIMIT(0, INT_MAX)\n\ntypedef unsigned __bitwise xa_mark_t;\n#define XA_MARK_0\t\t((__force xa_mark_t)0U)\n#define XA_MARK_1\t\t((__force xa_mark_t)1U)\n#define XA_MARK_2\t\t((__force xa_mark_t)2U)\n#define XA_PRESENT\t\t((__force xa_mark_t)8U)\n#define XA_MARK_MAX\t\tXA_MARK_2\n#define XA_FREE_MARK\t\tXA_MARK_0\n\nenum xa_lock_type {\n\tXA_LOCK_IRQ = 1,\n\tXA_LOCK_BH = 2,\n};\n\n/*\n * Values for xa_flags.  The radix tree stores its GFP flags in the xa_flags,\n * and we remain compatible with that.\n */\n#define XA_FLAGS_LOCK_IRQ\t((__force gfp_t)XA_LOCK_IRQ)\n#define XA_FLAGS_LOCK_BH\t((__force gfp_t)XA_LOCK_BH)\n#define XA_FLAGS_TRACK_FREE\t((__force gfp_t)4U)\n#define XA_FLAGS_ZERO_BUSY\t((__force gfp_t)8U)\n#define XA_FLAGS_ALLOC_WRAPPED\t((__force gfp_t)16U)\n#define XA_FLAGS_ACCOUNT\t((__force gfp_t)32U)\n#define XA_FLAGS_MARK(mark)\t((__force gfp_t)((1U << __GFP_BITS_SHIFT) << \\\n\t\t\t\t\t\t(__force unsigned)(mark)))\n\n/* ALLOC is for a normal 0-based alloc.  ALLOC1 is for an 1-based alloc */\n#define XA_FLAGS_ALLOC\t(XA_FLAGS_TRACK_FREE | XA_FLAGS_MARK(XA_FREE_MARK))\n#define XA_FLAGS_ALLOC1\t(XA_FLAGS_TRACK_FREE | XA_FLAGS_ZERO_BUSY)\n\n/**\n * struct xarray - The anchor of the XArray.\n * @xa_lock: Lock that protects the contents of the XArray.\n *\n * To use the xarray, define it statically or embed it in your data structure.\n * It is a very small data structure, so it does not usually make sense to\n * allocate it separately and keep a pointer to it in your data structure.\n *\n * You may use the xa_lock to protect your own data structures as well.\n */\n/*\n * If all of the entries in the array are NULL, @xa_head is a NULL pointer.\n * If the only non-NULL entry in the array is at index 0, @xa_head is that\n * entry.  If any other entry in the array is non-NULL, @xa_head points\n * to an @xa_node.\n */\nstruct xarray {\n\tspinlock_t\txa_lock;\n/* private: The rest of the data structure is not to be used directly. */\n\tgfp_t\t\txa_flags;\n\tvoid __rcu *\txa_head;\n};\n\n#define XARRAY_INIT(name, flags) {\t\t\t\t\\\n\t.xa_lock = __SPIN_LOCK_UNLOCKED(name.xa_lock),\t\t\\\n\t.xa_flags = flags,\t\t\t\t\t\\\n\t.xa_head = NULL,\t\t\t\t\t\\\n}\n\n/**\n * DEFINE_XARRAY_FLAGS() - Define an XArray with custom flags.\n * @name: A string that names your XArray.\n * @flags: XA_FLAG values.\n *\n * This is intended for file scope definitions of XArrays.  It declares\n * and initialises an empty XArray with the chosen name and flags.  It is\n * equivalent to calling xa_init_flags() on the array, but it does the\n * initialisation at compiletime instead of runtime.\n */\n#define DEFINE_XARRAY_FLAGS(name, flags)\t\t\t\t\\\n\tstruct xarray name = XARRAY_INIT(name, flags)\n\n/**\n * DEFINE_XARRAY() - Define an XArray.\n * @name: A string that names your XArray.\n *\n * This is intended for file scope definitions of XArrays.  It declares\n * and initialises an empty XArray with the chosen name.  It is equivalent\n * to calling xa_init() on the array, but it does the initialisation at\n * compiletime instead of runtime.\n */\n#define DEFINE_XARRAY(name) DEFINE_XARRAY_FLAGS(name, 0)\n\n/**\n * DEFINE_XARRAY_ALLOC() - Define an XArray which allocates IDs starting at 0.\n * @name: A string that names your XArray.\n *\n * This is intended for file scope definitions of allocating XArrays.\n * See also DEFINE_XARRAY().\n */\n#define DEFINE_XARRAY_ALLOC(name) DEFINE_XARRAY_FLAGS(name, XA_FLAGS_ALLOC)\n\n/**\n * DEFINE_XARRAY_ALLOC1() - Define an XArray which allocates IDs starting at 1.\n * @name: A string that names your XArray.\n *\n * This is intended for file scope definitions of allocating XArrays.\n * See also DEFINE_XARRAY().\n */\n#define DEFINE_XARRAY_ALLOC1(name) DEFINE_XARRAY_FLAGS(name, XA_FLAGS_ALLOC1)\n\nvoid *xa_load(struct xarray *, unsigned long index);\nvoid *xa_store(struct xarray *, unsigned long index, void *entry, gfp_t);\nvoid *xa_erase(struct xarray *, unsigned long index);\nvoid *xa_store_range(struct xarray *, unsigned long first, unsigned long last,\n\t\t\tvoid *entry, gfp_t);\nbool xa_get_mark(struct xarray *, unsigned long index, xa_mark_t);\nvoid xa_set_mark(struct xarray *, unsigned long index, xa_mark_t);\nvoid xa_clear_mark(struct xarray *, unsigned long index, xa_mark_t);\nvoid *xa_find(struct xarray *xa, unsigned long *index,\n\t\tunsigned long max, xa_mark_t) __attribute__((nonnull(2)));\nvoid *xa_find_after(struct xarray *xa, unsigned long *index,\n\t\tunsigned long max, xa_mark_t) __attribute__((nonnull(2)));\nunsigned int xa_extract(struct xarray *, void **dst, unsigned long start,\n\t\tunsigned long max, unsigned int n, xa_mark_t);\nvoid xa_destroy(struct xarray *);\n\n/**\n * xa_init_flags() - Initialise an empty XArray with flags.\n * @xa: XArray.\n * @flags: XA_FLAG values.\n *\n * If you need to initialise an XArray with special flags (eg you need\n * to take the lock from interrupt context), use this function instead\n * of xa_init().\n *\n * Context: Any context.\n */\nstatic inline void xa_init_flags(struct xarray *xa, gfp_t flags)\n{\n\tspin_lock_init(&xa->xa_lock);\n\txa->xa_flags = flags;\n\txa->xa_head = NULL;\n}\n\n/**\n * xa_init() - Initialise an empty XArray.\n * @xa: XArray.\n *\n * An empty XArray is full of NULL entries.\n *\n * Context: Any context.\n */\nstatic inline void xa_init(struct xarray *xa)\n{\n\txa_init_flags(xa, 0);\n}\n\n/**\n * xa_empty() - Determine if an array has any present entries.\n * @xa: XArray.\n *\n * Context: Any context.\n * Return: %true if the array contains only NULL pointers.\n */\nstatic inline bool xa_empty(const struct xarray *xa)\n{\n\treturn xa->xa_head == NULL;\n}\n\n/**\n * xa_marked() - Inquire whether any entry in this array has a mark set\n * @xa: Array\n * @mark: Mark value\n *\n * Context: Any context.\n * Return: %true if any entry has this mark set.\n */\nstatic inline bool xa_marked(const struct xarray *xa, xa_mark_t mark)\n{\n\treturn xa->xa_flags & XA_FLAGS_MARK(mark);\n}\n\n/**\n * xa_for_each_start() - Iterate over a portion of an XArray.\n * @xa: XArray.\n * @index: Index of @entry.\n * @entry: Entry retrieved from array.\n * @start: First index to retrieve from array.\n *\n * During the iteration, @entry will have the value of the entry stored\n * in @xa at @index.  You may modify @index during the iteration if you\n * want to skip or reprocess indices.  It is safe to modify the array\n * during the iteration.  At the end of the iteration, @entry will be set\n * to NULL and @index will have a value less than or equal to max.\n *\n * xa_for_each_start() is O(n.log(n)) while xas_for_each() is O(n).  You have\n * to handle your own locking with xas_for_each(), and if you have to unlock\n * after each iteration, it will also end up being O(n.log(n)).\n * xa_for_each_start() will spin if it hits a retry entry; if you intend to\n * see retry entries, you should use the xas_for_each() iterator instead.\n * The xas_for_each() iterator will expand into more inline code than\n * xa_for_each_start().\n *\n * Context: Any context.  Takes and releases the RCU lock.\n */\n#define xa_for_each_start(xa, index, entry, start)\t\t\t\\\n\tfor (index = start,\t\t\t\t\t\t\\\n\t     entry = xa_find(xa, &index, ULONG_MAX, XA_PRESENT);\t\\\n\t     entry;\t\t\t\t\t\t\t\\\n\t     entry = xa_find_after(xa, &index, ULONG_MAX, XA_PRESENT))\n\n/**\n * xa_for_each() - Iterate over present entries in an XArray.\n * @xa: XArray.\n * @index: Index of @entry.\n * @entry: Entry retrieved from array.\n *\n * During the iteration, @entry will have the value of the entry stored\n * in @xa at @index.  You may modify @index during the iteration if you want\n * to skip or reprocess indices.  It is safe to modify the array during the\n * iteration.  At the end of the iteration, @entry will be set to NULL and\n * @index will have a value less than or equal to max.\n *\n * xa_for_each() is O(n.log(n)) while xas_for_each() is O(n).  You have\n * to handle your own locking with xas_for_each(), and if you have to unlock\n * after each iteration, it will also end up being O(n.log(n)).  xa_for_each()\n * will spin if it hits a retry entry; if you intend to see retry entries,\n * you should use the xas_for_each() iterator instead.  The xas_for_each()\n * iterator will expand into more inline code than xa_for_each().\n *\n * Context: Any context.  Takes and releases the RCU lock.\n */\n#define xa_for_each(xa, index, entry) \\\n\txa_for_each_start(xa, index, entry, 0)\n\n/**\n * xa_for_each_marked() - Iterate over marked entries in an XArray.\n * @xa: XArray.\n * @index: Index of @entry.\n * @entry: Entry retrieved from array.\n * @filter: Selection criterion.\n *\n * During the iteration, @entry will have the value of the entry stored\n * in @xa at @index.  The iteration will skip all entries in the array\n * which do not match @filter.  You may modify @index during the iteration\n * if you want to skip or reprocess indices.  It is safe to modify the array\n * during the iteration.  At the end of the iteration, @entry will be set to\n * NULL and @index will have a value less than or equal to max.\n *\n * xa_for_each_marked() is O(n.log(n)) while xas_for_each_marked() is O(n).\n * You have to handle your own locking with xas_for_each(), and if you have\n * to unlock after each iteration, it will also end up being O(n.log(n)).\n * xa_for_each_marked() will spin if it hits a retry entry; if you intend to\n * see retry entries, you should use the xas_for_each_marked() iterator\n * instead.  The xas_for_each_marked() iterator will expand into more inline\n * code than xa_for_each_marked().\n *\n * Context: Any context.  Takes and releases the RCU lock.\n */\n#define xa_for_each_marked(xa, index, entry, filter) \\\n\tfor (index = 0, entry = xa_find(xa, &index, ULONG_MAX, filter); \\\n\t     entry; entry = xa_find_after(xa, &index, ULONG_MAX, filter))\n\n#define xa_trylock(xa)\t\tspin_trylock(&(xa)->xa_lock)\n#define xa_lock(xa)\t\tspin_lock(&(xa)->xa_lock)\n#define xa_unlock(xa)\t\tspin_unlock(&(xa)->xa_lock)\n#define xa_lock_bh(xa)\t\tspin_lock_bh(&(xa)->xa_lock)\n#define xa_unlock_bh(xa)\tspin_unlock_bh(&(xa)->xa_lock)\n#define xa_lock_irq(xa)\t\tspin_lock_irq(&(xa)->xa_lock)\n#define xa_unlock_irq(xa)\tspin_unlock_irq(&(xa)->xa_lock)\n#define xa_lock_irqsave(xa, flags) \\\n\t\t\t\tspin_lock_irqsave(&(xa)->xa_lock, flags)\n#define xa_unlock_irqrestore(xa, flags) \\\n\t\t\t\tspin_unlock_irqrestore(&(xa)->xa_lock, flags)\n\n/*\n * Versions of the normal API which require the caller to hold the\n * xa_lock.  If the GFP flags allow it, they will drop the lock to\n * allocate memory, then reacquire it afterwards.  These functions\n * may also re-enable interrupts if the XArray flags indicate the\n * locking should be interrupt safe.\n */\nvoid *__xa_erase(struct xarray *, unsigned long index);\nvoid *__xa_store(struct xarray *, unsigned long index, void *entry, gfp_t);\nvoid *__xa_cmpxchg(struct xarray *, unsigned long index, void *old,\n\t\tvoid *entry, gfp_t);\nint __must_check __xa_insert(struct xarray *, unsigned long index,\n\t\tvoid *entry, gfp_t);\nint __must_check __xa_alloc(struct xarray *, u32 *id, void *entry,\n\t\tstruct xa_limit, gfp_t);\nint __must_check __xa_alloc_cyclic(struct xarray *, u32 *id, void *entry,\n\t\tstruct xa_limit, u32 *next, gfp_t);\nvoid __xa_set_mark(struct xarray *, unsigned long index, xa_mark_t);\nvoid __xa_clear_mark(struct xarray *, unsigned long index, xa_mark_t);\n\n/**\n * xa_store_bh() - Store this entry in the XArray.\n * @xa: XArray.\n * @index: Index into array.\n * @entry: New entry.\n * @gfp: Memory allocation flags.\n *\n * This function is like calling xa_store() except it disables softirqs\n * while holding the array lock.\n *\n * Context: Any context.  Takes and releases the xa_lock while\n * disabling softirqs.\n * Return: The entry which used to be at this index.\n */\nstatic inline void *xa_store_bh(struct xarray *xa, unsigned long index,\n\t\tvoid *entry, gfp_t gfp)\n{\n\tvoid *curr;\n\n\txa_lock_bh(xa);\n\tcurr = __xa_store(xa, index, entry, gfp);\n\txa_unlock_bh(xa);\n\n\treturn curr;\n}\n\n/**\n * xa_store_irq() - Store this entry in the XArray.\n * @xa: XArray.\n * @index: Index into array.\n * @entry: New entry.\n * @gfp: Memory allocation flags.\n *\n * This function is like calling xa_store() except it disables interrupts\n * while holding the array lock.\n *\n * Context: Process context.  Takes and releases the xa_lock while\n * disabling interrupts.\n * Return: The entry which used to be at this index.\n */\nstatic inline void *xa_store_irq(struct xarray *xa, unsigned long index,\n\t\tvoid *entry, gfp_t gfp)\n{\n\tvoid *curr;\n\n\txa_lock_irq(xa);\n\tcurr = __xa_store(xa, index, entry, gfp);\n\txa_unlock_irq(xa);\n\n\treturn curr;\n}\n\n/**\n * xa_erase_bh() - Erase this entry from the XArray.\n * @xa: XArray.\n * @index: Index of entry.\n *\n * After this function returns, loading from @index will return %NULL.\n * If the index is part of a multi-index entry, all indices will be erased\n * and none of the entries will be part of a multi-index entry.\n *\n * Context: Any context.  Takes and releases the xa_lock while\n * disabling softirqs.\n * Return: The entry which used to be at this index.\n */\nstatic inline void *xa_erase_bh(struct xarray *xa, unsigned long index)\n{\n\tvoid *entry;\n\n\txa_lock_bh(xa);\n\tentry = __xa_erase(xa, index);\n\txa_unlock_bh(xa);\n\n\treturn entry;\n}\n\n/**\n * xa_erase_irq() - Erase this entry from the XArray.\n * @xa: XArray.\n * @index: Index of entry.\n *\n * After this function returns, loading from @index will return %NULL.\n * If the index is part of a multi-index entry, all indices will be erased\n * and none of the entries will be part of a multi-index entry.\n *\n * Context: Process context.  Takes and releases the xa_lock while\n * disabling interrupts.\n * Return: The entry which used to be at this index.\n */\nstatic inline void *xa_erase_irq(struct xarray *xa, unsigned long index)\n{\n\tvoid *entry;\n\n\txa_lock_irq(xa);\n\tentry = __xa_erase(xa, index);\n\txa_unlock_irq(xa);\n\n\treturn entry;\n}\n\n/**\n * xa_cmpxchg() - Conditionally replace an entry in the XArray.\n * @xa: XArray.\n * @index: Index into array.\n * @old: Old value to test against.\n * @entry: New value to place in array.\n * @gfp: Memory allocation flags.\n *\n * If the entry at @index is the same as @old, replace it with @entry.\n * If the return value is equal to @old, then the exchange was successful.\n *\n * Context: Any context.  Takes and releases the xa_lock.  May sleep\n * if the @gfp flags permit.\n * Return: The old value at this index or xa_err() if an error happened.\n */\nstatic inline void *xa_cmpxchg(struct xarray *xa, unsigned long index,\n\t\t\tvoid *old, void *entry, gfp_t gfp)\n{\n\tvoid *curr;\n\n\txa_lock(xa);\n\tcurr = __xa_cmpxchg(xa, index, old, entry, gfp);\n\txa_unlock(xa);\n\n\treturn curr;\n}\n\n/**\n * xa_cmpxchg_bh() - Conditionally replace an entry in the XArray.\n * @xa: XArray.\n * @index: Index into array.\n * @old: Old value to test against.\n * @entry: New value to place in array.\n * @gfp: Memory allocation flags.\n *\n * This function is like calling xa_cmpxchg() except it disables softirqs\n * while holding the array lock.\n *\n * Context: Any context.  Takes and releases the xa_lock while\n * disabling softirqs.  May sleep if the @gfp flags permit.\n * Return: The old value at this index or xa_err() if an error happened.\n */\nstatic inline void *xa_cmpxchg_bh(struct xarray *xa, unsigned long index,\n\t\t\tvoid *old, void *entry, gfp_t gfp)\n{\n\tvoid *curr;\n\n\txa_lock_bh(xa);\n\tcurr = __xa_cmpxchg(xa, index, old, entry, gfp);\n\txa_unlock_bh(xa);\n\n\treturn curr;\n}\n\n/**\n * xa_cmpxchg_irq() - Conditionally replace an entry in the XArray.\n * @xa: XArray.\n * @index: Index into array.\n * @old: Old value to test against.\n * @entry: New value to place in array.\n * @gfp: Memory allocation flags.\n *\n * This function is like calling xa_cmpxchg() except it disables interrupts\n * while holding the array lock.\n *\n * Context: Process context.  Takes and releases the xa_lock while\n * disabling interrupts.  May sleep if the @gfp flags permit.\n * Return: The old value at this index or xa_err() if an error happened.\n */\nstatic inline void *xa_cmpxchg_irq(struct xarray *xa, unsigned long index,\n\t\t\tvoid *old, void *entry, gfp_t gfp)\n{\n\tvoid *curr;\n\n\txa_lock_irq(xa);\n\tcurr = __xa_cmpxchg(xa, index, old, entry, gfp);\n\txa_unlock_irq(xa);\n\n\treturn curr;\n}\n\n/**\n * xa_insert() - Store this entry in the XArray unless another entry is\n *\t\t\talready present.\n * @xa: XArray.\n * @index: Index into array.\n * @entry: New entry.\n * @gfp: Memory allocation flags.\n *\n * Inserting a NULL entry will store a reserved entry (like xa_reserve())\n * if no entry is present.  Inserting will fail if a reserved entry is\n * present, even though loading from this index will return NULL.\n *\n * Context: Any context.  Takes and releases the xa_lock.  May sleep if\n * the @gfp flags permit.\n * Return: 0 if the store succeeded.  -EBUSY if another entry was present.\n * -ENOMEM if memory could not be allocated.\n */\nstatic inline int __must_check xa_insert(struct xarray *xa,\n\t\tunsigned long index, void *entry, gfp_t gfp)\n{\n\tint err;\n\n\txa_lock(xa);\n\terr = __xa_insert(xa, index, entry, gfp);\n\txa_unlock(xa);\n\n\treturn err;\n}\n\n/**\n * xa_insert_bh() - Store this entry in the XArray unless another entry is\n *\t\t\talready present.\n * @xa: XArray.\n * @index: Index into array.\n * @entry: New entry.\n * @gfp: Memory allocation flags.\n *\n * Inserting a NULL entry will store a reserved entry (like xa_reserve())\n * if no entry is present.  Inserting will fail if a reserved entry is\n * present, even though loading from this index will return NULL.\n *\n * Context: Any context.  Takes and releases the xa_lock while\n * disabling softirqs.  May sleep if the @gfp flags permit.\n * Return: 0 if the store succeeded.  -EBUSY if another entry was present.\n * -ENOMEM if memory could not be allocated.\n */\nstatic inline int __must_check xa_insert_bh(struct xarray *xa,\n\t\tunsigned long index, void *entry, gfp_t gfp)\n{\n\tint err;\n\n\txa_lock_bh(xa);\n\terr = __xa_insert(xa, index, entry, gfp);\n\txa_unlock_bh(xa);\n\n\treturn err;\n}\n\n/**\n * xa_insert_irq() - Store this entry in the XArray unless another entry is\n *\t\t\talready present.\n * @xa: XArray.\n * @index: Index into array.\n * @entry: New entry.\n * @gfp: Memory allocation flags.\n *\n * Inserting a NULL entry will store a reserved entry (like xa_reserve())\n * if no entry is present.  Inserting will fail if a reserved entry is\n * present, even though loading from this index will return NULL.\n *\n * Context: Process context.  Takes and releases the xa_lock while\n * disabling interrupts.  May sleep if the @gfp flags permit.\n * Return: 0 if the store succeeded.  -EBUSY if another entry was present.\n * -ENOMEM if memory could not be allocated.\n */\nstatic inline int __must_check xa_insert_irq(struct xarray *xa,\n\t\tunsigned long index, void *entry, gfp_t gfp)\n{\n\tint err;\n\n\txa_lock_irq(xa);\n\terr = __xa_insert(xa, index, entry, gfp);\n\txa_unlock_irq(xa);\n\n\treturn err;\n}\n\n/**\n * xa_alloc() - Find somewhere to store this entry in the XArray.\n * @xa: XArray.\n * @id: Pointer to ID.\n * @entry: New entry.\n * @limit: Range of ID to allocate.\n * @gfp: Memory allocation flags.\n *\n * Finds an empty entry in @xa between @limit.min and @limit.max,\n * stores the index into the @id pointer, then stores the entry at\n * that index.  A concurrent lookup will not see an uninitialised @id.\n *\n * Context: Any context.  Takes and releases the xa_lock.  May sleep if\n * the @gfp flags permit.\n * Return: 0 on success, -ENOMEM if memory could not be allocated or\n * -EBUSY if there are no free entries in @limit.\n */\nstatic inline __must_check int xa_alloc(struct xarray *xa, u32 *id,\n\t\tvoid *entry, struct xa_limit limit, gfp_t gfp)\n{\n\tint err;\n\n\txa_lock(xa);\n\terr = __xa_alloc(xa, id, entry, limit, gfp);\n\txa_unlock(xa);\n\n\treturn err;\n}\n\n/**\n * xa_alloc_bh() - Find somewhere to store this entry in the XArray.\n * @xa: XArray.\n * @id: Pointer to ID.\n * @entry: New entry.\n * @limit: Range of ID to allocate.\n * @gfp: Memory allocation flags.\n *\n * Finds an empty entry in @xa between @limit.min and @limit.max,\n * stores the index into the @id pointer, then stores the entry at\n * that index.  A concurrent lookup will not see an uninitialised @id.\n *\n * Context: Any context.  Takes and releases the xa_lock while\n * disabling softirqs.  May sleep if the @gfp flags permit.\n * Return: 0 on success, -ENOMEM if memory could not be allocated or\n * -EBUSY if there are no free entries in @limit.\n */\nstatic inline int __must_check xa_alloc_bh(struct xarray *xa, u32 *id,\n\t\tvoid *entry, struct xa_limit limit, gfp_t gfp)\n{\n\tint err;\n\n\txa_lock_bh(xa);\n\terr = __xa_alloc(xa, id, entry, limit, gfp);\n\txa_unlock_bh(xa);\n\n\treturn err;\n}\n\n/**\n * xa_alloc_irq() - Find somewhere to store this entry in the XArray.\n * @xa: XArray.\n * @id: Pointer to ID.\n * @entry: New entry.\n * @limit: Range of ID to allocate.\n * @gfp: Memory allocation flags.\n *\n * Finds an empty entry in @xa between @limit.min and @limit.max,\n * stores the index into the @id pointer, then stores the entry at\n * that index.  A concurrent lookup will not see an uninitialised @id.\n *\n * Context: Process context.  Takes and releases the xa_lock while\n * disabling interrupts.  May sleep if the @gfp flags permit.\n * Return: 0 on success, -ENOMEM if memory could not be allocated or\n * -EBUSY if there are no free entries in @limit.\n */\nstatic inline int __must_check xa_alloc_irq(struct xarray *xa, u32 *id,\n\t\tvoid *entry, struct xa_limit limit, gfp_t gfp)\n{\n\tint err;\n\n\txa_lock_irq(xa);\n\terr = __xa_alloc(xa, id, entry, limit, gfp);\n\txa_unlock_irq(xa);\n\n\treturn err;\n}\n\n/**\n * xa_alloc_cyclic() - Find somewhere to store this entry in the XArray.\n * @xa: XArray.\n * @id: Pointer to ID.\n * @entry: New entry.\n * @limit: Range of allocated ID.\n * @next: Pointer to next ID to allocate.\n * @gfp: Memory allocation flags.\n *\n * Finds an empty entry in @xa between @limit.min and @limit.max,\n * stores the index into the @id pointer, then stores the entry at\n * that index.  A concurrent lookup will not see an uninitialised @id.\n * The search for an empty entry will start at @next and will wrap\n * around if necessary.\n *\n * Context: Any context.  Takes and releases the xa_lock.  May sleep if\n * the @gfp flags permit.\n * Return: 0 if the allocation succeeded without wrapping.  1 if the\n * allocation succeeded after wrapping, -ENOMEM if memory could not be\n * allocated or -EBUSY if there are no free entries in @limit.\n */\nstatic inline int xa_alloc_cyclic(struct xarray *xa, u32 *id, void *entry,\n\t\tstruct xa_limit limit, u32 *next, gfp_t gfp)\n{\n\tint err;\n\n\txa_lock(xa);\n\terr = __xa_alloc_cyclic(xa, id, entry, limit, next, gfp);\n\txa_unlock(xa);\n\n\treturn err;\n}\n\n/**\n * xa_alloc_cyclic_bh() - Find somewhere to store this entry in the XArray.\n * @xa: XArray.\n * @id: Pointer to ID.\n * @entry: New entry.\n * @limit: Range of allocated ID.\n * @next: Pointer to next ID to allocate.\n * @gfp: Memory allocation flags.\n *\n * Finds an empty entry in @xa between @limit.min and @limit.max,\n * stores the index into the @id pointer, then stores the entry at\n * that index.  A concurrent lookup will not see an uninitialised @id.\n * The search for an empty entry will start at @next and will wrap\n * around if necessary.\n *\n * Context: Any context.  Takes and releases the xa_lock while\n * disabling softirqs.  May sleep if the @gfp flags permit.\n * Return: 0 if the allocation succeeded without wrapping.  1 if the\n * allocation succeeded after wrapping, -ENOMEM if memory could not be\n * allocated or -EBUSY if there are no free entries in @limit.\n */\nstatic inline int xa_alloc_cyclic_bh(struct xarray *xa, u32 *id, void *entry,\n\t\tstruct xa_limit limit, u32 *next, gfp_t gfp)\n{\n\tint err;\n\n\txa_lock_bh(xa);\n\terr = __xa_alloc_cyclic(xa, id, entry, limit, next, gfp);\n\txa_unlock_bh(xa);\n\n\treturn err;\n}\n\n/**\n * xa_alloc_cyclic_irq() - Find somewhere to store this entry in the XArray.\n * @xa: XArray.\n * @id: Pointer to ID.\n * @entry: New entry.\n * @limit: Range of allocated ID.\n * @next: Pointer to next ID to allocate.\n * @gfp: Memory allocation flags.\n *\n * Finds an empty entry in @xa between @limit.min and @limit.max,\n * stores the index into the @id pointer, then stores the entry at\n * that index.  A concurrent lookup will not see an uninitialised @id.\n * The search for an empty entry will start at @next and will wrap\n * around if necessary.\n *\n * Context: Process context.  Takes and releases the xa_lock while\n * disabling interrupts.  May sleep if the @gfp flags permit.\n * Return: 0 if the allocation succeeded without wrapping.  1 if the\n * allocation succeeded after wrapping, -ENOMEM if memory could not be\n * allocated or -EBUSY if there are no free entries in @limit.\n */\nstatic inline int xa_alloc_cyclic_irq(struct xarray *xa, u32 *id, void *entry,\n\t\tstruct xa_limit limit, u32 *next, gfp_t gfp)\n{\n\tint err;\n\n\txa_lock_irq(xa);\n\terr = __xa_alloc_cyclic(xa, id, entry, limit, next, gfp);\n\txa_unlock_irq(xa);\n\n\treturn err;\n}\n\n/**\n * xa_reserve() - Reserve this index in the XArray.\n * @xa: XArray.\n * @index: Index into array.\n * @gfp: Memory allocation flags.\n *\n * Ensures there is somewhere to store an entry at @index in the array.\n * If there is already something stored at @index, this function does\n * nothing.  If there was nothing there, the entry is marked as reserved.\n * Loading from a reserved entry returns a %NULL pointer.\n *\n * If you do not use the entry that you have reserved, call xa_release()\n * or xa_erase() to free any unnecessary memory.\n *\n * Context: Any context.  Takes and releases the xa_lock.\n * May sleep if the @gfp flags permit.\n * Return: 0 if the reservation succeeded or -ENOMEM if it failed.\n */\nstatic inline __must_check\nint xa_reserve(struct xarray *xa, unsigned long index, gfp_t gfp)\n{\n\treturn xa_err(xa_cmpxchg(xa, index, NULL, XA_ZERO_ENTRY, gfp));\n}\n\n/**\n * xa_reserve_bh() - Reserve this index in the XArray.\n * @xa: XArray.\n * @index: Index into array.\n * @gfp: Memory allocation flags.\n *\n * A softirq-disabling version of xa_reserve().\n *\n * Context: Any context.  Takes and releases the xa_lock while\n * disabling softirqs.\n * Return: 0 if the reservation succeeded or -ENOMEM if it failed.\n */\nstatic inline __must_check\nint xa_reserve_bh(struct xarray *xa, unsigned long index, gfp_t gfp)\n{\n\treturn xa_err(xa_cmpxchg_bh(xa, index, NULL, XA_ZERO_ENTRY, gfp));\n}\n\n/**\n * xa_reserve_irq() - Reserve this index in the XArray.\n * @xa: XArray.\n * @index: Index into array.\n * @gfp: Memory allocation flags.\n *\n * An interrupt-disabling version of xa_reserve().\n *\n * Context: Process context.  Takes and releases the xa_lock while\n * disabling interrupts.\n * Return: 0 if the reservation succeeded or -ENOMEM if it failed.\n */\nstatic inline __must_check\nint xa_reserve_irq(struct xarray *xa, unsigned long index, gfp_t gfp)\n{\n\treturn xa_err(xa_cmpxchg_irq(xa, index, NULL, XA_ZERO_ENTRY, gfp));\n}\n\n/**\n * xa_release() - Release a reserved entry.\n * @xa: XArray.\n * @index: Index of entry.\n *\n * After calling xa_reserve(), you can call this function to release the\n * reservation.  If the entry at @index has been stored to, this function\n * will do nothing.\n */\nstatic inline void xa_release(struct xarray *xa, unsigned long index)\n{\n\txa_cmpxchg(xa, index, XA_ZERO_ENTRY, NULL, 0);\n}\n\n/* Everything below here is the Advanced API.  Proceed with caution. */\n\n/*\n * The xarray is constructed out of a set of 'chunks' of pointers.  Choosing\n * the best chunk size requires some tradeoffs.  A power of two recommends\n * itself so that we can walk the tree based purely on shifts and masks.\n * Generally, the larger the better; as the number of slots per level of the\n * tree increases, the less tall the tree needs to be.  But that needs to be\n * balanced against the memory consumption of each node.  On a 64-bit system,\n * xa_node is currently 576 bytes, and we get 7 of them per 4kB page.  If we\n * doubled the number of slots per node, we'd get only 3 nodes per 4kB page.\n */\n#ifndef XA_CHUNK_SHIFT\n#define XA_CHUNK_SHIFT\t\t(CONFIG_BASE_SMALL ? 4 : 6)\n#endif\n#define XA_CHUNK_SIZE\t\t(1UL << XA_CHUNK_SHIFT)\n#define XA_CHUNK_MASK\t\t(XA_CHUNK_SIZE - 1)\n#define XA_MAX_MARKS\t\t3\n#define XA_MARK_LONGS\t\tDIV_ROUND_UP(XA_CHUNK_SIZE, BITS_PER_LONG)\n\n/*\n * @count is the count of every non-NULL element in the ->slots array\n * whether that is a value entry, a retry entry, a user pointer,\n * a sibling entry or a pointer to the next level of the tree.\n * @nr_values is the count of every element in ->slots which is\n * either a value entry or a sibling of a value entry.\n */\nstruct xa_node {\n\tunsigned char\tshift;\t\t/* Bits remaining in each slot */\n\tunsigned char\toffset;\t\t/* Slot offset in parent */\n\tunsigned char\tcount;\t\t/* Total entry count */\n\tunsigned char\tnr_values;\t/* Value entry count */\n\tstruct xa_node __rcu *parent;\t/* NULL at top of tree */\n\tstruct xarray\t*array;\t\t/* The array we belong to */\n\tunion {\n\t\tstruct list_head private_list;\t/* For tree user */\n\t\tstruct rcu_head\trcu_head;\t/* Used when freeing node */\n\t};\n\tvoid __rcu\t*slots[XA_CHUNK_SIZE];\n\tunion {\n\t\tunsigned long\ttags[XA_MAX_MARKS][XA_MARK_LONGS];\n\t\tunsigned long\tmarks[XA_MAX_MARKS][XA_MARK_LONGS];\n\t};\n};\n\nvoid xa_dump(const struct xarray *);\nvoid xa_dump_node(const struct xa_node *);\n\n#ifdef XA_DEBUG\n#define XA_BUG_ON(xa, x) do {\t\t\t\t\t\\\n\t\tif (x) {\t\t\t\t\t\\\n\t\t\txa_dump(xa);\t\t\t\t\\\n\t\t\tBUG();\t\t\t\t\t\\\n\t\t}\t\t\t\t\t\t\\\n\t} while (0)\n#define XA_NODE_BUG_ON(node, x) do {\t\t\t\t\\\n\t\tif (x) {\t\t\t\t\t\\\n\t\t\tif (node) xa_dump_node(node);\t\t\\\n\t\t\tBUG();\t\t\t\t\t\\\n\t\t}\t\t\t\t\t\t\\\n\t} while (0)\n#else\n#define XA_BUG_ON(xa, x)\tdo { } while (0)\n#define XA_NODE_BUG_ON(node, x)\tdo { } while (0)\n#endif\n\n/* Private */\nstatic inline void *xa_head(const struct xarray *xa)\n{\n\treturn rcu_dereference_check(xa->xa_head,\n\t\t\t\t\t\tlockdep_is_held(&xa->xa_lock));\n}\n\n/* Private */\nstatic inline void *xa_head_locked(const struct xarray *xa)\n{\n\treturn rcu_dereference_protected(xa->xa_head,\n\t\t\t\t\t\tlockdep_is_held(&xa->xa_lock));\n}\n\n/* Private */\nstatic inline void *xa_entry(const struct xarray *xa,\n\t\t\t\tconst struct xa_node *node, unsigned int offset)\n{\n\tXA_NODE_BUG_ON(node, offset >= XA_CHUNK_SIZE);\n\treturn rcu_dereference_check(node->slots[offset],\n\t\t\t\t\t\tlockdep_is_held(&xa->xa_lock));\n}\n\n/* Private */\nstatic inline void *xa_entry_locked(const struct xarray *xa,\n\t\t\t\tconst struct xa_node *node, unsigned int offset)\n{\n\tXA_NODE_BUG_ON(node, offset >= XA_CHUNK_SIZE);\n\treturn rcu_dereference_protected(node->slots[offset],\n\t\t\t\t\t\tlockdep_is_held(&xa->xa_lock));\n}\n\n/* Private */\nstatic inline struct xa_node *xa_parent(const struct xarray *xa,\n\t\t\t\t\tconst struct xa_node *node)\n{\n\treturn rcu_dereference_check(node->parent,\n\t\t\t\t\t\tlockdep_is_held(&xa->xa_lock));\n}\n\n/* Private */\nstatic inline struct xa_node *xa_parent_locked(const struct xarray *xa,\n\t\t\t\t\tconst struct xa_node *node)\n{\n\treturn rcu_dereference_protected(node->parent,\n\t\t\t\t\t\tlockdep_is_held(&xa->xa_lock));\n}\n\n/* Private */\nstatic inline void *xa_mk_node(const struct xa_node *node)\n{\n\treturn (void *)((unsigned long)node | 2);\n}\n\n/* Private */\nstatic inline struct xa_node *xa_to_node(const void *entry)\n{\n\treturn (struct xa_node *)((unsigned long)entry - 2);\n}\n\n/* Private */\nstatic inline bool xa_is_node(const void *entry)\n{\n\treturn xa_is_internal(entry) && (unsigned long)entry > 4096;\n}\n\n/* Private */\nstatic inline void *xa_mk_sibling(unsigned int offset)\n{\n\treturn xa_mk_internal(offset);\n}\n\n/* Private */\nstatic inline unsigned long xa_to_sibling(const void *entry)\n{\n\treturn xa_to_internal(entry);\n}\n\n/**\n * xa_is_sibling() - Is the entry a sibling entry?\n * @entry: Entry retrieved from the XArray\n *\n * Return: %true if the entry is a sibling entry.\n */\nstatic inline bool xa_is_sibling(const void *entry)\n{\n\treturn IS_ENABLED(CONFIG_XARRAY_MULTI) && xa_is_internal(entry) &&\n\t\t(entry < xa_mk_sibling(XA_CHUNK_SIZE - 1));\n}\n\n#define XA_RETRY_ENTRY\t\txa_mk_internal(256)\n\n/**\n * xa_is_retry() - Is the entry a retry entry?\n * @entry: Entry retrieved from the XArray\n *\n * Return: %true if the entry is a retry entry.\n */\nstatic inline bool xa_is_retry(const void *entry)\n{\n\treturn unlikely(entry == XA_RETRY_ENTRY);\n}\n\n/**\n * xa_is_advanced() - Is the entry only permitted for the advanced API?\n * @entry: Entry to be stored in the XArray.\n *\n * Return: %true if the entry cannot be stored by the normal API.\n */\nstatic inline bool xa_is_advanced(const void *entry)\n{\n\treturn xa_is_internal(entry) && (entry <= XA_RETRY_ENTRY);\n}\n\n/**\n * typedef xa_update_node_t - A callback function from the XArray.\n * @node: The node which is being processed\n *\n * This function is called every time the XArray updates the count of\n * present and value entries in a node.  It allows advanced users to\n * maintain the private_list in the node.\n *\n * Context: The xa_lock is held and interrupts may be disabled.\n *\t    Implementations should not drop the xa_lock, nor re-enable\n *\t    interrupts.\n */\ntypedef void (*xa_update_node_t)(struct xa_node *node);\n\n/*\n * The xa_state is opaque to its users.  It contains various different pieces\n * of state involved in the current operation on the XArray.  It should be\n * declared on the stack and passed between the various internal routines.\n * The various elements in it should not be accessed directly, but only\n * through the provided accessor functions.  The below documentation is for\n * the benefit of those working on the code, not for users of the XArray.\n *\n * @xa_node usually points to the xa_node containing the slot we're operating\n * on (and @xa_offset is the offset in the slots array).  If there is a\n * single entry in the array at index 0, there are no allocated xa_nodes to\n * point to, and so we store %NULL in @xa_node.  @xa_node is set to\n * the value %XAS_RESTART if the xa_state is not walked to the correct\n * position in the tree of nodes for this operation.  If an error occurs\n * during an operation, it is set to an %XAS_ERROR value.  If we run off the\n * end of the allocated nodes, it is set to %XAS_BOUNDS.\n */\nstruct xa_state {\n\tstruct xarray *xa;\n\tunsigned long xa_index;\n\tunsigned char xa_shift;\n\tunsigned char xa_sibs;\n\tunsigned char xa_offset;\n\tunsigned char xa_pad;\t\t/* Helps gcc generate better code */\n\tstruct xa_node *xa_node;\n\tstruct xa_node *xa_alloc;\n\txa_update_node_t xa_update;\n};\n\n/*\n * We encode errnos in the xas->xa_node.  If an error has happened, we need to\n * drop the lock to fix it, and once we've done so the xa_state is invalid.\n */\n#define XA_ERROR(errno) ((struct xa_node *)(((unsigned long)errno << 2) | 2UL))\n#define XAS_BOUNDS\t((struct xa_node *)1UL)\n#define XAS_RESTART\t((struct xa_node *)3UL)\n\n#define __XA_STATE(array, index, shift, sibs)  {\t\\\n\t.xa = array,\t\t\t\t\t\\\n\t.xa_index = index,\t\t\t\t\\\n\t.xa_shift = shift,\t\t\t\t\\\n\t.xa_sibs = sibs,\t\t\t\t\\\n\t.xa_offset = 0,\t\t\t\t\t\\\n\t.xa_pad = 0,\t\t\t\t\t\\\n\t.xa_node = XAS_RESTART,\t\t\t\t\\\n\t.xa_alloc = NULL,\t\t\t\t\\\n\t.xa_update = NULL\t\t\t\t\\\n}\n\n/**\n * XA_STATE() - Declare an XArray operation state.\n * @name: Name of this operation state (usually xas).\n * @array: Array to operate on.\n * @index: Initial index of interest.\n *\n * Declare and initialise an xa_state on the stack.\n */\n#define XA_STATE(name, array, index)\t\t\t\t\\\n\tstruct xa_state name = __XA_STATE(array, index, 0, 0)\n\n/**\n * XA_STATE_ORDER() - Declare an XArray operation state.\n * @name: Name of this operation state (usually xas).\n * @array: Array to operate on.\n * @index: Initial index of interest.\n * @order: Order of entry.\n *\n * Declare and initialise an xa_state on the stack.  This variant of\n * XA_STATE() allows you to specify the 'order' of the element you\n * want to operate on.`\n */\n#define XA_STATE_ORDER(name, array, index, order)\t\t\\\n\tstruct xa_state name = __XA_STATE(array,\t\t\\\n\t\t\t(index >> order) << order,\t\t\\\n\t\t\torder - (order % XA_CHUNK_SHIFT),\t\\\n\t\t\t(1U << (order % XA_CHUNK_SHIFT)) - 1)\n\n#define xas_marked(xas, mark)\txa_marked((xas)->xa, (mark))\n#define xas_trylock(xas)\txa_trylock((xas)->xa)\n#define xas_lock(xas)\t\txa_lock((xas)->xa)\n#define xas_unlock(xas)\t\txa_unlock((xas)->xa)\n#define xas_lock_bh(xas)\txa_lock_bh((xas)->xa)\n#define xas_unlock_bh(xas)\txa_unlock_bh((xas)->xa)\n#define xas_lock_irq(xas)\txa_lock_irq((xas)->xa)\n#define xas_unlock_irq(xas)\txa_unlock_irq((xas)->xa)\n#define xas_lock_irqsave(xas, flags) \\\n\t\t\t\txa_lock_irqsave((xas)->xa, flags)\n#define xas_unlock_irqrestore(xas, flags) \\\n\t\t\t\txa_unlock_irqrestore((xas)->xa, flags)\n\n/**\n * xas_error() - Return an errno stored in the xa_state.\n * @xas: XArray operation state.\n *\n * Return: 0 if no error has been noted.  A negative errno if one has.\n */\nstatic inline int xas_error(const struct xa_state *xas)\n{\n\treturn xa_err(xas->xa_node);\n}\n\n/**\n * xas_set_err() - Note an error in the xa_state.\n * @xas: XArray operation state.\n * @err: Negative error number.\n *\n * Only call this function with a negative @err; zero or positive errors\n * will probably not behave the way you think they should.  If you want\n * to clear the error from an xa_state, use xas_reset().\n */\nstatic inline void xas_set_err(struct xa_state *xas, long err)\n{\n\txas->xa_node = XA_ERROR(err);\n}\n\n/**\n * xas_invalid() - Is the xas in a retry or error state?\n * @xas: XArray operation state.\n *\n * Return: %true if the xas cannot be used for operations.\n */\nstatic inline bool xas_invalid(const struct xa_state *xas)\n{\n\treturn (unsigned long)xas->xa_node & 3;\n}\n\n/**\n * xas_valid() - Is the xas a valid cursor into the array?\n * @xas: XArray operation state.\n *\n * Return: %true if the xas can be used for operations.\n */\nstatic inline bool xas_valid(const struct xa_state *xas)\n{\n\treturn !xas_invalid(xas);\n}\n\n/**\n * xas_is_node() - Does the xas point to a node?\n * @xas: XArray operation state.\n *\n * Return: %true if the xas currently references a node.\n */\nstatic inline bool xas_is_node(const struct xa_state *xas)\n{\n\treturn xas_valid(xas) && xas->xa_node;\n}\n\n/* True if the pointer is something other than a node */\nstatic inline bool xas_not_node(struct xa_node *node)\n{\n\treturn ((unsigned long)node & 3) || !node;\n}\n\n/* True if the node represents RESTART or an error */\nstatic inline bool xas_frozen(struct xa_node *node)\n{\n\treturn (unsigned long)node & 2;\n}\n\n/* True if the node represents head-of-tree, RESTART or BOUNDS */\nstatic inline bool xas_top(struct xa_node *node)\n{\n\treturn node <= XAS_RESTART;\n}\n\n/**\n * xas_reset() - Reset an XArray operation state.\n * @xas: XArray operation state.\n *\n * Resets the error or walk state of the @xas so future walks of the\n * array will start from the root.  Use this if you have dropped the\n * xarray lock and want to reuse the xa_state.\n *\n * Context: Any context.\n */\nstatic inline void xas_reset(struct xa_state *xas)\n{\n\txas->xa_node = XAS_RESTART;\n}\n\n/**\n * xas_retry() - Retry the operation if appropriate.\n * @xas: XArray operation state.\n * @entry: Entry from xarray.\n *\n * The advanced functions may sometimes return an internal entry, such as\n * a retry entry or a zero entry.  This function sets up the @xas to restart\n * the walk from the head of the array if needed.\n *\n * Context: Any context.\n * Return: true if the operation needs to be retried.\n */\nstatic inline bool xas_retry(struct xa_state *xas, const void *entry)\n{\n\tif (xa_is_zero(entry))\n\t\treturn true;\n\tif (!xa_is_retry(entry))\n\t\treturn false;\n\txas_reset(xas);\n\treturn true;\n}\n\nvoid *xas_load(struct xa_state *);\nvoid *xas_store(struct xa_state *, void *entry);\nvoid *xas_find(struct xa_state *, unsigned long max);\nvoid *xas_find_conflict(struct xa_state *);\n\nbool xas_get_mark(const struct xa_state *, xa_mark_t);\nvoid xas_set_mark(const struct xa_state *, xa_mark_t);\nvoid xas_clear_mark(const struct xa_state *, xa_mark_t);\nvoid *xas_find_marked(struct xa_state *, unsigned long max, xa_mark_t);\nvoid xas_init_marks(const struct xa_state *);\n\nbool xas_nomem(struct xa_state *, gfp_t);\nvoid xas_pause(struct xa_state *);\n\nvoid xas_create_range(struct xa_state *);\n\n/**\n * xas_reload() - Refetch an entry from the xarray.\n * @xas: XArray operation state.\n *\n * Use this function to check that a previously loaded entry still has\n * the same value.  This is useful for the lockless pagecache lookup where\n * we walk the array with only the RCU lock to protect us, lock the page,\n * then check that the page hasn't moved since we looked it up.\n *\n * The caller guarantees that @xas is still valid.  If it may be in an\n * error or restart state, call xas_load() instead.\n *\n * Return: The entry at this location in the xarray.\n */\nstatic inline void *xas_reload(struct xa_state *xas)\n{\n\tstruct xa_node *node = xas->xa_node;\n\n\tif (node)\n\t\treturn xa_entry(xas->xa, node, xas->xa_offset);\n\treturn xa_head(xas->xa);\n}\n\n/**\n * xas_set() - Set up XArray operation state for a different index.\n * @xas: XArray operation state.\n * @index: New index into the XArray.\n *\n * Move the operation state to refer to a different index.  This will\n * have the effect of starting a walk from the top; see xas_next()\n * to move to an adjacent index.\n */\nstatic inline void xas_set(struct xa_state *xas, unsigned long index)\n{\n\txas->xa_index = index;\n\txas->xa_node = XAS_RESTART;\n}\n\n/**\n * xas_set_order() - Set up XArray operation state for a multislot entry.\n * @xas: XArray operation state.\n * @index: Target of the operation.\n * @order: Entry occupies 2^@order indices.\n */\nstatic inline void xas_set_order(struct xa_state *xas, unsigned long index,\n\t\t\t\t\tunsigned int order)\n{\n#ifdef CONFIG_XARRAY_MULTI\n\txas->xa_index = order < BITS_PER_LONG ? (index >> order) << order : 0;\n\txas->xa_shift = order - (order % XA_CHUNK_SHIFT);\n\txas->xa_sibs = (1 << (order % XA_CHUNK_SHIFT)) - 1;\n\txas->xa_node = XAS_RESTART;\n#else\n\tBUG_ON(order > 0);\n\txas_set(xas, index);\n#endif\n}\n\n/**\n * xas_set_update() - Set up XArray operation state for a callback.\n * @xas: XArray operation state.\n * @update: Function to call when updating a node.\n *\n * The XArray can notify a caller after it has updated an xa_node.\n * This is advanced functionality and is only needed by the page cache.\n */\nstatic inline void xas_set_update(struct xa_state *xas, xa_update_node_t update)\n{\n\txas->xa_update = update;\n}\n\n/**\n * xas_next_entry() - Advance iterator to next present entry.\n * @xas: XArray operation state.\n * @max: Highest index to return.\n *\n * xas_next_entry() is an inline function to optimise xarray traversal for\n * speed.  It is equivalent to calling xas_find(), and will call xas_find()\n * for all the hard cases.\n *\n * Return: The next present entry after the one currently referred to by @xas.\n */\nstatic inline void *xas_next_entry(struct xa_state *xas, unsigned long max)\n{\n\tstruct xa_node *node = xas->xa_node;\n\tvoid *entry;\n\n\tif (unlikely(xas_not_node(node) || node->shift ||\n\t\t\txas->xa_offset != (xas->xa_index & XA_CHUNK_MASK)))\n\t\treturn xas_find(xas, max);\n\n\tdo {\n\t\tif (unlikely(xas->xa_index >= max))\n\t\t\treturn xas_find(xas, max);\n\t\tif (unlikely(xas->xa_offset == XA_CHUNK_MASK))\n\t\t\treturn xas_find(xas, max);\n\t\tentry = xa_entry(xas->xa, node, xas->xa_offset + 1);\n\t\tif (unlikely(xa_is_internal(entry)))\n\t\t\treturn xas_find(xas, max);\n\t\txas->xa_offset++;\n\t\txas->xa_index++;\n\t} while (!entry);\n\n\treturn entry;\n}\n\n/* Private */\nstatic inline unsigned int xas_find_chunk(struct xa_state *xas, bool advance,\n\t\txa_mark_t mark)\n{\n\tunsigned long *addr = xas->xa_node->marks[(__force unsigned)mark];\n\tunsigned int offset = xas->xa_offset;\n\n\tif (advance)\n\t\toffset++;\n\tif (XA_CHUNK_SIZE == BITS_PER_LONG) {\n\t\tif (offset < XA_CHUNK_SIZE) {\n\t\t\tunsigned long data = *addr & (~0UL << offset);\n\t\t\tif (data)\n\t\t\t\treturn __ffs(data);\n\t\t}\n\t\treturn XA_CHUNK_SIZE;\n\t}\n\n\treturn find_next_bit(addr, XA_CHUNK_SIZE, offset);\n}\n\n/**\n * xas_next_marked() - Advance iterator to next marked entry.\n * @xas: XArray operation state.\n * @max: Highest index to return.\n * @mark: Mark to search for.\n *\n * xas_next_marked() is an inline function to optimise xarray traversal for\n * speed.  It is equivalent to calling xas_find_marked(), and will call\n * xas_find_marked() for all the hard cases.\n *\n * Return: The next marked entry after the one currently referred to by @xas.\n */\nstatic inline void *xas_next_marked(struct xa_state *xas, unsigned long max,\n\t\t\t\t\t\t\t\txa_mark_t mark)\n{\n\tstruct xa_node *node = xas->xa_node;\n\tunsigned int offset;\n\n\tif (unlikely(xas_not_node(node) || node->shift))\n\t\treturn xas_find_marked(xas, max, mark);\n\toffset = xas_find_chunk(xas, true, mark);\n\txas->xa_offset = offset;\n\txas->xa_index = (xas->xa_index & ~XA_CHUNK_MASK) + offset;\n\tif (xas->xa_index > max)\n\t\treturn NULL;\n\tif (offset == XA_CHUNK_SIZE)\n\t\treturn xas_find_marked(xas, max, mark);\n\treturn xa_entry(xas->xa, node, offset);\n}\n\n/*\n * If iterating while holding a lock, drop the lock and reschedule\n * every %XA_CHECK_SCHED loops.\n */\nenum {\n\tXA_CHECK_SCHED = 4096,\n};\n\n/**\n * xas_for_each() - Iterate over a range of an XArray.\n * @xas: XArray operation state.\n * @entry: Entry retrieved from the array.\n * @max: Maximum index to retrieve from array.\n *\n * The loop body will be executed for each entry present in the xarray\n * between the current xas position and @max.  @entry will be set to\n * the entry retrieved from the xarray.  It is safe to delete entries\n * from the array in the loop body.  You should hold either the RCU lock\n * or the xa_lock while iterating.  If you need to drop the lock, call\n * xas_pause() first.\n */\n#define xas_for_each(xas, entry, max) \\\n\tfor (entry = xas_find(xas, max); entry; \\\n\t     entry = xas_next_entry(xas, max))\n\n/**\n * xas_for_each_marked() - Iterate over a range of an XArray.\n * @xas: XArray operation state.\n * @entry: Entry retrieved from the array.\n * @max: Maximum index to retrieve from array.\n * @mark: Mark to search for.\n *\n * The loop body will be executed for each marked entry in the xarray\n * between the current xas position and @max.  @entry will be set to\n * the entry retrieved from the xarray.  It is safe to delete entries\n * from the array in the loop body.  You should hold either the RCU lock\n * or the xa_lock while iterating.  If you need to drop the lock, call\n * xas_pause() first.\n */\n#define xas_for_each_marked(xas, entry, max, mark) \\\n\tfor (entry = xas_find_marked(xas, max, mark); entry; \\\n\t     entry = xas_next_marked(xas, max, mark))\n\n/**\n * xas_for_each_conflict() - Iterate over a range of an XArray.\n * @xas: XArray operation state.\n * @entry: Entry retrieved from the array.\n *\n * The loop body will be executed for each entry in the XArray that lies\n * within the range specified by @xas.  If the loop completes successfully,\n * any entries that lie in this range will be replaced by @entry.  The caller\n * may break out of the loop; if they do so, the contents of the XArray will\n * be unchanged.  The operation may fail due to an out of memory condition.\n * The caller may also call xa_set_err() to exit the loop while setting an\n * error to record the reason.\n */\n#define xas_for_each_conflict(xas, entry) \\\n\twhile ((entry = xas_find_conflict(xas)))\n\nvoid *__xas_next(struct xa_state *);\nvoid *__xas_prev(struct xa_state *);\n\n/**\n * xas_prev() - Move iterator to previous index.\n * @xas: XArray operation state.\n *\n * If the @xas was in an error state, it will remain in an error state\n * and this function will return %NULL.  If the @xas has never been walked,\n * it will have the effect of calling xas_load().  Otherwise one will be\n * subtracted from the index and the state will be walked to the correct\n * location in the array for the next operation.\n *\n * If the iterator was referencing index 0, this function wraps\n * around to %ULONG_MAX.\n *\n * Return: The entry at the new index.  This may be %NULL or an internal\n * entry.\n */\nstatic inline void *xas_prev(struct xa_state *xas)\n{\n\tstruct xa_node *node = xas->xa_node;\n\n\tif (unlikely(xas_not_node(node) || node->shift ||\n\t\t\t\txas->xa_offset == 0))\n\t\treturn __xas_prev(xas);\n\n\txas->xa_index--;\n\txas->xa_offset--;\n\treturn xa_entry(xas->xa, node, xas->xa_offset);\n}\n\n/**\n * xas_next() - Move state to next index.\n * @xas: XArray operation state.\n *\n * If the @xas was in an error state, it will remain in an error state\n * and this function will return %NULL.  If the @xas has never been walked,\n * it will have the effect of calling xas_load().  Otherwise one will be\n * added to the index and the state will be walked to the correct\n * location in the array for the next operation.\n *\n * If the iterator was referencing index %ULONG_MAX, this function wraps\n * around to 0.\n *\n * Return: The entry at the new index.  This may be %NULL or an internal\n * entry.\n */\nstatic inline void *xas_next(struct xa_state *xas)\n{\n\tstruct xa_node *node = xas->xa_node;\n\n\tif (unlikely(xas_not_node(node) || node->shift ||\n\t\t\t\txas->xa_offset == XA_CHUNK_MASK))\n\t\treturn __xas_next(xas);\n\n\txas->xa_index++;\n\txas->xa_offset++;\n\treturn xa_entry(xas->xa, node, xas->xa_offset);\n}\n\n#endif /* _LINUX_XARRAY_H */\n"
  },
  {
    "path": "t/tree/include/trace/events/i2c.h",
    "content": "/* SPDX-License-Identifier: GPL-2.0-or-later */\n/* I2C message transfer tracepoints\n *\n * Copyright (C) 2013 Red Hat, Inc. All Rights Reserved.\n * Written by David Howells (dhowells@redhat.com)\n */\n#undef TRACE_SYSTEM\n#define TRACE_SYSTEM i2c\n\n#if !defined(_TRACE_I2C_H) || defined(TRACE_HEADER_MULTI_READ)\n#define _TRACE_I2C_H\n\n#include <linux/i2c.h>\n#include <linux/tracepoint.h>\n\n/*\n * drivers/i2c/i2c-core-base.c\n */\nextern int i2c_transfer_trace_reg(void);\nextern void i2c_transfer_trace_unreg(void);\n\n/*\n * __i2c_transfer() write request\n */\nTRACE_EVENT_FN(i2c_write,\n\t       TP_PROTO(const struct i2c_adapter *adap, const struct i2c_msg *msg,\n\t\t\tint num),\n\t       TP_ARGS(adap, msg, num),\n\t       TP_STRUCT__entry(\n\t\t       __field(int,\tadapter_nr\t\t)\n\t\t       __field(__u16,\tmsg_nr\t\t\t)\n\t\t       __field(__u16,\taddr\t\t\t)\n\t\t       __field(__u16,\tflags\t\t\t)\n\t\t       __field(__u16,\tlen\t\t\t)\n\t\t       __dynamic_array(__u8, buf, msg->len)\t),\n\t       TP_fast_assign(\n\t\t       __entry->adapter_nr = adap->nr;\n\t\t       __entry->msg_nr = num;\n\t\t       __entry->addr = msg->addr;\n\t\t       __entry->flags = msg->flags;\n\t\t       __entry->len = msg->len;\n\t\t       memcpy(__get_dynamic_array(buf), msg->buf, msg->len);\n\t\t\t      ),\n\t       TP_printk(\"i2c-%d #%u a=%03x f=%04x l=%u [%*phD]\",\n\t\t\t __entry->adapter_nr,\n\t\t\t __entry->msg_nr,\n\t\t\t __entry->addr,\n\t\t\t __entry->flags,\n\t\t\t __entry->len,\n\t\t\t __entry->len, __get_dynamic_array(buf)\n\t\t\t ),\n\t       i2c_transfer_trace_reg,\n\t       i2c_transfer_trace_unreg);\n\n/*\n * __i2c_transfer() read request\n */\nTRACE_EVENT_FN(i2c_read,\n\t       TP_PROTO(const struct i2c_adapter *adap, const struct i2c_msg *msg,\n\t\t\tint num),\n\t       TP_ARGS(adap, msg, num),\n\t       TP_STRUCT__entry(\n\t\t       __field(int,\tadapter_nr\t\t)\n\t\t       __field(__u16,\tmsg_nr\t\t\t)\n\t\t       __field(__u16,\taddr\t\t\t)\n\t\t       __field(__u16,\tflags\t\t\t)\n\t\t       __field(__u16,\tlen\t\t\t)\n\t\t\t\t),\n\t       TP_fast_assign(\n\t\t       __entry->adapter_nr = adap->nr;\n\t\t       __entry->msg_nr = num;\n\t\t       __entry->addr = msg->addr;\n\t\t       __entry->flags = msg->flags;\n\t\t       __entry->len = msg->len;\n\t\t\t      ),\n\t       TP_printk(\"i2c-%d #%u a=%03x f=%04x l=%u\",\n\t\t\t __entry->adapter_nr,\n\t\t\t __entry->msg_nr,\n\t\t\t __entry->addr,\n\t\t\t __entry->flags,\n\t\t\t __entry->len\n\t\t\t ),\n\t       i2c_transfer_trace_reg,\n\t\t       i2c_transfer_trace_unreg);\n\n/*\n * __i2c_transfer() read reply\n */\nTRACE_EVENT_FN(i2c_reply,\n\t       TP_PROTO(const struct i2c_adapter *adap, const struct i2c_msg *msg,\n\t\t\tint num),\n\t       TP_ARGS(adap, msg, num),\n\t       TP_STRUCT__entry(\n\t\t       __field(int,\tadapter_nr\t\t)\n\t\t       __field(__u16,\tmsg_nr\t\t\t)\n\t\t       __field(__u16,\taddr\t\t\t)\n\t\t       __field(__u16,\tflags\t\t\t)\n\t\t       __field(__u16,\tlen\t\t\t)\n\t\t       __dynamic_array(__u8, buf, msg->len)\t),\n\t       TP_fast_assign(\n\t\t       __entry->adapter_nr = adap->nr;\n\t\t       __entry->msg_nr = num;\n\t\t       __entry->addr = msg->addr;\n\t\t       __entry->flags = msg->flags;\n\t\t       __entry->len = msg->len;\n\t\t       memcpy(__get_dynamic_array(buf), msg->buf, msg->len);\n\t\t\t      ),\n\t       TP_printk(\"i2c-%d #%u a=%03x f=%04x l=%u [%*phD]\",\n\t\t\t __entry->adapter_nr,\n\t\t\t __entry->msg_nr,\n\t\t\t __entry->addr,\n\t\t\t __entry->flags,\n\t\t\t __entry->len,\n\t\t\t __entry->len, __get_dynamic_array(buf)\n\t\t\t ),\n\t       i2c_transfer_trace_reg,\n\t       i2c_transfer_trace_unreg);\n\n/*\n * __i2c_transfer() result\n */\nTRACE_EVENT_FN(i2c_result,\n\t       TP_PROTO(const struct i2c_adapter *adap, int num, int ret),\n\t       TP_ARGS(adap, num, ret),\n\t       TP_STRUCT__entry(\n\t\t       __field(int,\tadapter_nr\t\t)\n\t\t       __field(__u16,\tnr_msgs\t\t\t)\n\t\t       __field(__s16,\tret\t\t\t)\n\t\t\t\t),\n\t       TP_fast_assign(\n\t\t       __entry->adapter_nr = adap->nr;\n\t\t       __entry->nr_msgs = num;\n\t\t       __entry->ret = ret;\n\t\t\t      ),\n\t       TP_printk(\"i2c-%d n=%u ret=%d\",\n\t\t\t __entry->adapter_nr,\n\t\t\t __entry->nr_msgs,\n\t\t\t __entry->ret\n\t\t\t ),\n\t       i2c_transfer_trace_reg,\n\t       i2c_transfer_trace_unreg);\n\n#endif /* _TRACE_I2C_H */\n\n/* This part must be outside protection */\n#include <trace/define_trace.h>\n"
  },
  {
    "path": "t/tree/include/uapi/linux/apm_bios.h",
    "content": "/* SPDX-License-Identifier: GPL-2.0+ WITH Linux-syscall-note */\n/*\n * Include file for the interface to an APM BIOS\n * Copyright 1994-2001 Stephen Rothwell (sfr@canb.auug.org.au)\n *\n * This program is free software; you can redistribute it and/or modify it\n * under the terms of the GNU General Public License as published by the\n * Free Software Foundation; either version 2, or (at your option) any\n * later version.\n *\n * This program is distributed in the hope that it will be useful, but\n * WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n * General Public License for more details.\n */\n#ifndef _UAPI_LINUX_APM_H\n#define _UAPI_LINUX_APM_H\n\n\n#include <linux/types.h>\n\ntypedef unsigned short\tapm_event_t;\ntypedef unsigned short\tapm_eventinfo_t;\n\nstruct apm_bios_info {\n\t__u16\tversion;\n\t__u16\tcseg;\n\t__u32\toffset;\n\t__u16\tcseg_16;\n\t__u16\tdseg;\n\t__u16\tflags;\n\t__u16\tcseg_len;\n\t__u16\tcseg_16_len;\n\t__u16\tdseg_len;\n};\n\n\n/*\n * Power states\n */\n#define APM_STATE_READY\t\t0x0000\n#define APM_STATE_STANDBY\t0x0001\n#define APM_STATE_SUSPEND\t0x0002\n#define APM_STATE_OFF\t\t0x0003\n#define APM_STATE_BUSY\t\t0x0004\n#define APM_STATE_REJECT\t0x0005\n#define APM_STATE_OEM_SYS\t0x0020\n#define APM_STATE_OEM_DEV\t0x0040\n\n#define APM_STATE_DISABLE\t0x0000\n#define APM_STATE_ENABLE\t0x0001\n\n#define APM_STATE_DISENGAGE\t0x0000\n#define APM_STATE_ENGAGE\t0x0001\n\n/*\n * Events (results of Get PM Event)\n */\n#define APM_SYS_STANDBY\t\t0x0001\n#define APM_SYS_SUSPEND\t\t0x0002\n#define APM_NORMAL_RESUME\t0x0003\n#define APM_CRITICAL_RESUME\t0x0004\n#define APM_LOW_BATTERY\t\t0x0005\n#define APM_POWER_STATUS_CHANGE\t0x0006\n#define APM_UPDATE_TIME\t\t0x0007\n#define APM_CRITICAL_SUSPEND\t0x0008\n#define APM_USER_STANDBY\t0x0009\n#define APM_USER_SUSPEND\t0x000a\n#define APM_STANDBY_RESUME\t0x000b\n#define APM_CAPABILITY_CHANGE\t0x000c\n#define APM_USER_HIBERNATION\t0x000d\n#define APM_HIBERNATION_RESUME\t0x000e\n\n/*\n * Error codes\n */\n#define APM_SUCCESS\t\t0x00\n#define APM_DISABLED\t\t0x01\n#define APM_CONNECTED\t\t0x02\n#define APM_NOT_CONNECTED\t0x03\n#define APM_16_CONNECTED\t0x05\n#define APM_16_UNSUPPORTED\t0x06\n#define APM_32_CONNECTED\t0x07\n#define APM_32_UNSUPPORTED\t0x08\n#define APM_BAD_DEVICE\t\t0x09\n#define APM_BAD_PARAM\t\t0x0a\n#define APM_NOT_ENGAGED\t\t0x0b\n#define APM_BAD_FUNCTION\t0x0c\n#define APM_RESUME_DISABLED\t0x0d\n#define APM_NO_ERROR\t\t0x53\n#define APM_BAD_STATE\t\t0x60\n#define APM_NO_EVENTS\t\t0x80\n#define APM_NOT_PRESENT\t\t0x86\n\n/*\n * APM Device IDs\n */\n#define APM_DEVICE_BIOS\t\t0x0000\n#define APM_DEVICE_ALL\t\t0x0001\n#define APM_DEVICE_DISPLAY\t0x0100\n#define APM_DEVICE_STORAGE\t0x0200\n#define APM_DEVICE_PARALLEL\t0x0300\n#define APM_DEVICE_SERIAL\t0x0400\n#define APM_DEVICE_NETWORK\t0x0500\n#define APM_DEVICE_PCMCIA\t0x0600\n#define APM_DEVICE_BATTERY\t0x8000\n#define APM_DEVICE_OEM\t\t0xe000\n#define APM_DEVICE_OLD_ALL\t0xffff\n#define APM_DEVICE_CLASS\t0x00ff\n#define APM_DEVICE_MASK\t\t0xff00\n\n\n/*\n * Battery status\n */\n#define APM_MAX_BATTERIES\t2\n\n/*\n * APM defined capability bit flags\n */\n#define APM_CAP_GLOBAL_STANDBY\t\t0x0001\n#define APM_CAP_GLOBAL_SUSPEND\t\t0x0002\n#define APM_CAP_RESUME_STANDBY_TIMER\t0x0004 /* Timer resume from standby */\n#define APM_CAP_RESUME_SUSPEND_TIMER\t0x0008 /* Timer resume from suspend */\n#define APM_CAP_RESUME_STANDBY_RING\t0x0010 /* Resume on Ring fr standby */\n#define APM_CAP_RESUME_SUSPEND_RING\t0x0020 /* Resume on Ring fr suspend */\n#define APM_CAP_RESUME_STANDBY_PCMCIA\t0x0040 /* Resume on PCMCIA Ring\t*/\n#define APM_CAP_RESUME_SUSPEND_PCMCIA\t0x0080 /* Resume on PCMCIA Ring\t*/\n\n/*\n * ioctl operations\n */\n#include <linux/ioctl.h>\n\n#define APM_IOC_STANDBY\t\t_IO('A', 1)\n#define APM_IOC_SUSPEND\t\t_IO('A', 2)\n\n#endif /* _UAPI_LINUX_APM_H */\n"
  },
  {
    "path": "t/tree/include/uapi/linux/eventpoll.h",
    "content": "/* SPDX-License-Identifier: GPL-2.0+ WITH Linux-syscall-note */\n/*\n *  include/linux/eventpoll.h ( Efficient event polling implementation )\n *  Copyright (C) 2001,...,2006\t Davide Libenzi\n *\n *  This program is free software; you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation; either version 2 of the License, or\n *  (at your option) any later version.\n *\n *  Davide Libenzi <davidel@xmailserver.org>\n *\n */\n\n#ifndef _UAPI_LINUX_EVENTPOLL_H\n#define _UAPI_LINUX_EVENTPOLL_H\n\n/* For O_CLOEXEC */\n#include <linux/fcntl.h>\n#include <linux/types.h>\n\n/* Flags for epoll_create1.  */\n#define EPOLL_CLOEXEC O_CLOEXEC\n\n/* Valid opcodes to issue to sys_epoll_ctl() */\n#define EPOLL_CTL_ADD 1\n#define EPOLL_CTL_DEL 2\n#define EPOLL_CTL_MOD 3\n\n/* Epoll event masks */\n#define EPOLLIN\t\t(__force __poll_t)0x00000001\n#define EPOLLPRI\t(__force __poll_t)0x00000002\n#define EPOLLOUT\t(__force __poll_t)0x00000004\n#define EPOLLERR\t(__force __poll_t)0x00000008\n#define EPOLLHUP\t(__force __poll_t)0x00000010\n#define EPOLLNVAL\t(__force __poll_t)0x00000020\n#define EPOLLRDNORM\t(__force __poll_t)0x00000040\n#define EPOLLRDBAND\t(__force __poll_t)0x00000080\n#define EPOLLWRNORM\t(__force __poll_t)0x00000100\n#define EPOLLWRBAND\t(__force __poll_t)0x00000200\n#define EPOLLMSG\t(__force __poll_t)0x00000400\n#define EPOLLRDHUP\t(__force __poll_t)0x00002000\n\n/* Set exclusive wakeup mode for the target file descriptor */\n#define EPOLLEXCLUSIVE\t((__force __poll_t)(1U << 28))\n\n/*\n * Request the handling of system wakeup events so as to prevent system suspends\n * from happening while those events are being processed.\n *\n * Assuming neither EPOLLET nor EPOLLONESHOT is set, system suspends will not be\n * re-allowed until epoll_wait is called again after consuming the wakeup\n * event(s).\n *\n * Requires CAP_BLOCK_SUSPEND\n */\n#define EPOLLWAKEUP\t((__force __poll_t)(1U << 29))\n\n/* Set the One Shot behaviour for the target file descriptor */\n#define EPOLLONESHOT\t((__force __poll_t)(1U << 30))\n\n/* Set the Edge Triggered behaviour for the target file descriptor */\n#define EPOLLET\t\t((__force __poll_t)(1U << 31))\n\n/* \n * On x86-64 make the 64bit structure have the same alignment as the\n * 32bit structure. This makes 32bit emulation easier.\n *\n * UML/x86_64 needs the same packing as x86_64\n */\n#ifdef __x86_64__\n#define EPOLL_PACKED __attribute__((packed))\n#else\n#define EPOLL_PACKED\n#endif\n\nstruct epoll_event {\n\t__poll_t events;\n\t__u64 data;\n} EPOLL_PACKED;\n\n#ifdef CONFIG_PM_SLEEP\nstatic inline void ep_take_care_of_epollwakeup(struct epoll_event *epev)\n{\n\tif ((epev->events & EPOLLWAKEUP) && !capable(CAP_BLOCK_SUSPEND))\n\t\tepev->events &= ~EPOLLWAKEUP;\n}\n#else\nstatic inline void ep_take_care_of_epollwakeup(struct epoll_event *epev)\n{\n\tepev->events &= ~EPOLLWAKEUP;\n}\n#endif\n#endif /* _UAPI_LINUX_EVENTPOLL_H */\n"
  },
  {
    "path": "t/tree/include/uapi/linux/i2c.h",
    "content": "/* SPDX-License-Identifier: GPL-2.0+ WITH Linux-syscall-note */\n/* ------------------------------------------------------------------------- */\n/*\t\t\t\t\t\t\t\t\t     */\n/* i2c.h - definitions for the i2c-bus interface\t\t\t     */\n/*\t\t\t\t\t\t\t\t\t     */\n/* ------------------------------------------------------------------------- */\n/*   Copyright (C) 1995-2000 Simon G. Vogl\n\n    This program is free software; you can redistribute it and/or modify\n    it under the terms of the GNU General Public License as published by\n    the Free Software Foundation; either version 2 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU General Public License for more details.\n\n    You should have received a copy of the GNU General Public License\n    along with this program; if not, write to the Free Software\n    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,\n    MA 02110-1301 USA.\t\t\t\t\t\t\t     */\n/* ------------------------------------------------------------------------- */\n\n/* With some changes from Kyösti Mälkki <kmalkki@cc.hut.fi> and\n   Frodo Looijaard <frodol@dds.nl> */\n\n#ifndef _UAPI_LINUX_I2C_H\n#define _UAPI_LINUX_I2C_H\n\n#include <linux/types.h>\n\n/**\n * struct i2c_msg - an I2C transaction segment beginning with START\n * @addr: Slave address, either seven or ten bits.  When this is a ten\n *\tbit address, I2C_M_TEN must be set in @flags and the adapter\n *\tmust support I2C_FUNC_10BIT_ADDR.\n * @flags: I2C_M_RD is handled by all adapters.  No other flags may be\n *\tprovided unless the adapter exported the relevant I2C_FUNC_*\n *\tflags through i2c_check_functionality().\n * @len: Number of data bytes in @buf being read from or written to the\n *\tI2C slave address.  For read transactions where I2C_M_RECV_LEN\n *\tis set, the caller guarantees that this buffer can hold up to\n *\t32 bytes in addition to the initial length byte sent by the\n *\tslave (plus, if used, the SMBus PEC); and this value will be\n *\tincremented by the number of block data bytes received.\n * @buf: The buffer into which data is read, or from which it's written.\n *\n * An i2c_msg is the low level representation of one segment of an I2C\n * transaction.  It is visible to drivers in the @i2c_transfer() procedure,\n * to userspace from i2c-dev, and to I2C adapter drivers through the\n * @i2c_adapter.@master_xfer() method.\n *\n * Except when I2C \"protocol mangling\" is used, all I2C adapters implement\n * the standard rules for I2C transactions.  Each transaction begins with a\n * START.  That is followed by the slave address, and a bit encoding read\n * versus write.  Then follow all the data bytes, possibly including a byte\n * with SMBus PEC.  The transfer terminates with a NAK, or when all those\n * bytes have been transferred and ACKed.  If this is the last message in a\n * group, it is followed by a STOP.  Otherwise it is followed by the next\n * @i2c_msg transaction segment, beginning with a (repeated) START.\n *\n * Alternatively, when the adapter supports I2C_FUNC_PROTOCOL_MANGLING then\n * passing certain @flags may have changed those standard protocol behaviors.\n * Those flags are only for use with broken/nonconforming slaves, and with\n * adapters which are known to support the specific mangling options they\n * need (one or more of IGNORE_NAK, NO_RD_ACK, NOSTART, and REV_DIR_ADDR).\n */\nstruct i2c_msg {\n\t__u16 addr;\t/* slave address\t\t\t*/\n\t__u16 flags;\n#define I2C_M_RD\t\t0x0001\t/* read data, from slave to master */\n\t\t\t\t\t/* I2C_M_RD is guaranteed to be 0x0001! */\n#define I2C_M_TEN\t\t0x0010\t/* this is a ten bit chip address */\n#define I2C_M_DMA_SAFE\t\t0x0200\t/* the buffer of this message is DMA safe */\n\t\t\t\t\t/* makes only sense in kernelspace */\n\t\t\t\t\t/* userspace buffers are copied anyway */\n#define I2C_M_RECV_LEN\t\t0x0400\t/* length will be first received byte */\n#define I2C_M_NO_RD_ACK\t\t0x0800\t/* if I2C_FUNC_PROTOCOL_MANGLING */\n#define I2C_M_IGNORE_NAK\t0x1000\t/* if I2C_FUNC_PROTOCOL_MANGLING */\n#define I2C_M_REV_DIR_ADDR\t0x2000\t/* if I2C_FUNC_PROTOCOL_MANGLING */\n#define I2C_M_NOSTART\t\t0x4000\t/* if I2C_FUNC_NOSTART */\n#define I2C_M_STOP\t\t0x8000\t/* if I2C_FUNC_PROTOCOL_MANGLING */\n\t__u16 len;\t\t/* msg length\t\t\t\t*/\n\t__u8 *buf;\t\t/* pointer to msg data\t\t\t*/\n};\n\n/* To determine what functionality is present */\n\n#define I2C_FUNC_I2C\t\t\t0x00000001\n#define I2C_FUNC_10BIT_ADDR\t\t0x00000002\n#define I2C_FUNC_PROTOCOL_MANGLING\t0x00000004 /* I2C_M_IGNORE_NAK etc. */\n#define I2C_FUNC_SMBUS_PEC\t\t0x00000008\n#define I2C_FUNC_NOSTART\t\t0x00000010 /* I2C_M_NOSTART */\n#define I2C_FUNC_SLAVE\t\t\t0x00000020\n#define I2C_FUNC_SMBUS_BLOCK_PROC_CALL\t0x00008000 /* SMBus 2.0 */\n#define I2C_FUNC_SMBUS_QUICK\t\t0x00010000\n#define I2C_FUNC_SMBUS_READ_BYTE\t0x00020000\n#define I2C_FUNC_SMBUS_WRITE_BYTE\t0x00040000\n#define I2C_FUNC_SMBUS_READ_BYTE_DATA\t0x00080000\n#define I2C_FUNC_SMBUS_WRITE_BYTE_DATA\t0x00100000\n#define I2C_FUNC_SMBUS_READ_WORD_DATA\t0x00200000\n#define I2C_FUNC_SMBUS_WRITE_WORD_DATA\t0x00400000\n#define I2C_FUNC_SMBUS_PROC_CALL\t0x00800000\n#define I2C_FUNC_SMBUS_READ_BLOCK_DATA\t0x01000000\n#define I2C_FUNC_SMBUS_WRITE_BLOCK_DATA 0x02000000\n#define I2C_FUNC_SMBUS_READ_I2C_BLOCK\t0x04000000 /* I2C-like block xfer  */\n#define I2C_FUNC_SMBUS_WRITE_I2C_BLOCK\t0x08000000 /* w/ 1-byte reg. addr. */\n#define I2C_FUNC_SMBUS_HOST_NOTIFY\t0x10000000\n\n#define I2C_FUNC_SMBUS_BYTE\t\t(I2C_FUNC_SMBUS_READ_BYTE | \\\n\t\t\t\t\t I2C_FUNC_SMBUS_WRITE_BYTE)\n#define I2C_FUNC_SMBUS_BYTE_DATA\t(I2C_FUNC_SMBUS_READ_BYTE_DATA | \\\n\t\t\t\t\t I2C_FUNC_SMBUS_WRITE_BYTE_DATA)\n#define I2C_FUNC_SMBUS_WORD_DATA\t(I2C_FUNC_SMBUS_READ_WORD_DATA | \\\n\t\t\t\t\t I2C_FUNC_SMBUS_WRITE_WORD_DATA)\n#define I2C_FUNC_SMBUS_BLOCK_DATA\t(I2C_FUNC_SMBUS_READ_BLOCK_DATA | \\\n\t\t\t\t\t I2C_FUNC_SMBUS_WRITE_BLOCK_DATA)\n#define I2C_FUNC_SMBUS_I2C_BLOCK\t(I2C_FUNC_SMBUS_READ_I2C_BLOCK | \\\n\t\t\t\t\t I2C_FUNC_SMBUS_WRITE_I2C_BLOCK)\n\n#define I2C_FUNC_SMBUS_EMUL\t\t(I2C_FUNC_SMBUS_QUICK | \\\n\t\t\t\t\t I2C_FUNC_SMBUS_BYTE | \\\n\t\t\t\t\t I2C_FUNC_SMBUS_BYTE_DATA | \\\n\t\t\t\t\t I2C_FUNC_SMBUS_WORD_DATA | \\\n\t\t\t\t\t I2C_FUNC_SMBUS_PROC_CALL | \\\n\t\t\t\t\t I2C_FUNC_SMBUS_WRITE_BLOCK_DATA | \\\n\t\t\t\t\t I2C_FUNC_SMBUS_I2C_BLOCK | \\\n\t\t\t\t\t I2C_FUNC_SMBUS_PEC)\n\n/*\n * Data for SMBus Messages\n */\n#define I2C_SMBUS_BLOCK_MAX\t32\t/* As specified in SMBus standard */\nunion i2c_smbus_data {\n\t__u8 byte;\n\t__u16 word;\n\t__u8 block[I2C_SMBUS_BLOCK_MAX + 2]; /* block[0] is used for length */\n\t\t\t       /* and one more for user-space compatibility */\n};\n\n/* i2c_smbus_xfer read or write markers */\n#define I2C_SMBUS_READ\t1\n#define I2C_SMBUS_WRITE\t0\n\n/* SMBus transaction types (size parameter in the above functions)\n   Note: these no longer correspond to the (arbitrary) PIIX4 internal codes! */\n#define I2C_SMBUS_QUICK\t\t    0\n#define I2C_SMBUS_BYTE\t\t    1\n#define I2C_SMBUS_BYTE_DATA\t    2\n#define I2C_SMBUS_WORD_DATA\t    3\n#define I2C_SMBUS_PROC_CALL\t    4\n#define I2C_SMBUS_BLOCK_DATA\t    5\n#define I2C_SMBUS_I2C_BLOCK_BROKEN  6\n#define I2C_SMBUS_BLOCK_PROC_CALL   7\t\t/* SMBus 2.0 */\n#define I2C_SMBUS_I2C_BLOCK_DATA    8\n\n#endif /* _UAPI_LINUX_I2C_H */\n"
  },
  {
    "path": "t/tree/include/uapi/linux/rseq.h",
    "content": "/* SPDX-License-Identifier: GPL-2.0+ WITH Linux-syscall-note */\n#ifndef _UAPI_LINUX_RSEQ_H\n#define _UAPI_LINUX_RSEQ_H\n\n/*\n * linux/rseq.h\n *\n * Restartable sequences system call API\n *\n * Copyright (c) 2015-2018 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>\n */\n\n#include <linux/types.h>\n#include <asm/byteorder.h>\n\nenum rseq_cpu_id_state {\n\tRSEQ_CPU_ID_UNINITIALIZED\t\t= -1,\n\tRSEQ_CPU_ID_REGISTRATION_FAILED\t\t= -2,\n};\n\nenum rseq_flags {\n\tRSEQ_FLAG_UNREGISTER = (1 << 0),\n};\n\nenum rseq_cs_flags_bit {\n\tRSEQ_CS_FLAG_NO_RESTART_ON_PREEMPT_BIT\t= 0,\n\tRSEQ_CS_FLAG_NO_RESTART_ON_SIGNAL_BIT\t= 1,\n\tRSEQ_CS_FLAG_NO_RESTART_ON_MIGRATE_BIT\t= 2,\n};\n\nenum rseq_cs_flags {\n\tRSEQ_CS_FLAG_NO_RESTART_ON_PREEMPT\t=\n\t\t(1U << RSEQ_CS_FLAG_NO_RESTART_ON_PREEMPT_BIT),\n\tRSEQ_CS_FLAG_NO_RESTART_ON_SIGNAL\t=\n\t\t(1U << RSEQ_CS_FLAG_NO_RESTART_ON_SIGNAL_BIT),\n\tRSEQ_CS_FLAG_NO_RESTART_ON_MIGRATE\t=\n\t\t(1U << RSEQ_CS_FLAG_NO_RESTART_ON_MIGRATE_BIT),\n};\n\n/*\n * struct rseq_cs is aligned on 4 * 8 bytes to ensure it is always\n * contained within a single cache-line. It is usually declared as\n * link-time constant data.\n */\nstruct rseq_cs {\n\t/* Version of this structure. */\n\t__u32 version;\n\t/* enum rseq_cs_flags */\n\t__u32 flags;\n\t__u64 start_ip;\n\t/* Offset from start_ip. */\n\t__u64 post_commit_offset;\n\t__u64 abort_ip;\n} __attribute__((aligned(4 * sizeof(__u64))));\n\n/*\n * struct rseq is aligned on 4 * 8 bytes to ensure it is always\n * contained within a single cache-line.\n *\n * A single struct rseq per thread is allowed.\n */\nstruct rseq {\n\t/*\n\t * Restartable sequences cpu_id_start field. Updated by the\n\t * kernel. Read by user-space with single-copy atomicity\n\t * semantics. This field should only be read by the thread which\n\t * registered this data structure. Aligned on 32-bit. Always\n\t * contains a value in the range of possible CPUs, although the\n\t * value may not be the actual current CPU (e.g. if rseq is not\n\t * initialized). This CPU number value should always be compared\n\t * against the value of the cpu_id field before performing a rseq\n\t * commit or returning a value read from a data structure indexed\n\t * using the cpu_id_start value.\n\t */\n\t__u32 cpu_id_start;\n\t/*\n\t * Restartable sequences cpu_id field. Updated by the kernel.\n\t * Read by user-space with single-copy atomicity semantics. This\n\t * field should only be read by the thread which registered this\n\t * data structure. Aligned on 32-bit. Values\n\t * RSEQ_CPU_ID_UNINITIALIZED and RSEQ_CPU_ID_REGISTRATION_FAILED\n\t * have a special semantic: the former means \"rseq uninitialized\",\n\t * and latter means \"rseq initialization failed\". This value is\n\t * meant to be read within rseq critical sections and compared\n\t * with the cpu_id_start value previously read, before performing\n\t * the commit instruction, or read and compared with the\n\t * cpu_id_start value before returning a value loaded from a data\n\t * structure indexed using the cpu_id_start value.\n\t */\n\t__u32 cpu_id;\n\t/*\n\t * Restartable sequences rseq_cs field.\n\t *\n\t * Contains NULL when no critical section is active for the current\n\t * thread, or holds a pointer to the currently active struct rseq_cs.\n\t *\n\t * Updated by user-space, which sets the address of the currently\n\t * active rseq_cs at the beginning of assembly instruction sequence\n\t * block, and set to NULL by the kernel when it restarts an assembly\n\t * instruction sequence block, as well as when the kernel detects that\n\t * it is preempting or delivering a signal outside of the range\n\t * targeted by the rseq_cs. Also needs to be set to NULL by user-space\n\t * before reclaiming memory that contains the targeted struct rseq_cs.\n\t *\n\t * Read and set by the kernel. Set by user-space with single-copy\n\t * atomicity semantics. This field should only be updated by the\n\t * thread which registered this data structure. Aligned on 64-bit.\n\t */\n\tunion {\n\t\t__u64 ptr64;\n#ifdef __LP64__\n\t\t__u64 ptr;\n#else\n\t\tstruct {\n#if (defined(__BYTE_ORDER) && (__BYTE_ORDER == __BIG_ENDIAN)) || defined(__BIG_ENDIAN)\n\t\t\t__u32 padding;\t\t/* Initialized to zero. */\n\t\t\t__u32 ptr32;\n#else /* LITTLE */\n\t\t\t__u32 ptr32;\n\t\t\t__u32 padding;\t\t/* Initialized to zero. */\n#endif /* ENDIAN */\n\t\t} ptr;\n#endif\n\t} rseq_cs;\n\n\t/*\n\t * Restartable sequences flags field.\n\t *\n\t * This field should only be updated by the thread which\n\t * registered this data structure. Read by the kernel.\n\t * Mainly used for single-stepping through rseq critical sections\n\t * with debuggers.\n\t *\n\t * - RSEQ_CS_FLAG_NO_RESTART_ON_PREEMPT\n\t *     Inhibit instruction sequence block restart on preemption\n\t *     for this thread.\n\t * - RSEQ_CS_FLAG_NO_RESTART_ON_SIGNAL\n\t *     Inhibit instruction sequence block restart on signal\n\t *     delivery for this thread.\n\t * - RSEQ_CS_FLAG_NO_RESTART_ON_MIGRATE\n\t *     Inhibit instruction sequence block restart on migration for\n\t *     this thread.\n\t */\n\t__u32 flags;\n} __attribute__((aligned(4 * sizeof(__u64))));\n\n#endif /* _UAPI_LINUX_RSEQ_H */\n"
  },
  {
    "path": "t/tree/issue102.c",
    "content": "void foo(void)\n{\n}\n/* This file triggers the bug described in #102. */\n\n/**\n * documented_function_XYZZY\n */\nvoid documented_function_XYZZY(void)\n{\n}\n\n/* t/tree/issue102.c */\n/* SPDX-License-Identifier: CC0-1.0 */\n"
  },
  {
    "path": "t/tree/issue131.h",
    "content": "/* This file triggers the bug described in #131. */\n\n/**\n * struct class - structure\n * @member:     A member\n *\n * Description.\n */\nstruct class {\n    int member;\n};\n\nvoid foo(struct class *klass)\n{\n    klass->member = 42;\n}\n\n/* t/tree/issue131.c */\n/* SPDX-License-Identifier: CC0-1.0 */\n"
  },
  {
    "path": "t/tree/issue134.c",
    "content": "/*\n * issue134.c: tests exhibiting problems noted in\n * https://github.com/bootlin/elixir/issues/134#issue-624392766\n *\n * t/tree/issue134.c\n * SPDX-License-Identifier: CC0-1.0\n */\n\n/**\n * issue134_function1:\n *\tDo something magical\n *\tand something quotidian\n *\n * @p1: Param\n *\n * Do something\n *\n * Returns whatever\n */\nint issue134_function1(int p1)\n{\n    write_test_cases();\n}\n\n/**\n * issue134_function2: - does what it does\n * @param:  something\n *\n * Whatever\n *\n * Whatever, paragraph 2.\n */\nvoid __sched issue134_function2(struct completion *x)\n{\n\ttake_action();\n}\n\n/**\n * issue134_function3() - something\n * @param: whatever\n * @paramii: whatever else\n *\n * Description\n *\n * Return: %magic or\n *\t   %-EIEIO if the farm bought\n */\nint issue134_function3(struct issue134_struct1 *param,\n\t\t\t       struct issue134_struct2 *paramii);\n"
  },
  {
    "path": "t/tree/issue150.S",
    "content": "/* Function memset should be located as a definition --- #150. */\n\n#include <asm/assembler.h>\n\n    .text\n\nENTRY(memset)\n    nop\nENDPROC(memset)\n\n/* t/tree/issue150.S */\n/* SPDX-License-Identifier: CC0-1.0 */\n"
  },
  {
    "path": "t/tree/issue186-counterexamples.c",
    "content": "// SPDX-License-Identifier: CC0-1.0\n// This file is the situation of #186, but with documentation.\n\n#ifdef SOMETHING\n/**\n * i186c_fn1 - do something\n */\nstatic int i186c_fn1(struct platform_device *pdev)\n{\n}\n#else\n#define i186c_fn1\tNULL\n#endif\n\n#ifdef SOMETHING\nstatic int i186c_fn2(struct platform_device *pdev)\n{\n}\n#else\n/**\n * i186c_fn2 - do something\n */\n#define i186c_fn2\tNULL\n#endif\n"
  },
  {
    "path": "t/tree/issue186.c",
    "content": "// SPDX-License-Identifier: CC0-1.0\n// This file triggers the bug described in #186.\n\n#ifdef SOMETHING\nstatic int undocumented_function(struct platform_device *pdev)\n{\n}\n\n#else\n#define undocumented_function\tNULL\n#endif\n"
  },
  {
    "path": "t/tree/issue188.c",
    "content": "// SPDX-License-Identifier: CC0-1.0\n// This file triggers the bug described in #188.\n\nstatic int undocumented_function(struct platform_device *pdev)\n{\n    int foo;\n    #define BAR (42)\n    foo=1;\n    return foo;\n}\n"
  },
  {
    "path": "t/tree/issue192.c",
    "content": "/* t/tree/issue192.c */\n/* SPDX-License-Identifier: CC0-1.0 */\n/* This file triggers the bug described in #192. */\n\n/**\n * issue192a: - do something\n **/\nint\nissue192a(const struct foo **bar, const char *bat,\n         struct baz *quux)\n{\n    return 0;\n}\n\n/**\n * issue192b()\n *\n * Allow an uppercase return type\n */\nAMAZING_RETURN_TYPE\nissue192b(void *parameter)\n{\n    return (AMAZING_RETURN_TYPE)31337;\n}\n"
  },
  {
    "path": "t/tree/syscall_define.c",
    "content": "SYSCALL_DEFINE3(init_module)\n{\n}\n"
  },
  {
    "path": "templates/error.html",
    "content": "{% extends \"layout.html\" %}\n\n{% block title %}\n    Elixir error - Bootlin\n{% endblock %}\n\n{% block main %}\n\n<div class=\"lxrerror\">\n    <h2>{{ error_title }}</h2>\n    <div id=\"error-details\">\n        {{ error_details|default('') }}\n    </div>\n    <span>You might want to:</span>\n    <ul>\n        {% if referer is not none -%}\n            <li><a class=\"link\" href=\"{{ referer }}\">Go back</a></li>\n        {%- endif %}\n        <li><a class=\"link\" href=\"{{ home_page_url }}\">Go to home page</a></li>\n        {% if bug_report_url is not none -%}\n            <li><a class=\"link\" href=\"{{ bug_report_url }}\">Report a bug</a></li>\n        {%- endif %}\n    </ul>\n    {% if report_error_details is not none -%}\n    <details>\n        <summary id=\"report-error-details-header\">Error details for a bug report</summary>\n        <pre>{{ report_error_details }}</pre>\n    </details>\n    {% endif -%}\n</div>\n\n{% endblock %}\n"
  },
  {
    "path": "templates/header.html",
    "content": "<header class=\"header\">\n    <nav>\n        <ul class=\"nav-links\">\n            <li><a href=\"https://bootlin.com/\">Home</a></li>\n            <li><a href=\"https://bootlin.com/engineering/\">Engineering</a></li>\n            <li><a href=\"https://bootlin.com/training/\">Training</a></li>\n            <li><a href=\"https://bootlin.com/docs/\">Docs</a></li>\n            <li><a href=\"https://bootlin.com/community/\">Community</a></li>\n            <li><a href=\"https://bootlin.com/company/\">Company</a></li>\n        </ul>\n        <ul class=\"social-icons\">\n            <li><a target=\"_blank\" class=\"icon-twitter\" href=\"http://twitter.com/bootlincom\">twitter</a></li>\n            <li><a target=\"_blank\" class=\"icon-mastodon\" href=\"https://fosstodon.org/@bootlin\">mastodon</a></li>\n            <li><a target=\"_blank\" class=\"icon-linkedin\" href=\"https://www.linkedin.com/company/bootlin/\">linkedin</a></li>\n            <li><a target=\"_blank\" class=\"icon-github\" href=\"https://github.com/bootlin\">github</a></li>\n        </ul>\n    </nav>\n    <div class=\"header-main\">\n        <div class=\"banners\">\n            <a class=\"message-link\" target=\"_blank\" href=\"https://bootlin.com/\">\n                <div class=\"message-banner\">\n                    <div class=\"container\">\n                        <p class=\"title\"></p>\n                        <div class=\"subtitle\"></div>\n                        <div class=\"action\">\n                            <div class=\"action-inner\">\n                            </div>\n                        </div>\n                    </div>\n                </div>\n            </a>\n        </div>\n        <div class=\"header-logo\">\n            <h1>\n                <img src=\"/static/img/bootlin-logo-white.svg\" alt=\"Bootlin logo\"/>\n            </h1>\n            <h2>Elixir Cross Referencer</h2>\n        </div>\n        <div></div>\n    </div>\n</header>\n"
  },
  {
    "path": "templates/ident.html",
    "content": "{% extends \"layout.html\" %}\n\n{% block title %}\n    {{ searched_ident|e }} identifier - {{ current_project|capitalize }} source code {{ current_tag }} - Bootlin Elixir Cross Referencer\n{% endblock %}\n\n{% block description -%}\n    Elixir Cross Referencer - {{ searched_ident|e }} identifier references search for {{ current_project|capitalize }} {{ current_tag }}.\n    {%- for section in symbol_sections -%}\n        {%- if 'symbols' in section -%}\n            {%- for type, symbols in (section['symbols'].items()) -%}\n                {%- if (symbols|length) == 1 %}\n                    {{ section['title'] }} {{- ' as a '+type if type != '_unknown' else '' }} in {{ symbols[0].path }}.\n                {%- else %}\n                    {{ section['title'] }} in {{ symbols|length }} files {{- ' as a '+type if type != '_unknown' else '' -}}: {{ symbols[0].path }}...\n                {%- endif %}\n            {%- endfor -%}\n        {%- endif -%}\n    {%- endfor -%}\n{%- endblock -%}\n\n{% block main %}\n\n<div class=\"lxrident\">\n{% if symbol_sections|length != 0 %}\n    {% for section in symbol_sections %}\n        {% if 'symbols' in section %}\n            {% for type, symbols in section['symbols'].items() %}\n                <h2>{{ section['title'] }} in {{ symbols|length }} files\n                    {{- ' as a '+type if type != '_unknown' else '' -}}:</h2>\n                <ul>\n                {% for symbol in symbols %}\n                    <li>\n                    <a href=\"{{ symbol.lines[0].url }}\">\n                        <strong>{{ symbol.path }}</strong>\n                        {%- if symbol.lines|length == 1 %},\n                            line {{ symbol.lines[0].lineno }}\n                        {%- elif symbols|length > 100 %},\n                            <em>{{ symbol.lines|length }} times</em>\n                        {% endif %}\n                        {% if symbol.type is not none %}\n                            <em>(as a {{ symbol.type }})</em>\n                        {% endif %}\n                    </a>\n                    {% if symbol.lines|length > 1 and symbols|length <= 100 %}\n                        <ul>\n                        {% for line, url in symbol.lines %}\n                            <li><a href=\"{{ url }}\">line {{ line }}</a>\n                        {% endfor %}\n                        </ul>\n                    {% endif %}\n                {% endfor %}\n                </ul>\n            {% endfor %}\n        {% else %}\n            <h2>{{ section['message'] }}</h2>\n        {% endif %}\n    {% endfor %}\n{% else %}\n    <h2>Unknown identifier '{{ searched_ident|e }}'</h2>\n    {% if symbol_exists %}\n    <div id=\"error-details\">\n        The '{{ searched_ident|e }}' symbol is defined in another version.\n        Elixir cannot efficiently tell where.\n    </div>\n    {% endif %}\n{% endif %}\n</div>\n\n{% endblock %}\n"
  },
  {
    "path": "templates/layout.html",
    "content": "<!doctype html>\n<html class=\"no-js\">\n    <head>\n        <meta charset=\"utf-8\">\n        <meta http-equiv=\"x-ua-compatible\" content=\"ie=edge\">\n        <link rel=\"shortcut icon\" type=\"image/x-icon\" href=\"/favicon.ico\" />\n        <title>\n        {% block title %}\n            Bootlin - Elixir Cross Referencer\n        {% endblock %}\n        </title>\n        <meta name=\"description\"\n            content=\"\n            {%- block description -%}\n            Elixir Cross Referencer - Explore source code in your browser - Particularly useful for the Linux kernel and other low-level projects in C/C++ (bootloaders, C libraries...)\n            {%- endblock %}\">\n        <meta name=\"viewport\" content=\"user-scalable=no, initial-scale=1, maximum-scale=1, minimum-scale=1\" />\n        <link rel=\"stylesheet\" href=\"/static/style.css?v=16\">\n\n        <link rel=\"preload\" href=\"/static/img/2penguins.svg\" as=\"image\" />\n        <link rel=\"preload\" href=\"/static/img/arrow-dropdown-16.svg\" as=\"image\" />\n\n        <link rel=\"preload\" crossorigin href=\"/static/fonts/lxr.ttf\" as=\"font\" />\n        <link rel=\"preload\" crossorigin href=\"/static/fonts/ubuntu/ubuntu-v14-cyrillic_greek_latin_latin-ext_greek-ext_cyrillic-ext-regular.woff2\" as=\"font\" />\n        <link rel=\"preload\" crossorigin href=\"/static/fonts/ubuntu/ubuntu-v14-cyrillic_greek_latin_latin-ext_greek-ext_cyrillic-ext-700.woff2\" as=\"font\" />\n        <link rel=\"preload\" crossorigin href=\"/static/fonts/ubuntu/ubuntu-v14-cyrillic_greek_latin_latin-ext_greek-ext_cyrillic-ext-italic.woff2\" as=\"font\" />\n\n        <link rel=\"preload\" crossorigin href=\"/static/messages.json\" as=\"fetch\" />\n\n        <script>\n            document.documentElement.classList.remove('no-js');\n            document.documentElement.classList.add('js');\n\n            //NOTE: placing this here, instead of script.js makes the sidebar less likely to flash on navigation\n            const showSidebarStr = window.localStorage.getItem('show-sidebar');\n            const showSidebar = showSidebarStr == \"true\" || showSidebarStr == null;\n            if (showSidebar) {\n              // special class that opens the sidebar only on widescreen devices\n              document.documentElement.classList.add('show-menu');\n            }\n        </script>\n    </head>\n    <body>\n        <!--[if lte IE 9]>\n                <p class=\"browserupgrade\">You are using an <strong>outdated</strong> browser. Please <a href=\"http://browsehappy.com/\">upgrade your browser</a> to improve your experience and security.</p>\n        <![endif]-->\n        <div class=\"wrapper\">\n            {% include 'header.html' %}\n            {% include 'topbar.html' %}\n            <main>\n                {% include \"sidebar.html\" %}\n                <div class=\"workspace\">\n                    <div id=\"reference-popup-wrapper\">\n                        <div id=\"reference-popup\"></div>\n                        <div id=\"loading-popup\">Loading...</div>\n                    </div>\n                    {% block main %}\n                    {% endblock %}\n                </div>\n            </main>\n            <footer class=\"footer\">\n                <span class=\"version\">\n                    <a href=\"{{ source_base_url }}\">{{ current_project }}</a>\n                    <em class=\"icon-tag\">{{ current_tag }}</em>\n                </span>\n                {% block footer %}\n                {% endblock %}\n                <a title=\"Go to top of the page\" class=\"go-top icon-up screenreader\" href=\"#\">\n                    Top\n                </a>\n                <span class=\"poweredby\">powered by\n                    <a target=\"_blank\" href=\"{{ elixir_repo_url }}\">\n                        Elixir {{ elixir_version_string }}\n                    </a>\n                </span>\n            </footer>\n        </div>\n        <script src=\"/static/script.js?v=17\"></script>\n        <script src=\"/static/dynamic-references.js?v=4\"></script>\n        <script src=\"/static/autocomplete.js\" project=\"{{ current_project }}\"></script>\n    </body>\n</html>\n"
  },
  {
    "path": "templates/sidebar.html",
    "content": "<aside class=\"sidebar\" id=\"menu\">\n    <div class=\"filter\">\n        <select class=\"select-projects\" onchange=\"window.location.href=this.value\">\n        {%- for p in projects %}\n            <option {% if p.name == current_project -%} selected {%- endif %} value=\"{{ p.url }}\">{{ p.name }}</option>\n        {%- endfor %}\n        </select>\n        <input class=\"filter-input\" placeholder=\"Filter tags\">\n        <a title=\"Close Menu\" class=\"close-menu icon-cross\"></a>\n        <button class=\"icon-filter\" tabindex=\"-1\"><span class=\"screenreader\">Filter tags</span></button>\n    </div>\n    <nav>\n        <h3 class=\"screenreader\">Projects</h3>\n        <ul class=\"projects\">\n        {%- for p in projects %}\n            <li {%- if p.name == current_project %} class=\"active\" {% endif -%}><a href=\"{{ p.url }}\">{{ p.name }}</a></li>\n        {%- endfor %}\n        </ul>\n\n        <h3 class=\"screenreader\">Versions</h3>\n        <ul class=\"versions\">\n            {% set current_major, current_minor, current_version = current_version_path %}\n            {% for major, major_versions in (versions|default({})).items() %}\n            <li>\n                <span class=\"{{ 'active' if current_major == major else '' }}\">{{ major }}</span>\n                <ul>\n                {% for minor, minor_versions in major_versions.items() %}\n                    {% if minor == minor_versions[0] and minor_versions|length == 1 %}\n                        <li class=\"li-link\">\n                            <a href=\"{{ minor_versions[0].url }}\">{{ minor_versions[0].version }}</a>\n                        </li>\n                    {% else %}\n                        <li>\n                            <span class=\"{{ 'active' if minor == current_minor else '' }}\">{{ minor }}</span>\n                            <ul>\n                                {% for v in minor_versions %}\n                                    <li class=\"li-link {{ 'active' if v.version == current_tag else '' }}\">\n                                        <a href=\"{{ v.url }}\">\n                                            {{ v.version }}\n                                        </a>\n                                    </li>\n                                {% endfor %}\n                            </ul>\n                        </li>\n                    {% endif %}\n                {% endfor %}\n                </ul>\n            </li>\n        {% endfor %}\n        </ul>\n\n        <div class=\"filter-results\"></div>\n    </nav>\n</aside>\n"
  },
  {
    "path": "templates/source.html",
    "content": "{% extends \"layout.html\" %}\n\n{% block title %}\n    {{ title_path }} {{ current_project|capitalize }} source code {{ current_tag }} - Bootlin Elixir Cross Referencer\n{% endblock %}\n\n{% block description -%}\n    Elixir Cross Referencer - source code of {{ current_project|capitalize }} {{ current_tag -}} {{- '' if path|length <= 1 else ': ' + path[1:] }}\n{%- endblock %}\n\n{% block main %}\n<div class=\"lxrcode\">\n    {{ code }}\n</div>\n{% endblock %}\n\n{% block footer %}\n<span id=\"file-download-link\">\n    <a href=\"?raw\">Download file</a>\n</span>\n{% endblock %}\n\n"
  },
  {
    "path": "templates/topbar.html",
    "content": "<header class=\"topbar\">\n    <div class=\"breadcrumb\">\n        <a href=\"#menu\" class=\"open-menu icon-menu screenreader\" title=\"Open Menu\">Open Menu</a>\n        <a class=\"project\" href=\"{{ source_base_url }}\">/</a>\n        {% for name, url in breadcrumb_urls %}\n            <a href=\"{{ url }}\">{{ name }}</a>\n            {{ '/' if not loop.last else '' }}\n        {% endfor %}\n    </div>\n    <div class=\"search\">\n        <form method=\"GET\" action=\"{{ ident_base_url }}\" id=\"search-form\">\n            <select name=\"f\" title=\"Restricts search to specific file families\">\n            {% for id, description in topbar_families.items() %}\n                <option value=\"{{ id }}\" {{ 'selected' if (current_family == id or current_family is not defined) else '' }}>\n                {{ description }}\n                </option>\n            {% endfor %}\n            </select>\n\n            <div class=\"search-controls\">\n                <input placeholder=\"Search Identifier\" type=\"text\" id=\"search-input\" name=\"i\"\n                    value=\"{{ searched_ident|default('')|e }}\" autofocus required/>\n                <button type=\"button\" id=\"clear-search\" class=\"visible-if-js icon-cross\"><span class=\"screenreader\">Clear</span></button>\n                <button type=\"submit\" class=\"icon-search\"><span class=\"screenreader\">Go get it</span></button>\n            </div>\n        </form>\n    </div>\n</header>\n"
  },
  {
    "path": "templates/tree.html",
    "content": "{% extends \"layout.html\" %}\n\n{% block title %}\n    {{ title_path }} {{ current_project|capitalize }} source code ({{ current_tag }}) - Bootlin Elixir Cross Referencer\n{% endblock %}\n\n{% block description -%}\n    {%- if path == '' -%}\n        Elixir Cross Referencer - explore {{ current_project|capitalize }} {{ current_tag }} source code in your browser.\n    {%- else -%}\n        Elixir Cross Referencer - source tree of {{ current_project|capitalize }} {{ current_tag -}} {{- '' if path|length <= 1 else ': ' + path[1:] }}\n    {%- endif -%}\n{%- endblock -%}\n\n{% block main %}\n\n<div class=\"lxrtree\">\n    <table>\n        <tbody>\n        {% if back_url is not none %}\n            <tr>\n                <td><a class=\"tree-icon icon-back\" href=\"{{ back_url }}\">Parent directory</a></td>\n                <td><a tabindex=\"-1\" class=\"size\" href=\"{{ back_url }}\"></a></td>\n            </tr>\n        {% endif %}\n        {% for type, name, path, url, size in dir_entries %}\n            <tr>\n                <td>\n                    <a class=\"tree-icon icon-{{- type if type != 'symlink' else 'blob' -}}\"\n                       href=\"{{ url }}\">\n                    {% if type == 'symlink' %}\n                        {{ name }} -> {{  path }}\n                    {% else %}\n                        {{ name }}\n                    {% endif %}\n                    </a>\n                </td>\n                <td>\n                    <a tabindex=\"-1\" class=\"size\" href=\"{{ url }}\">\n                    {% if size is not none %}\n                        {{ size }} bytes\n                    {% endif %}\n                    </a>\n                </td>\n            </tr>\n        {% endfor %}\n        </tbody>\n    </table>\n</div>\n\n{% endblock %}\n"
  },
  {
    "path": "update.py",
    "content": "#!/usr/bin/env python3\n\n#  This file is part of Elixir, a source code cross-referencer.\n#\n#  Copyright (C) 2017--2020 Mikaël Bouillot <mikael.bouillot@bootlin.com>\n#                           Maxime Chretien <maxime.chretien@bootlin.com>\n#                           and contributors\n#\n#  Elixir is free software: you can redistribute it and/or modify\n#  it under the terms of the GNU Affero General Public License as published by\n#  the Free Software Foundation, either version 3 of the License, or\n#  (at your option) any later version.\n#\n#  Elixir is distributed in the hope that it will be useful,\n#  but WITHOUT ANY WARRANTY; without even the implied warranty of\n#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n#  GNU Affero General Public License for more details.\n#\n#  You should have received a copy of the GNU Affero General Public License\n#  along with Elixir.  If not, see <http://www.gnu.org/licenses/>.\n\n# Throughout, an \"idx\" is the sequential number associated with a blob.\n# This is different from that blob's Git hash.\n\nfrom sys import argv\nfrom threading import Thread, Lock, Event, Condition\n\nimport elixir.lib as lib\nfrom elixir.lib import script, scriptLines\nimport elixir.data as data\nfrom elixir.data import PathList\nfrom find_compatible_dts import FindCompatibleDTS\n\nverbose = False\n\ndts_comp_support = int(script('dts-comp'))\n\ncompatibles_parser = FindCompatibleDTS()\n\ndb = data.DB(lib.getDataDir(), readonly=False, shared=True, dtscomp=dts_comp_support)\n\n# Number of cpu threads (+2 for version indexing)\ncpu = 10\nthreads_list = []\n\nhash_file_lock = Lock() # Lock for db.hash and db.file\nblobs_lock = Lock() # Lock for db.blobs\ndefs_lock = Lock() # Lock for db.defs\nrefs_lock = Lock() # Lock for db.refs\ndocs_lock = Lock() # Lock for db.docs\ncomps_lock = Lock() # Lock for db.comps\ncomps_docs_lock = Lock() # Lock for db.comps_docs\ntag_ready = Condition() # Waiting for new tags\n\nnew_idxes = [] # (new idxes, Event idxes ready, Event defs ready, Event comps ready, Event vers ready)\nbindings_idxes = [] # DT bindings documentation files\nidx_key_mod = 1000000\ndefs_idxes = {} # Idents definitions stored with (idx*idx_key_mod + line) as the key.\n\ntags_done = False # True if all tags have been added to new_idxes\n\n# Progress variables [tags, finished threads]\ntags_defs = [0, 0]\ntags_defs_lock = Lock()\ntags_refs = [0, 0]\ntags_refs_lock = Lock()\ntags_docs = [0, 0]\ntags_docs_lock = Lock()\ntags_comps = [0, 0]\ntags_comps_lock = Lock()\ntags_comps_docs = [0, 0]\ntags_comps_docs_lock = Lock()\n\nclass UpdateIds(Thread):\n    def __init__(self, tag_buf):\n        Thread.__init__(self, name=\"UpdateIdsElixir\")\n        self.tag_buf = tag_buf\n\n    def run(self):\n        global new_idxes, tags_done, tag_ready\n        self.index = 0\n\n        for tag in self.tag_buf:\n\n            new_idxes.append((self.update_blob_ids(tag), Event(), Event(), Event(), Event()))\n\n            progress('ids: ' +  tag.decode() + ': ' + str(len(new_idxes[self.index][0])) +\n                        ' new blobs', self.index+1)\n\n            new_idxes[self.index][1].set() # Tell that the tag is ready\n\n            self.index += 1\n\n            # Wake up waiting threads\n            with tag_ready:\n                tag_ready.notify_all()\n\n        tags_done = True\n        progress('ids: Thread finished', self.index)\n\n    def update_blob_ids(self, tag):\n\n        global hash_file_lock, blobs_lock\n\n        if db.vars.exists('numBlobs'):\n            idx = db.vars.get('numBlobs')\n        else:\n            idx = 0\n\n        # Get blob hashes and associated file names (without path)\n        blobs = scriptLines('list-blobs', '-f', tag)\n\n        new_idxes = []\n        for blob in blobs:\n            hash, filename = blob.split(b' ',maxsplit=1)\n            with blobs_lock:\n                blob_exist = db.blob.exists(hash)\n                if not blob_exist:\n                    db.blob.put(hash, idx)\n\n            if not blob_exist:\n                with hash_file_lock:\n                    db.hash.put(idx, hash)\n                    db.file.put(idx, filename)\n\n                new_idxes.append(idx)\n                if verbose:\n                    print(f\"New blob #{idx} {hash}:{filename}\")\n                idx += 1\n        db.vars.put('numBlobs', idx)\n        return new_idxes\n\n\nclass UpdateVersions(Thread):\n    def __init__(self, tag_buf):\n        Thread.__init__(self, name=\"UpdateVersionsElixir\")\n        self.tag_buf = tag_buf\n\n    def run(self):\n        global new_idxes, tag_ready\n\n        index = 0\n\n        while index < len(self.tag_buf):\n            if index >= len(new_idxes):\n                # Wait for new tags\n                with tag_ready:\n                    tag_ready.wait()\n                continue\n\n            tag = self.tag_buf[index]\n\n            new_idxes[index][1].wait() # Make sure the tag is ready\n\n            self.update_versions(tag)\n\n            new_idxes[index][4].set() # Tell that UpdateVersions processed the tag\n\n            progress('vers: ' + tag.decode() + ' done', index+1)\n\n            index += 1\n\n        progress('vers: Thread finished', index)\n\n    def update_versions(self, tag):\n        global blobs_lock\n\n        # Get blob hashes and associated file paths\n        blobs = scriptLines('list-blobs', '-p', tag)\n        buf = []\n\n        for blob in blobs:\n            hash, path = blob.split(b' ', maxsplit=1)\n            with blobs_lock:\n                idx = db.blob.get(hash)\n            buf.append((idx, path))\n\n        buf = sorted(buf)\n        obj = PathList()\n        for idx, path in buf:\n            obj.append(idx, path)\n\n            # Store DT bindings documentation files to parse them later\n            if path[:33] == b'Documentation/devicetree/bindings':\n                bindings_idxes.append(idx)\n\n            if verbose:\n                print(f\"Tag {tag}: adding #{idx} {path}\")\n        db.vers.put(tag, obj, sync=True)\n\n\ndef generate_defs_caches():\n    for key in db.defs.get_keys():\n        value = db.defs.get(key)\n        for family in ['C', 'K', 'D', 'M']:\n            if (lib.compatibleFamily(value.get_families(), family) or\n                        lib.compatibleMacro(value.get_macros(), family)):\n                db.defs_cache[family].put(key, b'')\n\n\nclass UpdateDefs(Thread):\n    def __init__(self, start, inc):\n        Thread.__init__(self, name=\"UpdateDefsElixir\")\n        self.index = start\n        self.inc = inc # Equivalent to the number of defs threads\n\n    def run(self):\n        global new_idxes, tags_done, tag_ready, tags_defs, tags_defs_lock\n\n        while not (tags_done and self.index >= len(new_idxes)):\n            if self.index >= len(new_idxes):\n                # Wait for new tags\n                with tag_ready:\n                    tag_ready.wait()\n                continue\n\n            new_idxes[self.index][1].wait() # Make sure the tag is ready\n\n            with tags_defs_lock:\n                tags_defs[0] += 1\n\n            self.update_definitions(new_idxes[self.index][0])\n\n            new_idxes[self.index][2].set() # Tell that UpdateDefs processed the tag\n\n            self.index += self.inc\n\n        with tags_defs_lock:\n            tags_defs[1] += 1\n            progress('defs: Thread ' + str(tags_defs[1]) + '/' + str(self.inc) + ' finished', tags_defs[0])\n\n\n    def update_definitions(self, idxes):\n        global hash_file_lock, defs_lock, tags_defs\n\n        for idx in idxes:\n            if idx % 1000 == 0: progress('defs: ' + str(idx), tags_defs[0])\n\n            with hash_file_lock:\n                hash = db.hash.get(idx)\n                filename = db.file.get(idx)\n\n            family = lib.getFileFamily(filename)\n            if family in [None, 'M']: continue\n\n            lines = scriptLines('parse-defs', hash, filename, family)\n\n            with defs_lock:\n                for l in lines:\n                    ident, type, line = l.split(b' ')\n                    type = type.decode()\n                    line = int(line.decode())\n\n                    defs_idxes[idx*idx_key_mod + line] = ident\n\n                    if db.defs.exists(ident):\n                        obj = db.defs.get(ident)\n                    elif lib.isIdent(ident):\n                        obj = data.DefList()\n                    else:\n                        continue\n\n                    obj.append(idx, type, line, family)\n                    if verbose:\n                        print(f\"def {type} {ident} in #{idx} @ {line}\")\n                    db.defs.put(ident, obj)\n\n        generate_defs_caches()\n\n\nclass UpdateRefs(Thread):\n    def __init__(self, start, inc):\n        Thread.__init__(self, name=\"UpdateRefsElixir\")\n        self.index = start\n        self.inc = inc # Equivalent to the number of refs threads\n\n    def run(self):\n        global new_idxes, tags_done, tags_refs, tags_refs_lock\n\n        while not (tags_done and self.index >= len(new_idxes)):\n            if self.index >= len(new_idxes):\n                # Wait for new tags\n                with tag_ready:\n                    tag_ready.wait()\n                continue\n\n            new_idxes[self.index][1].wait() # Make sure the tag is ready\n            new_idxes[self.index][2].wait() # Make sure UpdateDefs processed the tag\n\n            with tags_refs_lock:\n                tags_refs[0] += 1\n\n            self.update_references(new_idxes[self.index][0])\n\n            self.index += self.inc\n\n        with tags_refs_lock:\n            tags_refs[1] += 1\n            progress('refs: Thread ' + str(tags_refs[1]) + '/' + str(self.inc) + ' finished', tags_refs[0])\n\n    def update_references(self, idxes):\n        global hash_file_lock, defs_lock, refs_lock, tags_refs\n\n        for idx in idxes:\n            if idx % 1000 == 0: progress('refs: ' + str(idx), tags_refs[0])\n\n            with hash_file_lock:\n                hash = db.hash.get(idx)\n                filename = db.file.get(idx)\n\n            family = lib.getFileFamily(filename)\n            if family == None: continue\n\n            prefix = b''\n            # Kconfig values are saved as CONFIG_<value>\n            if family == 'K':\n                prefix = b'CONFIG_'\n\n            tokens = scriptLines('tokenize-file', '-b', hash, family)\n            even = True\n            line_num = 1\n            idents = {}\n            with defs_lock:\n                for tok in tokens:\n                    even = not even\n                    if even:\n                        tok = prefix + tok\n\n                        if (db.defs.exists(tok) and\n                            not ( (idx*idx_key_mod + line_num) in defs_idxes and\n                                defs_idxes[idx*idx_key_mod + line_num] == tok ) and\n                            (family != 'M' or tok.startswith(b'CONFIG_'))):\n                            # We only index CONFIG_??? in makefiles\n                            if tok in idents:\n                                idents[tok] += ',' + str(line_num)\n                            else:\n                                idents[tok] = str(line_num)\n\n                    else:\n                        line_num += tok.count(b'\\1')\n\n            with refs_lock:\n                for ident, lines in idents.items():\n                    if db.refs.exists(ident):\n                        obj = db.refs.get(ident)\n                    else:\n                        obj = data.RefList()\n\n                    obj.append(idx, lines, family)\n                    if verbose:\n                        print(f\"ref: {ident} in #{idx} @ {lines}\")\n                    db.refs.put(ident, obj)\n\n\nclass UpdateDocs(Thread):\n    def __init__(self, start, inc):\n        Thread.__init__(self, name=\"UpdateDocsElixir\")\n        self.index = start\n        self.inc = inc # Equivalent to the number of docs threads\n\n    def run(self):\n        global new_idxes, tags_done, tags_docs, tags_docs_lock\n\n        while not (tags_done and self.index >= len(new_idxes)):\n            if self.index >= len(new_idxes):\n                # Wait for new tags\n                with tag_ready:\n                    tag_ready.wait()\n                continue\n\n            new_idxes[self.index][1].wait() # Make sure the tag is ready\n\n            with tags_docs_lock:\n                tags_docs[0] += 1\n\n            self.update_doc_comments(new_idxes[self.index][0])\n\n            self.index += self.inc\n\n        with tags_docs_lock:\n            tags_docs[1] += 1\n            progress('docs: Thread ' + str(tags_docs[1]) + '/' + str(self.inc) + ' finished', tags_docs[0])\n\n    def update_doc_comments(self, idxes):\n        global hash_file_lock, docs_lock, tags_docs\n\n        for idx in idxes:\n            if idx % 1000 == 0: progress('docs: ' + str(idx), tags_docs[0])\n\n            with hash_file_lock:\n                hash = db.hash.get(idx)\n                filename = db.file.get(idx)\n\n            family = lib.getFileFamily(filename)\n            if family in [None, 'M']: continue\n\n            lines = scriptLines('parse-docs', hash, filename)\n            with docs_lock:\n                for l in lines:\n                    ident, line = l.split(b' ')\n                    line = int(line.decode())\n\n                    if db.docs.exists(ident):\n                        obj = db.docs.get(ident)\n                    else:\n                        obj = data.RefList()\n\n                    obj.append(idx, str(line), family)\n                    if verbose:\n                        print(f\"doc: {ident} in #{idx} @ {line}\")\n                    db.docs.put(ident, obj)\n\n\nclass UpdateComps(Thread):\n    def __init__(self, start, inc):\n        Thread.__init__(self, name=\"UpdateCompsElixir\")\n        self.index = start\n        self.inc = inc # Equivalent to the number of comps threads\n\n    def run(self):\n        global new_idxes, tags_done, tags_comps, tags_comps_lock\n\n        while not (tags_done and self.index >= len(new_idxes)):\n            if self.index >= len(new_idxes):\n                # Wait for new tags\n                with tag_ready:\n                    tag_ready.wait()\n                continue\n\n            new_idxes[self.index][1].wait() # Make sure the tag is ready\n\n            with tags_comps_lock:\n                tags_comps[0] += 1\n\n            self.update_compatibles(new_idxes[self.index][0])\n\n            new_idxes[self.index][3].set() # Tell that UpdateComps processed the tag\n\n            self.index += self.inc\n\n        with tags_comps_lock:\n            tags_comps[1] += 1\n            progress('comps: Thread ' + str(tags_comps[1]) + '/' + str(self.inc) + ' finished', tags_comps[0])\n\n    def update_compatibles(self, idxes):\n        global hash_file_lock, comps_lock, tags_comps\n\n        for idx in idxes:\n            if idx % 1000 == 0: progress('comps: ' + str(idx), tags_comps[0])\n\n            with hash_file_lock:\n                hash = db.hash.get(idx)\n                filename = db.file.get(idx)\n\n            family = lib.getFileFamily(filename)\n            if family in [None, 'K', 'M']: continue\n\n            lines = compatibles_parser.run(scriptLines('get-blob', hash), family)\n            comps = {}\n            for l in lines:\n                ident, line = l.split(' ')\n\n                if ident in comps:\n                    comps[ident] += ',' + str(line)\n                else:\n                    comps[ident] = str(line)\n\n            with comps_lock:\n                for ident, lines in comps.items():\n                    if db.comps.exists(ident):\n                        obj = db.comps.get(ident)\n                    else:\n                        obj = data.RefList()\n\n                    obj.append(idx, lines, family)\n                    if verbose:\n                        print(f\"comps: {ident} in #{idx} @ {line}\")\n                    db.comps.put(ident, obj)\n\n\nclass UpdateCompsDocs(Thread):\n    def __init__(self, start, inc):\n        Thread.__init__(self, name=\"UpdateCompsDocsElixir\")\n        self.index = start\n        self.inc = inc # Equivalent to the number of comps_docs threads\n\n    def run(self):\n        global new_idxes, tags_done, tags_comps_docs, tags_comps_docs_lock\n\n        while not (tags_done and self.index >= len(new_idxes)):\n            if self.index >= len(new_idxes):\n                # Wait for new tags\n                with tag_ready:\n                    tag_ready.wait()\n                continue\n\n            new_idxes[self.index][1].wait() # Make sure the tag is ready\n            new_idxes[self.index][3].wait() # Make sure UpdateComps processed the tag\n            new_idxes[self.index][4].wait() # Make sure UpdateVersions processed the tag\n\n            with tags_comps_docs_lock:\n                tags_comps_docs[0] += 1\n\n            self.update_compatibles_bindings(new_idxes[self.index][0])\n\n            self.index += self.inc\n\n        with tags_comps_docs_lock:\n            tags_comps_docs[1] += 1\n            progress('comps_docs: Thread ' + str(tags_comps_docs[1]) + '/' + str(self.inc) + ' finished', tags_comps_docs[0])\n\n    def update_compatibles_bindings(self, idxes):\n        global hash_file_lock, comps_lock, comps_docs_lock, tags_comps_docs, bindings_idxes\n\n        for idx in idxes:\n            if idx % 1000 == 0: progress('comps_docs: ' + str(idx), tags_comps_docs[0])\n\n            if not idx in bindings_idxes: # Parse only bindings doc files\n                continue\n\n            with hash_file_lock:\n                hash = db.hash.get(idx)\n\n            family = 'B'\n            lines = compatibles_parser.run(scriptLines('get-blob', hash), family)\n            comps_docs = {}\n            with comps_lock:\n                for l in lines:\n                    ident, line = l.split(' ')\n\n                    if db.comps.exists(ident):\n                        if ident in comps_docs:\n                            comps_docs[ident] += ',' + str(line)\n                        else:\n                            comps_docs[ident] = str(line)\n\n            with comps_docs_lock:\n                for ident, lines in comps_docs.items():\n                    if db.comps_docs.exists(ident):\n                        obj = db.comps_docs.get(ident)\n                    else:\n                        obj = data.RefList()\n\n                    obj.append(idx, lines, family)\n                    if verbose:\n                        print(f\"comps_docs: {ident} in #{idx} @ {line}\")\n                    db.comps_docs.put(ident, obj)\n\n\ndef progress(msg, current):\n    print('{} - {} ({:.1%})'.format(project, msg, current/num_tags))\n\n\n# Main\n\n# Check number of threads arg\nif len(argv) >= 2 and argv[1].isdigit() :\n    cpu = int(argv[1])\n\n    if cpu < 5 :\n        cpu = 5\n\n# Distribute threads among functions using the following rules :\n# There are more (or equal) refs threads than others\n# There are more (or equal) defs threads than docs or comps threads\n# Example : if cpu=6 : defs=1, refs=2, docs=1, comps=1, comps_docs=1\n#           if cpu=7 : defs=2, refs=2, docs=1, comps=1, comps_docs=1\n#           if cpu=8 : defs=2, refs=3, docs=1, comps=1, comps_docs=1\n#           if cpu=11: defs=2, refs=3, docs=2, comps=2, comps_docs=2\nquo, rem = divmod(cpu, 5)\nnum_th_refs = quo\nnum_th_defs = quo\nnum_th_docs = quo\n\n# If DT bindings support is enabled, use $quo threads for each of the 2 threads\n# Otherwise add them to the remaining threads\nif dts_comp_support:\n    num_th_comps = quo\n    num_th_comps_docs = quo\nelse :\n    num_th_comps = 0\n    num_th_comps_docs = 0\n    rem += 2*quo\n\nquo, rem = divmod(rem, 2)\nnum_th_defs += quo\nnum_th_refs += quo + rem\n\ntag_buf = []\nfor tag in scriptLines('list-tags'):\n    if not db.vers.exists(tag):\n        tag_buf.append(tag)\n\nnum_tags = len(tag_buf)\nproject = lib.currentProject()\n\nprint(project + ' - found ' + str(num_tags) + ' new tags')\n\nif not num_tags:\n    # Backward-compatibility: generate defs caches if they are empty.\n    if db.defs_cache['C'].db.stat()['nkeys'] == 0:\n        generate_defs_caches()\n    exit(0)\n\nthreads_list.append(UpdateIds(tag_buf))\nthreads_list.append(UpdateVersions(tag_buf))\n\n# Define defs threads\nfor i in range(num_th_defs):\n    threads_list.append(UpdateDefs(i, num_th_defs))\n# Define refs threads\nfor i in range(num_th_refs):\n    threads_list.append(UpdateRefs(i, num_th_refs))\n# Define docs threads\nfor i in range(num_th_docs):\n    threads_list.append(UpdateDocs(i, num_th_docs))\n# Define comps threads\nfor i in range(num_th_comps):\n    threads_list.append(UpdateComps(i, num_th_comps))\n# Define comps_docs threads\nfor i in range(num_th_comps_docs):\n    threads_list.append(UpdateCompsDocs(i, num_th_comps_docs))\n\n\n# Start to process tags\nthreads_list[0].start()\n\n# Wait until the first tag is ready\nwith tag_ready:\n    tag_ready.wait()\n\n# Start remaining threads\nfor i in range(1, len(threads_list)):\n    threads_list[i].start()\n\n# Make sure all threads finished\nfor i in range(len(threads_list)):\n    threads_list[i].join()\n"
  },
  {
    "path": "utils/index",
    "content": "#!/bin/bash\n\nif test $# -lt 2; then\n    echo \"Usage: $0 <elixir_data_path> <project_name> [<repo_urls>...]\"\n    echo \"Usage: $0 <elixir_data_path> --all\"\n    exit 1\nfi\n\n# $1 is the project path (inside will be created data/ and repo/).\n# It supports being called on an existing project.\nproject_init() {\n    # Detect already inited projects. Avoids stderr logs.\n    # Using `git tag -n1` because `git status` doesn't work on bare repos.\n    if git -C $1/repo tag -n1 >/dev/null 2>/dev/null; then\n        return;\n    fi\n\n    mkdir -p $1/data $1/repo\n\n    git -C $1/repo -c init.defaultBranch=main init --bare\n}\n\n# $1 is the project path (parent of data/ and repo/).\n# $2 is the remote URL.\nproject_add_remote() {\n    git=\"git -C $1/repo -c safe.directory=$1/repo\"\n\n    # Do nothing if remote already exists.\n    if $git remote | xargs -L1 -r $git remote get-url 2>/dev/null | grep -qxF \"$2\"; then\n        return;\n    fi\n\n    # Remotes are called remote$i with $i = 0, 1, 2...\n    i=\"$($git remote | awk '\n        BEGIN { n=-1; }\n        $0 ~ /^remote[0-9]+$/ { i=substr($0, length(\"remote\")+1);\n                                if (i>n) n=i; }\n        END { print n+1; }')\"\n\n    $git remote add remote$i \"$2\"\n}\n\n# $1 is the project path (parent of data/ and repo/).\nproject_fetch() {\n    git=\"git -C $1/repo -c safe.directory=$1/repo\"\n\n    $git fetch --all --tags -j4\n\n    # A gc.log file implies a garbage collect failed in the past.\n    # Also, create a hidden flag which could be useful to trigger GCs manually.\n    if test -e $1/repo/gc.log -o \"$ELIXIR_GC\"; then\n        $git gc --aggressive\n    else\n        # Otherwise, give Git an occasion to trigger a GC.\n        # Porcelain commands should trigger that, but we don't use any.\n        $git gc --auto\n    fi\n}\n\n# $1 is the project path (parent of data/ and repo/).\nproject_index() {\n    if test -z \"$ELIXIR_THREADS\"; then\n        ELIXIR_THREADS=\"$(nproc)\"\n    fi\n\n    elixir_sources=\"$(dirname \"$(dirname \"$0\")\")\"\n\n    LXR_REPO_DIR=$1/repo LXR_DATA_DIR=$1/data \\\n        python3 \"$elixir_sources/update.py\" $ELIXIR_THREADS\n}\n\n# $1 is the Elixir root data path.\n# $2 is the project name.\n# $... are the remote URLs.\nadd_remotes() {\n    dir=\"$1/$2\"\n\n    project_init \"$dir\"\n\n    shift\n    shift\n    for remote\n    do\n        project_add_remote \"$dir\" \"$remote\"\n    done\n}\n\n# Call add_remotes() if no remotes are passed as arguments.\n#\n# $1 is the Elixir root data path.\n# $2 is the CLI arg count.\n# $3 is the CLI arg for project name (can be --all).\n# $4 is the project name.\n# $... are the default remote URLs.\nadd_default_remotes() {\n    if test $2 -eq 2 -a \\( \"$3\" = \"--all\" -o \"$3\" = \"$4\" \\); then\n        add_remotes \"$1\" \"$4\" ${@:5}\n    fi\n}\n\ndo_index() {\n    if test ! \"$(find $1/data -type f)\"; then\n        # If we are indexing from scratch, do it twice as the initial one\n        # probably took a lot of time.\n        project_fetch \"$1\"\n        project_index \"$1\"\n        project_fetch \"$1\"\n        project_index \"$1\"\n    else\n        project_fetch \"$1\"\n        project_index \"$1\"\n    fi\n}\n\n# Add all known projects remotes. This works in two cases:\n#     ./utils/index <elixir_data_path> --all   # => Add default remotes for all projects\n#     ./utils/index <elixir_data_path> musl    # => Add default remote for musl\nadd_default_remotes $1 $# $2 amazon-freertos https://github.com/aws/amazon-freertos.git\nadd_default_remotes $1 $# $2 arm-trusted-firmware https://github.com/ARM-software/arm-trusted-firmware\nadd_default_remotes $1 $# $2 barebox https://git.pengutronix.de/git/barebox\nadd_default_remotes $1 $# $2 busybox https://git.busybox.net/busybox\nadd_default_remotes $1 $# $2 coreboot https://review.coreboot.org/coreboot.git\nadd_default_remotes $1 $# $2 dpdk https://dpdk.org/git/dpdk \\\n                                  https://dpdk.org/git/dpdk-stable\nadd_default_remotes $1 $# $2 glibc https://sourceware.org/git/glibc.git\nadd_default_remotes $1 $# $2 llvm https://github.com/llvm/llvm-project.git\nadd_default_remotes $1 $# $2 mesa https://gitlab.freedesktop.org/mesa/mesa.git\nadd_default_remotes $1 $# $2 musl https://git.musl-libc.org/git/musl\nadd_default_remotes $1 $# $2 ofono https://git.kernel.org/pub/scm/network/ofono/ofono.git\nadd_default_remotes $1 $# $2 op-tee https://github.com/OP-TEE/optee_os.git\nadd_default_remotes $1 $# $2 qemu https://gitlab.com/qemu-project/qemu.git\nadd_default_remotes $1 $# $2 u-boot https://source.denx.de/u-boot/u-boot.git\nadd_default_remotes $1 $# $2 uclibc-ng https://cgit.uclibc-ng.org/cgi/cgit/uclibc-ng.git\nadd_default_remotes $1 $# $2 zephyr https://github.com/zephyrproject-rtos/zephyr\nadd_default_remotes $1 $# $2 toybox https://github.com/landley/toybox.git\nadd_default_remotes $1 $# $2 grub https://git.savannah.gnu.org/git/grub.git\nadd_default_remotes $1 $# $2 bluez https://git.kernel.org/pub/scm/bluetooth/bluez.git\nadd_default_remotes $1 $# $2 linux https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git \\\n                                   https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git \\\n                                   https://github.com/bootlin/linux-history.git\nadd_default_remotes $1 $# $2 xen https://xenbits.xen.org/git-http/xen.git\nadd_default_remotes $1 $# $2 freebsd https://git.freebsd.org/src.git\nadd_default_remotes $1 $# $2 opensbi https://github.com/riscv-software-src/opensbi\nadd_default_remotes $1 $# $2 iproute2 https://git.kernel.org/pub/scm/network/iproute2/iproute2.git\nadd_default_remotes $1 $# $2 vpp https://gerrit.fd.io/r/vpp\n\n# Index a single project\nif test \"x$2\" != \"x--all\"; then\n    dir=\"$1/$2\"\n    add_remotes \"$@\"\n    do_index \"$dir\"\nelse\n    # Index all projects.\n    # Note: this is not only the default projects ones but all the ones in $1.\n    find $1 -mindepth 1 -maxdepth 1 -type d | \\\n    while read dir; do\n        do_index \"$dir\"\n    done\nfi\n\n"
  },
  {
    "path": "utils/query.py",
    "content": "from elixir.query import Query\nfrom elixir import lib\n\ndef cmd_stats(q, **kwargs):\n    print(\"Versions: \", len(q.db.vers))\n    print(\"Blobs: \", len(q.db.blob))\n    if len(q.db.blob) != len(q.db.hash) or len(q.db.hash) != len(q.db.file):\n        print(\"Warning, number of blobs, hashes or files is not equal\")\n    print(\"Definitions: \", len(q.db.defs))\n    print(\"References: \", len(q.db.refs))\n\ndef cmd_versions(q, **kwargs):\n    for major in q.get_versions().values():\n        for minor in major.values():\n            for v in minor:\n                print(v)\n\ndef cmd_ident(q, version, ident, family, **kwargs):\n    symbol_definitions, symbol_references, symbol_doccomments, _ = q.search_ident(version, ident, family)\n    print(\"Symbol Definitions:\")\n    for symbol_definition in symbol_definitions:\n        print(symbol_definition)\n\n    print(\"\\nSymbol References:\")\n    for symbol_reference in symbol_references:\n        print(symbol_reference)\n\n    print(\"\\nDocumented in:\")\n    for symbol_doccomment in symbol_doccomments:\n        print(symbol_doccomment)\n\ndef cmd_file(q, version, path, **kwargs):\n    code = q.get_tokenized_file(version, path)\n    print(code)\n\nif __name__ == \"__main__\":\n    import argparse\n\n    query = Query(lib.getDataDir(), lib.getRepoDir())\n\n    parser = argparse.ArgumentParser()\n    subparsers = parser.add_subparsers(required=True)\n\n    ident_subparser = subparsers.add_parser('stats', help=\"Get basic database stats\")\n    ident_subparser.set_defaults(func=cmd_stats, q=query)\n\n    ident_subparser = subparsers.add_parser('versions', help=\"Get list of versions in the project\")\n    ident_subparser.set_defaults(func=cmd_versions, q=query)\n\n    ident_subparser = subparsers.add_parser('ident', help=\"Get definitions and references of an identifier\")\n    ident_subparser.add_argument(\"version\", help=\"The version of the project\", type=str, default=\"latest\")\n    ident_subparser.add_argument('ident', type=str, help=\"The name of the identifier\")\n    ident_subparser.add_argument('family', type=str, help=\"The file family requested\")\n    ident_subparser.set_defaults(func=cmd_ident, q=query)\n\n    file_subparser = subparsers.add_parser('file', help=\"Get a source file\")\n    file_subparser.add_argument(\"version\", help=\"The version of the project\", type=str, default=\"latest\")\n    file_subparser.add_argument('path', type=str, help=\"The path of the source file\")\n    file_subparser.set_defaults(func=cmd_file, q=query)\n\n    args = parser.parse_args()\n    args.func(**vars(args))\n\n"
  },
  {
    "path": "utils/speedtest.py",
    "content": "#!/usr/bin/env python3\n\n#  This file is part of Elixir, a source code cross-referencer.\n#\n#  Copyright (C) 2020 Maxime Chretien\n#\n#  Elixir is free software: you can redistribute it and/or modify\n#  it under the terms of the GNU Affero General Public License as published by\n#  the Free Software Foundation, either version 3 of the License, or\n#  (at your option) any later version.\n#\n#  Elixir is distributed in the hope that it will be useful,\n#  but WITHOUT ANY WARRANTY; without even the implied warranty of\n#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n#  GNU Affero General Public License for more details.\n#\n#  You should have received a copy of the GNU Affero General Public License\n#  along with Elixir.  If not, see <http://www.gnu.org/licenses/>.\n\nfrom time import time\nimport os\nimport sys\n\nBOLD = '\\033[1m'\nNORMAL = '\\033[0m'\n\nELIXIR_DIR = os.path.dirname(__file__) + '/..'\nsys.path = [ ELIXIR_DIR ] + sys.path\n\n#Parameters\nrun_number = 100\nverbose = False\n\n#List of test elements\nproject = 'linux'\nversions = ['latest', 'v5.6.2']\nidents = [  ('loopback', 'C'),\n            ('devm_register_reboot_notifier', 'C'),\n            ('notrace', 'C'),\n            ('arch_local_irq_restore', 'C'),\n            ('blk_queue_dma_alignment', 'C'),\n            ('spinlock_t', 'C'),\n            ('max', 'C'),\n            ('task_struct', 'C'),\n            ('eth_header', 'C'),\n            ('sk_buff', 'C') ]\n\nfiles = [   '/block/partitions/osf.c',\n            '/mm/kasan/quarantine.c',\n            '/include/crypto/internal/hash.h',\n            '/drivers/gpu/drm/gma500/gma_display.c',\n            '/drivers/hwmon/pmbus/ltc2978.c',\n            '/virt/lib/irqbypass.c',\n            '/Makefile',\n            '/fs/btrfs/tree-checker.c',\n            '/kernel/locking/qspinlock_stat.h',\n            '/arch/arm/boot/dts/armada-375.dtsi' ]\n\n\n#Test results\nidents_results = []\nidents_max = 0\nidents_min = 0\nidents_average = 0\n\nfiles_results = []\nfiles_max = 0\nfiles_min = 0\nfiles_average = 0\n\n\ndef init_query(project):\n    if 'LXR_PROJ_DIR' not in os.environ:\n        print(\"ERROR : LXR_PROJ_DIR not defined !\")\n        return None;\n\n    basedir = os.environ['LXR_PROJ_DIR']\n    datadir = basedir + '/' + project + '/data'\n    repodir = basedir + '/' + project + '/repo'\n\n    from elixir.query import Query\n    return Query(datadir, repodir)\n\n\ndef get_ident(query, ident, version):\n    if version == ('latest', 'latest-rc'):\n        rc = version == 'latest'\n        version = query.get_latest_tag(rc=rc)\n\n    return query.search_ident(version, ident[0], ident[1])\n\ndef get_file(query, path, version):\n    if version == ('latest', 'latest-rc'):\n        rc = version == 'latest'\n        version = query.get_latest_tag(rc=rc)\n\n    return query.get_file(version, path)\n\n\n#Read arguments\nif len(sys.argv) > 1:\n    if sys.argv[1] == '-v':\n        verbose = True\n    elif sys.argv[1] == '-h':\n        print(\"LXR_PROJ_DIR needs to be set before launching this script\\n\" +\n                \"Options :\\n\" +\n                \"-v     Verbose mode (Show requests details)\")\n        exit()\n\n#Query init\nquery = init_query(project)\nif query == None:\n    exit()\n\n#Database test\nprint((BOLD + \"Database test for project {}\" + NORMAL).format(project))\n\nprint(\"Each test runs {} times\".format(run_number))\n\nfor version in versions:\n    print((BOLD + \"\\nVersion tested : {}\\n\" + NORMAL).format(version))\n\n    print(BOLD + \"Identifiers access test\\n\" + NORMAL)\n    for i in range(run_number):\n        for ident in idents:\n            start_time = time()\n            get_ident(query, ident, version)\n            end_time = time()\n\n            elapsed_time = (end_time - start_time)*1000 #convert to ms\n            idents_results.append(elapsed_time)\n\n            if verbose:\n                print(\"Identifier : {}\".format(ident))\n                print(\"Elapsed time : {0:.6f} ms\\n\".format(elapsed_time))\n\n\n    idents_min = min(idents_results)\n    idents_max = max(idents_results)\n    idents_average = sum(idents_results)/len(idents_results)\n\n    print((BOLD + \"Min:\" + NORMAL + \" {0:.6f} ms\\n\"\n            + BOLD + \"Max:\" + NORMAL + \" {1:.6f} ms\\n\"\n            + BOLD + \"Average:\" + NORMAL + \" {2:.6f} ms\\n\"\n            ).format(idents_min, idents_max, idents_average))\n\n    print(BOLD + \"Files access test\\n\" + NORMAL)\n    for i in range(run_number):\n        for file in files:\n            start_time = time()\n            get_file(query, file, version)\n            end_time = time()\n\n            elapsed_time = (end_time - start_time) * 1000 #convert to ms\n            files_results.append(elapsed_time)\n\n            if verbose:\n                print(\"File : {}\".format(file))\n                print(\"Elapsed time : {0:.6f} ms\\n\".format(elapsed_time))\n\n\n    files_min = min(files_results)\n    files_max = max(files_results)\n    files_average = sum(files_results)/len(files_results)\n\n    print((BOLD + \"Min:\" + NORMAL + \" {0:.6f} ms\\n\"\n            + BOLD + \"Max:\" + NORMAL + \" {1:.6f} ms\\n\"\n            + BOLD + \"Average:\" + NORMAL + \" {2:.6f} ms\\n\"\n            ).format(files_min, files_max, files_average))\n"
  },
  {
    "path": "wsgi.py",
    "content": "from elixir.web import application\n"
  }
]