├── .gitignore ├── .travis.yml ├── LICENSE ├── Makefile ├── README.md ├── contrib └── dkms │ ├── .gitignore │ ├── Makefile │ ├── README.md │ ├── dkms.conf │ └── patch.sh ├── hpsa.h ├── kernel ├── 4.19-patchset-v2 │ ├── v2-0001-scsi-hpsa-Add-function-to-check-if-device-is-a-di.patch │ ├── v2-0002-scsi-hpsa-Support-HBA-mode-on-HP-Smart-Array-P410.patch │ ├── v2-0003-scsi-hpsa-Add-mask-existing-devices-on-rescan-if-.patch │ ├── v2-0004-scsi-hpsa-Ignore-HBA-flag-from-NVRAM-if-logical-d.patch │ ├── v2-0005-scsi-hpsa-Name-more-fields-in-struct-bmic_identif.patch │ └── v2-0006-scsi-hpsa-Do-not-use-HBA-flag-from-NVRAM-if-HBA-i.patch ├── 4.20-patchset-v2 ├── 5.0-patchset-v2 ├── 5.1-patchset-v2 ├── 5.10-patchset-v2 ├── 5.11-patchset-v2 ├── 5.12-patchset-v2 │ ├── 0001-scsi-hpsa-Add-function-to-check-if-device-is-a-disk-.patch │ ├── 0002-scsi-hpsa-Support-HBA-mode-on-HP-Smart-Array-P410i-c.patch │ ├── 0003-scsi-hpsa-Add-mask-existing-devices-on-rescan-if-vis.patch │ ├── 0004-scsi-hpsa-Ignore-HBA-flag-from-NVRAM-if-logical-devi.patch │ ├── 0005-scsi-hpsa-Name-more-fields-in-struct-bmic_identify_c.patch │ └── 0006-scsi-hpsa-Do-not-use-HBA-flag-from-NVRAM-if-HBA-is-n.patch ├── 5.13-patchset-v2 ├── 5.14-patchset-v2 ├── 5.15-patchset-v2 ├── 5.16-patchset-v2 ├── 5.17-patchset-v2 ├── 5.18-patchset-v2 │ ├── 0001-scsi-hpsa-Add-function-to-check-if-device-is-a-disk-.patch │ ├── 0002-scsi-hpsa-Support-HBA-mode-on-HP-Smart-Array-P410i-c.patch │ ├── 0003-scsi-hpsa-Add-mask-existing-devices-on-rescan-if-vis.patch │ ├── 0004-scsi-hpsa-Ignore-HBA-flag-from-NVRAM-if-logical-devi.patch │ ├── 0005-scsi-hpsa-Name-more-fields-in-struct-bmic_identify_c.patch │ └── 0006-scsi-hpsa-Do-not-use-HBA-flag-from-NVRAM-if-HBA-is-n.patch ├── 5.3-patchset-v2 │ ├── 0001-scsi-hpsa-Add-function-to-check-if-device-is-a-disk-.patch │ ├── 0002-scsi-hpsa-Support-HBA-mode-on-HP-Smart-Array-P410i-c.patch │ ├── 0003-scsi-hpsa-Add-mask-existing-devices-on-rescan-if-vis.patch │ ├── 0004-scsi-hpsa-Ignore-HBA-flag-from-NVRAM-if-logical-devi.patch │ ├── 0005-scsi-hpsa-Name-more-fields-in-struct-bmic_identify_c.patch │ └── 0006-scsi-hpsa-Do-not-use-HBA-flag-from-NVRAM-if-HBA-is-n.patch ├── 5.4-patchset-v2 ├── 5.5-patchset-v2 ├── 5.6-patchset-v2 ├── 5.7-patchset-v2 ├── 5.8-patchset-v2 └── 5.9-patchset-v2 └── main.c /.gitignore: -------------------------------------------------------------------------------- 1 | *.o 2 | hpsahba 3 | hpsahba.8 4 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | os: 2 | - linux 3 | 4 | dist: focal 5 | 6 | # To install additional packages. 7 | sudo: required 8 | 9 | before_install: 10 | - sudo apt-get -qq update 11 | - sudo apt-get install -y pandoc wget dkms linux-headers-$( uname -r ) 12 | 13 | script: 14 | - make all 15 | - make clean 16 | - make CC=gcc CFLAGS="-Werror" all 17 | - make clean 18 | - make CC=clang CFLAGS="-Wno-gnu-zero-variadic-macro-arguments -Werror" all 19 | - >- 20 | cd "contrib/dkms" && 21 | ./patch.sh && 22 | sudo dkms add . && 23 | sudo dkms install --force -k $( uname -r ) "hpsa-dkms/1.0" 24 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 2, June 1991 3 | 4 | Copyright (C) 1989, 1991 Free Software Foundation, Inc., 5 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 6 | Everyone is permitted to copy and distribute verbatim copies 7 | of this license document, but changing it is not allowed. 8 | 9 | Preamble 10 | 11 | The licenses for most software are designed to take away your 12 | freedom to share and change it. By contrast, the GNU General Public 13 | License is intended to guarantee your freedom to share and change free 14 | software--to make sure the software is free for all its users. This 15 | General Public License applies to most of the Free Software 16 | Foundation's software and to any other program whose authors commit to 17 | using it. (Some other Free Software Foundation software is covered by 18 | the GNU Lesser General Public License instead.) You can apply it to 19 | your programs, too. 20 | 21 | When we speak of free software, we are referring to freedom, not 22 | price. Our General Public Licenses are designed to make sure that you 23 | have the freedom to distribute copies of free software (and charge for 24 | this service if you wish), that you receive source code or can get it 25 | if you want it, that you can change the software or use pieces of it 26 | in new free programs; and that you know you can do these things. 27 | 28 | To protect your rights, we need to make restrictions that forbid 29 | anyone to deny you these rights or to ask you to surrender the rights. 30 | These restrictions translate to certain responsibilities for you if you 31 | distribute copies of the software, or if you modify it. 32 | 33 | For example, if you distribute copies of such a program, whether 34 | gratis or for a fee, you must give the recipients all the rights that 35 | you have. You must make sure that they, too, receive or can get the 36 | source code. And you must show them these terms so they know their 37 | rights. 38 | 39 | We protect your rights with two steps: (1) copyright the software, and 40 | (2) offer you this license which gives you legal permission to copy, 41 | distribute and/or modify the software. 42 | 43 | Also, for each author's protection and ours, we want to make certain 44 | that everyone understands that there is no warranty for this free 45 | software. If the software is modified by someone else and passed on, we 46 | want its recipients to know that what they have is not the original, so 47 | that any problems introduced by others will not reflect on the original 48 | authors' reputations. 49 | 50 | Finally, any free program is threatened constantly by software 51 | patents. We wish to avoid the danger that redistributors of a free 52 | program will individually obtain patent licenses, in effect making the 53 | program proprietary. To prevent this, we have made it clear that any 54 | patent must be licensed for everyone's free use or not licensed at all. 55 | 56 | The precise terms and conditions for copying, distribution and 57 | modification follow. 58 | 59 | GNU GENERAL PUBLIC LICENSE 60 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 61 | 62 | 0. This License applies to any program or other work which contains 63 | a notice placed by the copyright holder saying it may be distributed 64 | under the terms of this General Public License. The "Program", below, 65 | refers to any such program or work, and a "work based on the Program" 66 | means either the Program or any derivative work under copyright law: 67 | that is to say, a work containing the Program or a portion of it, 68 | either verbatim or with modifications and/or translated into another 69 | language. (Hereinafter, translation is included without limitation in 70 | the term "modification".) Each licensee is addressed as "you". 71 | 72 | Activities other than copying, distribution and modification are not 73 | covered by this License; they are outside its scope. The act of 74 | running the Program is not restricted, and the output from the Program 75 | is covered only if its contents constitute a work based on the 76 | Program (independent of having been made by running the Program). 77 | Whether that is true depends on what the Program does. 78 | 79 | 1. You may copy and distribute verbatim copies of the Program's 80 | source code as you receive it, in any medium, provided that you 81 | conspicuously and appropriately publish on each copy an appropriate 82 | copyright notice and disclaimer of warranty; keep intact all the 83 | notices that refer to this License and to the absence of any warranty; 84 | and give any other recipients of the Program a copy of this License 85 | along with the Program. 86 | 87 | You may charge a fee for the physical act of transferring a copy, and 88 | you may at your option offer warranty protection in exchange for a fee. 89 | 90 | 2. You may modify your copy or copies of the Program or any portion 91 | of it, thus forming a work based on the Program, and copy and 92 | distribute such modifications or work under the terms of Section 1 93 | above, provided that you also meet all of these conditions: 94 | 95 | a) You must cause the modified files to carry prominent notices 96 | stating that you changed the files and the date of any change. 97 | 98 | b) You must cause any work that you distribute or publish, that in 99 | whole or in part contains or is derived from the Program or any 100 | part thereof, to be licensed as a whole at no charge to all third 101 | parties under the terms of this License. 102 | 103 | c) If the modified program normally reads commands interactively 104 | when run, you must cause it, when started running for such 105 | interactive use in the most ordinary way, to print or display an 106 | announcement including an appropriate copyright notice and a 107 | notice that there is no warranty (or else, saying that you provide 108 | a warranty) and that users may redistribute the program under 109 | these conditions, and telling the user how to view a copy of this 110 | License. (Exception: if the Program itself is interactive but 111 | does not normally print such an announcement, your work based on 112 | the Program is not required to print an announcement.) 113 | 114 | These requirements apply to the modified work as a whole. If 115 | identifiable sections of that work are not derived from the Program, 116 | and can be reasonably considered independent and separate works in 117 | themselves, then this License, and its terms, do not apply to those 118 | sections when you distribute them as separate works. But when you 119 | distribute the same sections as part of a whole which is a work based 120 | on the Program, the distribution of the whole must be on the terms of 121 | this License, whose permissions for other licensees extend to the 122 | entire whole, and thus to each and every part regardless of who wrote it. 123 | 124 | Thus, it is not the intent of this section to claim rights or contest 125 | your rights to work written entirely by you; rather, the intent is to 126 | exercise the right to control the distribution of derivative or 127 | collective works based on the Program. 128 | 129 | In addition, mere aggregation of another work not based on the Program 130 | with the Program (or with a work based on the Program) on a volume of 131 | a storage or distribution medium does not bring the other work under 132 | the scope of this License. 133 | 134 | 3. You may copy and distribute the Program (or a work based on it, 135 | under Section 2) in object code or executable form under the terms of 136 | Sections 1 and 2 above provided that you also do one of the following: 137 | 138 | a) Accompany it with the complete corresponding machine-readable 139 | source code, which must be distributed under the terms of Sections 140 | 1 and 2 above on a medium customarily used for software interchange; or, 141 | 142 | b) Accompany it with a written offer, valid for at least three 143 | years, to give any third party, for a charge no more than your 144 | cost of physically performing source distribution, a complete 145 | machine-readable copy of the corresponding source code, to be 146 | distributed under the terms of Sections 1 and 2 above on a medium 147 | customarily used for software interchange; or, 148 | 149 | c) Accompany it with the information you received as to the offer 150 | to distribute corresponding source code. (This alternative is 151 | allowed only for noncommercial distribution and only if you 152 | received the program in object code or executable form with such 153 | an offer, in accord with Subsection b above.) 154 | 155 | The source code for a work means the preferred form of the work for 156 | making modifications to it. For an executable work, complete source 157 | code means all the source code for all modules it contains, plus any 158 | associated interface definition files, plus the scripts used to 159 | control compilation and installation of the executable. However, as a 160 | special exception, the source code distributed need not include 161 | anything that is normally distributed (in either source or binary 162 | form) with the major components (compiler, kernel, and so on) of the 163 | operating system on which the executable runs, unless that component 164 | itself accompanies the executable. 165 | 166 | If distribution of executable or object code is made by offering 167 | access to copy from a designated place, then offering equivalent 168 | access to copy the source code from the same place counts as 169 | distribution of the source code, even though third parties are not 170 | compelled to copy the source along with the object code. 171 | 172 | 4. You may not copy, modify, sublicense, or distribute the Program 173 | except as expressly provided under this License. Any attempt 174 | otherwise to copy, modify, sublicense or distribute the Program is 175 | void, and will automatically terminate your rights under this License. 176 | However, parties who have received copies, or rights, from you under 177 | this License will not have their licenses terminated so long as such 178 | parties remain in full compliance. 179 | 180 | 5. You are not required to accept this License, since you have not 181 | signed it. However, nothing else grants you permission to modify or 182 | distribute the Program or its derivative works. These actions are 183 | prohibited by law if you do not accept this License. Therefore, by 184 | modifying or distributing the Program (or any work based on the 185 | Program), you indicate your acceptance of this License to do so, and 186 | all its terms and conditions for copying, distributing or modifying 187 | the Program or works based on it. 188 | 189 | 6. Each time you redistribute the Program (or any work based on the 190 | Program), the recipient automatically receives a license from the 191 | original licensor to copy, distribute or modify the Program subject to 192 | these terms and conditions. You may not impose any further 193 | restrictions on the recipients' exercise of the rights granted herein. 194 | You are not responsible for enforcing compliance by third parties to 195 | this License. 196 | 197 | 7. If, as a consequence of a court judgment or allegation of patent 198 | infringement or for any other reason (not limited to patent issues), 199 | conditions are imposed on you (whether by court order, agreement or 200 | otherwise) that contradict the conditions of this License, they do not 201 | excuse you from the conditions of this License. If you cannot 202 | distribute so as to satisfy simultaneously your obligations under this 203 | License and any other pertinent obligations, then as a consequence you 204 | may not distribute the Program at all. For example, if a patent 205 | license would not permit royalty-free redistribution of the Program by 206 | all those who receive copies directly or indirectly through you, then 207 | the only way you could satisfy both it and this License would be to 208 | refrain entirely from distribution of the Program. 209 | 210 | If any portion of this section is held invalid or unenforceable under 211 | any particular circumstance, the balance of the section is intended to 212 | apply and the section as a whole is intended to apply in other 213 | circumstances. 214 | 215 | It is not the purpose of this section to induce you to infringe any 216 | patents or other property right claims or to contest validity of any 217 | such claims; this section has the sole purpose of protecting the 218 | integrity of the free software distribution system, which is 219 | implemented by public license practices. Many people have made 220 | generous contributions to the wide range of software distributed 221 | through that system in reliance on consistent application of that 222 | system; it is up to the author/donor to decide if he or she is willing 223 | to distribute software through any other system and a licensee cannot 224 | impose that choice. 225 | 226 | This section is intended to make thoroughly clear what is believed to 227 | be a consequence of the rest of this License. 228 | 229 | 8. If the distribution and/or use of the Program is restricted in 230 | certain countries either by patents or by copyrighted interfaces, the 231 | original copyright holder who places the Program under this License 232 | may add an explicit geographical distribution limitation excluding 233 | those countries, so that distribution is permitted only in or among 234 | countries not thus excluded. In such case, this License incorporates 235 | the limitation as if written in the body of this License. 236 | 237 | 9. The Free Software Foundation may publish revised and/or new versions 238 | of the General Public License from time to time. Such new versions will 239 | be similar in spirit to the present version, but may differ in detail to 240 | address new problems or concerns. 241 | 242 | Each version is given a distinguishing version number. If the Program 243 | specifies a version number of this License which applies to it and "any 244 | later version", you have the option of following the terms and conditions 245 | either of that version or of any later version published by the Free 246 | Software Foundation. If the Program does not specify a version number of 247 | this License, you may choose any version ever published by the Free Software 248 | Foundation. 249 | 250 | 10. If you wish to incorporate parts of the Program into other free 251 | programs whose distribution conditions are different, write to the author 252 | to ask for permission. For software which is copyrighted by the Free 253 | Software Foundation, write to the Free Software Foundation; we sometimes 254 | make exceptions for this. Our decision will be guided by the two goals 255 | of preserving the free status of all derivatives of our free software and 256 | of promoting the sharing and reuse of software generally. 257 | 258 | NO WARRANTY 259 | 260 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY 261 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN 262 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES 263 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED 264 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 265 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS 266 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE 267 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, 268 | REPAIR OR CORRECTION. 269 | 270 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 271 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR 272 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, 273 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING 274 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED 275 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY 276 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER 277 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE 278 | POSSIBILITY OF SUCH DAMAGES. 279 | 280 | END OF TERMS AND CONDITIONS 281 | 282 | How to Apply These Terms to Your New Programs 283 | 284 | If you develop a new program, and you want it to be of the greatest 285 | possible use to the public, the best way to achieve this is to make it 286 | free software which everyone can redistribute and change under these terms. 287 | 288 | To do so, attach the following notices to the program. It is safest 289 | to attach them to the start of each source file to most effectively 290 | convey the exclusion of warranty; and each file should have at least 291 | the "copyright" line and a pointer to where the full notice is found. 292 | 293 | 294 | Copyright (C) 295 | 296 | This program is free software; you can redistribute it and/or modify 297 | it under the terms of the GNU General Public License as published by 298 | the Free Software Foundation; either version 2 of the License, or 299 | (at your option) any later version. 300 | 301 | This program is distributed in the hope that it will be useful, 302 | but WITHOUT ANY WARRANTY; without even the implied warranty of 303 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 304 | GNU General Public License for more details. 305 | 306 | You should have received a copy of the GNU General Public License along 307 | with this program; if not, write to the Free Software Foundation, Inc., 308 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 309 | 310 | Also add information on how to contact you by electronic and paper mail. 311 | 312 | If the program is interactive, make it output a short notice like this 313 | when it starts in an interactive mode: 314 | 315 | Gnomovision version 69, Copyright (C) year name of author 316 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 317 | This is free software, and you are welcome to redistribute it 318 | under certain conditions; type `show c' for details. 319 | 320 | The hypothetical commands `show w' and `show c' should show the appropriate 321 | parts of the General Public License. Of course, the commands you use may 322 | be called something other than `show w' and `show c'; they could even be 323 | mouse-clicks or menu items--whatever suits your program. 324 | 325 | You should also get your employer (if you work as a programmer) or your 326 | school, if any, to sign a "copyright disclaimer" for the program, if 327 | necessary. Here is a sample; alter the names: 328 | 329 | Yoyodyne, Inc., hereby disclaims all copyright interest in the program 330 | `Gnomovision' (which makes passes at compilers) written by James Hacker. 331 | 332 | , 1 April 1989 333 | Ty Coon, President of Vice 334 | 335 | This General Public License does not permit incorporating your program into 336 | proprietary programs. If your program is a subroutine library, you may 337 | consider it more useful to permit linking proprietary applications with the 338 | library. If this is what you want to do, use the GNU Lesser General 339 | Public License instead of this License. 340 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | .POSIX: 2 | .SUFFIXES: .c .o 3 | 4 | CC = gcc 5 | PANDOC = pandoc 6 | 7 | BASE_CFLAGS = -std=gnu99 -Wall -Wextra 8 | CFLAGS = -O2 -g 9 | BASE_LDFLAGS = 10 | LDFLAGS = 11 | 12 | 13 | all: hpsahba hpsahba.8 14 | 15 | .c.o: 16 | $(CC) $(BASE_CFLAGS) $(CFLAGS) -c -o $(@) $(<) 17 | 18 | main.o: hpsa.h 19 | 20 | hpsahba: main.o 21 | $(CC) $(BASE_CFLAGS) $(CFLAGS) $(BASE_LDFLAGS) $(LDFLAGS) -o $(@) $(<) 22 | 23 | hpsahba.8: README.md 24 | $(PANDOC) --from markdown --to man --standalone --metadata "title=HPSAHBA(8)" --output $(@) $(<) 25 | 26 | clean: 27 | rm -f *.o 28 | rm -f hpsahba 29 | rm -f hpsahba.8 30 | 31 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # NAME 2 | 3 | **hpsahba** - tool to enable/disable HBA mode on some HP Smart Array 4 | controllers. 5 | 6 | # SYNOPSIS 7 | 8 | * hpsahba -h 9 | * hpsahba -v 10 | * hpsahba -i /dev/sgN 11 | * hpsahba -E /dev/sgN 12 | * hpsahba -d /dev/sgN 13 | 14 | # DESCRIPTION 15 | 16 | **CAUTION: This tool will destroy your data and may damage your hardware!** 17 | 18 | **hpsahba** is able to enable or disable HBA mode on some HP Smart Array 19 | controllers on which regular tools, like 'ssacli', reports HBA mode as not 20 | supported. 21 | 22 | When enabling or disabling HBA mode, RAID controller changes its internal 23 | configuration immediately, without requiring reboot. Any existing data 24 | may be lost after changing the HBA mode, so be extremely careful. 25 | 26 | Some servers may not be able to boot from disks attached to controller in 27 | HBA mode. Move the /boot partition and the bootloader out of disks attached to 28 | controller onto USB flash driver or SD card to circumvent this limitation. 29 | 30 | When HBA mode is enabled, controller usually prints some diagnostic message 31 | during boot, like *"Hardware RAID support is disabled via controller NVRAM 32 | configuration settings"* (example from P410i). Attempts to configure RAID 33 | arrays in this mode are expected to fail. 34 | 35 | ## Options 36 | 37 | * **hpsahba -h** 38 | 39 | Show help message and exit. 40 | 41 | * **hpsahba -v** 42 | 43 | Show version and exit. 44 | 45 | * **hpsahba -i DEVICE_PATH** 46 | 47 | Show some information about device. This Includes HBA mode support bit 48 | (supported/not supported) and current state of HBA mode (enabled/disabled). 49 | It is recommended to run this before trying to enable or disable HBA mode. 50 | 51 | * **hpsahba -E DEVICE_PATH** 52 | 53 | Enable HBA mode. 54 | 55 | * **hpsahba -d DEVICE_PATH** 56 | 57 | Disable HBA mode. 58 | 59 | ## Kernel driver support 60 | 61 | **hpsahba** itself is able to work on any modern Linux system. 62 | 63 | However, to get system actually see and use disks in HBA mode, few kernel 64 | patches required: 65 | . 66 | 67 | This functionality is disabled by default. To enable, load module hpsa with 68 | parameter hpsa_use_nvram_hba_flag set to "1". Or set it in the kernel command 69 | line: "hpsa.hpsa_use_nvram_hba_flag=1". 70 | 71 | Patchset changelog: 72 | 73 | * V1 -> V2: 74 | * Device visibility change properly detected if device is both updated 75 | and masked/unmasked in the same time. 76 | 77 | This will never be upstreamed and officially supported (for P410), see 78 | the email from Don Brace: . So use 79 | at your own risk. 80 | 81 | You can use DKMS package in 82 | to patch hpsa driver 83 | in a compiled kernel. 84 | 85 | ## Supported hardware 86 | 87 | Tested on following hardware so far: 88 | 89 | * HP Smart Array P410i (PCI ID: 103c:3245, board ID: 0x3245103c, 90 | firmware: 6.64) 91 | * HP Smart Array P812 (PCI ID: 103c:3249, board ID: 0x3249103c, 92 | firmware: 6.64) 93 | * Hewlett-Packard Company Smart Array G6 controllers / P410 (PCI ID: 94 | 103c:323a, board ID: 0x3243103c, firmware: 6.64) 95 | * Hewlett-Packard Company Smart Array G6 controllers / P212 (PCI ID: 96 | 103c:323a, board ID: 0x3241103c, firmware: 6.64) 97 | 98 | (open an issue or a pull request if you successfully used this tool on 99 | other controllers) 100 | 101 | ## Additional links 102 | 103 | * 104 | 105 | Archive containing saupdate.efi - EFI binary for ia64 architecture which 106 | implements the same functionality for P410i. Seems not usable anywhere except 107 | of old HP Integrity servers. 108 | 109 | # BUGS 110 | 111 | See issues on GitHub: . 112 | 113 | # AUTHOR 114 | 115 | **hpsahba** was written by Ivan Mironov \ 116 | -------------------------------------------------------------------------------- /contrib/dkms/.gitignore: -------------------------------------------------------------------------------- 1 | hpsa.c 2 | hpsa.h 3 | hpsa_cmd.h 4 | -------------------------------------------------------------------------------- /contrib/dkms/Makefile: -------------------------------------------------------------------------------- 1 | obj-m := hpsa.o 2 | 3 | ifndef KERNELRELEASE 4 | KRELEASE := $(shell uname -r) 5 | else 6 | KRELEASE := $(KERNELRELEASE) 7 | endif 8 | 9 | KDIR := /usr/lib/modules/$(KRELEASE)/build 10 | PWD := $(shell pwd) 11 | 12 | 13 | default: 14 | $(MAKE) -C $(KDIR) M=$(PWD) modules 15 | 16 | clean: 17 | $(MAKE) -C $(KDIR) M=$(PWD) clean 18 | -------------------------------------------------------------------------------- /contrib/dkms/README.md: -------------------------------------------------------------------------------- 1 | # Patched hpsa DKMS package 2 | 3 | Downloads and automatically patches hpsa driver from stable linux kernel tree. 4 | 5 | # Usage 6 | 7 | Run `./patch.sh` to download and patch hpsa driver. This script also takes an 8 | optional argument VERSION that sets what kernel version to patch. 9 | 10 | Make sure that you have your current kernel headers and dkms package installed. 11 | 12 | sudo apt install dkms linux-headers-$(uname -r) 13 | 14 | Add the dkms module to the tree 15 | 16 | sudo dkms add ./ 17 | 18 | And then you can install it. 19 | 20 | sudo dkms install --force hpsa-dkms/1.0 21 | 22 | When running in a chroot you have to manually set the kernel version 23 | 24 | dkms install --force -k 4.19.0-9-amd64 hpsa-dkms/1.0 25 | 26 | After that is done, unload the old hpsa driver and insert the new one 27 | 28 | sudo modprobe -r hpsa 29 | sudo modprobe hpsa hpsa_use_nvram_hba_flag=1 30 | -------------------------------------------------------------------------------- /contrib/dkms/dkms.conf: -------------------------------------------------------------------------------- 1 | PACKAGE_NAME="hpsa-dkms" 2 | PACKAGE_VERSION="1.0" 3 | BUILT_MODULE_NAME[0]="hpsa" 4 | MAKE[0]="make" 5 | DEST_MODULE_LOCATION[0]="/kernel/drivers/scsi" 6 | AUTOINSTALL="yes" 7 | -------------------------------------------------------------------------------- /contrib/dkms/patch.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | 4 | VERSION=${1:-5.8} 5 | 6 | echo "Patching for kernel ${VERSION}" 7 | 8 | wget "https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/plain/drivers/scsi/hpsa.h?h=linux-${VERSION}.y" -O hpsa.h 9 | wget "https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/plain/drivers/scsi/hpsa.c?h=linux-${VERSION}.y" -O hpsa.c 10 | wget "https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/plain/drivers/scsi/hpsa_cmd.h?h=linux-${VERSION}.y" -O hpsa_cmd.h 11 | 12 | shopt -s nullglob 13 | for PATCH in ../../kernel/"${VERSION}"*/*.patch; do 14 | echo "Applying ${PATCH}" 15 | patch --no-backup-if-mismatch -Np3 < "${PATCH}" 16 | done 17 | -------------------------------------------------------------------------------- /hpsa.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Tool to enable/disable HBA mode on some HP Smart Array controllers. 3 | * Copyright (C) 2018 Ivan Mironov 4 | * 5 | * This program is free software; you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation; either version 2 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program; if not, write to the Free Software 17 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 18 | */ 19 | #ifndef HPSAHBA_HPSA_H 20 | #define HPSAHBA_HPSA_H 21 | 22 | #include 23 | 24 | /* Just to annotate fields. It looks like all ints are little-endian. */ 25 | #define u8 uint8_t 26 | #define u16le uint16_t 27 | #define u32le uint32_t 28 | 29 | /* 30 | * Most of information about various structures and constants was borrowed 31 | * from $KERNEL_SRC/drivers/scsi/hpsa* and cciss_vol_status tool. 32 | * Some parts was guessed by author. 33 | */ 34 | 35 | #pragma pack(1) 36 | 37 | #define BMIC_READ 0x26 38 | #define BMIC_WRITE 0x27 39 | 40 | #define BMIC_IDENTIFY_CONTROLLER 0x11 41 | #define BMIC_SET_CONTROLLER_PARAMETERS 0x63 42 | #define BMIC_SENSE_CONTROLLER_PARAMETERS 0x64 43 | 44 | #define FIRMWARE_REV_LEN 4 45 | #define VENDOR_ID_LEN 8 46 | #define PRODUCT_ID_LEN 16 47 | #define SOFTWARE_NAME_LEN 64 48 | #define HARDWARE_NAME_LEN 32 49 | #define MAX_STR_BUF_LEN SOFTWARE_NAME_LEN 50 | 51 | struct bmic_identify_controller { 52 | u8 num_logical_drives; 53 | u32le signature; 54 | char running_firm_rev[FIRMWARE_REV_LEN]; 55 | char rom_firm_rev[FIRMWARE_REV_LEN]; 56 | u8 hardware_rev; 57 | u8 reserved_1[4]; 58 | u32le drive_present_bit_map; 59 | u32le external_drive_bit_map; 60 | u32le board_id; 61 | u8 reserved_2; 62 | u32le non_disk_map; 63 | u8 reserved_3[5]; 64 | u8 marketing_revision; 65 | u8 controller_flags; 66 | u8 host_flags; 67 | u8 expand_disable_code; 68 | u8 scsi_chip_count; 69 | u8 reserved_4[4]; 70 | u32le ctlr_clock; 71 | u8 drives_per_scsi_bus; 72 | u16le big_drive_present_map[8]; 73 | u16le big_ext_drive_map[8]; 74 | u16le big_non_disk_map[8]; 75 | 76 | /* used for FW debugging */ 77 | u16le task_flags; 78 | /* Bitmap used for ICL between controllers */ 79 | u8 icl_bus_map; 80 | /* See REDUNDANT MODE VALUES */ 81 | u8 redund_ctlr_modes_support; 82 | /* See REDUNDANT MODE VALUES */ 83 | u8 curr_redund_ctlr_mode; 84 | /* See REDUNDANT STATUS FLAG */ 85 | u8 redund_ctlr_status; 86 | /* See REDUNDANT FAILURE VALUES */ 87 | u8 redund_op_failure_code; 88 | u8 unsupported_nile_bus; 89 | u8 host_i2c_autorev; 90 | u8 cpld_revision; 91 | u8 fibre_chip_count; 92 | u8 daughterboard_type; 93 | u8 reserved_5[2]; 94 | 95 | u8 access_module_status; 96 | u8 features_supported[12]; 97 | /* Recovery ROM inactive f/w revision */ 98 | char rec_rom_inactive_rev[FIRMWARE_REV_LEN]; 99 | /* Recovery ROM flags */ 100 | u8 rec_rom_flags; 101 | u8 pci_to_pci_bridge_status; 102 | /* Reserved for future use */ 103 | u8 reserved_6[4]; 104 | /* Percent of memory allocated to write cache */ 105 | u8 percent_write_cache; 106 | /* Total cache board size */ 107 | u16le daughter_board_cache_size; 108 | /* Number of cache batteries */ 109 | u8 cache_battery_count; 110 | /* Total size (MB) of atttached memory */ 111 | u16le total_memory_size; 112 | /* Additional controller flags byte */ 113 | u8 more_controller_flags; 114 | /* 2nd byte of 3 byte autorev field */ 115 | u8 x_board_host_i2c_autorev; 116 | /* BBWC PIC revision */ 117 | u8 battery_pic_rev; 118 | /* DDFF update engine version */ 119 | u8 ddff_version[4]; 120 | /* Maximum logical units supported */ 121 | u16le max_logical_units; 122 | /* Big num configured logical units */ 123 | u16le ext_logical_unit_count; 124 | /* Maximum physical devices supported */ 125 | u16le max_physical_devices; 126 | /* Max physical drive per logical unit */ 127 | u16le max_phy_drv_per_logical_unit; 128 | /* Number of attached enclosures */ 129 | u8 enclosure_count; 130 | /* Number of expanders detected */ 131 | u8 expander_count; 132 | /* Offset to extended drive present map*/ 133 | u16le offset_to_edp_bitmap; 134 | /* Offset to extended external drive present map */ 135 | u16le offset_to_eedp_bitmap; 136 | /* Offset to extended non-disk map */ 137 | u16le offset_to_end_bitmap; 138 | /* Internal port status bytes */ 139 | u8 internal_port_status[8]; 140 | /* External port status bytes */ 141 | u8 external_port_status[8]; 142 | /* Yet More Controller flags */ 143 | u32le yet_more_controller_flags; 144 | /* Last lockup code */ 145 | u8 last_lockup; 146 | /* PCI slot according to option ROM*/ 147 | u8 pci_slot; 148 | /* Build number */ 149 | u16le build_num; 150 | /* Maximum safe full stripe size */ 151 | u32le max_safe_full_stripe_size; 152 | /* Total structure length */ 153 | u32le total_length; 154 | /* Vendor ID */ 155 | char vendor_id[VENDOR_ID_LEN]; 156 | /* Product ID */ 157 | char product_id[PRODUCT_ID_LEN]; 158 | u8 reserved_7[288]; 159 | }; 160 | 161 | #define YET_MORE_CTLR_FLAG_HBA_MODE_SUPP (1 << 25) 162 | 163 | struct bmic_controller_parameters { 164 | u8 led_flags; 165 | u8 enable_command_list_verification; 166 | u8 backed_out_write_drives; 167 | u16le stripes_for_parity; 168 | u8 parity_distribution_mode_flags; 169 | u16le max_driver_requests; 170 | u16le elevator_trend_count; 171 | u8 disable_elevator; 172 | u8 force_scan_complete; 173 | u8 scsi_transfer_mode; 174 | u8 force_narrow; 175 | u8 rebuild_priority; 176 | u8 expand_priority; 177 | u8 host_sdb_asic_fix; 178 | u8 pdpi_burst_from_host_disabled; 179 | char software_name[SOFTWARE_NAME_LEN]; 180 | char hardware_name[HARDWARE_NAME_LEN]; 181 | u8 bridge_revision; 182 | u8 snapshot_priority; 183 | u32le os_specific; 184 | u8 post_prompt_timeout; 185 | u8 automatic_drive_slamming; 186 | u8 reserved_1; 187 | u8 nvram_flags; 188 | u8 cache_nvram_flags; 189 | u8 drive_config_flags; 190 | u16le reserved_2; 191 | u8 temp_warning_level; 192 | u8 temp_shutdown_level; 193 | u8 temp_condition_reset; 194 | u8 max_coalesce_commands; 195 | u32le max_coalesce_delay; 196 | u8 orca_password[4]; 197 | u8 access_id[16]; 198 | u8 reserved[356]; 199 | }; 200 | 201 | #define NVRAM_FLAG_HBA_MODE_ENABLED (1 << 3) 202 | 203 | #pragma pack() 204 | #endif /* HPSAHBA_HPSA_H */ 205 | -------------------------------------------------------------------------------- /kernel/4.19-patchset-v2/v2-0001-scsi-hpsa-Add-function-to-check-if-device-is-a-di.patch: -------------------------------------------------------------------------------- 1 | From 4ece16a2f3bf40f1fa0123a59c2df569c9916d67 Mon Sep 17 00:00:00 2001 2 | From: Ivan Mironov 3 | Date: Wed, 5 Dec 2018 20:20:57 +0500 4 | Subject: [PATCH v2 1/6] scsi: hpsa: Add function to check if device is a disk 5 | or a zoned device 6 | 7 | This check is used multiple times within the driver. New function makes 8 | conditional statements a bit shorter and more readable. 9 | 10 | Signed-off-by: Ivan Mironov 11 | --- 12 | drivers/scsi/hpsa.c | 21 +++++++++++---------- 13 | 1 file changed, 11 insertions(+), 10 deletions(-) 14 | 15 | diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c 16 | index c9cccf35e9d7..fc06b790f16b 100644 17 | --- a/drivers/scsi/hpsa.c 18 | +++ b/drivers/scsi/hpsa.c 19 | @@ -768,6 +768,11 @@ static ssize_t sas_address_show(struct device *dev, 20 | return snprintf(buf, PAGE_SIZE, "0x%016llx\n", sas_address); 21 | } 22 | 23 | +static inline bool is_disk_or_zbc(const struct hpsa_scsi_dev_t *hdev) 24 | +{ 25 | + return hdev->devtype == TYPE_DISK || hdev->devtype == TYPE_ZBC; 26 | +} 27 | + 28 | static ssize_t host_show_hp_ssd_smart_path_enabled(struct device *dev, 29 | struct device_attribute *attr, char *buf) 30 | { 31 | @@ -788,7 +793,7 @@ static ssize_t host_show_hp_ssd_smart_path_enabled(struct device *dev, 32 | offload_enabled = hdev->offload_enabled; 33 | spin_unlock_irqrestore(&h->lock, flags); 34 | 35 | - if (hdev->devtype == TYPE_DISK || hdev->devtype == TYPE_ZBC) 36 | + if (is_disk_or_zbc(hdev)) 37 | return snprintf(buf, 20, "%d\n", offload_enabled); 38 | else 39 | return snprintf(buf, 40, "%s\n", 40 | @@ -855,8 +860,7 @@ static ssize_t path_info_show(struct device *dev, 41 | PAGE_SIZE - output_len, 42 | "PORT: %.2s ", 43 | phys_connector); 44 | - if ((hdev->devtype == TYPE_DISK || hdev->devtype == TYPE_ZBC) && 45 | - hdev->expose_device) { 46 | + if (is_disk_or_zbc(hdev) && hdev->expose_device) { 47 | if (box == 0 || box == 0xFF) { 48 | output_len += scnprintf(buf + output_len, 49 | PAGE_SIZE - output_len, 50 | @@ -1715,8 +1719,7 @@ static void hpsa_figure_phys_disk_ptrs(struct ctlr_info *h, 51 | for (j = 0; j < ndevices; j++) { 52 | if (dev[j] == NULL) 53 | continue; 54 | - if (dev[j]->devtype != TYPE_DISK && 55 | - dev[j]->devtype != TYPE_ZBC) 56 | + if (!is_disk_or_zbc(dev[j])) 57 | continue; 58 | if (is_logical_device(dev[j])) 59 | continue; 60 | @@ -1770,8 +1773,7 @@ static void hpsa_update_log_drive_phys_drive_ptrs(struct ctlr_info *h, 61 | for (i = 0; i < ndevices; i++) { 62 | if (dev[i] == NULL) 63 | continue; 64 | - if (dev[i]->devtype != TYPE_DISK && 65 | - dev[i]->devtype != TYPE_ZBC) 66 | + if (!is_disk_or_zbc(dev[i])) 67 | continue; 68 | if (!is_logical_device(dev[i])) 69 | continue; 70 | @@ -3965,9 +3967,8 @@ static int hpsa_update_device_info(struct ctlr_info *h, 71 | scsi_device_type(this_device->devtype), 72 | this_device->model); 73 | 74 | - if ((this_device->devtype == TYPE_DISK || 75 | - this_device->devtype == TYPE_ZBC) && 76 | - is_logical_dev_addr_mode(scsi3addr)) { 77 | + if (is_disk_or_zbc(this_device) && 78 | + is_logical_dev_addr_mode(scsi3addr)) { 79 | unsigned char volume_offline; 80 | 81 | hpsa_get_raid_level(h, scsi3addr, &this_device->raid_level); 82 | -- 83 | 2.20.1 84 | 85 | -------------------------------------------------------------------------------- /kernel/4.19-patchset-v2/v2-0002-scsi-hpsa-Support-HBA-mode-on-HP-Smart-Array-P410.patch: -------------------------------------------------------------------------------- 1 | From 6ab519311736efd17d5794cee5f449e2ee1cb24c Mon Sep 17 00:00:00 2001 2 | From: Ivan Mironov 3 | Date: Wed, 5 Dec 2018 15:24:57 +0500 4 | Subject: [PATCH v2 2/6] scsi: hpsa: Support HBA mode on HP Smart Array P410i 5 | controllers 6 | 7 | This patch is based on code from the 316b221, most of which was removed by 8 | the b9092b7. 9 | 10 | Originally, HBA mode on these controllers was supported only on 11 | Itanium-based HP Integrity servers running HP-UX. Tool for switching 12 | between RAID and HBA modes existed only in form of EFI binary for 13 | ia64 architecture: saupdate.efi[1]. However, I guessed how to overwrite the 14 | corresponding flags field in controller's NVRAM, and was able to 15 | reimplement RAID/HBA mode switching tool for Linux[2]. 16 | 17 | This change was successfully tested using blktests[3] and xfstests[4] on 18 | my hardware, with embedded P410i controller (PCI ID: 103c:3245, board 19 | ID: 0x3245103c) with firmware version 6.64. 20 | 21 | This may work with some other controllers, but it is not tested 22 | (because I do not have the hardware) and it may be very dangerous. That is 23 | why this functionality is disabled by default and may be enabled only 24 | manually using the new module parameter. 25 | 26 | [1] https://support.hpe.com/hpsc/swd/public/detail?swItemId=MTX_0b76aec489764aea9802a6d27b 27 | [2] https://github.com/im-0/hpsahba 28 | [3] https://github.com/osandov/blktests 29 | [4] https://git.kernel.org/pub/scm/fs/xfs/xfstests-dev.git 30 | 31 | Signed-off-by: Ivan Mironov 32 | --- 33 | drivers/scsi/hpsa.c | 98 +++++++++++++++++++++++++++++++++++++++++++-- 34 | drivers/scsi/hpsa.h | 3 ++ 35 | 2 files changed, 97 insertions(+), 4 deletions(-) 36 | 37 | diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c 38 | index fc06b790f16b..ee3d7c722a63 100644 39 | --- a/drivers/scsi/hpsa.c 40 | +++ b/drivers/scsi/hpsa.c 41 | @@ -88,6 +88,11 @@ module_param(hpsa_simple_mode, int, S_IRUGO|S_IWUSR); 42 | MODULE_PARM_DESC(hpsa_simple_mode, 43 | "Use 'simple mode' rather than 'performant mode'"); 44 | 45 | +static bool hpsa_use_nvram_hba_flag; 46 | +module_param(hpsa_use_nvram_hba_flag, bool, 0444); 47 | +MODULE_PARM_DESC(hpsa_use_nvram_hba_flag, 48 | + "Use flag from NVRAM to enable HBA mode"); 49 | + 50 | /* define the PCI info for the cards we can control */ 51 | static const struct pci_device_id hpsa_pci_device_id[] = { 52 | {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSE, 0x103C, 0x3241}, 53 | @@ -3039,6 +3044,37 @@ static int hpsa_scsi_do_inquiry(struct ctlr_info *h, unsigned char *scsi3addr, 54 | return rc; 55 | } 56 | 57 | +static int hpsa_bmic_ctrl_mode_sense(struct ctlr_info *h, 58 | + struct bmic_controller_parameters *buf) 59 | +{ 60 | + int rc = IO_OK; 61 | + struct CommandList *c; 62 | + struct ErrorInfo *ei; 63 | + 64 | + c = cmd_alloc(h); 65 | + 66 | + if (fill_cmd(c, BMIC_SENSE_CONTROLLER_PARAMETERS, h, buf, sizeof(*buf), 67 | + 0, RAID_CTLR_LUNID, TYPE_CMD)) { 68 | + rc = -1; 69 | + goto out; 70 | + } 71 | + 72 | + rc = hpsa_scsi_do_simple_cmd_with_retry(h, c, PCI_DMA_FROMDEVICE, 73 | + NO_TIMEOUT); 74 | + if (rc) 75 | + goto out; 76 | + 77 | + ei = c->err_info; 78 | + if (ei->CommandStatus != 0 && ei->CommandStatus != CMD_DATA_UNDERRUN) { 79 | + hpsa_scsi_interpret_error(h, c); 80 | + rc = -1; 81 | + } 82 | + 83 | +out: 84 | + cmd_free(h, c); 85 | + return rc; 86 | +} 87 | + 88 | static int hpsa_send_reset(struct ctlr_info *h, unsigned char *scsi3addr, 89 | u8 reset_type, int reply_queue) 90 | { 91 | @@ -4296,6 +4332,50 @@ static bool hpsa_skip_device(struct ctlr_info *h, u8 *lunaddrbytes, 92 | return false; 93 | } 94 | 95 | +static int hpsa_nvram_hba_flag_enabled(struct ctlr_info *h, bool *flag_enabled) 96 | +{ 97 | + int rc; 98 | + struct bmic_controller_parameters *ctlr_params; 99 | + 100 | + ctlr_params = kzalloc(sizeof(*ctlr_params), GFP_KERNEL); 101 | + if (!ctlr_params) { 102 | + rc = -ENOMEM; 103 | + goto out; 104 | + } 105 | + 106 | + rc = hpsa_bmic_ctrl_mode_sense(h, ctlr_params); 107 | + if (rc) 108 | + goto out; 109 | + 110 | + *flag_enabled = ctlr_params->nvram_flags & HPSA_NVRAM_FLAG_HBA; 111 | + 112 | +out: 113 | + kfree(ctlr_params); 114 | + return rc; 115 | +} 116 | + 117 | +static int hpsa_update_nvram_hba_mode(struct ctlr_info *h) 118 | +{ 119 | + int rc; 120 | + bool flag_enabled; 121 | + 122 | + if (!hpsa_use_nvram_hba_flag) 123 | + return 0; 124 | + 125 | + rc = hpsa_nvram_hba_flag_enabled(h, &flag_enabled); 126 | + if (rc == -ENOMEM) 127 | + dev_warn(&h->pdev->dev, "Out of memory.\n"); 128 | + if (rc) 129 | + return rc; 130 | + 131 | + dev_info(&h->pdev->dev, "NVRAM HBA flag: %s\n", 132 | + flag_enabled ? "enabled" : "disabled"); 133 | + 134 | + h->nvram_hba_mode_enabled = flag_enabled; 135 | + 136 | + return 0; 137 | +} 138 | + 139 | static void hpsa_update_scsi_devices(struct ctlr_info *h) 140 | { 141 | /* the idea here is we could get notified 142 | @@ -4352,6 +4432,11 @@ static void hpsa_update_scsi_devices(struct ctlr_info *h) 143 | __func__); 144 | } 145 | 146 | + if (hpsa_update_nvram_hba_mode(h)) { 147 | + h->drv_req_rescan = 1; 148 | + goto out; 149 | + } 150 | + 151 | /* We might see up to the maximum number of logical and physical disks 152 | * plus external target devices, and a device for the local RAID 153 | * controller. 154 | @@ -4437,11 +4522,16 @@ static void hpsa_update_scsi_devices(struct ctlr_info *h) 155 | * Expose all devices except for physical devices that 156 | * are masked. 157 | */ 158 | - if (MASKED_DEVICE(lunaddrbytes) && this_device->physical_device) 159 | - this_device->expose_device = 0; 160 | - else 161 | + if (MASKED_DEVICE(lunaddrbytes) && 162 | + this_device->physical_device) { 163 | + if (is_disk_or_zbc(this_device) && 164 | + h->nvram_hba_mode_enabled) 165 | + this_device->expose_device = 1; 166 | + else 167 | + this_device->expose_device = 0; 168 | + } else { 169 | this_device->expose_device = 1; 170 | - 171 | + } 172 | 173 | /* 174 | * Get the SAS address for physical devices that are exposed. 175 | diff --git a/drivers/scsi/hpsa.h b/drivers/scsi/hpsa.h 176 | index 59e023696fff..5b508f270520 100644 177 | --- a/drivers/scsi/hpsa.h 178 | +++ b/drivers/scsi/hpsa.h 179 | @@ -158,6 +158,8 @@ struct bmic_controller_parameters { 180 | }; 181 | #pragma pack() 182 | 183 | +#define HPSA_NVRAM_FLAG_HBA (1 << 3) 184 | + 185 | struct ctlr_info { 186 | unsigned int *reply_map; 187 | int ctlr; 188 | @@ -182,6 +184,7 @@ struct ctlr_info { 189 | unsigned int msix_vectors; 190 | int intr_mode; /* either PERF_MODE_INT or SIMPLE_MODE_INT */ 191 | struct access_method access; 192 | + bool nvram_hba_mode_enabled; 193 | 194 | /* queue and queue Info */ 195 | unsigned int Qdepth; 196 | -- 197 | 2.20.1 198 | 199 | -------------------------------------------------------------------------------- /kernel/4.19-patchset-v2/v2-0003-scsi-hpsa-Add-mask-existing-devices-on-rescan-if-.patch: -------------------------------------------------------------------------------- 1 | From 6294c1422ac881f268cfdbf9ba464267acc9011f Mon Sep 17 00:00:00 2001 2 | From: Ivan Mironov 3 | Date: Wed, 5 Dec 2018 20:32:44 +0500 4 | Subject: [PATCH v2 3/6] scsi: hpsa: Add/mask existing devices on rescan if 5 | visibility changes 6 | 7 | Controller may be switched between RAID and HBA modes even without a 8 | reboot. 9 | 10 | When changing to HBA mode, it does some internal reset magic and 11 | automatically removes any configured RAID arrays. Without this patch, 12 | driver successfully detects disappearance of logical arrays, but does 13 | not expose any physical disks. 14 | 15 | Signed-off-by: Ivan Mironov 16 | --- 17 | drivers/scsi/hpsa.c | 10 ++++++++++ 18 | 1 file changed, 10 insertions(+) 19 | 20 | diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c 21 | index ee3d7c722a63..8e70a4030cae 100644 22 | --- a/drivers/scsi/hpsa.c 23 | +++ b/drivers/scsi/hpsa.c 24 | @@ -1541,6 +1541,14 @@ static inline int device_updated(struct hpsa_scsi_dev_t *dev1, 25 | return 0; 26 | } 27 | 28 | +static inline bool device_expose_changed(struct hpsa_scsi_dev_t *dev1, 29 | + struct hpsa_scsi_dev_t *dev2) 30 | +{ 31 | + if (dev1->expose_device != dev2->expose_device) 32 | + return true; 33 | + return false; 34 | +} 35 | + 36 | /* Find needle in haystack. If exact match found, return DEVICE_SAME, 37 | * and return needle location in *index. If scsi3addr matches, but not 38 | * vendor, model, serial num, etc. return DEVICE_CHANGED, and return needle 39 | @@ -1567,6 +1575,8 @@ static int hpsa_scsi_find_entry(struct hpsa_scsi_dev_t *needle, 40 | if (SCSI3ADDR_EQ(needle->scsi3addr, haystack[i]->scsi3addr)) { 41 | *index = i; 42 | if (device_is_the_same(needle, haystack[i])) { 43 | + if (device_expose_changed(needle, haystack[i])) 44 | + return DEVICE_CHANGED; 45 | if (device_updated(needle, haystack[i])) 46 | return DEVICE_UPDATED; 47 | return DEVICE_SAME; 48 | -- 49 | 2.20.1 50 | 51 | -------------------------------------------------------------------------------- /kernel/4.19-patchset-v2/v2-0004-scsi-hpsa-Ignore-HBA-flag-from-NVRAM-if-logical-d.patch: -------------------------------------------------------------------------------- 1 | From 7e721111451f25fa103a876c8d364f6875a2050e Mon Sep 17 00:00:00 2001 2 | From: Ivan Mironov 3 | Date: Mon, 10 Dec 2018 17:44:37 +0500 4 | Subject: [PATCH v2 4/6] scsi: hpsa: Ignore HBA flag from NVRAM if logical 5 | devices exist 6 | 7 | Simultaneous use of physical devices and logical RAID devices may be 8 | dangerous. 9 | 10 | Signed-off-by: Ivan Mironov 11 | --- 12 | drivers/scsi/hpsa.c | 14 +++++++++----- 13 | 1 file changed, 9 insertions(+), 5 deletions(-) 14 | 15 | diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c 16 | index 8e70a4030cae..93376bfc6921 100644 17 | --- a/drivers/scsi/hpsa.c 18 | +++ b/drivers/scsi/hpsa.c 19 | @@ -4364,10 +4364,11 @@ static int hpsa_nvram_hba_flag_enabled(struct ctlr_info *h, bool *flag_enabled) 20 | return rc; 21 | } 22 | 23 | -static int hpsa_update_nvram_hba_mode(struct ctlr_info *h) 24 | +static int hpsa_update_nvram_hba_mode(struct ctlr_info *h, u32 nlogicals) 25 | { 26 | int rc; 27 | bool flag_enabled; 28 | + bool ignore; 29 | 30 | if (!hpsa_use_nvram_hba_flag) 31 | return 0; 32 | @@ -4378,10 +4379,13 @@ static int hpsa_update_nvram_hba_mode(struct ctlr_info *h) 33 | if (rc) 34 | return rc; 35 | 36 | - dev_info(&h->pdev->dev, "NVRAM HBA flag: %s\n", 37 | - flag_enabled ? "enabled" : "disabled"); 38 | + ignore = flag_enabled && nlogicals; 39 | 40 | - h->nvram_hba_mode_enabled = flag_enabled; 41 | + dev_info(&h->pdev->dev, "NVRAM HBA flag: %s%s\n", 42 | + flag_enabled ? "enabled" : "disabled", 43 | + ignore ? " (ignored because of existing logical devices)" : ""); 44 | + 45 | + h->nvram_hba_mode_enabled = flag_enabled && !ignore; 46 | 47 | return 0; 48 | } 49 | @@ -4442,7 +4446,7 @@ static void hpsa_update_scsi_devices(struct ctlr_info *h) 50 | __func__); 51 | } 52 | 53 | - if (hpsa_update_nvram_hba_mode(h)) { 54 | + if (hpsa_update_nvram_hba_mode(h, nlogicals)) { 55 | h->drv_req_rescan = 1; 56 | goto out; 57 | } 58 | -- 59 | 2.20.1 60 | 61 | -------------------------------------------------------------------------------- /kernel/4.19-patchset-v2/v2-0005-scsi-hpsa-Name-more-fields-in-struct-bmic_identif.patch: -------------------------------------------------------------------------------- 1 | From 354f9f13743de514e570d1aa8659e8223c27b2ee Mon Sep 17 00:00:00 2001 2 | From: Ivan Mironov 3 | Date: Mon, 10 Dec 2018 18:26:32 +0500 4 | Subject: [PATCH v2 5/6] scsi: hpsa: Name more fields in "struct 5 | bmic_identify_controller" 6 | 7 | Based on information from "struct identify_controller" from 8 | cciss_vol_status.c from the cciss_vol_status tool[1]. 9 | 10 | [1] https://sourceforge.net/projects/cciss/files/cciss_vol_status/ 11 | 12 | Signed-off-by: Ivan Mironov 13 | --- 14 | drivers/scsi/hpsa_cmd.h | 109 ++++++++++++++++++++++++++++++++++++++-- 15 | 1 file changed, 106 insertions(+), 3 deletions(-) 16 | 17 | diff --git a/drivers/scsi/hpsa_cmd.h b/drivers/scsi/hpsa_cmd.h 18 | index 21a726e2eec6..64100a33f844 100644 19 | --- a/drivers/scsi/hpsa_cmd.h 20 | +++ b/drivers/scsi/hpsa_cmd.h 21 | @@ -695,11 +695,114 @@ struct hpsa_pci_info { 22 | 23 | struct bmic_identify_controller { 24 | u8 configured_logical_drive_count; /* offset 0 */ 25 | - u8 pad1[153]; 26 | + __le32 signature; 27 | + char running_firm_rev[4]; 28 | + char rom_firm_rev[4]; 29 | + u8 hardware_rev; 30 | + u8 reserved_1[4]; 31 | + __le32 drive_present_bit_map; 32 | + __le32 external_drive_bit_map; 33 | + __le32 board_id; 34 | + u8 reserved_2; 35 | + __le32 non_disk_map; 36 | + u8 reserved_3[5]; 37 | + u8 marketing_revision; 38 | + u8 controller_flags; 39 | + u8 host_flags; 40 | + u8 expand_disable_code; 41 | + u8 scsi_chip_count; 42 | + u8 reserved_4[4]; 43 | + __le32 ctlr_clock; 44 | + u8 drives_per_scsi_bus; 45 | + __le16 big_drive_present_map[8]; 46 | + __le16 big_ext_drive_map[8]; 47 | + __le16 big_non_disk_map[8]; 48 | + 49 | + /* used for FW debugging */ 50 | + __le16 task_flags; 51 | + /* Bitmap used for ICL between controllers */ 52 | + u8 icl_bus_map; 53 | + /* See REDUNDANT MODE VALUES */ 54 | + u8 redund_ctlr_modes_support; 55 | + /* See REDUNDANT MODE VALUES */ 56 | + u8 curr_redund_ctlr_mode; 57 | + /* See REDUNDANT STATUS FLAG */ 58 | + u8 redund_ctlr_status; 59 | + /* See REDUNDANT FAILURE VALUES */ 60 | + u8 redund_op_failure_code; 61 | + u8 unsupported_nile_bus; 62 | + u8 host_i2c_autorev; 63 | + u8 cpld_revision; 64 | + u8 fibre_chip_count; 65 | + u8 daughterboard_type; 66 | + u8 reserved_5[2]; 67 | + 68 | + u8 access_module_status; 69 | + u8 features_supported[12]; 70 | + /* Recovery ROM inactive f/w revision */ 71 | + char rec_rom_inactive_rev[4]; 72 | + /* Recovery ROM flags */ 73 | + u8 rec_rom_flags; 74 | + u8 pci_to_pci_bridge_status; 75 | + /* Reserved for future use */ 76 | + u8 reserved_6[4]; 77 | + /* Percent of memory allocated to write cache */ 78 | + u8 percent_write_cache; 79 | + /* Total cache board size */ 80 | + __le16 daughter_board_cache_size; 81 | + /* Number of cache batteries */ 82 | + u8 cache_battery_count; 83 | + /* Total size (MB) of atttached memory */ 84 | + __le16 total_memory_size; 85 | + /* Additional controller flags byte */ 86 | + u8 more_controller_flags; 87 | + /* 2nd byte of 3 byte autorev field */ 88 | + u8 x_board_host_i2c_autorev; 89 | + /* BBWC PIC revision */ 90 | + u8 battery_pic_rev; 91 | + /* DDFF update engine version */ 92 | + u8 ddff_version[4]; 93 | + /* Maximum logical units supported */ 94 | + __le16 max_logical_units; 95 | + /* Big num configured logical units */ 96 | __le16 extended_logical_unit_count; /* offset 154 */ 97 | - u8 pad2[136]; 98 | + /* Maximum physical devices supported */ 99 | + __le16 max_physical_devices; 100 | + /* Max physical drive per logical unit */ 101 | + __le16 max_phy_drv_per_logical_unit; 102 | + /* Number of attached enclosures */ 103 | + u8 enclosure_count; 104 | + /* Number of expanders detected */ 105 | + u8 expander_count; 106 | + /* Offset to extended drive present map*/ 107 | + __le16 offset_to_edp_bitmap; 108 | + /* Offset to extended external drive present map */ 109 | + __le16 offset_to_eedp_bitmap; 110 | + /* Offset to extended non-disk map */ 111 | + __le16 offset_to_end_bitmap; 112 | + /* Internal port status bytes */ 113 | + u8 internal_port_status[8]; 114 | + /* External port status bytes */ 115 | + u8 external_port_status[8]; 116 | + /* Yet More Controller flags */ 117 | + __le32 yet_more_controller_flags; 118 | + /* Last lockup code */ 119 | + u8 last_lockup; 120 | + /* PCI slot according to option ROM*/ 121 | + u8 pci_slot; 122 | + /* Build number */ 123 | + __le16 build_num; 124 | + /* Maximum safe full stripe size */ 125 | + __le32 max_safe_full_stripe_size; 126 | + /* Total structure length */ 127 | + __le32 total_length; 128 | + /* Vendor ID */ 129 | + char vendor_id[8]; 130 | + /* Product ID */ 131 | + char product_id[16]; 132 | + u8 reserved_7[68]; 133 | u8 controller_mode; /* offset 292 */ 134 | - u8 pad3[32]; 135 | + u8 reserved_8[32]; 136 | }; 137 | 138 | 139 | -- 140 | 2.20.1 141 | 142 | -------------------------------------------------------------------------------- /kernel/4.19-patchset-v2/v2-0006-scsi-hpsa-Do-not-use-HBA-flag-from-NVRAM-if-HBA-i.patch: -------------------------------------------------------------------------------- 1 | From 573dc6a38178db2f000b2b7c8a9c1421976314a2 Mon Sep 17 00:00:00 2001 2 | From: Ivan Mironov 3 | Date: Mon, 10 Dec 2018 18:51:35 +0500 4 | Subject: [PATCH v2 6/6] scsi: hpsa: Do not use HBA flag from NVRAM if HBA is 5 | not supported 6 | 7 | Check bmic_identify_controller.yet_more_controller_flags for HBA support 8 | bit before trying to enable HBA mode. 9 | 10 | HP's ssacli tool calls this bit "Hba Mode Supported" in full diagnostics 11 | report. 12 | 13 | Signed-off-by: Ivan Mironov 14 | --- 15 | drivers/scsi/hpsa.c | 16 ++++++++++++++-- 16 | drivers/scsi/hpsa_cmd.h | 4 ++++ 17 | 2 files changed, 18 insertions(+), 2 deletions(-) 18 | 19 | diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c 20 | index 93376bfc6921..5b4c2dd71d21 100644 21 | --- a/drivers/scsi/hpsa.c 22 | +++ b/drivers/scsi/hpsa.c 23 | @@ -4342,6 +4342,12 @@ static bool hpsa_skip_device(struct ctlr_info *h, u8 *lunaddrbytes, 24 | return false; 25 | } 26 | 27 | +static bool is_hba_supported(const struct bmic_identify_controller *id_ctlr) 28 | +{ 29 | + return le32_to_cpu(id_ctlr->yet_more_controller_flags) & 30 | + YET_MORE_CTLR_FLAG_HBA_MODE_SUPP; 31 | +} 32 | + 33 | static int hpsa_nvram_hba_flag_enabled(struct ctlr_info *h, bool *flag_enabled) 34 | { 35 | int rc; 36 | @@ -4364,7 +4370,8 @@ static int hpsa_nvram_hba_flag_enabled(struct ctlr_info *h, bool *flag_enabled) 37 | return rc; 38 | } 39 | 40 | -static int hpsa_update_nvram_hba_mode(struct ctlr_info *h, u32 nlogicals) 41 | +static int hpsa_update_nvram_hba_mode(struct ctlr_info *h, u32 nlogicals, 42 | + const struct bmic_identify_controller *id_ctlr) 43 | { 44 | int rc; 45 | bool flag_enabled; 46 | @@ -4373,6 +4380,11 @@ static int hpsa_update_nvram_hba_mode(struct ctlr_info *h, u32 nlogicals) 47 | if (!hpsa_use_nvram_hba_flag) 48 | return 0; 49 | 50 | + if (!is_hba_supported(id_ctlr)) { 51 | + dev_info(&h->pdev->dev, "NVRAM HBA flag: not supported\n"); 52 | + return 0; 53 | + } 54 | + 55 | rc = hpsa_nvram_hba_flag_enabled(h, &flag_enabled); 56 | if (rc == -ENOMEM) 57 | dev_warn(&h->pdev->dev, "Out of memory.\n"); 58 | @@ -4446,7 +4458,7 @@ static void hpsa_update_scsi_devices(struct ctlr_info *h) 59 | __func__); 60 | } 61 | 62 | - if (hpsa_update_nvram_hba_mode(h, nlogicals)) { 63 | + if (hpsa_update_nvram_hba_mode(h, nlogicals, id_ctlr)) { 64 | h->drv_req_rescan = 1; 65 | goto out; 66 | } 67 | diff --git a/drivers/scsi/hpsa_cmd.h b/drivers/scsi/hpsa_cmd.h 68 | index 64100a33f844..b27f94b257bc 100644 69 | --- a/drivers/scsi/hpsa_cmd.h 70 | +++ b/drivers/scsi/hpsa_cmd.h 71 | @@ -806,6 +806,10 @@ struct bmic_identify_controller { 72 | }; 73 | 74 | 75 | +/* ssacli calls this bit "Hba Mode Supported". */ 76 | +#define YET_MORE_CTLR_FLAG_HBA_MODE_SUPP (1 << 25) 77 | + 78 | + 79 | struct bmic_identify_physical_device { 80 | u8 scsi_bus; /* SCSI Bus number on controller */ 81 | u8 scsi_id; /* SCSI ID on this bus */ 82 | -- 83 | 2.20.1 84 | 85 | -------------------------------------------------------------------------------- /kernel/4.20-patchset-v2: -------------------------------------------------------------------------------- 1 | ./4.19-patchset-v2 -------------------------------------------------------------------------------- /kernel/5.0-patchset-v2: -------------------------------------------------------------------------------- 1 | ./4.19-patchset-v2 -------------------------------------------------------------------------------- /kernel/5.1-patchset-v2: -------------------------------------------------------------------------------- 1 | ./4.19-patchset-v2 -------------------------------------------------------------------------------- /kernel/5.10-patchset-v2: -------------------------------------------------------------------------------- 1 | ./5.3-patchset-v2 -------------------------------------------------------------------------------- /kernel/5.11-patchset-v2: -------------------------------------------------------------------------------- 1 | ./5.3-patchset-v2 -------------------------------------------------------------------------------- /kernel/5.12-patchset-v2/0001-scsi-hpsa-Add-function-to-check-if-device-is-a-disk-.patch: -------------------------------------------------------------------------------- 1 | From 1fcef046292cb8a5e64ea789ee1da6d0a5e37e3c Mon Sep 17 00:00:00 2001 2 | From: Ivan Mironov 3 | Date: Wed, 5 Dec 2018 20:20:57 +0500 4 | Subject: [PATCH 1/6] scsi: hpsa: Add function to check if device is a disk or 5 | a zoned device 6 | 7 | This check is used multiple times within the driver. New function makes 8 | conditional statements a bit shorter and more readable. 9 | 10 | Signed-off-by: Ivan Mironov 11 | --- 12 | drivers/scsi/hpsa.c | 21 +++++++++++---------- 13 | 1 file changed, 11 insertions(+), 10 deletions(-) 14 | 15 | diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c 16 | index f135a10f582b..80536f1773e3 100644 17 | --- a/drivers/scsi/hpsa.c 18 | +++ b/drivers/scsi/hpsa.c 19 | @@ -775,6 +775,11 @@ static ssize_t sas_address_show(struct device *dev, 20 | return snprintf(buf, PAGE_SIZE, "0x%016llx\n", sas_address); 21 | } 22 | 23 | +static inline bool is_disk_or_zbc(const struct hpsa_scsi_dev_t *hdev) 24 | +{ 25 | + return hdev->devtype == TYPE_DISK || hdev->devtype == TYPE_ZBC; 26 | +} 27 | + 28 | static ssize_t host_show_hp_ssd_smart_path_enabled(struct device *dev, 29 | struct device_attribute *attr, char *buf) 30 | { 31 | @@ -795,7 +800,7 @@ static ssize_t host_show_hp_ssd_smart_path_enabled(struct device *dev, 32 | offload_enabled = hdev->offload_enabled; 33 | spin_unlock_irqrestore(&h->lock, flags); 34 | 35 | - if (hdev->devtype == TYPE_DISK || hdev->devtype == TYPE_ZBC) 36 | + if (is_disk_or_zbc(hdev)) 37 | return snprintf(buf, 20, "%d\n", offload_enabled); 38 | else 39 | return snprintf(buf, 40, "%s\n", 40 | @@ -862,8 +867,7 @@ static ssize_t path_info_show(struct device *dev, 41 | PAGE_SIZE - output_len, 42 | "PORT: %.2s ", 43 | phys_connector); 44 | - if ((hdev->devtype == TYPE_DISK || hdev->devtype == TYPE_ZBC) && 45 | - hdev->expose_device) { 46 | + if (is_disk_or_zbc(hdev) && hdev->expose_device) { 47 | if (box == 0 || box == 0xFF) { 48 | output_len += scnprintf(buf + output_len, 49 | PAGE_SIZE - output_len, 50 | @@ -1723,8 +1727,7 @@ static void hpsa_figure_phys_disk_ptrs(struct ctlr_info *h, 51 | for (j = 0; j < ndevices; j++) { 52 | if (dev[j] == NULL) 53 | continue; 54 | - if (dev[j]->devtype != TYPE_DISK && 55 | - dev[j]->devtype != TYPE_ZBC) 56 | + if (!is_disk_or_zbc(dev[j])) 57 | continue; 58 | if (is_logical_device(dev[j])) 59 | continue; 60 | @@ -1777,8 +1780,7 @@ static void hpsa_update_log_drive_phys_drive_ptrs(struct ctlr_info *h, 61 | for (i = 0; i < ndevices; i++) { 62 | if (dev[i] == NULL) 63 | continue; 64 | - if (dev[i]->devtype != TYPE_DISK && 65 | - dev[i]->devtype != TYPE_ZBC) 66 | + if (!is_disk_or_zbc(dev[i])) 67 | continue; 68 | if (!is_logical_device(dev[i])) 69 | continue; 70 | @@ -3988,9 +3990,8 @@ static int hpsa_update_device_info(struct ctlr_info *h, 71 | goto bail_out; 72 | } 73 | 74 | - if ((this_device->devtype == TYPE_DISK || 75 | - this_device->devtype == TYPE_ZBC) && 76 | - is_logical_dev_addr_mode(scsi3addr)) { 77 | + if (is_disk_or_zbc(this_device) && 78 | + is_logical_dev_addr_mode(scsi3addr)) { 79 | unsigned char volume_offline; 80 | 81 | hpsa_get_raid_level(h, scsi3addr, &this_device->raid_level); 82 | -- 83 | 2.31.1 84 | 85 | -------------------------------------------------------------------------------- /kernel/5.12-patchset-v2/0002-scsi-hpsa-Support-HBA-mode-on-HP-Smart-Array-P410i-c.patch: -------------------------------------------------------------------------------- 1 | From ff4314d26ca62aa6eac32e8b754aa01ea1a5f5a3 Mon Sep 17 00:00:00 2001 2 | From: Ivan Mironov 3 | Date: Wed, 5 Dec 2018 15:24:57 +0500 4 | Subject: [PATCH 2/6] scsi: hpsa: Support HBA mode on HP Smart Array P410i 5 | controllers 6 | 7 | This patch is based on code from the 316b221, most of which was removed by 8 | the b9092b7. 9 | 10 | Originally, HBA mode on these controllers was supported only on 11 | Itanium-based HP Integrity servers running HP-UX. Tool for switching 12 | between RAID and HBA modes existed only in form of EFI binary for 13 | ia64 architecture: saupdate.efi[1]. However, I guessed how to overwrite the 14 | corresponding flags field in controller's NVRAM, and was able to 15 | reimplement RAID/HBA mode switching tool for Linux[2]. 16 | 17 | This change was successfully tested using blktests[3] and xfstests[4] on 18 | my hardware, with embedded P410i controller (PCI ID: 103c:3245, board 19 | ID: 0x3245103c) with firmware version 6.64. 20 | 21 | This may work with some other controllers, but it is not tested 22 | (because I do not have the hardware) and it may be very dangerous. That is 23 | why this functionality is disabled by default and may be enabled only 24 | manually using the new module parameter. 25 | 26 | [1] https://support.hpe.com/hpsc/swd/public/detail?swItemId=MTX_0b76aec489764aea9802a6d27b 27 | [2] https://github.com/im-0/hpsahba 28 | [3] https://github.com/osandov/blktests 29 | [4] https://git.kernel.org/pub/scm/fs/xfs/xfstests-dev.git 30 | 31 | Signed-off-by: Ivan Mironov 32 | --- 33 | drivers/scsi/hpsa.c | 98 +++++++++++++++++++++++++++++++++++++++++++-- 34 | drivers/scsi/hpsa.h | 3 ++ 35 | 2 files changed, 97 insertions(+), 4 deletions(-) 36 | 37 | diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c 38 | index 80536f1773e3..87736059a95d 100644 39 | --- a/drivers/scsi/hpsa.c 40 | +++ b/drivers/scsi/hpsa.c 41 | @@ -89,6 +89,11 @@ module_param(hpsa_simple_mode, int, S_IRUGO|S_IWUSR); 42 | MODULE_PARM_DESC(hpsa_simple_mode, 43 | "Use 'simple mode' rather than 'performant mode'"); 44 | 45 | +static bool hpsa_use_nvram_hba_flag; 46 | +module_param(hpsa_use_nvram_hba_flag, bool, 0444); 47 | +MODULE_PARM_DESC(hpsa_use_nvram_hba_flag, 48 | + "Use flag from NVRAM to enable HBA mode"); 49 | + 50 | /* define the PCI info for the cards we can control */ 51 | static const struct pci_device_id hpsa_pci_device_id[] = { 52 | {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSE, 0x103C, 0x3241}, 53 | @@ -3078,6 +3083,37 @@ static int hpsa_scsi_do_inquiry(struct ctlr_info *h, unsigned char *scsi3addr, 54 | return rc; 55 | } 56 | 57 | +static int hpsa_bmic_ctrl_mode_sense(struct ctlr_info *h, 58 | + struct bmic_controller_parameters *buf) 59 | +{ 60 | + int rc = IO_OK; 61 | + struct CommandList *c; 62 | + struct ErrorInfo *ei; 63 | + 64 | + c = cmd_alloc(h); 65 | + 66 | + if (fill_cmd(c, BMIC_SENSE_CONTROLLER_PARAMETERS, h, buf, sizeof(*buf), 67 | + 0, RAID_CTLR_LUNID, TYPE_CMD)) { 68 | + rc = -1; 69 | + goto out; 70 | + } 71 | + 72 | + rc = hpsa_scsi_do_simple_cmd_with_retry(h, c, PCI_DMA_FROMDEVICE, 73 | + NO_TIMEOUT); 74 | + if (rc) 75 | + goto out; 76 | + 77 | + ei = c->err_info; 78 | + if (ei->CommandStatus != 0 && ei->CommandStatus != CMD_DATA_UNDERRUN) { 79 | + hpsa_scsi_interpret_error(h, c); 80 | + rc = -1; 81 | + } 82 | + 83 | +out: 84 | + cmd_free(h, c); 85 | + return rc; 86 | +} 87 | + 88 | static int hpsa_send_reset(struct ctlr_info *h, struct hpsa_scsi_dev_t *dev, 89 | u8 reset_type, int reply_queue) 90 | { 91 | @@ -4326,6 +4362,50 @@ static bool hpsa_skip_device(struct ctlr_info *h, u8 *lunaddrbytes, 92 | return false; 93 | } 94 | 95 | +static int hpsa_nvram_hba_flag_enabled(struct ctlr_info *h, bool *flag_enabled) 96 | +{ 97 | + int rc; 98 | + struct bmic_controller_parameters *ctlr_params; 99 | + 100 | + ctlr_params = kzalloc(sizeof(*ctlr_params), GFP_KERNEL); 101 | + if (!ctlr_params) { 102 | + rc = -ENOMEM; 103 | + goto out; 104 | + } 105 | + 106 | + rc = hpsa_bmic_ctrl_mode_sense(h, ctlr_params); 107 | + if (rc) 108 | + goto out; 109 | + 110 | + *flag_enabled = ctlr_params->nvram_flags & HPSA_NVRAM_FLAG_HBA; 111 | + 112 | +out: 113 | + kfree(ctlr_params); 114 | + return rc; 115 | +} 116 | + 117 | +static int hpsa_update_nvram_hba_mode(struct ctlr_info *h) 118 | +{ 119 | + int rc; 120 | + bool flag_enabled; 121 | + 122 | + if (!hpsa_use_nvram_hba_flag) 123 | + return 0; 124 | + 125 | + rc = hpsa_nvram_hba_flag_enabled(h, &flag_enabled); 126 | + if (rc == -ENOMEM) 127 | + dev_warn(&h->pdev->dev, "Out of memory.\n"); 128 | + if (rc) 129 | + return rc; 130 | + 131 | + dev_info(&h->pdev->dev, "NVRAM HBA flag: %s\n", 132 | + flag_enabled ? "enabled" : "disabled"); 133 | + 134 | + h->nvram_hba_mode_enabled = flag_enabled; 135 | + 136 | + return 0; 137 | +} 138 | + 139 | static void hpsa_update_scsi_devices(struct ctlr_info *h) 140 | { 141 | /* the idea here is we could get notified 142 | @@ -4382,6 +4462,11 @@ static void hpsa_update_scsi_devices(struct ctlr_info *h) 143 | __func__); 144 | } 145 | 146 | + if (hpsa_update_nvram_hba_mode(h)) { 147 | + h->drv_req_rescan = 1; 148 | + goto out; 149 | + } 150 | + 151 | /* We might see up to the maximum number of logical and physical disks 152 | * plus external target devices, and a device for the local RAID 153 | * controller. 154 | @@ -4467,11 +4552,16 @@ static void hpsa_update_scsi_devices(struct ctlr_info *h) 155 | * Expose all devices except for physical devices that 156 | * are masked. 157 | */ 158 | - if (MASKED_DEVICE(lunaddrbytes) && this_device->physical_device) 159 | - this_device->expose_device = 0; 160 | - else 161 | + if (MASKED_DEVICE(lunaddrbytes) && 162 | + this_device->physical_device) { 163 | + if (is_disk_or_zbc(this_device) && 164 | + h->nvram_hba_mode_enabled) 165 | + this_device->expose_device = 1; 166 | + else 167 | + this_device->expose_device = 0; 168 | + } else { 169 | this_device->expose_device = 1; 170 | - 171 | + } 172 | 173 | /* 174 | * Get the SAS address for physical devices that are exposed. 175 | diff --git a/drivers/scsi/hpsa.h b/drivers/scsi/hpsa.h 176 | index 99b0750850b2..4cb0d55ac2f9 100644 177 | --- a/drivers/scsi/hpsa.h 178 | +++ b/drivers/scsi/hpsa.h 179 | @@ -161,6 +161,8 @@ struct bmic_controller_parameters { 180 | }; 181 | #pragma pack() 182 | 183 | +#define HPSA_NVRAM_FLAG_HBA (1 << 3) 184 | + 185 | struct ctlr_info { 186 | unsigned int *reply_map; 187 | int ctlr; 188 | @@ -186,6 +188,7 @@ struct ctlr_info { 189 | unsigned int msix_vectors; 190 | int intr_mode; /* either PERF_MODE_INT or SIMPLE_MODE_INT */ 191 | struct access_method access; 192 | + bool nvram_hba_mode_enabled; 193 | 194 | /* queue and queue Info */ 195 | unsigned int Qdepth; 196 | -- 197 | 2.31.1 198 | 199 | -------------------------------------------------------------------------------- /kernel/5.12-patchset-v2/0003-scsi-hpsa-Add-mask-existing-devices-on-rescan-if-vis.patch: -------------------------------------------------------------------------------- 1 | From 0b7d296b4dd06ba9cddee59178350d1fe21d8e0b Mon Sep 17 00:00:00 2001 2 | From: Ivan Mironov 3 | Date: Wed, 5 Dec 2018 20:32:44 +0500 4 | Subject: [PATCH 3/6] scsi: hpsa: Add/mask existing devices on rescan if 5 | visibility changes 6 | 7 | Controller may be switched between RAID and HBA modes even without a 8 | reboot. 9 | 10 | When changing to HBA mode, it does some internal reset magic and 11 | automatically removes any configured RAID arrays. Without this patch, 12 | driver successfully detects disappearance of logical arrays, but does 13 | not expose any physical disks. 14 | 15 | Signed-off-by: Ivan Mironov 16 | --- 17 | drivers/scsi/hpsa.c | 10 ++++++++++ 18 | 1 file changed, 10 insertions(+) 19 | 20 | diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c 21 | index 87736059a95d..2f54152955aa 100644 22 | --- a/drivers/scsi/hpsa.c 23 | +++ b/drivers/scsi/hpsa.c 24 | @@ -1549,6 +1549,14 @@ static inline int device_updated(struct hpsa_scsi_dev_t *dev1, 25 | return 0; 26 | } 27 | 28 | +static inline bool device_expose_changed(struct hpsa_scsi_dev_t *dev1, 29 | + struct hpsa_scsi_dev_t *dev2) 30 | +{ 31 | + if (dev1->expose_device != dev2->expose_device) 32 | + return true; 33 | + return false; 34 | +} 35 | + 36 | /* Find needle in haystack. If exact match found, return DEVICE_SAME, 37 | * and return needle location in *index. If scsi3addr matches, but not 38 | * vendor, model, serial num, etc. return DEVICE_CHANGED, and return needle 39 | @@ -1575,6 +1583,8 @@ static int hpsa_scsi_find_entry(struct hpsa_scsi_dev_t *needle, 40 | if (SCSI3ADDR_EQ(needle->scsi3addr, haystack[i]->scsi3addr)) { 41 | *index = i; 42 | if (device_is_the_same(needle, haystack[i])) { 43 | + if (device_expose_changed(needle, haystack[i])) 44 | + return DEVICE_CHANGED; 45 | if (device_updated(needle, haystack[i])) 46 | return DEVICE_UPDATED; 47 | return DEVICE_SAME; 48 | -- 49 | 2.31.1 50 | 51 | -------------------------------------------------------------------------------- /kernel/5.12-patchset-v2/0004-scsi-hpsa-Ignore-HBA-flag-from-NVRAM-if-logical-devi.patch: -------------------------------------------------------------------------------- 1 | From cd084e9366d76b053472c2c405b04f9620f815fe Mon Sep 17 00:00:00 2001 2 | From: Ivan Mironov 3 | Date: Mon, 10 Dec 2018 17:44:37 +0500 4 | Subject: [PATCH 4/6] scsi: hpsa: Ignore HBA flag from NVRAM if logical devices 5 | exist 6 | 7 | Simultaneous use of physical devices and logical RAID devices may be 8 | dangerous. 9 | 10 | Signed-off-by: Ivan Mironov 11 | --- 12 | drivers/scsi/hpsa.c | 14 +++++++++----- 13 | 1 file changed, 9 insertions(+), 5 deletions(-) 14 | 15 | diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c 16 | index 2f54152955aa..4075b5d782a1 100644 17 | --- a/drivers/scsi/hpsa.c 18 | +++ b/drivers/scsi/hpsa.c 19 | @@ -4394,10 +4394,11 @@ static int hpsa_nvram_hba_flag_enabled(struct ctlr_info *h, bool *flag_enabled) 20 | return rc; 21 | } 22 | 23 | -static int hpsa_update_nvram_hba_mode(struct ctlr_info *h) 24 | +static int hpsa_update_nvram_hba_mode(struct ctlr_info *h, u32 nlogicals) 25 | { 26 | int rc; 27 | bool flag_enabled; 28 | + bool ignore; 29 | 30 | if (!hpsa_use_nvram_hba_flag) 31 | return 0; 32 | @@ -4408,10 +4409,13 @@ static int hpsa_update_nvram_hba_mode(struct ctlr_info *h) 33 | if (rc) 34 | return rc; 35 | 36 | - dev_info(&h->pdev->dev, "NVRAM HBA flag: %s\n", 37 | - flag_enabled ? "enabled" : "disabled"); 38 | + ignore = flag_enabled && nlogicals; 39 | 40 | - h->nvram_hba_mode_enabled = flag_enabled; 41 | + dev_info(&h->pdev->dev, "NVRAM HBA flag: %s%s\n", 42 | + flag_enabled ? "enabled" : "disabled", 43 | + ignore ? " (ignored because of existing logical devices)" : ""); 44 | + 45 | + h->nvram_hba_mode_enabled = flag_enabled && !ignore; 46 | 47 | return 0; 48 | } 49 | @@ -4472,7 +4476,7 @@ static void hpsa_update_scsi_devices(struct ctlr_info *h) 50 | __func__); 51 | } 52 | 53 | - if (hpsa_update_nvram_hba_mode(h)) { 54 | + if (hpsa_update_nvram_hba_mode(h, nlogicals)) { 55 | h->drv_req_rescan = 1; 56 | goto out; 57 | } 58 | -- 59 | 2.31.1 60 | 61 | -------------------------------------------------------------------------------- /kernel/5.12-patchset-v2/0005-scsi-hpsa-Name-more-fields-in-struct-bmic_identify_c.patch: -------------------------------------------------------------------------------- 1 | From 74e4d34904331b893a806a26a05ba3e4aeadc973 Mon Sep 17 00:00:00 2001 2 | From: Ivan Mironov 3 | Date: Mon, 10 Dec 2018 18:26:32 +0500 4 | Subject: [PATCH 5/6] scsi: hpsa: Name more fields in "struct 5 | bmic_identify_controller" 6 | 7 | Based on information from "struct identify_controller" from 8 | cciss_vol_status.c from the cciss_vol_status tool[1]. 9 | 10 | [1] https://sourceforge.net/projects/cciss/files/cciss_vol_status/ 11 | 12 | Signed-off-by: Ivan Mironov 13 | --- 14 | drivers/scsi/hpsa_cmd.h | 109 ++++++++++++++++++++++++++++++++++++++-- 15 | 1 file changed, 106 insertions(+), 3 deletions(-) 16 | 17 | diff --git a/drivers/scsi/hpsa_cmd.h b/drivers/scsi/hpsa_cmd.h 18 | index ba6a3aa8d954..61d1757253f1 100644 19 | --- a/drivers/scsi/hpsa_cmd.h 20 | +++ b/drivers/scsi/hpsa_cmd.h 21 | @@ -710,11 +710,114 @@ struct hpsa_pci_info { 22 | 23 | struct bmic_identify_controller { 24 | u8 configured_logical_drive_count; /* offset 0 */ 25 | - u8 pad1[153]; 26 | + __le32 signature; 27 | + char running_firm_rev[4]; 28 | + char rom_firm_rev[4]; 29 | + u8 hardware_rev; 30 | + u8 reserved_1[4]; 31 | + __le32 drive_present_bit_map; 32 | + __le32 external_drive_bit_map; 33 | + __le32 board_id; 34 | + u8 reserved_2; 35 | + __le32 non_disk_map; 36 | + u8 reserved_3[5]; 37 | + u8 marketing_revision; 38 | + u8 controller_flags; 39 | + u8 host_flags; 40 | + u8 expand_disable_code; 41 | + u8 scsi_chip_count; 42 | + u8 reserved_4[4]; 43 | + __le32 ctlr_clock; 44 | + u8 drives_per_scsi_bus; 45 | + __le16 big_drive_present_map[8]; 46 | + __le16 big_ext_drive_map[8]; 47 | + __le16 big_non_disk_map[8]; 48 | + 49 | + /* used for FW debugging */ 50 | + __le16 task_flags; 51 | + /* Bitmap used for ICL between controllers */ 52 | + u8 icl_bus_map; 53 | + /* See REDUNDANT MODE VALUES */ 54 | + u8 redund_ctlr_modes_support; 55 | + /* See REDUNDANT MODE VALUES */ 56 | + u8 curr_redund_ctlr_mode; 57 | + /* See REDUNDANT STATUS FLAG */ 58 | + u8 redund_ctlr_status; 59 | + /* See REDUNDANT FAILURE VALUES */ 60 | + u8 redund_op_failure_code; 61 | + u8 unsupported_nile_bus; 62 | + u8 host_i2c_autorev; 63 | + u8 cpld_revision; 64 | + u8 fibre_chip_count; 65 | + u8 daughterboard_type; 66 | + u8 reserved_5[2]; 67 | + 68 | + u8 access_module_status; 69 | + u8 features_supported[12]; 70 | + /* Recovery ROM inactive f/w revision */ 71 | + char rec_rom_inactive_rev[4]; 72 | + /* Recovery ROM flags */ 73 | + u8 rec_rom_flags; 74 | + u8 pci_to_pci_bridge_status; 75 | + /* Reserved for future use */ 76 | + u8 reserved_6[4]; 77 | + /* Percent of memory allocated to write cache */ 78 | + u8 percent_write_cache; 79 | + /* Total cache board size */ 80 | + __le16 daughter_board_cache_size; 81 | + /* Number of cache batteries */ 82 | + u8 cache_battery_count; 83 | + /* Total size (MB) of atttached memory */ 84 | + __le16 total_memory_size; 85 | + /* Additional controller flags byte */ 86 | + u8 more_controller_flags; 87 | + /* 2nd byte of 3 byte autorev field */ 88 | + u8 x_board_host_i2c_autorev; 89 | + /* BBWC PIC revision */ 90 | + u8 battery_pic_rev; 91 | + /* DDFF update engine version */ 92 | + u8 ddff_version[4]; 93 | + /* Maximum logical units supported */ 94 | + __le16 max_logical_units; 95 | + /* Big num configured logical units */ 96 | __le16 extended_logical_unit_count; /* offset 154 */ 97 | - u8 pad2[136]; 98 | + /* Maximum physical devices supported */ 99 | + __le16 max_physical_devices; 100 | + /* Max physical drive per logical unit */ 101 | + __le16 max_phy_drv_per_logical_unit; 102 | + /* Number of attached enclosures */ 103 | + u8 enclosure_count; 104 | + /* Number of expanders detected */ 105 | + u8 expander_count; 106 | + /* Offset to extended drive present map*/ 107 | + __le16 offset_to_edp_bitmap; 108 | + /* Offset to extended external drive present map */ 109 | + __le16 offset_to_eedp_bitmap; 110 | + /* Offset to extended non-disk map */ 111 | + __le16 offset_to_end_bitmap; 112 | + /* Internal port status bytes */ 113 | + u8 internal_port_status[8]; 114 | + /* External port status bytes */ 115 | + u8 external_port_status[8]; 116 | + /* Yet More Controller flags */ 117 | + __le32 yet_more_controller_flags; 118 | + /* Last lockup code */ 119 | + u8 last_lockup; 120 | + /* PCI slot according to option ROM*/ 121 | + u8 pci_slot; 122 | + /* Build number */ 123 | + __le16 build_num; 124 | + /* Maximum safe full stripe size */ 125 | + __le32 max_safe_full_stripe_size; 126 | + /* Total structure length */ 127 | + __le32 total_length; 128 | + /* Vendor ID */ 129 | + char vendor_id[8]; 130 | + /* Product ID */ 131 | + char product_id[16]; 132 | + u8 reserved_7[68]; 133 | u8 controller_mode; /* offset 292 */ 134 | - u8 pad3[32]; 135 | + u8 reserved_8[32]; 136 | } __packed; 137 | 138 | 139 | -- 140 | 2.31.1 141 | 142 | -------------------------------------------------------------------------------- /kernel/5.12-patchset-v2/0006-scsi-hpsa-Do-not-use-HBA-flag-from-NVRAM-if-HBA-is-n.patch: -------------------------------------------------------------------------------- 1 | From b8cae6d5b9a3be3e20626464bd89ea90bf98f6d3 Mon Sep 17 00:00:00 2001 2 | From: Ivan Mironov 3 | Date: Mon, 10 Dec 2018 18:51:35 +0500 4 | Subject: [PATCH 6/6] scsi: hpsa: Do not use HBA flag from NVRAM if HBA is not 5 | supported 6 | 7 | Check bmic_identify_controller.yet_more_controller_flags for HBA support 8 | bit before trying to enable HBA mode. 9 | 10 | HP's ssacli tool calls this bit "Hba Mode Supported" in full diagnostics 11 | report. 12 | 13 | Signed-off-by: Ivan Mironov 14 | --- 15 | drivers/scsi/hpsa.c | 16 ++++++++++++++-- 16 | drivers/scsi/hpsa_cmd.h | 4 ++++ 17 | 2 files changed, 18 insertions(+), 2 deletions(-) 18 | 19 | diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c 20 | index 4075b5d782a1..7687ecbaaa4d 100644 21 | --- a/drivers/scsi/hpsa.c 22 | +++ b/drivers/scsi/hpsa.c 23 | @@ -4372,6 +4372,12 @@ static bool hpsa_skip_device(struct ctlr_info *h, u8 *lunaddrbytes, 24 | return false; 25 | } 26 | 27 | +static bool is_hba_supported(const struct bmic_identify_controller *id_ctlr) 28 | +{ 29 | + return le32_to_cpu(id_ctlr->yet_more_controller_flags) & 30 | + YET_MORE_CTLR_FLAG_HBA_MODE_SUPP; 31 | +} 32 | + 33 | static int hpsa_nvram_hba_flag_enabled(struct ctlr_info *h, bool *flag_enabled) 34 | { 35 | int rc; 36 | @@ -4394,7 +4400,8 @@ static int hpsa_nvram_hba_flag_enabled(struct ctlr_info *h, bool *flag_enabled) 37 | return rc; 38 | } 39 | 40 | -static int hpsa_update_nvram_hba_mode(struct ctlr_info *h, u32 nlogicals) 41 | +static int hpsa_update_nvram_hba_mode(struct ctlr_info *h, u32 nlogicals, 42 | + const struct bmic_identify_controller *id_ctlr) 43 | { 44 | int rc; 45 | bool flag_enabled; 46 | @@ -4403,6 +4410,11 @@ static int hpsa_update_nvram_hba_mode(struct ctlr_info *h, u32 nlogicals) 47 | if (!hpsa_use_nvram_hba_flag) 48 | return 0; 49 | 50 | + if (!is_hba_supported(id_ctlr)) { 51 | + dev_info(&h->pdev->dev, "NVRAM HBA flag: not supported\n"); 52 | + return 0; 53 | + } 54 | + 55 | rc = hpsa_nvram_hba_flag_enabled(h, &flag_enabled); 56 | if (rc == -ENOMEM) 57 | dev_warn(&h->pdev->dev, "Out of memory.\n"); 58 | @@ -4476,7 +4488,7 @@ static void hpsa_update_scsi_devices(struct ctlr_info *h) 59 | __func__); 60 | } 61 | 62 | - if (hpsa_update_nvram_hba_mode(h, nlogicals)) { 63 | + if (hpsa_update_nvram_hba_mode(h, nlogicals, id_ctlr)) { 64 | h->drv_req_rescan = 1; 65 | goto out; 66 | } 67 | diff --git a/drivers/scsi/hpsa_cmd.h b/drivers/scsi/hpsa_cmd.h 68 | index 61d1757253f1..4c5b3d7ae22f 100644 69 | --- a/drivers/scsi/hpsa_cmd.h 70 | +++ b/drivers/scsi/hpsa_cmd.h 71 | @@ -821,6 +821,10 @@ struct bmic_identify_controller { 72 | } __packed; 73 | 74 | 75 | +/* ssacli calls this bit "Hba Mode Supported". */ 76 | +#define YET_MORE_CTLR_FLAG_HBA_MODE_SUPP (1 << 25) 77 | + 78 | + 79 | struct bmic_identify_physical_device { 80 | u8 scsi_bus; /* SCSI Bus number on controller */ 81 | u8 scsi_id; /* SCSI ID on this bus */ 82 | -- 83 | 2.31.1 84 | 85 | -------------------------------------------------------------------------------- /kernel/5.13-patchset-v2: -------------------------------------------------------------------------------- 1 | ./5.12-patchset-v2 -------------------------------------------------------------------------------- /kernel/5.14-patchset-v2: -------------------------------------------------------------------------------- 1 | ./5.12-patchset-v2 -------------------------------------------------------------------------------- /kernel/5.15-patchset-v2: -------------------------------------------------------------------------------- 1 | ./5.12-patchset-v2 -------------------------------------------------------------------------------- /kernel/5.16-patchset-v2: -------------------------------------------------------------------------------- 1 | ./5.12-patchset-v2 -------------------------------------------------------------------------------- /kernel/5.17-patchset-v2: -------------------------------------------------------------------------------- 1 | ./5.12-patchset-v2 -------------------------------------------------------------------------------- /kernel/5.18-patchset-v2/0001-scsi-hpsa-Add-function-to-check-if-device-is-a-disk-.patch: -------------------------------------------------------------------------------- 1 | From bcb8089af38939c2bf45daa407dff661717e3a84 Mon Sep 17 00:00:00 2001 2 | From: Ivan Mironov 3 | Date: Wed, 5 Dec 2018 20:20:57 +0500 4 | Subject: [PATCH 1/6] scsi: hpsa: Add function to check if device is a disk or 5 | a zoned device 6 | 7 | This check is used multiple times within the driver. New function makes 8 | conditional statements a bit shorter and more readable. 9 | 10 | Signed-off-by: Ivan Mironov 11 | --- 12 | drivers/scsi/hpsa.c | 21 +++++++++++---------- 13 | 1 file changed, 11 insertions(+), 10 deletions(-) 14 | 15 | diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c 16 | index a47bcce3c9c7..1b7327cd42bd 100644 17 | --- a/drivers/scsi/hpsa.c 18 | +++ b/drivers/scsi/hpsa.c 19 | @@ -775,6 +775,11 @@ static ssize_t sas_address_show(struct device *dev, 20 | return snprintf(buf, PAGE_SIZE, "0x%016llx\n", sas_address); 21 | } 22 | 23 | +static inline bool is_disk_or_zbc(const struct hpsa_scsi_dev_t *hdev) 24 | +{ 25 | + return hdev->devtype == TYPE_DISK || hdev->devtype == TYPE_ZBC; 26 | +} 27 | + 28 | static ssize_t host_show_hp_ssd_smart_path_enabled(struct device *dev, 29 | struct device_attribute *attr, char *buf) 30 | { 31 | @@ -795,7 +800,7 @@ static ssize_t host_show_hp_ssd_smart_path_enabled(struct device *dev, 32 | offload_enabled = hdev->offload_enabled; 33 | spin_unlock_irqrestore(&h->lock, flags); 34 | 35 | - if (hdev->devtype == TYPE_DISK || hdev->devtype == TYPE_ZBC) 36 | + if (is_disk_or_zbc(hdev)) 37 | return snprintf(buf, 20, "%d\n", offload_enabled); 38 | else 39 | return snprintf(buf, 40, "%s\n", 40 | @@ -862,8 +867,7 @@ static ssize_t path_info_show(struct device *dev, 41 | PAGE_SIZE - output_len, 42 | "PORT: %.2s ", 43 | phys_connector); 44 | - if ((hdev->devtype == TYPE_DISK || hdev->devtype == TYPE_ZBC) && 45 | - hdev->expose_device) { 46 | + if (is_disk_or_zbc(hdev) && hdev->expose_device) { 47 | if (box == 0 || box == 0xFF) { 48 | output_len += scnprintf(buf + output_len, 49 | PAGE_SIZE - output_len, 50 | @@ -1727,8 +1731,7 @@ static void hpsa_figure_phys_disk_ptrs(struct ctlr_info *h, 51 | for (j = 0; j < ndevices; j++) { 52 | if (dev[j] == NULL) 53 | continue; 54 | - if (dev[j]->devtype != TYPE_DISK && 55 | - dev[j]->devtype != TYPE_ZBC) 56 | + if (!is_disk_or_zbc(dev[j])) 57 | continue; 58 | if (is_logical_device(dev[j])) 59 | continue; 60 | @@ -1781,8 +1784,7 @@ static void hpsa_update_log_drive_phys_drive_ptrs(struct ctlr_info *h, 61 | for (i = 0; i < ndevices; i++) { 62 | if (dev[i] == NULL) 63 | continue; 64 | - if (dev[i]->devtype != TYPE_DISK && 65 | - dev[i]->devtype != TYPE_ZBC) 66 | + if (!is_disk_or_zbc(dev[i])) 67 | continue; 68 | if (!is_logical_device(dev[i])) 69 | continue; 70 | @@ -3992,9 +3994,8 @@ static int hpsa_update_device_info(struct ctlr_info *h, 71 | goto bail_out; 72 | } 73 | 74 | - if ((this_device->devtype == TYPE_DISK || 75 | - this_device->devtype == TYPE_ZBC) && 76 | - is_logical_dev_addr_mode(scsi3addr)) { 77 | + if (is_disk_or_zbc(this_device) && 78 | + is_logical_dev_addr_mode(scsi3addr)) { 79 | unsigned char volume_offline; 80 | 81 | hpsa_get_raid_level(h, scsi3addr, &this_device->raid_level); 82 | -- 83 | 2.36.1 84 | 85 | -------------------------------------------------------------------------------- /kernel/5.18-patchset-v2/0002-scsi-hpsa-Support-HBA-mode-on-HP-Smart-Array-P410i-c.patch: -------------------------------------------------------------------------------- 1 | From a15eace2fbce1b16bc2c693baf5f7f4ef3bd1491 Mon Sep 17 00:00:00 2001 2 | From: Ivan Mironov 3 | Date: Wed, 5 Dec 2018 15:24:57 +0500 4 | Subject: [PATCH 2/6] scsi: hpsa: Support HBA mode on HP Smart Array P410i 5 | controllers 6 | 7 | This patch is based on code from the 316b221, most of which was removed by 8 | the b9092b7. 9 | 10 | Originally, HBA mode on these controllers was supported only on 11 | Itanium-based HP Integrity servers running HP-UX. Tool for switching 12 | between RAID and HBA modes existed only in form of EFI binary for 13 | ia64 architecture: saupdate.efi[1]. However, I guessed how to overwrite the 14 | corresponding flags field in controller's NVRAM, and was able to 15 | reimplement RAID/HBA mode switching tool for Linux[2]. 16 | 17 | This change was successfully tested using blktests[3] and xfstests[4] on 18 | my hardware, with embedded P410i controller (PCI ID: 103c:3245, board 19 | ID: 0x3245103c) with firmware version 6.64. 20 | 21 | This may work with some other controllers, but it is not tested 22 | (because I do not have the hardware) and it may be very dangerous. That is 23 | why this functionality is disabled by default and may be enabled only 24 | manually using the new module parameter. 25 | 26 | [1] https://support.hpe.com/hpsc/swd/public/detail?swItemId=MTX_0b76aec489764aea9802a6d27b 27 | [2] https://github.com/im-0/hpsahba 28 | [3] https://github.com/osandov/blktests 29 | [4] https://git.kernel.org/pub/scm/fs/xfs/xfstests-dev.git 30 | 31 | Signed-off-by: Ivan Mironov 32 | --- 33 | drivers/scsi/hpsa.c | 98 +++++++++++++++++++++++++++++++++++++++++++-- 34 | drivers/scsi/hpsa.h | 3 ++ 35 | 2 files changed, 97 insertions(+), 4 deletions(-) 36 | 37 | diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c 38 | index 1b7327cd42bd..bd6daece9c2e 100644 39 | --- a/drivers/scsi/hpsa.c 40 | +++ b/drivers/scsi/hpsa.c 41 | @@ -89,6 +89,11 @@ module_param(hpsa_simple_mode, int, S_IRUGO|S_IWUSR); 42 | MODULE_PARM_DESC(hpsa_simple_mode, 43 | "Use 'simple mode' rather than 'performant mode'"); 44 | 45 | +static bool hpsa_use_nvram_hba_flag; 46 | +module_param(hpsa_use_nvram_hba_flag, bool, 0444); 47 | +MODULE_PARM_DESC(hpsa_use_nvram_hba_flag, 48 | + "Use flag from NVRAM to enable HBA mode"); 49 | + 50 | /* define the PCI info for the cards we can control */ 51 | static const struct pci_device_id hpsa_pci_device_id[] = { 52 | {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSE, 0x103C, 0x3241}, 53 | @@ -3082,6 +3087,37 @@ static int hpsa_scsi_do_inquiry(struct ctlr_info *h, unsigned char *scsi3addr, 54 | return rc; 55 | } 56 | 57 | +static int hpsa_bmic_ctrl_mode_sense(struct ctlr_info *h, 58 | + struct bmic_controller_parameters *buf) 59 | +{ 60 | + int rc = IO_OK; 61 | + struct CommandList *c; 62 | + struct ErrorInfo *ei; 63 | + 64 | + c = cmd_alloc(h); 65 | + 66 | + if (fill_cmd(c, BMIC_SENSE_CONTROLLER_PARAMETERS, h, buf, sizeof(*buf), 67 | + 0, RAID_CTLR_LUNID, TYPE_CMD)) { 68 | + rc = -1; 69 | + goto out; 70 | + } 71 | + 72 | + rc = hpsa_scsi_do_simple_cmd_with_retry(h, c, DMA_FROM_DEVICE, 73 | + NO_TIMEOUT); 74 | + if (rc) 75 | + goto out; 76 | + 77 | + ei = c->err_info; 78 | + if (ei->CommandStatus != 0 && ei->CommandStatus != CMD_DATA_UNDERRUN) { 79 | + hpsa_scsi_interpret_error(h, c); 80 | + rc = -1; 81 | + } 82 | + 83 | +out: 84 | + cmd_free(h, c); 85 | + return rc; 86 | +} 87 | + 88 | static int hpsa_send_reset(struct ctlr_info *h, struct hpsa_scsi_dev_t *dev, 89 | u8 reset_type, int reply_queue) 90 | { 91 | @@ -4330,6 +4366,50 @@ static bool hpsa_skip_device(struct ctlr_info *h, u8 *lunaddrbytes, 92 | return false; 93 | } 94 | 95 | +static int hpsa_nvram_hba_flag_enabled(struct ctlr_info *h, bool *flag_enabled) 96 | +{ 97 | + int rc; 98 | + struct bmic_controller_parameters *ctlr_params; 99 | + 100 | + ctlr_params = kzalloc(sizeof(*ctlr_params), GFP_KERNEL); 101 | + if (!ctlr_params) { 102 | + rc = -ENOMEM; 103 | + goto out; 104 | + } 105 | + 106 | + rc = hpsa_bmic_ctrl_mode_sense(h, ctlr_params); 107 | + if (rc) 108 | + goto out; 109 | + 110 | + *flag_enabled = ctlr_params->nvram_flags & HPSA_NVRAM_FLAG_HBA; 111 | + 112 | +out: 113 | + kfree(ctlr_params); 114 | + return rc; 115 | +} 116 | + 117 | +static int hpsa_update_nvram_hba_mode(struct ctlr_info *h) 118 | +{ 119 | + int rc; 120 | + bool flag_enabled; 121 | + 122 | + if (!hpsa_use_nvram_hba_flag) 123 | + return 0; 124 | + 125 | + rc = hpsa_nvram_hba_flag_enabled(h, &flag_enabled); 126 | + if (rc == -ENOMEM) 127 | + dev_warn(&h->pdev->dev, "Out of memory.\n"); 128 | + if (rc) 129 | + return rc; 130 | + 131 | + dev_info(&h->pdev->dev, "NVRAM HBA flag: %s\n", 132 | + flag_enabled ? "enabled" : "disabled"); 133 | + 134 | + h->nvram_hba_mode_enabled = flag_enabled; 135 | + 136 | + return 0; 137 | +} 138 | + 139 | static void hpsa_update_scsi_devices(struct ctlr_info *h) 140 | { 141 | /* the idea here is we could get notified 142 | @@ -4384,6 +4464,11 @@ static void hpsa_update_scsi_devices(struct ctlr_info *h) 143 | __func__); 144 | } 145 | 146 | + if (hpsa_update_nvram_hba_mode(h)) { 147 | + h->drv_req_rescan = 1; 148 | + goto out; 149 | + } 150 | + 151 | /* We might see up to the maximum number of logical and physical disks 152 | * plus external target devices, and a device for the local RAID 153 | * controller. 154 | @@ -4469,11 +4554,16 @@ static void hpsa_update_scsi_devices(struct ctlr_info *h) 155 | * Expose all devices except for physical devices that 156 | * are masked. 157 | */ 158 | - if (MASKED_DEVICE(lunaddrbytes) && this_device->physical_device) 159 | - this_device->expose_device = 0; 160 | - else 161 | + if (MASKED_DEVICE(lunaddrbytes) && 162 | + this_device->physical_device) { 163 | + if (is_disk_or_zbc(this_device) && 164 | + h->nvram_hba_mode_enabled) 165 | + this_device->expose_device = 1; 166 | + else 167 | + this_device->expose_device = 0; 168 | + } else { 169 | this_device->expose_device = 1; 170 | - 171 | + } 172 | 173 | /* 174 | * Get the SAS address for physical devices that are exposed. 175 | diff --git a/drivers/scsi/hpsa.h b/drivers/scsi/hpsa.h 176 | index 99b0750850b2..4cb0d55ac2f9 100644 177 | --- a/drivers/scsi/hpsa.h 178 | +++ b/drivers/scsi/hpsa.h 179 | @@ -161,6 +161,8 @@ struct bmic_controller_parameters { 180 | }; 181 | #pragma pack() 182 | 183 | +#define HPSA_NVRAM_FLAG_HBA (1 << 3) 184 | + 185 | struct ctlr_info { 186 | unsigned int *reply_map; 187 | int ctlr; 188 | @@ -186,6 +188,7 @@ struct ctlr_info { 189 | unsigned int msix_vectors; 190 | int intr_mode; /* either PERF_MODE_INT or SIMPLE_MODE_INT */ 191 | struct access_method access; 192 | + bool nvram_hba_mode_enabled; 193 | 194 | /* queue and queue Info */ 195 | unsigned int Qdepth; 196 | -- 197 | 2.36.1 198 | 199 | -------------------------------------------------------------------------------- /kernel/5.18-patchset-v2/0003-scsi-hpsa-Add-mask-existing-devices-on-rescan-if-vis.patch: -------------------------------------------------------------------------------- 1 | From 1624c1a6f67ef9e0b8052345d4bb4b721d46f8d2 Mon Sep 17 00:00:00 2001 2 | From: Ivan Mironov 3 | Date: Wed, 5 Dec 2018 20:32:44 +0500 4 | Subject: [PATCH 3/6] scsi: hpsa: Add/mask existing devices on rescan if 5 | visibility changes 6 | 7 | Controller may be switched between RAID and HBA modes even without a 8 | reboot. 9 | 10 | When changing to HBA mode, it does some internal reset magic and 11 | automatically removes any configured RAID arrays. Without this patch, 12 | driver successfully detects disappearance of logical arrays, but does 13 | not expose any physical disks. 14 | 15 | Signed-off-by: Ivan Mironov 16 | --- 17 | drivers/scsi/hpsa.c | 10 ++++++++++ 18 | 1 file changed, 10 insertions(+) 19 | 20 | diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c 21 | index bd6daece9c2e..466b4fa4dd5f 100644 22 | --- a/drivers/scsi/hpsa.c 23 | +++ b/drivers/scsi/hpsa.c 24 | @@ -1553,6 +1553,14 @@ static inline int device_updated(struct hpsa_scsi_dev_t *dev1, 25 | return 0; 26 | } 27 | 28 | +static inline bool device_expose_changed(struct hpsa_scsi_dev_t *dev1, 29 | + struct hpsa_scsi_dev_t *dev2) 30 | +{ 31 | + if (dev1->expose_device != dev2->expose_device) 32 | + return true; 33 | + return false; 34 | +} 35 | + 36 | /* Find needle in haystack. If exact match found, return DEVICE_SAME, 37 | * and return needle location in *index. If scsi3addr matches, but not 38 | * vendor, model, serial num, etc. return DEVICE_CHANGED, and return needle 39 | @@ -1579,6 +1587,8 @@ static int hpsa_scsi_find_entry(struct hpsa_scsi_dev_t *needle, 40 | if (SCSI3ADDR_EQ(needle->scsi3addr, haystack[i]->scsi3addr)) { 41 | *index = i; 42 | if (device_is_the_same(needle, haystack[i])) { 43 | + if (device_expose_changed(needle, haystack[i])) 44 | + return DEVICE_CHANGED; 45 | if (device_updated(needle, haystack[i])) 46 | return DEVICE_UPDATED; 47 | return DEVICE_SAME; 48 | -- 49 | 2.36.1 50 | 51 | -------------------------------------------------------------------------------- /kernel/5.18-patchset-v2/0004-scsi-hpsa-Ignore-HBA-flag-from-NVRAM-if-logical-devi.patch: -------------------------------------------------------------------------------- 1 | From 2c8cf6b36bd6a5d13ad71d2af077140391d10cda Mon Sep 17 00:00:00 2001 2 | From: Ivan Mironov 3 | Date: Mon, 10 Dec 2018 17:44:37 +0500 4 | Subject: [PATCH 4/6] scsi: hpsa: Ignore HBA flag from NVRAM if logical devices 5 | exist 6 | 7 | Simultaneous use of physical devices and logical RAID devices may be 8 | dangerous. 9 | 10 | Signed-off-by: Ivan Mironov 11 | --- 12 | drivers/scsi/hpsa.c | 14 +++++++++----- 13 | 1 file changed, 9 insertions(+), 5 deletions(-) 14 | 15 | diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c 16 | index 466b4fa4dd5f..4d6f8a2e043a 100644 17 | --- a/drivers/scsi/hpsa.c 18 | +++ b/drivers/scsi/hpsa.c 19 | @@ -4398,10 +4398,11 @@ static int hpsa_nvram_hba_flag_enabled(struct ctlr_info *h, bool *flag_enabled) 20 | return rc; 21 | } 22 | 23 | -static int hpsa_update_nvram_hba_mode(struct ctlr_info *h) 24 | +static int hpsa_update_nvram_hba_mode(struct ctlr_info *h, u32 nlogicals) 25 | { 26 | int rc; 27 | bool flag_enabled; 28 | + bool ignore; 29 | 30 | if (!hpsa_use_nvram_hba_flag) 31 | return 0; 32 | @@ -4412,10 +4413,13 @@ static int hpsa_update_nvram_hba_mode(struct ctlr_info *h) 33 | if (rc) 34 | return rc; 35 | 36 | - dev_info(&h->pdev->dev, "NVRAM HBA flag: %s\n", 37 | - flag_enabled ? "enabled" : "disabled"); 38 | + ignore = flag_enabled && nlogicals; 39 | 40 | - h->nvram_hba_mode_enabled = flag_enabled; 41 | + dev_info(&h->pdev->dev, "NVRAM HBA flag: %s%s\n", 42 | + flag_enabled ? "enabled" : "disabled", 43 | + ignore ? " (ignored because of existing logical devices)" : ""); 44 | + 45 | + h->nvram_hba_mode_enabled = flag_enabled && !ignore; 46 | 47 | return 0; 48 | } 49 | @@ -4474,7 +4478,7 @@ static void hpsa_update_scsi_devices(struct ctlr_info *h) 50 | __func__); 51 | } 52 | 53 | - if (hpsa_update_nvram_hba_mode(h)) { 54 | + if (hpsa_update_nvram_hba_mode(h, nlogicals)) { 55 | h->drv_req_rescan = 1; 56 | goto out; 57 | } 58 | -- 59 | 2.36.1 60 | 61 | -------------------------------------------------------------------------------- /kernel/5.18-patchset-v2/0005-scsi-hpsa-Name-more-fields-in-struct-bmic_identify_c.patch: -------------------------------------------------------------------------------- 1 | From 33566d227a37d818e4a6c393730bbd22d3fccc27 Mon Sep 17 00:00:00 2001 2 | From: Ivan Mironov 3 | Date: Mon, 10 Dec 2018 18:26:32 +0500 4 | Subject: [PATCH 5/6] scsi: hpsa: Name more fields in "struct 5 | bmic_identify_controller" 6 | 7 | Based on information from "struct identify_controller" from 8 | cciss_vol_status.c from the cciss_vol_status tool[1]. 9 | 10 | [1] https://sourceforge.net/projects/cciss/files/cciss_vol_status/ 11 | 12 | Signed-off-by: Ivan Mironov 13 | --- 14 | drivers/scsi/hpsa_cmd.h | 109 ++++++++++++++++++++++++++++++++++++++-- 15 | 1 file changed, 106 insertions(+), 3 deletions(-) 16 | 17 | diff --git a/drivers/scsi/hpsa_cmd.h b/drivers/scsi/hpsa_cmd.h 18 | index ba6a3aa8d954..61d1757253f1 100644 19 | --- a/drivers/scsi/hpsa_cmd.h 20 | +++ b/drivers/scsi/hpsa_cmd.h 21 | @@ -710,11 +710,114 @@ struct hpsa_pci_info { 22 | 23 | struct bmic_identify_controller { 24 | u8 configured_logical_drive_count; /* offset 0 */ 25 | - u8 pad1[153]; 26 | + __le32 signature; 27 | + char running_firm_rev[4]; 28 | + char rom_firm_rev[4]; 29 | + u8 hardware_rev; 30 | + u8 reserved_1[4]; 31 | + __le32 drive_present_bit_map; 32 | + __le32 external_drive_bit_map; 33 | + __le32 board_id; 34 | + u8 reserved_2; 35 | + __le32 non_disk_map; 36 | + u8 reserved_3[5]; 37 | + u8 marketing_revision; 38 | + u8 controller_flags; 39 | + u8 host_flags; 40 | + u8 expand_disable_code; 41 | + u8 scsi_chip_count; 42 | + u8 reserved_4[4]; 43 | + __le32 ctlr_clock; 44 | + u8 drives_per_scsi_bus; 45 | + __le16 big_drive_present_map[8]; 46 | + __le16 big_ext_drive_map[8]; 47 | + __le16 big_non_disk_map[8]; 48 | + 49 | + /* used for FW debugging */ 50 | + __le16 task_flags; 51 | + /* Bitmap used for ICL between controllers */ 52 | + u8 icl_bus_map; 53 | + /* See REDUNDANT MODE VALUES */ 54 | + u8 redund_ctlr_modes_support; 55 | + /* See REDUNDANT MODE VALUES */ 56 | + u8 curr_redund_ctlr_mode; 57 | + /* See REDUNDANT STATUS FLAG */ 58 | + u8 redund_ctlr_status; 59 | + /* See REDUNDANT FAILURE VALUES */ 60 | + u8 redund_op_failure_code; 61 | + u8 unsupported_nile_bus; 62 | + u8 host_i2c_autorev; 63 | + u8 cpld_revision; 64 | + u8 fibre_chip_count; 65 | + u8 daughterboard_type; 66 | + u8 reserved_5[2]; 67 | + 68 | + u8 access_module_status; 69 | + u8 features_supported[12]; 70 | + /* Recovery ROM inactive f/w revision */ 71 | + char rec_rom_inactive_rev[4]; 72 | + /* Recovery ROM flags */ 73 | + u8 rec_rom_flags; 74 | + u8 pci_to_pci_bridge_status; 75 | + /* Reserved for future use */ 76 | + u8 reserved_6[4]; 77 | + /* Percent of memory allocated to write cache */ 78 | + u8 percent_write_cache; 79 | + /* Total cache board size */ 80 | + __le16 daughter_board_cache_size; 81 | + /* Number of cache batteries */ 82 | + u8 cache_battery_count; 83 | + /* Total size (MB) of atttached memory */ 84 | + __le16 total_memory_size; 85 | + /* Additional controller flags byte */ 86 | + u8 more_controller_flags; 87 | + /* 2nd byte of 3 byte autorev field */ 88 | + u8 x_board_host_i2c_autorev; 89 | + /* BBWC PIC revision */ 90 | + u8 battery_pic_rev; 91 | + /* DDFF update engine version */ 92 | + u8 ddff_version[4]; 93 | + /* Maximum logical units supported */ 94 | + __le16 max_logical_units; 95 | + /* Big num configured logical units */ 96 | __le16 extended_logical_unit_count; /* offset 154 */ 97 | - u8 pad2[136]; 98 | + /* Maximum physical devices supported */ 99 | + __le16 max_physical_devices; 100 | + /* Max physical drive per logical unit */ 101 | + __le16 max_phy_drv_per_logical_unit; 102 | + /* Number of attached enclosures */ 103 | + u8 enclosure_count; 104 | + /* Number of expanders detected */ 105 | + u8 expander_count; 106 | + /* Offset to extended drive present map*/ 107 | + __le16 offset_to_edp_bitmap; 108 | + /* Offset to extended external drive present map */ 109 | + __le16 offset_to_eedp_bitmap; 110 | + /* Offset to extended non-disk map */ 111 | + __le16 offset_to_end_bitmap; 112 | + /* Internal port status bytes */ 113 | + u8 internal_port_status[8]; 114 | + /* External port status bytes */ 115 | + u8 external_port_status[8]; 116 | + /* Yet More Controller flags */ 117 | + __le32 yet_more_controller_flags; 118 | + /* Last lockup code */ 119 | + u8 last_lockup; 120 | + /* PCI slot according to option ROM*/ 121 | + u8 pci_slot; 122 | + /* Build number */ 123 | + __le16 build_num; 124 | + /* Maximum safe full stripe size */ 125 | + __le32 max_safe_full_stripe_size; 126 | + /* Total structure length */ 127 | + __le32 total_length; 128 | + /* Vendor ID */ 129 | + char vendor_id[8]; 130 | + /* Product ID */ 131 | + char product_id[16]; 132 | + u8 reserved_7[68]; 133 | u8 controller_mode; /* offset 292 */ 134 | - u8 pad3[32]; 135 | + u8 reserved_8[32]; 136 | } __packed; 137 | 138 | 139 | -- 140 | 2.36.1 141 | 142 | -------------------------------------------------------------------------------- /kernel/5.18-patchset-v2/0006-scsi-hpsa-Do-not-use-HBA-flag-from-NVRAM-if-HBA-is-n.patch: -------------------------------------------------------------------------------- 1 | From 5f18845f54a8a8ab2de1f41884a5f1c3a97e9574 Mon Sep 17 00:00:00 2001 2 | From: Ivan Mironov 3 | Date: Mon, 10 Dec 2018 18:51:35 +0500 4 | Subject: [PATCH 6/6] scsi: hpsa: Do not use HBA flag from NVRAM if HBA is not 5 | supported 6 | 7 | Check bmic_identify_controller.yet_more_controller_flags for HBA support 8 | bit before trying to enable HBA mode. 9 | 10 | HP's ssacli tool calls this bit "Hba Mode Supported" in full diagnostics 11 | report. 12 | 13 | Signed-off-by: Ivan Mironov 14 | --- 15 | drivers/scsi/hpsa.c | 16 ++++++++++++++-- 16 | drivers/scsi/hpsa_cmd.h | 4 ++++ 17 | 2 files changed, 18 insertions(+), 2 deletions(-) 18 | 19 | diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c 20 | index 4d6f8a2e043a..1c7861833a5d 100644 21 | --- a/drivers/scsi/hpsa.c 22 | +++ b/drivers/scsi/hpsa.c 23 | @@ -4376,6 +4376,12 @@ static bool hpsa_skip_device(struct ctlr_info *h, u8 *lunaddrbytes, 24 | return false; 25 | } 26 | 27 | +static bool is_hba_supported(const struct bmic_identify_controller *id_ctlr) 28 | +{ 29 | + return le32_to_cpu(id_ctlr->yet_more_controller_flags) & 30 | + YET_MORE_CTLR_FLAG_HBA_MODE_SUPP; 31 | +} 32 | + 33 | static int hpsa_nvram_hba_flag_enabled(struct ctlr_info *h, bool *flag_enabled) 34 | { 35 | int rc; 36 | @@ -4398,7 +4404,8 @@ static int hpsa_nvram_hba_flag_enabled(struct ctlr_info *h, bool *flag_enabled) 37 | return rc; 38 | } 39 | 40 | -static int hpsa_update_nvram_hba_mode(struct ctlr_info *h, u32 nlogicals) 41 | +static int hpsa_update_nvram_hba_mode(struct ctlr_info *h, u32 nlogicals, 42 | + const struct bmic_identify_controller *id_ctlr) 43 | { 44 | int rc; 45 | bool flag_enabled; 46 | @@ -4407,6 +4414,11 @@ static int hpsa_update_nvram_hba_mode(struct ctlr_info *h, u32 nlogicals) 47 | if (!hpsa_use_nvram_hba_flag) 48 | return 0; 49 | 50 | + if (!is_hba_supported(id_ctlr)) { 51 | + dev_info(&h->pdev->dev, "NVRAM HBA flag: not supported\n"); 52 | + return 0; 53 | + } 54 | + 55 | rc = hpsa_nvram_hba_flag_enabled(h, &flag_enabled); 56 | if (rc == -ENOMEM) 57 | dev_warn(&h->pdev->dev, "Out of memory.\n"); 58 | @@ -4478,7 +4490,7 @@ static void hpsa_update_scsi_devices(struct ctlr_info *h) 59 | __func__); 60 | } 61 | 62 | - if (hpsa_update_nvram_hba_mode(h, nlogicals)) { 63 | + if (hpsa_update_nvram_hba_mode(h, nlogicals, id_ctlr)) { 64 | h->drv_req_rescan = 1; 65 | goto out; 66 | } 67 | diff --git a/drivers/scsi/hpsa_cmd.h b/drivers/scsi/hpsa_cmd.h 68 | index 61d1757253f1..4c5b3d7ae22f 100644 69 | --- a/drivers/scsi/hpsa_cmd.h 70 | +++ b/drivers/scsi/hpsa_cmd.h 71 | @@ -821,6 +821,10 @@ struct bmic_identify_controller { 72 | } __packed; 73 | 74 | 75 | +/* ssacli calls this bit "Hba Mode Supported". */ 76 | +#define YET_MORE_CTLR_FLAG_HBA_MODE_SUPP (1 << 25) 77 | + 78 | + 79 | struct bmic_identify_physical_device { 80 | u8 scsi_bus; /* SCSI Bus number on controller */ 81 | u8 scsi_id; /* SCSI ID on this bus */ 82 | -- 83 | 2.36.1 84 | 85 | -------------------------------------------------------------------------------- /kernel/5.3-patchset-v2/0001-scsi-hpsa-Add-function-to-check-if-device-is-a-disk-.patch: -------------------------------------------------------------------------------- 1 | From 90ce950eab0bcd0c10077e8de1eac13e709640d6 Mon Sep 17 00:00:00 2001 2 | From: Ivan Mironov 3 | Date: Wed, 5 Dec 2018 20:20:57 +0500 4 | Subject: [PATCH 1/6] scsi: hpsa: Add function to check if device is a disk or 5 | a zoned device 6 | 7 | This check is used multiple times within the driver. New function makes 8 | conditional statements a bit shorter and more readable. 9 | 10 | Signed-off-by: Ivan Mironov 11 | --- 12 | drivers/scsi/hpsa.c | 21 +++++++++++---------- 13 | 1 file changed, 11 insertions(+), 10 deletions(-) 14 | 15 | diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c 16 | index 216e557f703e..ad3b451f431f 100644 17 | --- a/drivers/scsi/hpsa.c 18 | +++ b/drivers/scsi/hpsa.c 19 | @@ -765,6 +765,11 @@ static ssize_t sas_address_show(struct device *dev, 20 | return snprintf(buf, PAGE_SIZE, "0x%016llx\n", sas_address); 21 | } 22 | 23 | +static inline bool is_disk_or_zbc(const struct hpsa_scsi_dev_t *hdev) 24 | +{ 25 | + return hdev->devtype == TYPE_DISK || hdev->devtype == TYPE_ZBC; 26 | +} 27 | + 28 | static ssize_t host_show_hp_ssd_smart_path_enabled(struct device *dev, 29 | struct device_attribute *attr, char *buf) 30 | { 31 | @@ -785,7 +790,7 @@ static ssize_t host_show_hp_ssd_smart_path_enabled(struct device *dev, 32 | offload_enabled = hdev->offload_enabled; 33 | spin_unlock_irqrestore(&h->lock, flags); 34 | 35 | - if (hdev->devtype == TYPE_DISK || hdev->devtype == TYPE_ZBC) 36 | + if (is_disk_or_zbc(hdev)) 37 | return snprintf(buf, 20, "%d\n", offload_enabled); 38 | else 39 | return snprintf(buf, 40, "%s\n", 40 | @@ -852,8 +857,7 @@ static ssize_t path_info_show(struct device *dev, 41 | PAGE_SIZE - output_len, 42 | "PORT: %.2s ", 43 | phys_connector); 44 | - if ((hdev->devtype == TYPE_DISK || hdev->devtype == TYPE_ZBC) && 45 | - hdev->expose_device) { 46 | + if (is_disk_or_zbc(hdev) && hdev->expose_device) { 47 | if (box == 0 || box == 0xFF) { 48 | output_len += scnprintf(buf + output_len, 49 | PAGE_SIZE - output_len, 50 | @@ -1710,8 +1714,7 @@ static void hpsa_figure_phys_disk_ptrs(struct ctlr_info *h, 51 | for (j = 0; j < ndevices; j++) { 52 | if (dev[j] == NULL) 53 | continue; 54 | - if (dev[j]->devtype != TYPE_DISK && 55 | - dev[j]->devtype != TYPE_ZBC) 56 | + if (!is_disk_or_zbc(dev[j])) 57 | continue; 58 | if (is_logical_device(dev[j])) 59 | continue; 60 | @@ -1765,8 +1768,7 @@ static void hpsa_update_log_drive_phys_drive_ptrs(struct ctlr_info *h, 61 | for (i = 0; i < ndevices; i++) { 62 | if (dev[i] == NULL) 63 | continue; 64 | - if (dev[i]->devtype != TYPE_DISK && 65 | - dev[i]->devtype != TYPE_ZBC) 66 | + if (!is_disk_or_zbc(dev[i])) 67 | continue; 68 | if (!is_logical_device(dev[i])) 69 | continue; 70 | @@ -3966,9 +3968,8 @@ static int hpsa_update_device_info(struct ctlr_info *h, 71 | goto bail_out; 72 | } 73 | 74 | - if ((this_device->devtype == TYPE_DISK || 75 | - this_device->devtype == TYPE_ZBC) && 76 | - is_logical_dev_addr_mode(scsi3addr)) { 77 | + if (is_disk_or_zbc(this_device) && 78 | + is_logical_dev_addr_mode(scsi3addr)) { 79 | unsigned char volume_offline; 80 | 81 | hpsa_get_raid_level(h, scsi3addr, &this_device->raid_level); 82 | -- 83 | 2.24.1 84 | 85 | -------------------------------------------------------------------------------- /kernel/5.3-patchset-v2/0002-scsi-hpsa-Support-HBA-mode-on-HP-Smart-Array-P410i-c.patch: -------------------------------------------------------------------------------- 1 | From e3fec6547bd07b58d41da566f27ade817574608f Mon Sep 17 00:00:00 2001 2 | From: Ivan Mironov 3 | Date: Wed, 5 Dec 2018 15:24:57 +0500 4 | Subject: [PATCH 2/6] scsi: hpsa: Support HBA mode on HP Smart Array P410i 5 | controllers 6 | 7 | This patch is based on code from the 316b221, most of which was removed by 8 | the b9092b7. 9 | 10 | Originally, HBA mode on these controllers was supported only on 11 | Itanium-based HP Integrity servers running HP-UX. Tool for switching 12 | between RAID and HBA modes existed only in form of EFI binary for 13 | ia64 architecture: saupdate.efi[1]. However, I guessed how to overwrite the 14 | corresponding flags field in controller's NVRAM, and was able to 15 | reimplement RAID/HBA mode switching tool for Linux[2]. 16 | 17 | This change was successfully tested using blktests[3] and xfstests[4] on 18 | my hardware, with embedded P410i controller (PCI ID: 103c:3245, board 19 | ID: 0x3245103c) with firmware version 6.64. 20 | 21 | This may work with some other controllers, but it is not tested 22 | (because I do not have the hardware) and it may be very dangerous. That is 23 | why this functionality is disabled by default and may be enabled only 24 | manually using the new module parameter. 25 | 26 | [1] https://support.hpe.com/hpsc/swd/public/detail?swItemId=MTX_0b76aec489764aea9802a6d27b 27 | [2] https://github.com/im-0/hpsahba 28 | [3] https://github.com/osandov/blktests 29 | [4] https://git.kernel.org/pub/scm/fs/xfs/xfstests-dev.git 30 | 31 | Signed-off-by: Ivan Mironov 32 | --- 33 | drivers/scsi/hpsa.c | 98 +++++++++++++++++++++++++++++++++++++++++++-- 34 | drivers/scsi/hpsa.h | 3 ++ 35 | 2 files changed, 97 insertions(+), 4 deletions(-) 36 | 37 | diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c 38 | index ad3b451f431f..e98d5db41803 100644 39 | --- a/drivers/scsi/hpsa.c 40 | +++ b/drivers/scsi/hpsa.c 41 | @@ -89,6 +89,11 @@ module_param(hpsa_simple_mode, int, S_IRUGO|S_IWUSR); 42 | MODULE_PARM_DESC(hpsa_simple_mode, 43 | "Use 'simple mode' rather than 'performant mode'"); 44 | 45 | +static bool hpsa_use_nvram_hba_flag; 46 | +module_param(hpsa_use_nvram_hba_flag, bool, 0444); 47 | +MODULE_PARM_DESC(hpsa_use_nvram_hba_flag, 48 | + "Use flag from NVRAM to enable HBA mode"); 49 | + 50 | /* define the PCI info for the cards we can control */ 51 | static const struct pci_device_id hpsa_pci_device_id[] = { 52 | {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSE, 0x103C, 0x3241}, 53 | @@ -3064,6 +3069,37 @@ static int hpsa_scsi_do_inquiry(struct ctlr_info *h, unsigned char *scsi3addr, 54 | return rc; 55 | } 56 | 57 | +static int hpsa_bmic_ctrl_mode_sense(struct ctlr_info *h, 58 | + struct bmic_controller_parameters *buf) 59 | +{ 60 | + int rc = IO_OK; 61 | + struct CommandList *c; 62 | + struct ErrorInfo *ei; 63 | + 64 | + c = cmd_alloc(h); 65 | + 66 | + if (fill_cmd(c, BMIC_SENSE_CONTROLLER_PARAMETERS, h, buf, sizeof(*buf), 67 | + 0, RAID_CTLR_LUNID, TYPE_CMD)) { 68 | + rc = -1; 69 | + goto out; 70 | + } 71 | + 72 | + rc = hpsa_scsi_do_simple_cmd_with_retry(h, c, PCI_DMA_FROMDEVICE, 73 | + NO_TIMEOUT); 74 | + if (rc) 75 | + goto out; 76 | + 77 | + ei = c->err_info; 78 | + if (ei->CommandStatus != 0 && ei->CommandStatus != CMD_DATA_UNDERRUN) { 79 | + hpsa_scsi_interpret_error(h, c); 80 | + rc = -1; 81 | + } 82 | + 83 | +out: 84 | + cmd_free(h, c); 85 | + return rc; 86 | +} 87 | + 88 | static int hpsa_send_reset(struct ctlr_info *h, struct hpsa_scsi_dev_t *dev, 89 | u8 reset_type, int reply_queue) 90 | { 91 | @@ -4297,6 +4333,50 @@ static bool hpsa_skip_device(struct ctlr_info *h, u8 *lunaddrbytes, 92 | return false; 93 | } 94 | 95 | +static int hpsa_nvram_hba_flag_enabled(struct ctlr_info *h, bool *flag_enabled) 96 | +{ 97 | + int rc; 98 | + struct bmic_controller_parameters *ctlr_params; 99 | + 100 | + ctlr_params = kzalloc(sizeof(*ctlr_params), GFP_KERNEL); 101 | + if (!ctlr_params) { 102 | + rc = -ENOMEM; 103 | + goto out; 104 | + } 105 | + 106 | + rc = hpsa_bmic_ctrl_mode_sense(h, ctlr_params); 107 | + if (rc) 108 | + goto out; 109 | + 110 | + *flag_enabled = ctlr_params->nvram_flags & HPSA_NVRAM_FLAG_HBA; 111 | + 112 | +out: 113 | + kfree(ctlr_params); 114 | + return rc; 115 | +} 116 | + 117 | +static int hpsa_update_nvram_hba_mode(struct ctlr_info *h) 118 | +{ 119 | + int rc; 120 | + bool flag_enabled; 121 | + 122 | + if (!hpsa_use_nvram_hba_flag) 123 | + return 0; 124 | + 125 | + rc = hpsa_nvram_hba_flag_enabled(h, &flag_enabled); 126 | + if (rc == -ENOMEM) 127 | + dev_warn(&h->pdev->dev, "Out of memory.\n"); 128 | + if (rc) 129 | + return rc; 130 | + 131 | + dev_info(&h->pdev->dev, "NVRAM HBA flag: %s\n", 132 | + flag_enabled ? "enabled" : "disabled"); 133 | + 134 | + h->nvram_hba_mode_enabled = flag_enabled; 135 | + 136 | + return 0; 137 | +} 138 | + 139 | static void hpsa_update_scsi_devices(struct ctlr_info *h) 140 | { 141 | /* the idea here is we could get notified 142 | @@ -4353,6 +4433,11 @@ static void hpsa_update_scsi_devices(struct ctlr_info *h) 143 | __func__); 144 | } 145 | 146 | + if (hpsa_update_nvram_hba_mode(h)) { 147 | + h->drv_req_rescan = 1; 148 | + goto out; 149 | + } 150 | + 151 | /* We might see up to the maximum number of logical and physical disks 152 | * plus external target devices, and a device for the local RAID 153 | * controller. 154 | @@ -4438,11 +4523,16 @@ static void hpsa_update_scsi_devices(struct ctlr_info *h) 155 | * Expose all devices except for physical devices that 156 | * are masked. 157 | */ 158 | - if (MASKED_DEVICE(lunaddrbytes) && this_device->physical_device) 159 | - this_device->expose_device = 0; 160 | - else 161 | + if (MASKED_DEVICE(lunaddrbytes) && 162 | + this_device->physical_device) { 163 | + if (is_disk_or_zbc(this_device) && 164 | + h->nvram_hba_mode_enabled) 165 | + this_device->expose_device = 1; 166 | + else 167 | + this_device->expose_device = 0; 168 | + } else { 169 | this_device->expose_device = 1; 170 | - 171 | + } 172 | 173 | /* 174 | * Get the SAS address for physical devices that are exposed. 175 | diff --git a/drivers/scsi/hpsa.h b/drivers/scsi/hpsa.h 176 | index f8c88fc7b80a..e5d8cbca0c57 100644 177 | --- a/drivers/scsi/hpsa.h 178 | +++ b/drivers/scsi/hpsa.h 179 | @@ -160,6 +160,8 @@ struct bmic_controller_parameters { 180 | }; 181 | #pragma pack() 182 | 183 | +#define HPSA_NVRAM_FLAG_HBA (1 << 3) 184 | + 185 | struct ctlr_info { 186 | unsigned int *reply_map; 187 | int ctlr; 188 | @@ -185,6 +187,7 @@ struct ctlr_info { 189 | unsigned int msix_vectors; 190 | int intr_mode; /* either PERF_MODE_INT or SIMPLE_MODE_INT */ 191 | struct access_method access; 192 | + bool nvram_hba_mode_enabled; 193 | 194 | /* queue and queue Info */ 195 | unsigned int Qdepth; 196 | -- 197 | 2.24.1 198 | 199 | -------------------------------------------------------------------------------- /kernel/5.3-patchset-v2/0003-scsi-hpsa-Add-mask-existing-devices-on-rescan-if-vis.patch: -------------------------------------------------------------------------------- 1 | From aee2c1dd4cf30ff8db73fe70e308b9ed0422482a Mon Sep 17 00:00:00 2001 2 | From: Ivan Mironov 3 | Date: Wed, 5 Dec 2018 20:32:44 +0500 4 | Subject: [PATCH 3/6] scsi: hpsa: Add/mask existing devices on rescan if 5 | visibility changes 6 | 7 | Controller may be switched between RAID and HBA modes even without a 8 | reboot. 9 | 10 | When changing to HBA mode, it does some internal reset magic and 11 | automatically removes any configured RAID arrays. Without this patch, 12 | driver successfully detects disappearance of logical arrays, but does 13 | not expose any physical disks. 14 | 15 | Signed-off-by: Ivan Mironov 16 | --- 17 | drivers/scsi/hpsa.c | 10 ++++++++++ 18 | 1 file changed, 10 insertions(+) 19 | 20 | diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c 21 | index e98d5db41803..8e36bbab2595 100644 22 | --- a/drivers/scsi/hpsa.c 23 | +++ b/drivers/scsi/hpsa.c 24 | @@ -1536,6 +1536,14 @@ static inline int device_updated(struct hpsa_scsi_dev_t *dev1, 25 | return 0; 26 | } 27 | 28 | +static inline bool device_expose_changed(struct hpsa_scsi_dev_t *dev1, 29 | + struct hpsa_scsi_dev_t *dev2) 30 | +{ 31 | + if (dev1->expose_device != dev2->expose_device) 32 | + return true; 33 | + return false; 34 | +} 35 | + 36 | /* Find needle in haystack. If exact match found, return DEVICE_SAME, 37 | * and return needle location in *index. If scsi3addr matches, but not 38 | * vendor, model, serial num, etc. return DEVICE_CHANGED, and return needle 39 | @@ -1562,6 +1570,8 @@ static int hpsa_scsi_find_entry(struct hpsa_scsi_dev_t *needle, 40 | if (SCSI3ADDR_EQ(needle->scsi3addr, haystack[i]->scsi3addr)) { 41 | *index = i; 42 | if (device_is_the_same(needle, haystack[i])) { 43 | + if (device_expose_changed(needle, haystack[i])) 44 | + return DEVICE_CHANGED; 45 | if (device_updated(needle, haystack[i])) 46 | return DEVICE_UPDATED; 47 | return DEVICE_SAME; 48 | -- 49 | 2.24.1 50 | 51 | -------------------------------------------------------------------------------- /kernel/5.3-patchset-v2/0004-scsi-hpsa-Ignore-HBA-flag-from-NVRAM-if-logical-devi.patch: -------------------------------------------------------------------------------- 1 | From 0ce47b8d34ec75acb1ff32035000669492cb0549 Mon Sep 17 00:00:00 2001 2 | From: Ivan Mironov 3 | Date: Mon, 10 Dec 2018 17:44:37 +0500 4 | Subject: [PATCH 4/6] scsi: hpsa: Ignore HBA flag from NVRAM if logical devices 5 | exist 6 | 7 | Simultaneous use of physical devices and logical RAID devices may be 8 | dangerous. 9 | 10 | Signed-off-by: Ivan Mironov 11 | --- 12 | drivers/scsi/hpsa.c | 14 +++++++++----- 13 | 1 file changed, 9 insertions(+), 5 deletions(-) 14 | 15 | diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c 16 | index 8e36bbab2595..6737fe4c2a97 100644 17 | --- a/drivers/scsi/hpsa.c 18 | +++ b/drivers/scsi/hpsa.c 19 | @@ -4365,10 +4365,11 @@ static int hpsa_nvram_hba_flag_enabled(struct ctlr_info *h, bool *flag_enabled) 20 | return rc; 21 | } 22 | 23 | -static int hpsa_update_nvram_hba_mode(struct ctlr_info *h) 24 | +static int hpsa_update_nvram_hba_mode(struct ctlr_info *h, u32 nlogicals) 25 | { 26 | int rc; 27 | bool flag_enabled; 28 | + bool ignore; 29 | 30 | if (!hpsa_use_nvram_hba_flag) 31 | return 0; 32 | @@ -4379,10 +4380,13 @@ static int hpsa_update_nvram_hba_mode(struct ctlr_info *h) 33 | if (rc) 34 | return rc; 35 | 36 | - dev_info(&h->pdev->dev, "NVRAM HBA flag: %s\n", 37 | - flag_enabled ? "enabled" : "disabled"); 38 | + ignore = flag_enabled && nlogicals; 39 | 40 | - h->nvram_hba_mode_enabled = flag_enabled; 41 | + dev_info(&h->pdev->dev, "NVRAM HBA flag: %s%s\n", 42 | + flag_enabled ? "enabled" : "disabled", 43 | + ignore ? " (ignored because of existing logical devices)" : ""); 44 | + 45 | + h->nvram_hba_mode_enabled = flag_enabled && !ignore; 46 | 47 | return 0; 48 | } 49 | @@ -4443,7 +4447,7 @@ static void hpsa_update_scsi_devices(struct ctlr_info *h) 50 | __func__); 51 | } 52 | 53 | - if (hpsa_update_nvram_hba_mode(h)) { 54 | + if (hpsa_update_nvram_hba_mode(h, nlogicals)) { 55 | h->drv_req_rescan = 1; 56 | goto out; 57 | } 58 | -- 59 | 2.24.1 60 | 61 | -------------------------------------------------------------------------------- /kernel/5.3-patchset-v2/0005-scsi-hpsa-Name-more-fields-in-struct-bmic_identify_c.patch: -------------------------------------------------------------------------------- 1 | From 55141b38995ab9cfa762c3842fc835e045aca42f Mon Sep 17 00:00:00 2001 2 | From: Ivan Mironov 3 | Date: Mon, 10 Dec 2018 18:26:32 +0500 4 | Subject: [PATCH 5/6] scsi: hpsa: Name more fields in "struct 5 | bmic_identify_controller" 6 | 7 | Based on information from "struct identify_controller" from 8 | cciss_vol_status.c from the cciss_vol_status tool[1]. 9 | 10 | [1] https://sourceforge.net/projects/cciss/files/cciss_vol_status/ 11 | 12 | Signed-off-by: Ivan Mironov 13 | --- 14 | drivers/scsi/hpsa_cmd.h | 109 ++++++++++++++++++++++++++++++++++++++-- 15 | 1 file changed, 106 insertions(+), 3 deletions(-) 16 | 17 | diff --git a/drivers/scsi/hpsa_cmd.h b/drivers/scsi/hpsa_cmd.h 18 | index 7825cbfea4dc..be58646fa22f 100644 19 | --- a/drivers/scsi/hpsa_cmd.h 20 | +++ b/drivers/scsi/hpsa_cmd.h 21 | @@ -696,11 +696,114 @@ struct hpsa_pci_info { 22 | 23 | struct bmic_identify_controller { 24 | u8 configured_logical_drive_count; /* offset 0 */ 25 | - u8 pad1[153]; 26 | + __le32 signature; 27 | + char running_firm_rev[4]; 28 | + char rom_firm_rev[4]; 29 | + u8 hardware_rev; 30 | + u8 reserved_1[4]; 31 | + __le32 drive_present_bit_map; 32 | + __le32 external_drive_bit_map; 33 | + __le32 board_id; 34 | + u8 reserved_2; 35 | + __le32 non_disk_map; 36 | + u8 reserved_3[5]; 37 | + u8 marketing_revision; 38 | + u8 controller_flags; 39 | + u8 host_flags; 40 | + u8 expand_disable_code; 41 | + u8 scsi_chip_count; 42 | + u8 reserved_4[4]; 43 | + __le32 ctlr_clock; 44 | + u8 drives_per_scsi_bus; 45 | + __le16 big_drive_present_map[8]; 46 | + __le16 big_ext_drive_map[8]; 47 | + __le16 big_non_disk_map[8]; 48 | + 49 | + /* used for FW debugging */ 50 | + __le16 task_flags; 51 | + /* Bitmap used for ICL between controllers */ 52 | + u8 icl_bus_map; 53 | + /* See REDUNDANT MODE VALUES */ 54 | + u8 redund_ctlr_modes_support; 55 | + /* See REDUNDANT MODE VALUES */ 56 | + u8 curr_redund_ctlr_mode; 57 | + /* See REDUNDANT STATUS FLAG */ 58 | + u8 redund_ctlr_status; 59 | + /* See REDUNDANT FAILURE VALUES */ 60 | + u8 redund_op_failure_code; 61 | + u8 unsupported_nile_bus; 62 | + u8 host_i2c_autorev; 63 | + u8 cpld_revision; 64 | + u8 fibre_chip_count; 65 | + u8 daughterboard_type; 66 | + u8 reserved_5[2]; 67 | + 68 | + u8 access_module_status; 69 | + u8 features_supported[12]; 70 | + /* Recovery ROM inactive f/w revision */ 71 | + char rec_rom_inactive_rev[4]; 72 | + /* Recovery ROM flags */ 73 | + u8 rec_rom_flags; 74 | + u8 pci_to_pci_bridge_status; 75 | + /* Reserved for future use */ 76 | + u8 reserved_6[4]; 77 | + /* Percent of memory allocated to write cache */ 78 | + u8 percent_write_cache; 79 | + /* Total cache board size */ 80 | + __le16 daughter_board_cache_size; 81 | + /* Number of cache batteries */ 82 | + u8 cache_battery_count; 83 | + /* Total size (MB) of atttached memory */ 84 | + __le16 total_memory_size; 85 | + /* Additional controller flags byte */ 86 | + u8 more_controller_flags; 87 | + /* 2nd byte of 3 byte autorev field */ 88 | + u8 x_board_host_i2c_autorev; 89 | + /* BBWC PIC revision */ 90 | + u8 battery_pic_rev; 91 | + /* DDFF update engine version */ 92 | + u8 ddff_version[4]; 93 | + /* Maximum logical units supported */ 94 | + __le16 max_logical_units; 95 | + /* Big num configured logical units */ 96 | __le16 extended_logical_unit_count; /* offset 154 */ 97 | - u8 pad2[136]; 98 | + /* Maximum physical devices supported */ 99 | + __le16 max_physical_devices; 100 | + /* Max physical drive per logical unit */ 101 | + __le16 max_phy_drv_per_logical_unit; 102 | + /* Number of attached enclosures */ 103 | + u8 enclosure_count; 104 | + /* Number of expanders detected */ 105 | + u8 expander_count; 106 | + /* Offset to extended drive present map*/ 107 | + __le16 offset_to_edp_bitmap; 108 | + /* Offset to extended external drive present map */ 109 | + __le16 offset_to_eedp_bitmap; 110 | + /* Offset to extended non-disk map */ 111 | + __le16 offset_to_end_bitmap; 112 | + /* Internal port status bytes */ 113 | + u8 internal_port_status[8]; 114 | + /* External port status bytes */ 115 | + u8 external_port_status[8]; 116 | + /* Yet More Controller flags */ 117 | + __le32 yet_more_controller_flags; 118 | + /* Last lockup code */ 119 | + u8 last_lockup; 120 | + /* PCI slot according to option ROM*/ 121 | + u8 pci_slot; 122 | + /* Build number */ 123 | + __le16 build_num; 124 | + /* Maximum safe full stripe size */ 125 | + __le32 max_safe_full_stripe_size; 126 | + /* Total structure length */ 127 | + __le32 total_length; 128 | + /* Vendor ID */ 129 | + char vendor_id[8]; 130 | + /* Product ID */ 131 | + char product_id[16]; 132 | + u8 reserved_7[68]; 133 | u8 controller_mode; /* offset 292 */ 134 | - u8 pad3[32]; 135 | + u8 reserved_8[32]; 136 | }; 137 | 138 | 139 | -- 140 | 2.24.1 141 | 142 | -------------------------------------------------------------------------------- /kernel/5.3-patchset-v2/0006-scsi-hpsa-Do-not-use-HBA-flag-from-NVRAM-if-HBA-is-n.patch: -------------------------------------------------------------------------------- 1 | From 3670b6ebead0d067d88347da8687e75eea689f7b Mon Sep 17 00:00:00 2001 2 | From: Ivan Mironov 3 | Date: Mon, 10 Dec 2018 18:51:35 +0500 4 | Subject: [PATCH 6/6] scsi: hpsa: Do not use HBA flag from NVRAM if HBA is not 5 | supported 6 | 7 | Check bmic_identify_controller.yet_more_controller_flags for HBA support 8 | bit before trying to enable HBA mode. 9 | 10 | HP's ssacli tool calls this bit "Hba Mode Supported" in full diagnostics 11 | report. 12 | 13 | Signed-off-by: Ivan Mironov 14 | --- 15 | drivers/scsi/hpsa.c | 16 ++++++++++++++-- 16 | drivers/scsi/hpsa_cmd.h | 4 ++++ 17 | 2 files changed, 18 insertions(+), 2 deletions(-) 18 | 19 | diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c 20 | index 6737fe4c2a97..1148f71a74b4 100644 21 | --- a/drivers/scsi/hpsa.c 22 | +++ b/drivers/scsi/hpsa.c 23 | @@ -4343,6 +4343,12 @@ static bool hpsa_skip_device(struct ctlr_info *h, u8 *lunaddrbytes, 24 | return false; 25 | } 26 | 27 | +static bool is_hba_supported(const struct bmic_identify_controller *id_ctlr) 28 | +{ 29 | + return le32_to_cpu(id_ctlr->yet_more_controller_flags) & 30 | + YET_MORE_CTLR_FLAG_HBA_MODE_SUPP; 31 | +} 32 | + 33 | static int hpsa_nvram_hba_flag_enabled(struct ctlr_info *h, bool *flag_enabled) 34 | { 35 | int rc; 36 | @@ -4365,7 +4371,8 @@ static int hpsa_nvram_hba_flag_enabled(struct ctlr_info *h, bool *flag_enabled) 37 | return rc; 38 | } 39 | 40 | -static int hpsa_update_nvram_hba_mode(struct ctlr_info *h, u32 nlogicals) 41 | +static int hpsa_update_nvram_hba_mode(struct ctlr_info *h, u32 nlogicals, 42 | + const struct bmic_identify_controller *id_ctlr) 43 | { 44 | int rc; 45 | bool flag_enabled; 46 | @@ -4374,6 +4381,11 @@ static int hpsa_update_nvram_hba_mode(struct ctlr_info *h, u32 nlogicals) 47 | if (!hpsa_use_nvram_hba_flag) 48 | return 0; 49 | 50 | + if (!is_hba_supported(id_ctlr)) { 51 | + dev_info(&h->pdev->dev, "NVRAM HBA flag: not supported\n"); 52 | + return 0; 53 | + } 54 | + 55 | rc = hpsa_nvram_hba_flag_enabled(h, &flag_enabled); 56 | if (rc == -ENOMEM) 57 | dev_warn(&h->pdev->dev, "Out of memory.\n"); 58 | @@ -4447,7 +4459,7 @@ static void hpsa_update_scsi_devices(struct ctlr_info *h) 59 | __func__); 60 | } 61 | 62 | - if (hpsa_update_nvram_hba_mode(h, nlogicals)) { 63 | + if (hpsa_update_nvram_hba_mode(h, nlogicals, id_ctlr)) { 64 | h->drv_req_rescan = 1; 65 | goto out; 66 | } 67 | diff --git a/drivers/scsi/hpsa_cmd.h b/drivers/scsi/hpsa_cmd.h 68 | index be58646fa22f..83c4ba6929b5 100644 69 | --- a/drivers/scsi/hpsa_cmd.h 70 | +++ b/drivers/scsi/hpsa_cmd.h 71 | @@ -807,6 +807,10 @@ struct bmic_identify_controller { 72 | }; 73 | 74 | 75 | +/* ssacli calls this bit "Hba Mode Supported". */ 76 | +#define YET_MORE_CTLR_FLAG_HBA_MODE_SUPP (1 << 25) 77 | + 78 | + 79 | struct bmic_identify_physical_device { 80 | u8 scsi_bus; /* SCSI Bus number on controller */ 81 | u8 scsi_id; /* SCSI ID on this bus */ 82 | -- 83 | 2.24.1 84 | 85 | -------------------------------------------------------------------------------- /kernel/5.4-patchset-v2: -------------------------------------------------------------------------------- 1 | ./5.3-patchset-v2 -------------------------------------------------------------------------------- /kernel/5.5-patchset-v2: -------------------------------------------------------------------------------- 1 | ./5.3-patchset-v2 -------------------------------------------------------------------------------- /kernel/5.6-patchset-v2: -------------------------------------------------------------------------------- 1 | ./5.3-patchset-v2 -------------------------------------------------------------------------------- /kernel/5.7-patchset-v2: -------------------------------------------------------------------------------- 1 | ./5.3-patchset-v2 -------------------------------------------------------------------------------- /kernel/5.8-patchset-v2: -------------------------------------------------------------------------------- 1 | ./5.3-patchset-v2 -------------------------------------------------------------------------------- /kernel/5.9-patchset-v2: -------------------------------------------------------------------------------- 1 | ./5.3-patchset-v2 -------------------------------------------------------------------------------- /main.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Tool to enable/disable HBA mode on some HP Smart Array controllers. 3 | * Copyright (C) 2018 Ivan Mironov 4 | * 5 | * This program is free software; you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation; either version 2 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program; if not, write to the Free Software 17 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 18 | */ 19 | 20 | /* Force assert() to work. */ 21 | #ifdef NDEBUG 22 | # undef NDEBUG 23 | #endif 24 | 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | 34 | #include 35 | #include 36 | 37 | #include 38 | #include 39 | #include 40 | 41 | #include "hpsa.h" 42 | 43 | static const char *const hpsahba_version = "0.0.0"; 44 | 45 | __attribute__((format(printf, 1, 2))) 46 | __attribute__((noreturn)) 47 | static void really_die(const char *format, ...) 48 | { va_list args; 49 | 50 | va_start(args, format); 51 | vfprintf(stderr, format, args); 52 | va_end(args); 53 | fflush(stderr); 54 | 55 | exit(1); 56 | } 57 | 58 | #define die(format, ...) \ 59 | really_die("FATAL ERROR: " format "\n", ##__VA_ARGS__) 60 | #define die_errno(format, ...) \ 61 | die(format ": %d %s", ##__VA_ARGS__, errno, strerror(errno)) 62 | #define die_dev(path, format, ...) \ 63 | die("%s: " format, path, ##__VA_ARGS__) 64 | #define die_dev_errno(path, format, ...) \ 65 | die_dev(path, format ": %d %s", ##__VA_ARGS__, errno, strerror(errno)) 66 | 67 | static void print_help(const char *exe_name) 68 | { 69 | fprintf(stderr, 70 | "hpsahba version %s, Copyright (C) 2018 " 71 | "Ivan Mironov \n" 72 | "\n" 73 | "Usage:\n" 74 | "\t%s -h\n" 75 | "\t%s -v\n" 76 | "\t%s -i /dev/sgN\n" 77 | "\t%s -E /dev/sgN\n" 78 | "\t%s -d /dev/sgN\n" 79 | "\n" 80 | "Options:\n" 81 | "\t-h\n" 82 | "\t\tPrint this help message and exit.\n" 83 | "\n" 84 | "\t-v\n" 85 | "\t\tPrint version number and exit.\n" 86 | "\n" 87 | "\t-i \n" 88 | "\t\tGet information about HP Smart Array controller.\n" 89 | "\n" 90 | "\t-E \n" 91 | "\t\tEnable HBA mode on controller.\n" 92 | "\n" 93 | "\t-d \n" 94 | "\t\tDisable HBA mode on controller.\n", 95 | hpsahba_version, 96 | exe_name, exe_name, exe_name, exe_name, exe_name); 97 | } 98 | 99 | static void print_version() 100 | { 101 | printf("%s\n", hpsahba_version); 102 | } 103 | 104 | #define TERM_FMT_RESET "0" 105 | #define TERM_FMT_BOLD "1" 106 | #define TERM_FMT_BLINK "5" 107 | 108 | #define TERM_FG_BLACK "30" 109 | #define TERM_FG_YELLOW "33" 110 | 111 | #define TERM_BG_RED "41" 112 | 113 | #define TERM_ATTR_START "\033[" 114 | #define TERM_ATTR_END "m" 115 | #define TERM_ATTR_RESET TERM_ATTR_START TERM_FMT_RESET TERM_ATTR_END 116 | 117 | static void print_caution_sign(bool no_color) 118 | { 119 | if (no_color) { 120 | fputs(" // CAUTION // ", stderr); 121 | } else { 122 | fputs( 123 | TERM_ATTR_START TERM_FMT_RESET ";" TERM_BG_RED ";" 124 | TERM_FMT_BOLD ";" TERM_FG_YELLOW TERM_ATTR_END 125 | " // " 126 | TERM_ATTR_START TERM_FMT_RESET ";" TERM_BG_RED ";" 127 | TERM_FMT_BLINK ";" TERM_FG_BLACK TERM_ATTR_END 128 | " CAUTION " 129 | TERM_ATTR_START TERM_FMT_RESET ";" TERM_BG_RED ";" 130 | TERM_FMT_BOLD ";" TERM_FG_YELLOW TERM_ATTR_END 131 | " // " 132 | TERM_ATTR_RESET, 133 | stderr); 134 | } 135 | } 136 | 137 | static void ask_user_confirmation() 138 | { 139 | char buf[5]; 140 | 141 | for (int i = 0; i < 5; i++) 142 | print_caution_sign((i % 2) || (isatty(2) != 1)); 143 | fprintf(stderr,"\n" 144 | "\tHBA MODE CHANGE WILL DESTROY YOU DATA!\n" 145 | "\tHBA MODE CHANGE MAY DAMAGE YOUR HARDWARE!\n" 146 | "Type uppercase \"yes\" to accept the risks and continue: "); 147 | if (fgets(buf, sizeof(buf), stdin) == NULL) 148 | die_errno("fgets() failed to read user confirmation"); 149 | if (strcmp(buf, "YES\n")) 150 | die("Cancelled by user"); 151 | } 152 | 153 | static int open_dev(const char *path) 154 | { 155 | int fd = open(path, O_RDWR); 156 | if (fd == -1) { 157 | die_dev_errno(path, "Unable to open device r/w"); 158 | } 159 | return fd; 160 | } 161 | 162 | static void close_dev(const char *path, int fd) 163 | { 164 | if (close(fd)) 165 | die_dev_errno(path, "close() failed"); 166 | } 167 | 168 | static void set_cdb_buf_size(uint8_t cdb[], size_t size) 169 | { 170 | assert(size <= UINT16_MAX); 171 | cdb[7] = size >> 8; 172 | cdb[8] = size & 0XFF; 173 | } 174 | 175 | static void set_cmd_buf(IOCTL_Command_struct *cmd, void *buf, 176 | size_t size) 177 | { 178 | set_cdb_buf_size(cmd->Request.CDB, size); 179 | cmd->buf_size = size; 180 | cmd->buf = buf; 181 | } 182 | 183 | static void fill_cmd(IOCTL_Command_struct *cmd, uint8_t cmd_num, void *buf, 184 | size_t size) 185 | { 186 | int direction_write = 0; 187 | 188 | switch (cmd_num) { 189 | case BMIC_IDENTIFY_CONTROLLER: 190 | case BMIC_SENSE_CONTROLLER_PARAMETERS: 191 | /* direction_write = 0; */ 192 | break; 193 | case BMIC_SET_CONTROLLER_PARAMETERS: 194 | direction_write = 1; 195 | break; 196 | default: 197 | /* Should never happen. */ 198 | assert(0); 199 | } 200 | cmd->Request.CDB[6] = cmd_num; 201 | 202 | if (direction_write) { 203 | cmd->Request.CDB[0] = BMIC_WRITE; 204 | cmd->Request.Type.Direction = XFER_WRITE; 205 | } else { 206 | cmd->Request.CDB[0] = BMIC_READ; 207 | cmd->Request.Type.Direction = XFER_READ; 208 | } 209 | 210 | set_cmd_buf(cmd, buf, size); 211 | 212 | cmd->Request.CDBLen = 10; 213 | 214 | cmd->Request.Type.Type = TYPE_CMD; 215 | cmd->Request.Type.Attribute = ATTR_SIMPLE; 216 | cmd->Request.Timeout = 0; 217 | } 218 | 219 | static void print_cmd_error(const ErrorInfo_struct *info) 220 | { 221 | size_t sense_len = info->SenseLen; 222 | 223 | fprintf(stderr, 224 | "HPSA SCSI error info:\n" 225 | "\tScsiStatus: 0x%02x\n" 226 | "\tSenseLen: %u\n" 227 | "\tCommandStatus: 0x%04x\n" 228 | "\tResidualCnt: 0x%08x\n" 229 | "\tSenseInfo:", 230 | info->ScsiStatus, 231 | info->SenseLen, 232 | info->CommandStatus, 233 | info->ResidualCnt); 234 | 235 | if (sense_len) { 236 | if (sense_len > sizeof(info->SenseInfo)) 237 | sense_len = sizeof(info->SenseInfo); 238 | for (size_t i = 0; i < sense_len; i++) 239 | fprintf(stderr, " 0x%02x", info->SenseInfo[i]); 240 | } else { 241 | fputs(" ", stderr); 242 | } 243 | fputc('\n', stderr); 244 | } 245 | 246 | static void really_exec_cmd(const char *path, int fd, uint8_t cmd_num, 247 | const char *cmd_name, void *buf, size_t size) 248 | { 249 | int rc; 250 | IOCTL_Command_struct cmd = {{{0}}, {0}, {0}, 0, 0}; 251 | 252 | fill_cmd(&cmd, cmd_num, buf, size); 253 | rc = ioctl(fd, CCISS_PASSTHRU, &cmd); 254 | if (rc) 255 | die_dev_errno(path, 256 | "ioctl(CCISS_PASSTHRU) failed with command " 257 | "%s, rc == %d", cmd_name, rc); 258 | 259 | if (cmd.error_info.CommandStatus) { 260 | print_cmd_error(&cmd.error_info); 261 | die_dev(path, "Command %s failed", cmd_name); 262 | } 263 | } 264 | 265 | #define exec_cmd(path, fd, cmd, buf, size) \ 266 | really_exec_cmd(path, fd, cmd, #cmd, buf, size) 267 | 268 | static void identify_controller(const char *path, int fd, 269 | struct bmic_identify_controller *controller_id) 270 | { 271 | exec_cmd(path, fd, BMIC_IDENTIFY_CONTROLLER, controller_id, 272 | sizeof(*controller_id)); 273 | } 274 | 275 | static int is_hba_mode_supported( 276 | const struct bmic_identify_controller *controller_id) 277 | { 278 | uint32_t f = le32toh(controller_id->yet_more_controller_flags); 279 | return (f & YET_MORE_CTLR_FLAG_HBA_MODE_SUPP) ? 1 : 0; 280 | } 281 | 282 | static void sense_controller_parameters(const char *path, int fd, 283 | struct bmic_controller_parameters *controller_params) 284 | { 285 | exec_cmd(path, fd, BMIC_SENSE_CONTROLLER_PARAMETERS, controller_params, 286 | sizeof(*controller_params)); 287 | } 288 | 289 | static void set_controller_parameters(const char *path, int fd, 290 | struct bmic_controller_parameters *controller_params) 291 | { 292 | exec_cmd(path, fd, BMIC_SET_CONTROLLER_PARAMETERS, controller_params, 293 | sizeof(*controller_params)); 294 | } 295 | 296 | static int is_hba_mode_enabled( 297 | const struct bmic_controller_parameters *controller_params) 298 | { 299 | uint8_t f = controller_params->nvram_flags; 300 | return (f & NVRAM_FLAG_HBA_MODE_ENABLED) ? 1 : 0; 301 | } 302 | 303 | static void fill_hba_mode( 304 | struct bmic_controller_parameters *controller_params, int enabled) 305 | { 306 | if (enabled) 307 | controller_params->nvram_flags |= NVRAM_FLAG_HBA_MODE_ENABLED; 308 | else 309 | controller_params->nvram_flags &= ~NVRAM_FLAG_HBA_MODE_ENABLED; 310 | } 311 | 312 | static const char *trim(char *str) 313 | { 314 | /* Remove leading spaces. */ 315 | while (isspace(*str)) 316 | str++; 317 | 318 | /* Remove trailing spaces. */ 319 | for (size_t i = strlen(str); i && isspace(str[i - 1]); i--) 320 | str[i - 1] = '\0'; 321 | 322 | return str; 323 | } 324 | 325 | static void print_info_str_buf(const char *var_name, const char *str_buf, 326 | size_t max_str_len) 327 | { 328 | /* Ensure that string is null-terminated. */ 329 | char str[MAX_STR_BUF_LEN + 1] = {0}; 330 | strncpy(str, str_buf, max_str_len); 331 | printf("%s='%s'\n", var_name, trim(str)); 332 | } 333 | 334 | static void print_info_fw_rev(const char *var_name, const char *rev_buf) 335 | { 336 | print_info_str_buf(var_name, rev_buf, FIRMWARE_REV_LEN); 337 | } 338 | 339 | static void print_info(const char *path, int fd) 340 | { 341 | struct bmic_identify_controller controller_id = {0}; 342 | struct bmic_controller_parameters controller_params = {0}; 343 | int hba_mode_supported; 344 | int hba_mode_enabled = 0; 345 | 346 | identify_controller(path, fd, &controller_id); 347 | sense_controller_parameters(path, fd, &controller_params); 348 | 349 | print_info_str_buf("VENDOR_ID", 350 | controller_id.vendor_id, VENDOR_ID_LEN); 351 | print_info_str_buf("PRODUCT_ID", 352 | controller_id.product_id, PRODUCT_ID_LEN); 353 | printf("BOARD_ID='0x%08x'\n", 354 | le32toh(controller_id.board_id)); 355 | print_info_str_buf("SOFTWARE_NAME", 356 | controller_params.software_name, SOFTWARE_NAME_LEN); 357 | print_info_str_buf("HARDWARE_NAME", 358 | controller_params.hardware_name, HARDWARE_NAME_LEN); 359 | print_info_fw_rev("RUNNING_FIRM_REV", 360 | controller_id.running_firm_rev); 361 | print_info_fw_rev("ROM_FIRM_REV", 362 | controller_id.rom_firm_rev); 363 | print_info_fw_rev("REC_ROM_INACTIVE_REV", 364 | controller_id.rec_rom_inactive_rev); 365 | printf("YET_MORE_CONTROLLER_FLAGS='0x%08x'\n", 366 | le32toh(controller_id.yet_more_controller_flags)); 367 | printf("NVRAM_FLAGS='0x%02x'\n", 368 | controller_params.nvram_flags); 369 | 370 | hba_mode_supported = is_hba_mode_supported(&controller_id); 371 | if (hba_mode_supported) 372 | hba_mode_enabled = is_hba_mode_enabled(&controller_params); 373 | printf("HBA_MODE_SUPPORTED=%d\n", 374 | hba_mode_supported); 375 | printf("HBA_MODE_ENABLED=%d\n", 376 | hba_mode_enabled); 377 | } 378 | 379 | static void verify_hba_mode(const char *path, int fd, int should_be_enabled) 380 | { 381 | struct bmic_controller_parameters controller_params = {0}; 382 | 383 | sense_controller_parameters(path, fd, &controller_params); 384 | if (should_be_enabled) { 385 | if (!is_hba_mode_enabled(&controller_params)) 386 | die_dev(path, 387 | "HBA mode enable failed, " 388 | "nvram_flags == 0x%02x", 389 | controller_params.nvram_flags); 390 | } else { 391 | if (is_hba_mode_enabled(&controller_params)) 392 | die_dev(path, 393 | "HBA mode disable failed, " 394 | "nvram_flags == 0x%02x", 395 | controller_params.nvram_flags); 396 | } 397 | } 398 | 399 | static void rescan_scsi(const char *path, int fd) 400 | { 401 | int rc = ioctl(fd, CCISS_REGNEWD); 402 | if (rc) 403 | die_dev_errno(path, 404 | "ioctl(CCISS_REGNEWD) failed, rc == %d", rc); 405 | } 406 | 407 | static void change_hba_mode(const char *path, int fd, int enabled) 408 | { 409 | struct bmic_identify_controller controller_id = {0}; 410 | struct bmic_controller_parameters controller_params = {0}; 411 | 412 | ask_user_confirmation(); 413 | 414 | identify_controller(path, fd, &controller_id); 415 | sense_controller_parameters(path, fd, &controller_params); 416 | 417 | if (!is_hba_mode_supported(&controller_id)) 418 | die_dev(path, "HBA mode is not supported on this controller"); 419 | 420 | fill_hba_mode(&controller_params, enabled); 421 | set_controller_parameters(path, fd, &controller_params); 422 | 423 | verify_hba_mode(path, fd, enabled); 424 | 425 | rescan_scsi(path, fd); 426 | } 427 | 428 | enum cli_action { 429 | ACTION_HELP, 430 | ACTION_VERSION, 431 | ACTION_INFO, 432 | ACTION_ENABLE, 433 | ACTION_DISABLE, 434 | 435 | ACTION_UNKNOWN, 436 | }; 437 | 438 | static void set_action(enum cli_action *cur_action, enum cli_action new_action) 439 | { 440 | if (*cur_action != ACTION_UNKNOWN) 441 | die("More than one option selected, try running with -h"); 442 | *cur_action = new_action; 443 | } 444 | 445 | int main(int argc, char *argv[]) 446 | { 447 | int opt = 0; 448 | enum cli_action action = ACTION_UNKNOWN; 449 | const char *path = NULL; 450 | int fd = -1; 451 | 452 | opterr = 0; 453 | while (opt != -1) { 454 | opt = getopt(argc, argv, ":hvi:E:d:"); 455 | 456 | switch (opt) { 457 | case -1: 458 | /* No more options. */ 459 | break; 460 | case 'h': 461 | set_action(&action, ACTION_HELP); 462 | break; 463 | case 'v': 464 | set_action(&action, ACTION_VERSION); 465 | break; 466 | case 'i': 467 | set_action(&action, ACTION_INFO); 468 | path = optarg; 469 | break; 470 | case 'E': 471 | set_action(&action, ACTION_ENABLE); 472 | path = optarg; 473 | break; 474 | case 'd': 475 | set_action(&action, ACTION_DISABLE); 476 | path = optarg; 477 | break; 478 | case '?': 479 | die("Unknown command line option: '%c', try running " 480 | "with -h", 481 | optopt); 482 | case ':': 483 | die("Missing argument for option '%c', try running " 484 | "with -h", 485 | optopt); 486 | default: 487 | die("getopt() returned unexpected value: %d", opt); 488 | } 489 | } 490 | 491 | if (argc > optind) 492 | die("Invalid argument in command line, try running with -h"); 493 | 494 | if (path != NULL) 495 | fd = open_dev(path); 496 | 497 | switch (action) { 498 | case ACTION_HELP: 499 | print_help(argv[0]); 500 | break; 501 | case ACTION_VERSION: 502 | print_version(); 503 | break; 504 | case ACTION_INFO: 505 | print_info(path, fd); 506 | break; 507 | case ACTION_ENABLE: 508 | change_hba_mode(path, fd, 1); 509 | break; 510 | case ACTION_DISABLE: 511 | change_hba_mode(path, fd, 0); 512 | break; 513 | default: 514 | die("No option selected, try running with -h"); 515 | } 516 | 517 | if (fd != -1) 518 | close_dev(path, fd); 519 | 520 | return 0; 521 | } 522 | --------------------------------------------------------------------------------