Pull SCSI updates from James Bottomley: "This update includes the usual round of major driver updates (hpsa, be2iscsi, hisi_sas, zfcp, cxlflash). There's a new incarnation of hpsa called smartpqi for which a driver is added, there's some cleanup work of the ibm vscsi target and updates to libfc, plus a whole host of minor fixes and updates and finally the removal of several ISA drivers which seem not to have been used for years" * tag 'scsi-misc' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi: (173 commits) scsi: mvsas: Mark symbols static where possible scsi: pm8001: Mark symbols static where possible scsi: arcmsr: Simplify user_len checking scsi: fcoe: fix off by one in eth2fc_speed() scsi: dtc: remove from tree scsi: t128: remove from tree scsi: pas16: remove from tree scsi: u14-34f: remove from tree scsi: ultrastor: remove from tree scsi: in2000: remove from tree scsi: wd7000: remove from tree scsi: scsi_dh_alua: Fix memory leak in alua_rtpg() scsi: lpfc: Mark symbols static where possible scsi: hpsa: correct call to hpsa_do_reset scsi: ufs: Get a TM service response from the correct offset scsi: ibmvfc: Fix I/O hang when port is not mapped scsi: megaraid_sas: clean function declarations in megaraid_sas_base.c up scsi: ipr: Remove redundant messages at adapter init time scsi: ipr: Don't log unnecessary 9084 error details scsi: smartpqi: raid bypass lba calculation fix ...
Unified · Split
| @@ -121,7 +121,7 @@ Block library API · 120 unmodified lines | |||
| 121 | below. | 121 | below. |
| 122 | 122 | ||
| 123 | The block library can be found on GitHub: | 123 | The block library can be found on GitHub: |
| 124 | http://www.github.com/mikehollinger/ibmcapikv | 124 | http://github.com/open-power/capiflash |
| 125 | 125 | ||
| 126 | 126 | ||
| 127 | CXL Flash Driver IOCTLs | 127 | CXL Flash Driver IOCTLs |
| @@ -171,11 +171,30 @@ DK_CXLFLASH_ATTACH · 43 unmodified lines | |||
| 171 | destroyed, the tokens are to be considered stale and subsequent | 171 | destroyed, the tokens are to be considered stale and subsequent |
| 172 | usage will result in errors. | 172 | usage will result in errors. |
| 173 | 173 | ||
| 174 | - A valid adapter file descriptor (fd2 >= 0) is only returned on | ||
| 175 | the initial attach for a context. Subsequent attaches to an | ||
| 176 | existing context (DK_CXLFLASH_ATTACH_REUSE_CONTEXT flag present) | ||
| 177 | do not provide the adapter file descriptor as it was previously | ||
| 178 | made known to the application. | ||
| 179 | |||
| 174 | - When a context is no longer needed, the user shall detach from | 180 | - When a context is no longer needed, the user shall detach from |
| 175 | the context via the DK_CXLFLASH_DETACH ioctl. | 181 | the context via the DK_CXLFLASH_DETACH ioctl. When this ioctl |
| 182 | returns with a valid adapter file descriptor and the return flag | ||
| 183 | DK_CXLFLASH_APP_CLOSE_ADAP_FD is present, the application _must_ | ||
| 184 | close the adapter file descriptor following a successful detach. | ||
| 185 | |||
| 186 | - When this ioctl returns with a valid fd2 and the return flag | ||
| 187 | DK_CXLFLASH_APP_CLOSE_ADAP_FD is present, the application _must_ | ||
| 188 | close fd2 in the following circumstances: | ||
| 189 | |||
| 190 | + Following a successful detach of the last user of the context | ||
| 191 | + Following a successful recovery on the context's original fd2 | ||
| 192 | + In the child process of a fork(), following a clone ioctl, | ||
| 193 | on the fd2 associated with the source context | ||
| 176 | 194 | ||
| 177 | - A close on fd2 will invalidate the tokens. This operation is not | 195 | - At any time, a close on fd2 will invalidate the tokens. Applications |
| 178 | required by the user. | 196 | should exercise caution to only close fd2 when appropriate (outlined |
| 197 | in the previous bullet) to avoid premature loss of I/O. | ||
| 179 | 198 | ||
| 180 | DK_CXLFLASH_USER_DIRECT | 199 | DK_CXLFLASH_USER_DIRECT |
| 181 | ----------------------- | 200 | ----------------------- |
| @@ -254,6 +273,10 @@ DK_CXLFLASH_DETACH · 72 unmodified lines | |||
| 254 | success, all "tokens" which had been provided to the user from the | 273 | success, all "tokens" which had been provided to the user from the |
| 255 | DK_CXLFLASH_ATTACH onward are no longer valid. | 274 | DK_CXLFLASH_ATTACH onward are no longer valid. |
| 256 | 275 | ||
| 276 | When the DK_CXLFLASH_APP_CLOSE_ADAP_FD flag was returned on a successful | ||
| 277 | attach, the application _must_ close the fd2 associated with the context | ||
| 278 | following the detach of the final user of the context. | ||
| 279 | |||
| 257 | DK_CXLFLASH_VLUN_CLONE | 280 | DK_CXLFLASH_VLUN_CLONE |
| 258 | ---------------------- | 281 | ---------------------- |
| 259 | This ioctl is responsible for cloning a previously created | 282 | This ioctl is responsible for cloning a previously created |
| @@ -261,7 +284,7 @@ DK_CXLFLASH_VLUN_CLONE · 1 unmodified line | |||
| 261 | support maintaining user space access to storage after a process | 284 | support maintaining user space access to storage after a process |
| 262 | forks. Upon success, the child process (which invoked the ioctl) | 285 | forks. Upon success, the child process (which invoked the ioctl) |
| 263 | will have access to the same LUNs via the same resource handle(s) | 286 | will have access to the same LUNs via the same resource handle(s) |
| 264 | and fd2 as the parent, but under a different context. | 287 | as the parent, but under a different context. |
| 265 | 288 | ||
| 266 | Context sharing across processes is not supported with CXL and | 289 | Context sharing across processes is not supported with CXL and |
| 267 | therefore each fork must be met with establishing a new context | 290 | therefore each fork must be met with establishing a new context |
| @@ -275,6 +298,12 @@ DK_CXLFLASH_VLUN_CLONE · 7 unmodified lines | |||
| 275 | translation tables are copied from the parent context to the child's | 298 | translation tables are copied from the parent context to the child's |
| 276 | and then synced with the AFU. | 299 | and then synced with the AFU. |
| 277 | 300 | ||
| 301 | When the DK_CXLFLASH_APP_CLOSE_ADAP_FD flag was returned on a successful | ||
| 302 | attach, the application _must_ close the fd2 associated with the source | ||
| 303 | context (still resident/accessible in the parent process) following the | ||
| 304 | clone. This is to avoid a stale entry in the file descriptor table of the | ||
| 305 | child process. | ||
| 306 | |||
| 278 | DK_CXLFLASH_VERIFY | 307 | DK_CXLFLASH_VERIFY |
| 279 | ------------------ | 308 | ------------------ |
| 280 | This ioctl is used to detect various changes such as the capacity of | 309 | This ioctl is used to detect various changes such as the capacity of |
| @@ -309,6 +338,11 @@ DK_CXLFLASH_RECOVER_AFU · 28 unmodified lines | |||
| 309 | at which time the context/resources they held will be freed as part of | 338 | at which time the context/resources they held will be freed as part of |
| 310 | the release fop. | 339 | the release fop. |
| 311 | 340 | ||
| 341 | When the DK_CXLFLASH_APP_CLOSE_ADAP_FD flag was returned on a successful | ||
| 342 | attach, the application _must_ unmap and close the fd2 associated with the | ||
| 343 | original context following this ioctl returning success and indicating that | ||
| 344 | the context was recovered (DK_CXLFLASH_RECOVER_AFU_CONTEXT_RESET). | ||
| 345 | |||
| 312 | DK_CXLFLASH_MANAGE_LUN | 346 | DK_CXLFLASH_MANAGE_LUN |
| 313 | ---------------------- | 347 | ---------------------- |
| 314 | This ioctl is used to switch a LUN from a mode where it is available | 348 | This ioctl is used to switch a LUN from a mode where it is available |
| @@ -64,8 +64,6 @@ hpsa.txt · 63 unmodified lines | |||
| 64 | - HP Smart Array Controller SCSI driver. | 64 | - HP Smart Array Controller SCSI driver. |
| 65 | hptiop.txt | 65 | hptiop.txt |
| 66 | - HIGHPOINT ROCKETRAID 3xxx RAID DRIVER | 66 | - HIGHPOINT ROCKETRAID 3xxx RAID DRIVER |
| 67 | in2000.txt | ||
| 68 | - info on in2000 driver | ||
| 69 | libsas.txt | 67 | libsas.txt |
| 70 | - Serial Attached SCSI management layer. | 68 | - Serial Attached SCSI management layer. |
| 71 | link_power_management_policy.txt | 69 | link_power_management_policy.txt |
| @@ -1,43 +0,0 @@ | |||
| 1 | README file for the Linux DTC3180/3280 scsi driver. | ||
| 2 | by Ray Van Tassle (rayvt@comm.mot.com) March 1996 | ||
| 3 | Based on the generic & core NCR5380 code by Drew Eckhard | ||
| 4 | |||
| 5 | SCSI device driver for the DTC 3180/3280. | ||
| 6 | Data Technology Corp---a division of Qume. | ||
| 7 | |||
| 8 | The 3280 has a standard floppy interface. | ||
| 9 | |||
| 10 | The 3180 does not. Otherwise, they are identical. | ||
| 11 | |||
| 12 | The DTC3x80 does not support DMA but it does have Pseudo-DMA which is | ||
| 13 | supported by the driver. | ||
| 14 | |||
| 15 | Its DTC406 scsi chip is supposedly compatible with the NCR 53C400. | ||
| 16 | It is memory mapped, uses an IRQ, but no dma or io-port. There is | ||
| 17 | internal DMA, between SCSI bus and an on-chip 128-byte buffer. Double | ||
| 18 | buffering is done automagically by the chip. Data is transferred | ||
| 19 | between the on-chip buffer and CPU/RAM via memory moves. | ||
| 20 | |||
| 21 | The driver detects the possible memory addresses (jumper selectable): | ||
| 22 | CC00, DC00, C800, and D800 | ||
| 23 | The possible IRQ's (jumper selectable) are: | ||
| 24 | IRQ 10, 11, 12, 15 | ||
| 25 | Parity is supported by the chip, but not by this driver. | ||
| 26 | Information can be obtained from /proc/scsi/dtc3c80/N. | ||
| 27 | |||
| 28 | Note on interrupts: | ||
| 29 | |||
| 30 | The documentation says that it can be set to interrupt whenever the | ||
| 31 | on-chip buffer needs CPU attention. I couldn't get this to work. So | ||
| 32 | the driver polls for data-ready in the pseudo-DMA transfer routine. | ||
| 33 | The interrupt support routines in the NCR3280.c core modules handle | ||
| 34 | scsi disconnect/reconnect, and this (mostly) works. However..... I | ||
| 35 | have tested it with 4 totally different hard drives (both SCSI-1 and | ||
| 36 | SCSI-2), and one CDROM drive. Interrupts works great for all but one | ||
| 37 | specific hard drive. For this one, the driver will eventually hang in | ||
| 38 | the transfer state. I have tested with: "dd bs=4k count=2k | ||
| 39 | of=/dev/null if=/dev/sdb". It reads ok for a while, then hangs. | ||
| 40 | After beating my head against this for a couple of weeks, getting | ||
| 41 | nowhere, I give up. So.....This driver does NOT use interrupts, even | ||
| 42 | if you have the card jumpered to an IRQ. Probably nobody will ever | ||
| 43 | care. | ||
| @@ -1,202 +0,0 @@ | |||
| 1 | |||
| 2 | UPDATE NEWS: version 1.33 - 26 Aug 98 | ||
| 3 | |||
| 4 | Interrupt management in this driver has become, over | ||
| 5 | time, increasingly odd and difficult to explain - this | ||
| 6 | has been mostly due to my own mental inadequacies. In | ||
| 7 | recent kernels, it has failed to function at all when | ||
| 8 | compiled for SMP. I've fixed that problem, and after | ||
| 9 | taking a fresh look at interrupts in general, greatly | ||
| 10 | reduced the number of places where they're fiddled | ||
| 11 | with. Done some heavy testing and it looks very good. | ||
| 12 | The driver now makes use of the __initfunc() and | ||
| 13 | __initdata macros to save about 4k of kernel memory. | ||
| 14 | Once again, the same code works for both 2.0.xx and | ||
| 15 | 2.1.xx kernels. | ||
| 16 | |||
| 17 | UPDATE NEWS: version 1.32 - 28 Mar 98 | ||
| 18 | |||
| 19 | Removed the check for legal IN2000 hardware versions: | ||
| 20 | It appears that the driver works fine with serial | ||
| 21 | EPROMs (the 8-pin chip that defines hardware rev) as | ||
| 22 | old as 2.1, so we'll assume that all cards are OK. | ||
| 23 | |||
| 24 | UPDATE NEWS: version 1.31 - 6 Jul 97 | ||
| 25 | |||
| 26 | Fixed a bug that caused incorrect SCSI status bytes to be | ||
| 27 | returned from commands sent to LUNs greater than 0. This | ||
| 28 | means that CDROM changers work now! Fixed a bug in the | ||
| 29 | handling of command-line arguments when loaded as a module. | ||
| 30 | Also put all the header data in in2000.h where it belongs. | ||
| 31 | There are no longer any differences between this driver in | ||
| 32 | the 2.1.xx source tree and the 2.0.xx tree, as of 2.0.31 | ||
| 33 | and 2.1.45 (or is it .46?) - this makes things much easier | ||
| 34 | for me... | ||
| 35 | |||
| 36 | UPDATE NEWS: version 1.30 - 14 Oct 96 | ||
| 37 | |||
| 38 | Fixed a bug in the code that sets the transfer direction | ||
| 39 | bit (DESTID_DPD in the WD_DESTINATION_ID register). There | ||
| 40 | are quite a few SCSI commands that do a write-to-device; | ||
| 41 | now we deal with all of them correctly. Thanks to Joerg | ||
| 42 | Dorchain for catching this one. | ||
| 43 | |||
| 44 | UPDATE NEWS: version 1.29 - 24 Sep 96 | ||
| 45 | |||
| 46 | The memory-mapped hardware on the card is now accessed via | ||
| 47 | the 'readb()' and 'readl()' macros - required by the new | ||
| 48 | memory management scheme in the 2.1.x kernel series. | ||
| 49 | As suggested by Andries Brouwer, 'bios_param()' no longer | ||
| 50 | forces an artificial 1023 track limit on drives. Also | ||
| 51 | removed some kludge-code left over from struggles with | ||
| 52 | older (buggy) compilers. | ||
| 53 | |||
| 54 | UPDATE NEWS: version 1.28 - 07 May 96 | ||
| 55 | |||
| 56 | Tightened up the "interrupts enabled/disabled" discipline | ||
| 57 | in 'in2000_queuecommand()' and maybe 1 or 2 other places. | ||
| 58 | I _think_ it may have been a little too lax, causing an | ||
| 59 | occasional crash during full moon. A fully functional | ||
| 60 | /proc interface is now in place - if you want to play | ||
| 61 | with it, start by doing 'cat /proc/scsi/in2000/0'. You | ||
| 62 | can also use it to change a few run-time parameters on | ||
| 63 | the fly, but it's mostly for debugging. The curious | ||
| 64 | should take a good look at 'in2000_proc_info()' in the | ||
| 65 | in2000.c file to get an understanding of what it's all | ||
| 66 | about; I figure that people who are really into it will | ||
| 67 | want to add features suited to their own needs... | ||
| 68 | Also, sync is now DISABLED by default. | ||
| 69 | |||
| 70 | UPDATE NEWS: version 1.27 - 10 Apr 96 | ||
| 71 | |||
| 72 | Fixed a well-hidden bug in the adaptive-disconnect code | ||
| 73 | that would show up every now and then during extreme | ||
| 74 | heavy loads involving 2 or more simultaneously active | ||
| 75 | devices. Thanks to Joe Mack for keeping my nose to the | ||
| 76 | grindstone on this one. | ||
| 77 | |||
| 78 | UPDATE NEWS: version 1.26 - 07 Mar 96 | ||
| 79 | |||
| 80 | 1.25 had a nasty bug that bit people with swap partitions | ||
| 81 | and tape drives. Also, in my attempt to guess my way | ||
| 82 | through Intel assembly language, I made an error in the | ||
| 83 | inline code for IO writes. Made a few other changes and | ||
| 84 | repairs - this version (fingers crossed) should work well. | ||
| 85 | |||
| 86 | UPDATE NEWS: version 1.25 - 05 Mar 96 | ||
| 87 | |||
| 88 | Kernel 1.3.70 interrupt mods added; old kernels still OK. | ||
| 89 | Big help from Bill Earnest and David Willmore on speed | ||
| 90 | testing and optimizing: I think there's a real improvement | ||
| 91 | in this area. | ||
| 92 | New! User-friendly command-line interface for LILO and | ||
| 93 | module loading - the old method is gone, so you'll need | ||
| 94 | to read the comments for 'setup_strings' near the top | ||
| 95 | of in2000.c. For people with CDROM's or other devices | ||
| 96 | that have a tough time with sync negotiation, you can | ||
| 97 | now selectively disable sync on individual devices - | ||
| 98 | search for the 'nosync' keyword in the command-line | ||
| 99 | comments. Some of you disable the BIOS on the card, which | ||
| 100 | caused the auto-detect function to fail; there is now a | ||
| 101 | command-line option to force detection of a ROM-less card. | ||
| 102 | |||
| 103 | UPDATE NEWS: version 1.24a - 24 Feb 96 | ||
| 104 | |||
| 105 | There was a bug in the synchronous transfer code. Only | ||
| 106 | a few people downloaded before I caught it - could have | ||
| 107 | been worse. | ||
| 108 | |||
| 109 | UPDATE NEWS: version 1.24 - 23 Feb 96 | ||
| 110 | |||
| 111 | Lots of good changes. Advice from Bill Earnest resulted | ||
| 112 | in much better detection of cards, more efficient usage | ||
| 113 | of the fifo, and (hopefully) faster data transfers. The | ||
| 114 | jury is still out on speed - I hope it's improved some. | ||
| 115 | One nifty new feature is a cool way of doing disconnect/ | ||
| 116 | reselect. The driver defaults to what I'm calling | ||
| 117 | 'adaptive disconnect' - meaning that each command is | ||
| 118 | evaluated individually as to whether or not it should be | ||
| 119 | run with the option to disconnect/reselect (if the device | ||
| 120 | chooses), or as a "SCSI-bus-hog". When several devices | ||
| 121 | are operating simultaneously, disconnects are usually an | ||
| 122 | advantage. In a single device system, or if only 1 device | ||
| 123 | is being accessed, transfers usually go faster if disconnects | ||
| 124 | are not allowed. | ||
| 125 | |||
| 126 | |||
| 127 | |||
| 128 | The default arguments (you get these when you don't give an 'in2000' | ||
| 129 | command-line argument, or you give a blank argument) will cause | ||
| 130 | the driver to do adaptive disconnect, synchronous transfers, and a | ||
| 131 | minimum of debug messages. If you want to fool with the options, | ||
| 132 | search for 'setup_strings' near the top of the in2000.c file and | ||
| 133 | check the 'hostdata->args' section in in2000.h - but be warned! Not | ||
| 134 | everything is working yet (some things will never work, probably). | ||
| 135 | I believe that disabling disconnects (DIS_NEVER) will allow you | ||
| 136 | to choose a LEVEL2 value higher than 'L2_BASIC', but I haven't | ||
| 137 | spent a lot of time testing this. You might try 'ENABLE_CLUSTERING' | ||
| 138 | to see what happens: my tests showed little difference either way. | ||
| 139 | There's also a define called 'DEFAULT_SX_PER'; this sets the data | ||
| 140 | transfer speed for the asynchronous mode. I've put it at 500 ns | ||
| 141 | despite the fact that the card could handle settings of 376 or | ||
| 142 | 252, because higher speeds may be a problem with poor quality | ||
| 143 | cables or improper termination; 500 ns is a compromise. You can | ||
| 144 | choose your own default through the command-line with the | ||
| 145 | 'period' keyword. | ||
| 146 | |||
| 147 | |||
| 148 | ------------------------------------------------ | ||
| 149 | *********** DIP switch settings ************** | ||
| 150 | ------------------------------------------------ | ||
| 151 | |||
| 152 | sw1-1 sw1-2 BIOS address (hex) | ||
| 153 | ----------------------------------------- | ||
| 154 | off off C8000 - CBFF0 | ||
| 155 | on off D8000 - DBFF0 | ||
| 156 | off on D0000 - D3FF0 | ||
| 157 | on on BIOS disabled | ||
| 158 | |||
| 159 | sw1-3 sw1-4 IO port address (hex) | ||
| 160 | ------------------------------------ | ||
| 161 | off off 220 - 22F | ||
| 162 | on off 200 - 20F | ||
| 163 | off on 110 - 11F | ||
| 164 | on on 100 - 10F | ||
| 165 | |||
| 166 | sw1-5 sw1-6 sw1-7 Interrupt | ||
| 167 | ------------------------------ | ||
| 168 | off off off 15 | ||
| 169 | off on off 14 | ||
| 170 | off off on 11 | ||
| 171 | off on on 10 | ||
| 172 | on - - disabled | ||
| 173 | |||
| 174 | sw1-8 function depends on BIOS version. In earlier versions this | ||
| 175 | controlled synchronous data transfer support for MSDOS: | ||
| 176 | off = disabled | ||
| 177 | on = enabled | ||
| 178 | In later ROMs (starting with 01.3 in April 1994) sw1-8 controls | ||
| 179 | the "greater than 2 disk drive" feature that first appeared in | ||
| 180 | MSDOS 5.0 (ignored by Linux): | ||
| 181 | off = 2 drives maximum | ||
| 182 | on = 7 drives maximum | ||
| 183 | |||
| 184 | sw1-9 Floppy controller | ||
| 185 | -------------------------- | ||
| 186 | off disabled | ||
| 187 | on enabled | ||
| 188 | |||
| 189 | ------------------------------------------------ | ||
| 190 | |||
| 191 | I should mention that Drew Eckhardt's 'Generic NCR5380' sources | ||
| 192 | were my main inspiration, with lots of reference to the IN2000 | ||
| 193 | driver currently distributed in the kernel source. I also owe | ||
| 194 | much to a driver written by Hamish Macdonald for Linux-m68k(!). | ||
| 195 | And to Eric Wright for being an ALPHA guinea pig. And to Bill | ||
| 196 | Earnest for 2 tons of great input and information. And to David | ||
| 197 | Willmore for extensive 'bonnie' testing. And to Joe Mack for | ||
| 198 | continual testing and feedback. | ||
| 199 | |||
| 200 | |||
| 201 | John Shifflett jshiffle@netcom.com | ||
| 202 | |||
| @@ -34,9 +34,6 @@ parameters may be changed at runtime by the command · 33 unmodified lines | |||
| 34 | See drivers/scsi/BusLogic.c, comment before function | 34 | See drivers/scsi/BusLogic.c, comment before function |
| 35 | BusLogic_ParseDriverOptions(). | 35 | BusLogic_ParseDriverOptions(). |
| 36 | 36 | ||
| 37 | dtc3181e= [HW,SCSI] | ||
| 38 | See Documentation/scsi/g_NCR5380.txt. | ||
| 39 | |||
| 40 | eata= [HW,SCSI] | 37 | eata= [HW,SCSI] |
| 41 | 38 | ||
| 42 | fdomain= [HW,SCSI] | 39 | fdomain= [HW,SCSI] |
| @@ -47,9 +44,6 @@ parameters may be changed at runtime by the command · 4 unmodified lines | |||
| 47 | 44 | ||
| 48 | gvp11= [HW,SCSI] | 45 | gvp11= [HW,SCSI] |
| 49 | 46 | ||
| 50 | in2000= [HW,SCSI] | ||
| 51 | See header of drivers/scsi/in2000.c. | ||
| 52 | |||
| 53 | ips= [HW,SCSI] Adaptec / IBM ServeRAID controller | 47 | ips= [HW,SCSI] Adaptec / IBM ServeRAID controller |
| 54 | See header of drivers/scsi/ips.c. | 48 | See header of drivers/scsi/ips.c. |
| 55 | 49 | ||
| @@ -83,9 +77,6 @@ parameters may be changed at runtime by the command · 27 unmodified lines | |||
| 83 | Format: <buffer_size>,<write_threshold> | 77 | Format: <buffer_size>,<write_threshold> |
| 84 | See also Documentation/scsi/st.txt. | 78 | See also Documentation/scsi/st.txt. |
| 85 | 79 | ||
| 86 | pas16= [HW,SCSI] | ||
| 87 | See header of drivers/scsi/pas16.c. | ||
| 88 | |||
| 89 | scsi_debug_*= [SCSI] | 80 | scsi_debug_*= [SCSI] |
| 90 | See drivers/scsi/scsi_debug.c. | 81 | See drivers/scsi/scsi_debug.c. |
| 91 | 82 | ||
| @@ -119,18 +110,9 @@ parameters may be changed at runtime by the command · 27 unmodified lines | |||
| 119 | sym53c416= [HW,SCSI] | 110 | sym53c416= [HW,SCSI] |
| 120 | See header of drivers/scsi/sym53c416.c. | 111 | See header of drivers/scsi/sym53c416.c. |
| 121 | 112 | ||
| 122 | t128= [HW,SCSI] | ||
| 123 | See header of drivers/scsi/t128.c. | ||
| 124 | |||
| 125 | tmscsim= [HW,SCSI] | 113 | tmscsim= [HW,SCSI] |
| 126 | See comment before function dc390_setup() in | 114 | See comment before function dc390_setup() in |
| 127 | drivers/scsi/tmscsim.c. | 115 | drivers/scsi/tmscsim.c. |
| 128 | 116 | ||
| 129 | u14-34f= [HW,SCSI] UltraStor 14F/34F SCSI host adapter | ||
| 130 | See header of drivers/scsi/u14-34f.c. | ||
| 131 | |||
| 132 | wd33c93= [HW,SCSI] | 117 | wd33c93= [HW,SCSI] |
| 133 | See header of drivers/scsi/wd33c93.c. | 118 | See header of drivers/scsi/wd33c93.c. |
| 134 | |||
| 135 | wd7000= [HW,SCSI] | ||
| 136 | See header of drivers/scsi/wd7000.c. | ||
| @@ -0,0 +1,80 @@ | |||
| 1 | |||
| 2 | SMARTPQI - Microsemi Smart PQI Driver | ||
| 3 | ----------------------------------------- | ||
| 4 | |||
| 5 | This file describes the smartpqi SCSI driver for Microsemi | ||
| 6 | (http://www.microsemi.com) PQI controllers. The smartpqi driver | ||
| 7 | is the next generation SCSI driver for Microsemi Corp. The smartpqi | ||
| 8 | driver is the first SCSI driver to implement the PQI queuing model. | ||
| 9 | |||
| 10 | The smartpqi driver will replace the aacraid driver for Adaptec Series 9 | ||
| 11 | controllers. Customers running an older kernel (Pre-4.9) using an Adaptec | ||
| 12 | Series 9 controller will have to configure the smartpqi driver or their | ||
| 13 | volumes will not be added to the OS. | ||
| 14 | |||
| 15 | For Microsemi smartpqi controller support, enable the smartpqi driver | ||
| 16 | when configuring the kernel. | ||
| 17 | |||
| 18 | For more information on the PQI Queuing Interface, please see: | ||
| 19 | http://www.t10.org/drafts.htm | ||
| 20 | http://www.t10.org/members/w_pqi2.htm | ||
| 21 | |||
| 22 | Supported devices: | ||
| 23 | ------------------ | ||
| 24 | <Controller names to be added as they become publically available.> | ||
| 25 | |||
| 26 | smartpqi specific entries in /sys | ||
| 27 | ----------------------------- | ||
| 28 | |||
| 29 | smartpqi host attributes: | ||
| 30 | ------------------------- | ||
| 31 | /sys/class/scsi_host/host*/rescan | ||
| 32 | /sys/class/scsi_host/host*/version | ||
| 33 | |||
| 34 | The host rescan attribute is a write only attribute. Writing to this | ||
| 35 | attribute will trigger the driver to scan for new, changed, or removed | ||
| 36 | devices and notify the SCSI mid-layer of any changes detected. | ||
| 37 | |||
| 38 | The version attribute is read-only and will return the driver version | ||
| 39 | and the controller firmware version. | ||
| 40 | For example: | ||
| 41 | driver: 0.9.13-370 | ||
| 42 | firmware: 0.01-522 | ||
| 43 | |||
| 44 | smartpqi sas device attributes | ||
| 45 | ------------------------------ | ||
| 46 | HBA devices are added to the SAS transport layer. These attributes are | ||
| 47 | automatically added by the SAS transport layer. | ||
| 48 | |||
| 49 | /sys/class/sas_device/end_device-X:X/sas_address | ||
| 50 | /sys/class/sas_device/end_device-X:X/enclosure_identifier | ||
| 51 | /sys/class/sas_device/end_device-X:X/scsi_target_id | ||
| 52 | |||
| 53 | smartpqi specific ioctls: | ||
| 54 | ------------------------- | ||
| 55 | |||
| 56 | For compatibility with applications written for the cciss protocol. | ||
| 57 | |||
| 58 | CCISS_DEREGDISK | ||
| 59 | CCISS_REGNEWDISK | ||
| 60 | CCISS_REGNEWD | ||
| 61 | |||
| 62 | The above three ioctls all do exactly the same thing, which is to cause the driver | ||
| 63 | to rescan for new devices. This does exactly the same thing as writing to the | ||
| 64 | smartpqi specific host "rescan" attribute. | ||
| 65 | |||
| 66 | CCISS_GETPCIINFO | ||
| 67 | |||
| 68 | Returns PCI domain, bus, device and function and "board ID" (PCI subsystem ID). | ||
| 69 | |||
| 70 | CCISS_GETDRIVVER | ||
| 71 | |||
| 72 | Returns driver version in three bytes encoded as: | ||
| 73 | (DRIVER_MAJOR << 28) | (DRIVER_MINOR << 24) | (DRIVER_RELEASE << 16) | DRIVER_REVISION; | ||
| 74 | |||
| 75 | CCISS_PASSTHRU | ||
| 76 | |||
| 77 | Allows "BMIC" and "CISS" commands to be passed through to the Smart Storage Array. | ||
| 78 | These are used extensively by the SSA Array Configuration Utility, SNMP storage | ||
| 79 | agents, etc. | ||
| 80 | |||
| @@ -7973,6 +7973,18 @@ W: http://www.melexis.com · 7972 unmodified lines | |||
| 7973 | S: Supported | 7973 | S: Supported |
| 7974 | F: drivers/iio/temperature/mlx90614.c | 7974 | F: drivers/iio/temperature/mlx90614.c |
| 7975 | 7975 | ||
| 7976 | MICROSEMI SMART ARRAY SMARTPQI DRIVER (smartpqi) | ||
| 7977 | M: Don Brace <don.brace@microsemi.com> | ||
| 7978 | L: esc.storagedev@microsemi.com | ||
| 7979 | L: linux-scsi@vger.kernel.org | ||
| 7980 | S: Supported | ||
| 7981 | F: drivers/scsi/smartpqi/smartpqi*.[ch] | ||
| 7982 | F: drivers/scsi/smartpqi/Kconfig | ||
| 7983 | F: drivers/scsi/smartpqi/Makefile | ||
| 7984 | F: include/linux/cciss*.h | ||
| 7985 | F: include/uapi/linux/cciss*.h | ||
| 7986 | F: Documentation/scsi/smartpqi.txt | ||
| 7987 | |||
| 7976 | MN88472 MEDIA DRIVER | 7988 | MN88472 MEDIA DRIVER |
| 7977 | M: Antti Palosaari <crope@iki.fi> | 7989 | M: Antti Palosaari <crope@iki.fi> |
| 7978 | L: linux-media@vger.kernel.org | 7990 | L: linux-media@vger.kernel.org |
| @@ -8185,20 +8197,16 @@ M: Michael Schmitz <schmitzmic@gmail.com> · 206 unmodified lines | |||
| 8185 | L: linux-scsi@vger.kernel.org | 8197 | L: linux-scsi@vger.kernel.org |
| 8186 | S: Maintained | 8198 | S: Maintained |
| 8187 | F: Documentation/scsi/g_NCR5380.txt | 8199 | F: Documentation/scsi/g_NCR5380.txt |
| 8188 | F: Documentation/scsi/dtc3x80.txt | ||
| 8189 | F: drivers/scsi/NCR5380.* | 8200 | F: drivers/scsi/NCR5380.* |
| 8190 | F: drivers/scsi/arm/cumana_1.c | 8201 | F: drivers/scsi/arm/cumana_1.c |
| 8191 | F: drivers/scsi/arm/oak.c | 8202 | F: drivers/scsi/arm/oak.c |
| 8192 | F: drivers/scsi/atari_scsi.* | 8203 | F: drivers/scsi/atari_scsi.* |
| 8193 | F: drivers/scsi/dmx3191d.c | 8204 | F: drivers/scsi/dmx3191d.c |
| 8194 | F: drivers/scsi/dtc.* | ||
| 8195 | F: drivers/scsi/g_NCR5380.* | 8205 | F: drivers/scsi/g_NCR5380.* |
| 8196 | F: drivers/scsi/g_NCR5380_mmio.c | 8206 | F: drivers/scsi/g_NCR5380_mmio.c |
| 8197 | F: drivers/scsi/mac_scsi.* | 8207 | F: drivers/scsi/mac_scsi.* |
| 8198 | F: drivers/scsi/pas16.* | ||
| 8199 | F: drivers/scsi/sun3_scsi.* | 8208 | F: drivers/scsi/sun3_scsi.* |
| 8200 | F: drivers/scsi/sun3_scsi_vme.c | 8209 | F: drivers/scsi/sun3_scsi_vme.c |
| 8201 | F: drivers/scsi/t128.* | ||
| 8202 | 8210 | ||
| 8203 | NCR DUAL 700 SCSI DRIVER (MICROCHANNEL) | 8211 | NCR DUAL 700 SCSI DRIVER (MICROCHANNEL) |
| 8204 | M: "James E.J. Bottomley" <James.Bottomley@HansenPartnership.com> | 8212 | M: "James E.J. Bottomley" <James.Bottomley@HansenPartnership.com> |
| @@ -10740,12 +10748,12 @@ S: Maintained · 2535 unmodified lines | |||
| 10740 | F: drivers/misc/phantom.c | 10748 | F: drivers/misc/phantom.c |
| 10741 | F: include/uapi/linux/phantom.h | 10749 | F: include/uapi/linux/phantom.h |
| 10742 | 10750 | ||
| 10743 | SERVER ENGINES 10Gbps iSCSI - BladeEngine 2 DRIVER | 10751 | Emulex 10Gbps iSCSI - OneConnect DRIVER |
| 10744 | M: Jayamohan Kallickal <jayamohan.kallickal@avagotech.com> | 10752 | M: Subbu Seetharaman <subbu.seetharaman@broadcom.com> |
| 10745 | M: Ketan Mukadam <ketan.mukadam@avagotech.com> | 10753 | M: Ketan Mukadam <ketan.mukadam@broadcom.com> |
| 10746 | M: John Soni Jose <sony.john@avagotech.com> | 10754 | M: Jitendra Bhivare <jitendra.bhivare@broadcom.com> |
| 10747 | L: linux-scsi@vger.kernel.org | 10755 | L: linux-scsi@vger.kernel.org |
| 10748 | W: http://www.avagotech.com | 10756 | W: http://www.broadcom.com |
| 10749 | S: Supported | 10757 | S: Supported |
| 10750 | F: drivers/scsi/be2iscsi/ | 10758 | F: drivers/scsi/be2iscsi/ |
| 10751 | 10759 | ||
| @@ -12143,12 +12151,6 @@ S: Maintained · 1391 unmodified lines | |||
| 12143 | F: drivers/tc/ | 12151 | F: drivers/tc/ |
| 12144 | F: include/linux/tc.h | 12152 | F: include/linux/tc.h |
| 12145 | 12153 | ||
| 12146 | U14-34F SCSI DRIVER | ||
| 12147 | M: Dario Ballabio <ballabio_dario@emc.com> | ||
| 12148 | L: linux-scsi@vger.kernel.org | ||
| 12149 | S: Maintained | ||
| 12150 | F: drivers/scsi/u14-34f.c | ||
| 12151 | |||
| 12152 | UBI FILE SYSTEM (UBIFS) | 12154 | UBI FILE SYSTEM (UBIFS) |
| 12153 | M: Richard Weinberger <richard@nod.at> | 12155 | M: Richard Weinberger <richard@nod.at> |
| 12154 | M: Artem Bityutskiy <dedekind1@gmail.com> | 12156 | M: Artem Bityutskiy <dedekind1@gmail.com> |
| @@ -12876,12 +12878,6 @@ F: drivers/watchdog/ · 721 unmodified lines | |||
| 12876 | F: include/linux/watchdog.h | 12878 | F: include/linux/watchdog.h |
| 12877 | F: include/uapi/linux/watchdog.h | 12879 | F: include/uapi/linux/watchdog.h |
| 12878 | 12880 | ||
| 12879 | WD7000 SCSI DRIVER | ||
| 12880 | M: Miroslav Zagorac <zaga@fly.cc.fer.hr> | ||
| 12881 | L: linux-scsi@vger.kernel.org | ||
| 12882 | S: Maintained | ||
| 12883 | F: drivers/scsi/wd7000.c | ||
| 12884 | |||
| 12885 | WIIMOTE HID DRIVER | 12881 | WIIMOTE HID DRIVER |
| 12886 | M: David Herrmann <dh.herrmann@googlemail.com> | 12882 | M: David Herrmann <dh.herrmann@googlemail.com> |
| 12887 | L: linux-input@vger.kernel.org | 12883 | L: linux-input@vger.kernel.org |
| @@ -1865,8 +1865,8 @@ mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id) · 1864 unmodified lines | |||
| 1865 | 1865 | ||
| 1866 | snprintf(ioc->reset_work_q_name, MPT_KOBJ_NAME_LEN, | 1866 | snprintf(ioc->reset_work_q_name, MPT_KOBJ_NAME_LEN, |
| 1867 | "mpt_poll_%d", ioc->id); | 1867 | "mpt_poll_%d", ioc->id); |
| 1868 | ioc->reset_work_q = | 1868 | ioc->reset_work_q = alloc_workqueue(ioc->reset_work_q_name, |
| 1869 | create_singlethread_workqueue(ioc->reset_work_q_name); | 1869 | WQ_MEM_RECLAIM, 0); |
| 1870 | if (!ioc->reset_work_q) { | 1870 | if (!ioc->reset_work_q) { |
| 1871 | printk(MYIOC_s_ERR_FMT "Insufficient memory to add adapter!\n", | 1871 | printk(MYIOC_s_ERR_FMT "Insufficient memory to add adapter!\n", |
| 1872 | ioc->name); | 1872 | ioc->name); |
| @@ -1992,7 +1992,8 @@ mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id) · 119 unmodified lines | |||
| 1992 | INIT_LIST_HEAD(&ioc->fw_event_list); | 1992 | INIT_LIST_HEAD(&ioc->fw_event_list); |
| 1993 | spin_lock_init(&ioc->fw_event_lock); | 1993 | spin_lock_init(&ioc->fw_event_lock); |
| 1994 | snprintf(ioc->fw_event_q_name, MPT_KOBJ_NAME_LEN, "mpt/%d", ioc->id); | 1994 | snprintf(ioc->fw_event_q_name, MPT_KOBJ_NAME_LEN, "mpt/%d", ioc->id); |
| 1995 | ioc->fw_event_q = create_singlethread_workqueue(ioc->fw_event_q_name); | 1995 | ioc->fw_event_q = alloc_workqueue(ioc->fw_event_q_name, |
| 1996 | WQ_MEM_RECLAIM, 0); | ||
| 1996 | if (!ioc->fw_event_q) { | 1997 | if (!ioc->fw_event_q) { |
| 1997 | printk(MYIOC_s_ERR_FMT "Insufficient memory to add adapter!\n", | 1998 | printk(MYIOC_s_ERR_FMT "Insufficient memory to add adapter!\n", |
| 1998 | ioc->name); | 1999 | ioc->name); |
| @@ -1324,9 +1324,12 @@ mptfc_probe(struct pci_dev *pdev, const struct pci_device_id *id) · 1323 unmodified lines | |||
| 1324 | snprintf(ioc->fc_rescan_work_q_name, sizeof(ioc->fc_rescan_work_q_name), | 1324 | snprintf(ioc->fc_rescan_work_q_name, sizeof(ioc->fc_rescan_work_q_name), |
| 1325 | "mptfc_wq_%d", sh->host_no); | 1325 | "mptfc_wq_%d", sh->host_no); |
| 1326 | ioc->fc_rescan_work_q = | 1326 | ioc->fc_rescan_work_q = |
| 1327 | create_singlethread_workqueue(ioc->fc_rescan_work_q_name); | 1327 | alloc_ordered_workqueue(ioc->fc_rescan_work_q_name, |
| 1328 | if (!ioc->fc_rescan_work_q) | 1328 | WQ_MEM_RECLAIM); |
| 1329 | if (!ioc->fc_rescan_work_q) { | ||
| 1330 | error = -ENOMEM; | ||
| 1329 | goto out_mptfc_probe; | 1331 | goto out_mptfc_probe; |
| 1332 | } | ||
| 1330 | 1333 | ||
| 1331 | /* | 1334 | /* |
| 1332 | * Pre-fetch FC port WWN and stuff... | 1335 | * Pre-fetch FC port WWN and stuff... |
| @@ -3,7 +3,7 @@ · 2 unmodified lines | |||
| 3 | * | 3 | * |
| 4 | * Debug traces for zfcp. | 4 | * Debug traces for zfcp. |
| 5 | * | 5 | * |
| 6 | * Copyright IBM Corp. 2002, 2013 | 6 | * Copyright IBM Corp. 2002, 2016 |
| 7 | */ | 7 | */ |
| 8 | 8 | ||
| 9 | #define KMSG_COMPONENT "zfcp" | 9 | #define KMSG_COMPONENT "zfcp" |
| @@ -65,7 +65,7 @@ void zfcp_dbf_pl_write(struct zfcp_dbf *dbf, void *data, u16 length, char *area, · 55 unmodified lines | |||
| 65 | * @tag: tag indicating which kind of unsolicited status has been received | 65 | * @tag: tag indicating which kind of unsolicited status has been received |
| 66 | * @req: request for which a response was received | 66 | * @req: request for which a response was received |
| 67 | */ | 67 | */ |
| 68 | void zfcp_dbf_hba_fsf_res(char *tag, struct zfcp_fsf_req *req) | 68 | void zfcp_dbf_hba_fsf_res(char *tag, int level, struct zfcp_fsf_req *req) |
| 69 | { | 69 | { |
| 70 | struct zfcp_dbf *dbf = req->adapter->dbf; | 70 | struct zfcp_dbf *dbf = req->adapter->dbf; |
| 71 | struct fsf_qtcb_prefix *q_pref = &req->qtcb->prefix; | 71 | struct fsf_qtcb_prefix *q_pref = &req->qtcb->prefix; |
| @@ -85,6 +85,8 @@ void zfcp_dbf_hba_fsf_res(char *tag, struct zfcp_fsf_req *req) · 13 unmodified lines | |||
| 85 | rec->u.res.req_issued = req->issued; | 85 | rec->u.res.req_issued = req->issued; |
| 86 | rec->u.res.prot_status = q_pref->prot_status; | 86 | rec->u.res.prot_status = q_pref->prot_status; |
| 87 | rec->u.res.fsf_status = q_head->fsf_status; | 87 | rec->u.res.fsf_status = q_head->fsf_status; |
| 88 | rec->u.res.port_handle = q_head->port_handle; | ||
| 89 | rec->u.res.lun_handle = q_head->lun_handle; | ||
| 88 | 90 | ||
| 89 | memcpy(rec->u.res.prot_status_qual, &q_pref->prot_status_qual, | 91 | memcpy(rec->u.res.prot_status_qual, &q_pref->prot_status_qual, |
| 90 | FSF_PROT_STATUS_QUAL_SIZE); | 92 | FSF_PROT_STATUS_QUAL_SIZE); |
| @@ -97,7 +99,7 @@ void zfcp_dbf_hba_fsf_res(char *tag, struct zfcp_fsf_req *req) · 6 unmodified lines | |||
| 97 | rec->pl_len, "fsf_res", req->req_id); | 99 | rec->pl_len, "fsf_res", req->req_id); |
| 98 | } | 100 | } |
| 99 | 101 | ||
| 100 | debug_event(dbf->hba, 1, rec, sizeof(*rec)); | 102 | debug_event(dbf->hba, level, rec, sizeof(*rec)); |
| 101 | spin_unlock_irqrestore(&dbf->hba_lock, flags); | 103 | spin_unlock_irqrestore(&dbf->hba_lock, flags); |
| 102 | } | 104 | } |
| 103 | 105 | ||
| @@ -241,7 +243,8 @@ static void zfcp_dbf_set_common(struct zfcp_dbf_rec *rec, · 137 unmodified lines | |||
| 241 | if (sdev) { | 243 | if (sdev) { |
| 242 | rec->lun_status = atomic_read(&sdev_to_zfcp(sdev)->status); | 244 | rec->lun_status = atomic_read(&sdev_to_zfcp(sdev)->status); |
| 243 | rec->lun = zfcp_scsi_dev_lun(sdev); | 245 | rec->lun = zfcp_scsi_dev_lun(sdev); |
| 244 | } | 246 | } else |
| 247 | rec->lun = ZFCP_DBF_INVALID_LUN; | ||
| 245 | } | 248 | } |
| 246 | 249 | ||
| 247 | /** | 250 | /** |
| @@ -320,13 +323,48 @@ void zfcp_dbf_rec_run(char *tag, struct zfcp_erp_action *erp) · 72 unmodified lines | |||
| 320 | spin_unlock_irqrestore(&dbf->rec_lock, flags); | 323 | spin_unlock_irqrestore(&dbf->rec_lock, flags); |
| 321 | } | 324 | } |
| 322 | 325 | ||
| 326 | /** | ||
| 327 | * zfcp_dbf_rec_run_wka - trace wka port event with info like running recovery | ||
| 328 | * @tag: identifier for event | ||
| 329 | * @wka_port: well known address port | ||
| 330 | * @req_id: request ID to correlate with potential HBA trace record | ||
| 331 | */ | ||
| 332 | void zfcp_dbf_rec_run_wka(char *tag, struct zfcp_fc_wka_port *wka_port, | ||
| 333 | u64 req_id) | ||
| 334 | { | ||
| 335 | struct zfcp_dbf *dbf = wka_port->adapter->dbf; | ||
| 336 | struct zfcp_dbf_rec *rec = &dbf->rec_buf; | ||
| 337 | unsigned long flags; | ||
| 338 | |||
| 339 | spin_lock_irqsave(&dbf->rec_lock, flags); | ||
| 340 | memset(rec, 0, sizeof(*rec)); | ||
| 341 | |||
| 342 | rec->id = ZFCP_DBF_REC_RUN; | ||
| 343 | memcpy(rec->tag, tag, ZFCP_DBF_TAG_LEN); | ||
| 344 | rec->port_status = wka_port->status; | ||
| 345 | rec->d_id = wka_port->d_id; | ||
| 346 | rec->lun = ZFCP_DBF_INVALID_LUN; | ||
| 347 | |||
| 348 | rec->u.run.fsf_req_id = req_id; | ||
| 349 | rec->u.run.rec_status = ~0; | ||
| 350 | rec->u.run.rec_step = ~0; | ||
| 351 | rec->u.run.rec_action = ~0; | ||
| 352 | rec->u.run.rec_count = ~0; | ||
| 353 | |||
| 354 | debug_event(dbf->rec, 1, rec, sizeof(*rec)); | ||
| 355 | spin_unlock_irqrestore(&dbf->rec_lock, flags); | ||
| 356 | } | ||
| 357 | |||
| 323 | static inline | 358 | static inline |
| 324 | void zfcp_dbf_san(char *tag, struct zfcp_dbf *dbf, void *data, u8 id, u16 len, | 359 | void zfcp_dbf_san(char *tag, struct zfcp_dbf *dbf, |
| 325 | u64 req_id, u32 d_id) | 360 | char *paytag, struct scatterlist *sg, u8 id, u16 len, |
| 361 | u64 req_id, u32 d_id, u16 cap_len) | ||
| 326 | { | 362 | { |
| 327 | struct zfcp_dbf_san *rec = &dbf->san_buf; | 363 | struct zfcp_dbf_san *rec = &dbf->san_buf; |
| 328 | u16 rec_len; | 364 | u16 rec_len; |
| 329 | unsigned long flags; | 365 | unsigned long flags; |
| 366 | struct zfcp_dbf_pay *payload = &dbf->pay_buf; | ||
| 367 | u16 pay_sum = 0; | ||
| 330 | 368 | ||
| 331 | spin_lock_irqsave(&dbf->san_lock, flags); | 369 | spin_lock_irqsave(&dbf->san_lock, flags); |
| 332 | memset(rec, 0, sizeof(*rec)); | 370 | memset(rec, 0, sizeof(*rec)); |
| @@ -334,10 +372,41 @@ void zfcp_dbf_san(char *tag, struct zfcp_dbf *dbf, void *data, u8 id, u16 len, · 1 unmodified line | |||
| 334 | rec->id = id; | 372 | rec->id = id; |
| 335 | rec->fsf_req_id = req_id; | 373 | rec->fsf_req_id = req_id; |
| 336 | rec->d_id = d_id; | 374 | rec->d_id = d_id; |
| 337 | rec_len = min(len, (u16)ZFCP_DBF_SAN_MAX_PAYLOAD); | ||
| 338 | memcpy(rec->payload, data, rec_len); | ||
| 339 | memcpy(rec->tag, tag, ZFCP_DBF_TAG_LEN); | 375 | memcpy(rec->tag, tag, ZFCP_DBF_TAG_LEN); |
| 376 | rec->pl_len = len; /* full length even if we cap pay below */ | ||
| 377 | if (!sg) | ||
| 378 | goto out; | ||
| 379 | rec_len = min_t(unsigned int, sg->length, ZFCP_DBF_SAN_MAX_PAYLOAD); | ||
| 380 | memcpy(rec->payload, sg_virt(sg), rec_len); /* part of 1st sg entry */ | ||
| 381 | if (len <= rec_len) | ||
| 382 | goto out; /* skip pay record if full content in rec->payload */ | ||
| 383 | |||
| 384 | /* if (len > rec_len): | ||
| 385 | * dump data up to cap_len ignoring small duplicate in rec->payload | ||
| 386 | */ | ||
| 387 | spin_lock_irqsave(&dbf->pay_lock, flags); | ||
| 388 | memset(payload, 0, sizeof(*payload)); | ||
| 389 | memcpy(payload->area, paytag, ZFCP_DBF_TAG_LEN); | ||
| 390 | payload->fsf_req_id = req_id; | ||
| 391 | payload->counter = 0; | ||
| 392 | for (; sg && pay_sum < cap_len; sg = sg_next(sg)) { | ||
| 393 | u16 pay_len, offset = 0; | ||
| 394 | |||
| 395 | while (offset < sg->length && pay_sum < cap_len) { | ||
| 396 | pay_len = min((u16)ZFCP_DBF_PAY_MAX_REC, | ||
| 397 | (u16)(sg->length - offset)); | ||
| 398 | /* cap_len <= pay_sum < cap_len+ZFCP_DBF_PAY_MAX_REC */ | ||
| 399 | memcpy(payload->data, sg_virt(sg) + offset, pay_len); | ||
| 400 | debug_event(dbf->pay, 1, payload, | ||
| 401 | zfcp_dbf_plen(pay_len)); | ||
| 402 | payload->counter++; | ||
| 403 | offset += pay_len; | ||
| 404 | pay_sum += pay_len; | ||
| 405 | } | ||
| 406 | } | ||
| 407 | spin_unlock(&dbf->pay_lock); | ||
| 340 | 408 | ||
| 409 | out: | ||
| 341 | debug_event(dbf->san, 1, rec, sizeof(*rec)); | 410 | debug_event(dbf->san, 1, rec, sizeof(*rec)); |
| 342 | spin_unlock_irqrestore(&dbf->san_lock, flags); | 411 | spin_unlock_irqrestore(&dbf->san_lock, flags); |
| 343 | } | 412 | } |
| @@ -354,9 +423,62 @@ void zfcp_dbf_san_req(char *tag, struct zfcp_fsf_req *fsf, u32 d_id) · 10 unmodified lines | |||
| 354 | struct zfcp_fsf_ct_els *ct_els = fsf->data; | 423 | struct zfcp_fsf_ct_els *ct_els = fsf->data; |
| 355 | u16 length; | 424 | u16 length; |
| 356 | 425 | ||
| 357 | length = (u16)(ct_els->req->length + FC_CT_HDR_LEN); | 426 | length = (u16)zfcp_qdio_real_bytes(ct_els->req); |
| 358 | zfcp_dbf_san(tag, dbf, sg_virt(ct_els->req), ZFCP_DBF_SAN_REQ, length, | 427 | zfcp_dbf_san(tag, dbf, "san_req", ct_els->req, ZFCP_DBF_SAN_REQ, |
| 359 | fsf->req_id, d_id); | 428 | length, fsf->req_id, d_id, length); |
| 429 | } | ||
| 430 | |||
| 431 | static u16 zfcp_dbf_san_res_cap_len_if_gpn_ft(char *tag, | ||
| 432 | struct zfcp_fsf_req *fsf, | ||
| 433 | u16 len) | ||
| 434 | { | ||
| 435 | struct zfcp_fsf_ct_els *ct_els = fsf->data; | ||
| 436 | struct fc_ct_hdr *reqh = sg_virt(ct_els->req); | ||
| 437 | struct fc_ns_gid_ft *reqn = (struct fc_ns_gid_ft *)(reqh + 1); | ||
| 438 | struct scatterlist *resp_entry = ct_els->resp; | ||
| 439 | struct fc_gpn_ft_resp *acc; | ||
| 440 | int max_entries, x, last = 0; | ||
| 441 | |||
| 442 | if (!(memcmp(tag, "fsscth2", 7) == 0 | ||
| 443 | && ct_els->d_id == FC_FID_DIR_SERV | ||
| 444 | && reqh->ct_rev == FC_CT_REV | ||
| 445 | && reqh->ct_in_id[0] == 0 | ||
| 446 | && reqh->ct_in_id[1] == 0 | ||
| 447 | && reqh->ct_in_id[2] == 0 | ||
| 448 | && reqh->ct_fs_type == FC_FST_DIR | ||
| 449 | && reqh->ct_fs_subtype == FC_NS_SUBTYPE | ||
| 450 | && reqh->ct_options == 0 | ||
| 451 | && reqh->_ct_resvd1 == 0 | ||
| 452 | && reqh->ct_cmd == FC_NS_GPN_FT | ||
| 453 | /* reqh->ct_mr_size can vary so do not match but read below */ | ||
| 454 | && reqh->_ct_resvd2 == 0 | ||
| 455 | && reqh->ct_reason == 0 | ||
| 456 | && reqh->ct_explan == 0 | ||
| 457 | && reqh->ct_vendor == 0 | ||
| 458 | && reqn->fn_resvd == 0 | ||
| 459 | && reqn->fn_domain_id_scope == 0 | ||
| 460 | && reqn->fn_area_id_scope == 0 | ||
| 461 | && reqn->fn_fc4_type == FC_TYPE_FCP)) | ||
| 462 | return len; /* not GPN_FT response so do not cap */ | ||
| 463 | |||
| 464 | acc = sg_virt(resp_entry); | ||
| 465 | max_entries = (reqh->ct_mr_size * 4 / sizeof(struct fc_gpn_ft_resp)) | ||
| 466 | + 1 /* zfcp_fc_scan_ports: bytes correct, entries off-by-one | ||
| 467 | * to account for header as 1st pseudo "entry" */; | ||
| 468 | |||
| 469 | /* the basic CT_IU preamble is the same size as one entry in the GPN_FT | ||
| 470 | * response, allowing us to skip special handling for it - just skip it | ||
| 471 | */ | ||
| 472 | for (x = 1; x < max_entries && !last; x++) { | ||
| 473 | if (x % (ZFCP_FC_GPN_FT_ENT_PAGE + 1)) | ||
| 474 | acc++; | ||
| 475 | else | ||
| 476 | acc = sg_virt(++resp_entry); | ||
| 477 | |||
| 478 | last = acc->fp_flags & FC_NS_FID_LAST; | ||
| 479 | } | ||
| 480 | len = min(len, (u16)(x * sizeof(struct fc_gpn_ft_resp))); | ||
| 481 | return len; /* cap after last entry */ | ||
| 360 | } | 482 | } |
| 361 | 483 | ||
| 362 | /** | 484 | /** |
| @@ -370,9 +492,10 @@ void zfcp_dbf_san_res(char *tag, struct zfcp_fsf_req *fsf) · 7 unmodified lines | |||
| 370 | struct zfcp_fsf_ct_els *ct_els = fsf->data; | 492 | struct zfcp_fsf_ct_els *ct_els = fsf->data; |
| 371 | u16 length; | 493 | u16 length; |
| 372 | 494 | ||
| 373 | length = (u16)(ct_els->resp->length + FC_CT_HDR_LEN); | 495 | length = (u16)zfcp_qdio_real_bytes(ct_els->resp); |
| 374 | zfcp_dbf_san(tag, dbf, sg_virt(ct_els->resp), ZFCP_DBF_SAN_RES, length, | 496 | zfcp_dbf_san(tag, dbf, "san_res", ct_els->resp, ZFCP_DBF_SAN_RES, |
| 375 | fsf->req_id, 0); | 497 | length, fsf->req_id, ct_els->d_id, |
| 498 | zfcp_dbf_san_res_cap_len_if_gpn_ft(tag, fsf, length)); | ||
| 376 | } | 499 | } |
| 377 | 500 | ||
| 378 | /** | 501 | /** |
| @@ -386,11 +509,13 @@ void zfcp_dbf_san_in_els(char *tag, struct zfcp_fsf_req *fsf) · 7 unmodified lines | |||
| 386 | struct fsf_status_read_buffer *srb = | 509 | struct fsf_status_read_buffer *srb = |
| 387 | (struct fsf_status_read_buffer *) fsf->data; | 510 | (struct fsf_status_read_buffer *) fsf->data; |
| 388 | u16 length; | 511 | u16 length; |
| 512 | struct scatterlist sg; | ||
| 389 | 513 | ||
| 390 | length = (u16)(srb->length - | 514 | length = (u16)(srb->length - |
| 391 | offsetof(struct fsf_status_read_buffer, payload)); | 515 | offsetof(struct fsf_status_read_buffer, payload)); |
| 392 | zfcp_dbf_san(tag, dbf, srb->payload.data, ZFCP_DBF_SAN_ELS, length, | 516 | sg_init_one(&sg, srb->payload.data, length); |
| 393 | fsf->req_id, ntoh24(srb->d_id)); | 517 | zfcp_dbf_san(tag, dbf, "san_els", &sg, ZFCP_DBF_SAN_ELS, length, |
| 518 | fsf->req_id, ntoh24(srb->d_id), length); | ||
| 394 | } | 519 | } |
| 395 | 520 | ||
| 396 | /** | 521 | /** |
| @@ -399,7 +524,8 @@ void zfcp_dbf_san_in_els(char *tag, struct zfcp_fsf_req *fsf) · 2 unmodified lines | |||
| 399 | * @sc: pointer to struct scsi_cmnd | 524 | * @sc: pointer to struct scsi_cmnd |
| 400 | * @fsf: pointer to struct zfcp_fsf_req | 525 | * @fsf: pointer to struct zfcp_fsf_req |
| 401 | */ | 526 | */ |
| 402 | void zfcp_dbf_scsi(char *tag, struct scsi_cmnd *sc, struct zfcp_fsf_req *fsf) | 527 | void zfcp_dbf_scsi(char *tag, int level, struct scsi_cmnd *sc, |
| 528 | struct zfcp_fsf_req *fsf) | ||
| 403 | { | 529 | { |
| 404 | struct zfcp_adapter *adapter = | 530 | struct zfcp_adapter *adapter = |
| 405 | (struct zfcp_adapter *) sc->device->host->hostdata[0]; | 531 | (struct zfcp_adapter *) sc->device->host->hostdata[0]; |
| @@ -442,7 +568,7 @@ void zfcp_dbf_scsi(char *tag, struct scsi_cmnd *sc, struct zfcp_fsf_req *fsf) · 36 unmodified lines | |||
| 442 | } | 568 | } |
| 443 | } | 569 | } |
| 444 | 570 | ||
| 445 | debug_event(dbf->scsi, 1, rec, sizeof(*rec)); | 571 | debug_event(dbf->scsi, level, rec, sizeof(*rec)); |
| 446 | spin_unlock_irqrestore(&dbf->scsi_lock, flags); | 572 | spin_unlock_irqrestore(&dbf->scsi_lock, flags); |
| 447 | } | 573 | } |
| 448 | 574 | ||
| @@ -2,7 +2,7 @@ · 1 unmodified line | |||
| 2 | * zfcp device driver | 2 | * zfcp device driver |
| 3 | * debug feature declarations | 3 | * debug feature declarations |
| 4 | * | 4 | * |
| 5 | * Copyright IBM Corp. 2008, 2010 | 5 | * Copyright IBM Corp. 2008, 2015 |
| 6 | */ | 6 | */ |
| 7 | 7 | ||
| 8 | #ifndef ZFCP_DBF_H | 8 | #ifndef ZFCP_DBF_H |
| @@ -17,6 +17,11 @@ · 8 unmodified lines | |||
| 17 | 17 | ||
| 18 | #define ZFCP_DBF_INVALID_LUN 0xFFFFFFFFFFFFFFFFull | 18 | #define ZFCP_DBF_INVALID_LUN 0xFFFFFFFFFFFFFFFFull |
| 19 | 19 | ||
| 20 | enum zfcp_dbf_pseudo_erp_act_type { | ||
| 21 | ZFCP_PSEUDO_ERP_ACTION_RPORT_ADD = 0xff, | ||
| 22 | ZFCP_PSEUDO_ERP_ACTION_RPORT_DEL = 0xfe, | ||
| 23 | }; | ||
| 24 | |||
| 20 | /** | 25 | /** |
| 21 | * struct zfcp_dbf_rec_trigger - trace record for triggered recovery action | 26 | * struct zfcp_dbf_rec_trigger - trace record for triggered recovery action |
| 22 | * @ready: number of ready recovery actions | 27 | * @ready: number of ready recovery actions |
| @@ -110,6 +115,7 @@ struct zfcp_dbf_san { · 87 unmodified lines | |||
| 110 | u32 d_id; | 115 | u32 d_id; |
| 111 | #define ZFCP_DBF_SAN_MAX_PAYLOAD (FC_CT_HDR_LEN + 32) | 116 | #define ZFCP_DBF_SAN_MAX_PAYLOAD (FC_CT_HDR_LEN + 32) |
| 112 | char payload[ZFCP_DBF_SAN_MAX_PAYLOAD]; | 117 | char payload[ZFCP_DBF_SAN_MAX_PAYLOAD]; |
| 118 | u16 pl_len; | ||
| 113 | } __packed; | 119 | } __packed; |
| 114 | 120 | ||
| 115 | /** | 121 | /** |
| @@ -126,6 +132,8 @@ struct zfcp_dbf_hba_res { · 10 unmodified lines | |||
| 126 | u8 prot_status_qual[FSF_PROT_STATUS_QUAL_SIZE]; | 132 | u8 prot_status_qual[FSF_PROT_STATUS_QUAL_SIZE]; |
| 127 | u32 fsf_status; | 133 | u32 fsf_status; |
| 128 | u8 fsf_status_qual[FSF_STATUS_QUALIFIER_SIZE]; | 134 | u8 fsf_status_qual[FSF_STATUS_QUALIFIER_SIZE]; |
| 135 | u32 port_handle; | ||
| 136 | u32 lun_handle; | ||
| 129 | } __packed; | 137 | } __packed; |
| 130 | 138 | ||
| 131 | /** | 139 | /** |
| @@ -279,7 +287,7 @@ static inline · 147 unmodified lines | |||
| 279 | void zfcp_dbf_hba_fsf_resp(char *tag, int level, struct zfcp_fsf_req *req) | 287 | void zfcp_dbf_hba_fsf_resp(char *tag, int level, struct zfcp_fsf_req *req) |
| 280 | { | 288 | { |
| 281 | if (debug_level_enabled(req->adapter->dbf->hba, level)) | 289 | if (debug_level_enabled(req->adapter->dbf->hba, level)) |
| 282 | zfcp_dbf_hba_fsf_res(tag, req); | 290 | zfcp_dbf_hba_fsf_res(tag, level, req); |
| 283 | } | 291 | } |
| 284 | 292 | ||
| 285 | /** | 293 | /** |
| @@ -318,7 +326,7 @@ void _zfcp_dbf_scsi(char *tag, int level, struct scsi_cmnd *scmd, · 32 unmodified lines | |||
| 318 | scmd->device->host->hostdata[0]; | 326 | scmd->device->host->hostdata[0]; |
| 319 | 327 | ||
| 320 | if (debug_level_enabled(adapter->dbf->scsi, level)) | 328 | if (debug_level_enabled(adapter->dbf->scsi, level)) |
| 321 | zfcp_dbf_scsi(tag, scmd, req); | 329 | zfcp_dbf_scsi(tag, level, scmd, req); |
| 322 | } | 330 | } |
| 323 | 331 | ||
| 324 | /** | 332 | /** |
| @@ -3,7 +3,7 @@ · 2 unmodified lines | |||
| 3 | * | 3 | * |
| 4 | * Error Recovery Procedures (ERP). | 4 | * Error Recovery Procedures (ERP). |
| 5 | * | 5 | * |
| 6 | * Copyright IBM Corp. 2002, 2010 | 6 | * Copyright IBM Corp. 2002, 2015 |
| 7 | */ | 7 | */ |
| 8 | 8 | ||
| 9 | #define KMSG_COMPONENT "zfcp" | 9 | #define KMSG_COMPONENT "zfcp" |
| @@ -1217,8 +1217,14 @@ static void zfcp_erp_action_cleanup(struct zfcp_erp_action *act, int result) · 1207 unmodified lines | |||
| 1217 | break; | 1217 | break; |
| 1218 | 1218 | ||
| 1219 | case ZFCP_ERP_ACTION_REOPEN_PORT: | 1219 | case ZFCP_ERP_ACTION_REOPEN_PORT: |
| 1220 | if (result == ZFCP_ERP_SUCCEEDED) | 1220 | /* This switch case might also happen after a forced reopen |
| 1221 | zfcp_scsi_schedule_rport_register(port); | 1221 | * was successfully done and thus overwritten with a new |
| 1222 | * non-forced reopen at `ersfs_2'. In this case, we must not | ||
| 1223 | * do the clean-up of the non-forced version. | ||
| 1224 | */ | ||
| 1225 | if (act->step != ZFCP_ERP_STEP_UNINITIALIZED) | ||
| 1226 | if (result == ZFCP_ERP_SUCCEEDED) | ||
| 1227 | zfcp_scsi_schedule_rport_register(port); | ||
| 1222 | /* fall through */ | 1228 | /* fall through */ |
| 1223 | case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED: | 1229 | case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED: |
| 1224 | put_device(&port->dev); | 1230 | put_device(&port->dev); |
| @@ -3,7 +3,7 @@ · 2 unmodified lines | |||
| 3 | * | 3 | * |
| 4 | * External function declarations. | 4 | * External function declarations. |
| 5 | * | 5 | * |
| 6 | * Copyright IBM Corp. 2002, 2010 | 6 | * Copyright IBM Corp. 2002, 2015 |
| 7 | */ | 7 | */ |
| 8 | 8 | ||
| 9 | #ifndef ZFCP_EXT_H | 9 | #ifndef ZFCP_EXT_H |
| @@ -35,8 +35,9 @@ extern void zfcp_dbf_adapter_unregister(struct zfcp_adapter *); · 25 unmodified lines | |||
| 35 | extern void zfcp_dbf_rec_trig(char *, struct zfcp_adapter *, | 35 | extern void zfcp_dbf_rec_trig(char *, struct zfcp_adapter *, |
| 36 | struct zfcp_port *, struct scsi_device *, u8, u8); | 36 | struct zfcp_port *, struct scsi_device *, u8, u8); |
| 37 | extern void zfcp_dbf_rec_run(char *, struct zfcp_erp_action *); | 37 | extern void zfcp_dbf_rec_run(char *, struct zfcp_erp_action *); |
| 38 | extern void zfcp_dbf_rec_run_wka(char *, struct zfcp_fc_wka_port *, u64); | ||
| 38 | extern void zfcp_dbf_hba_fsf_uss(char *, struct zfcp_fsf_req *); | 39 | extern void zfcp_dbf_hba_fsf_uss(char *, struct zfcp_fsf_req *); |
| 39 | extern void zfcp_dbf_hba_fsf_res(char *, struct zfcp_fsf_req *); | 40 | extern void zfcp_dbf_hba_fsf_res(char *, int, struct zfcp_fsf_req *); |
| 40 | extern void zfcp_dbf_hba_bit_err(char *, struct zfcp_fsf_req *); | 41 | extern void zfcp_dbf_hba_bit_err(char *, struct zfcp_fsf_req *); |
| 41 | extern void zfcp_dbf_hba_berr(struct zfcp_dbf *, struct zfcp_fsf_req *); | 42 | extern void zfcp_dbf_hba_berr(struct zfcp_dbf *, struct zfcp_fsf_req *); |
| 42 | extern void zfcp_dbf_hba_def_err(struct zfcp_adapter *, u64, u16, void **); | 43 | extern void zfcp_dbf_hba_def_err(struct zfcp_adapter *, u64, u16, void **); |
| @@ -44,7 +45,8 @@ extern void zfcp_dbf_hba_basic(char *, struct zfcp_adapter *); · 1 unmodified line | |||
| 44 | extern void zfcp_dbf_san_req(char *, struct zfcp_fsf_req *, u32); | 45 | extern void zfcp_dbf_san_req(char *, struct zfcp_fsf_req *, u32); |
| 45 | extern void zfcp_dbf_san_res(char *, struct zfcp_fsf_req *); | 46 | extern void zfcp_dbf_san_res(char *, struct zfcp_fsf_req *); |
| 46 | extern void zfcp_dbf_san_in_els(char *, struct zfcp_fsf_req *); | 47 | extern void zfcp_dbf_san_in_els(char *, struct zfcp_fsf_req *); |
| 47 | extern void zfcp_dbf_scsi(char *, struct scsi_cmnd *, struct zfcp_fsf_req *); | 48 | extern void zfcp_dbf_scsi(char *, int, struct scsi_cmnd *, |
| 49 | struct zfcp_fsf_req *); | ||
| 48 | 50 | ||
| 49 | /* zfcp_erp.c */ | 51 | /* zfcp_erp.c */ |
| 50 | extern void zfcp_erp_set_adapter_status(struct zfcp_adapter *, u32); | 52 | extern void zfcp_erp_set_adapter_status(struct zfcp_adapter *, u32); |
| @@ -3,7 +3,7 @@ · 2 unmodified lines | |||
| 3 | * | 3 | * |
| 4 | * Implementation of FSF commands. | 4 | * Implementation of FSF commands. |
| 5 | * | 5 | * |
| 6 | * Copyright IBM Corp. 2002, 2013 | 6 | * Copyright IBM Corp. 2002, 2015 |
| 7 | */ | 7 | */ |
| 8 | 8 | ||
| 9 | #define KMSG_COMPONENT "zfcp" | 9 | #define KMSG_COMPONENT "zfcp" |
| @@ -508,7 +508,10 @@ static int zfcp_fsf_exchange_config_evaluate(struct zfcp_fsf_req *req) · 498 unmodified lines | |||
| 508 | fc_host_port_type(shost) = FC_PORTTYPE_PTP; | 508 | fc_host_port_type(shost) = FC_PORTTYPE_PTP; |
| 509 | break; | 509 | break; |
| 510 | case FSF_TOPO_FABRIC: | 510 | case FSF_TOPO_FABRIC: |
| 511 | fc_host_port_type(shost) = FC_PORTTYPE_NPORT; | 511 | if (bottom->connection_features & FSF_FEATURE_NPIV_MODE) |
| 512 | fc_host_port_type(shost) = FC_PORTTYPE_NPIV; | ||
| 513 | else | ||
| 514 | fc_host_port_type(shost) = FC_PORTTYPE_NPORT; | ||
| 512 | break; | 515 | break; |
| 513 | case FSF_TOPO_AL: | 516 | case FSF_TOPO_AL: |
| 514 | fc_host_port_type(shost) = FC_PORTTYPE_NLPORT; | 517 | fc_host_port_type(shost) = FC_PORTTYPE_NLPORT; |
| @@ -613,7 +616,6 @@ static void zfcp_fsf_exchange_port_evaluate(struct zfcp_fsf_req *req) · 98 unmodified lines | |||
| 613 | 616 | ||
| 614 | if (adapter->connection_features & FSF_FEATURE_NPIV_MODE) { | 617 | if (adapter->connection_features & FSF_FEATURE_NPIV_MODE) { |
| 615 | fc_host_permanent_port_name(shost) = bottom->wwpn; | 618 | fc_host_permanent_port_name(shost) = bottom->wwpn; |
| 616 | fc_host_port_type(shost) = FC_PORTTYPE_NPIV; | ||
| 617 | } else | 619 | } else |
| 618 | fc_host_permanent_port_name(shost) = fc_host_port_name(shost); | 620 | fc_host_permanent_port_name(shost) = fc_host_port_name(shost); |
| 619 | fc_host_maxframe_size(shost) = bottom->maximum_frame_size; | 621 | fc_host_maxframe_size(shost) = bottom->maximum_frame_size; |
| @@ -982,8 +984,12 @@ static int zfcp_fsf_setup_ct_els_sbals(struct zfcp_fsf_req *req, · 362 unmodified lines | |||
| 982 | if (zfcp_adapter_multi_buffer_active(adapter)) { | 984 | if (zfcp_adapter_multi_buffer_active(adapter)) { |
| 983 | if (zfcp_qdio_sbals_from_sg(qdio, &req->qdio_req, sg_req)) | 985 | if (zfcp_qdio_sbals_from_sg(qdio, &req->qdio_req, sg_req)) |
| 984 | return -EIO; | 986 | return -EIO; |
| 987 | qtcb->bottom.support.req_buf_length = | ||
| 988 | zfcp_qdio_real_bytes(sg_req); | ||
| 985 | if (zfcp_qdio_sbals_from_sg(qdio, &req->qdio_req, sg_resp)) | 989 | if (zfcp_qdio_sbals_from_sg(qdio, &req->qdio_req, sg_resp)) |
| 986 | return -EIO; | 990 | return -EIO; |
| 991 | qtcb->bottom.support.resp_buf_length = | ||
| 992 | zfcp_qdio_real_bytes(sg_resp); | ||
| 987 | 993 | ||
| 988 | zfcp_qdio_set_data_div(qdio, &req->qdio_req, | 994 | zfcp_qdio_set_data_div(qdio, &req->qdio_req, |
| 989 | zfcp_qdio_sbale_count(sg_req)); | 995 | zfcp_qdio_sbale_count(sg_req)); |
| @@ -1073,6 +1079,7 @@ int zfcp_fsf_send_ct(struct zfcp_fc_wka_port *wka_port, · 83 unmodified lines | |||
| 1073 | 1079 | ||
| 1074 | req->handler = zfcp_fsf_send_ct_handler; | 1080 | req->handler = zfcp_fsf_send_ct_handler; |
| 1075 | req->qtcb->header.port_handle = wka_port->handle; | 1081 | req->qtcb->header.port_handle = wka_port->handle; |
| 1082 | ct->d_id = wka_port->d_id; | ||
| 1076 | req->data = ct; | 1083 | req->data = ct; |
| 1077 | 1084 | ||
| 1078 | zfcp_dbf_san_req("fssct_1", req, wka_port->d_id); | 1085 | zfcp_dbf_san_req("fssct_1", req, wka_port->d_id); |
| @@ -1169,6 +1176,7 @@ int zfcp_fsf_send_els(struct zfcp_adapter *adapter, u32 d_id, · 90 unmodified lines | |||
| 1169 | 1176 | ||
| 1170 | hton24(req->qtcb->bottom.support.d_id, d_id); | 1177 | hton24(req->qtcb->bottom.support.d_id, d_id); |
| 1171 | req->handler = zfcp_fsf_send_els_handler; | 1178 | req->handler = zfcp_fsf_send_els_handler; |
| 1179 | els->d_id = d_id; | ||
| 1172 | req->data = els; | 1180 | req->data = els; |
| 1173 | 1181 | ||
| 1174 | zfcp_dbf_san_req("fssels1", req, d_id); | 1182 | zfcp_dbf_san_req("fssels1", req, d_id); |
| @@ -1575,7 +1583,7 @@ out: · 400 unmodified lines | |||
| 1575 | int zfcp_fsf_open_wka_port(struct zfcp_fc_wka_port *wka_port) | 1583 | int zfcp_fsf_open_wka_port(struct zfcp_fc_wka_port *wka_port) |
| 1576 | { | 1584 | { |
| 1577 | struct zfcp_qdio *qdio = wka_port->adapter->qdio; | 1585 | struct zfcp_qdio *qdio = wka_port->adapter->qdio; |
| 1578 | struct zfcp_fsf_req *req; | 1586 | struct zfcp_fsf_req *req = NULL; |
| 1579 | int retval = -EIO; | 1587 | int retval = -EIO; |
| 1580 | 1588 | ||
| 1581 | spin_lock_irq(&qdio->req_q_lock); | 1589 | spin_lock_irq(&qdio->req_q_lock); |
| @@ -1604,6 +1612,8 @@ int zfcp_fsf_open_wka_port(struct zfcp_fc_wka_port *wka_port) · 22 unmodified lines | |||
| 1604 | zfcp_fsf_req_free(req); | 1612 | zfcp_fsf_req_free(req); |
| 1605 | out: | 1613 | out: |
| 1606 | spin_unlock_irq(&qdio->req_q_lock); | 1614 | spin_unlock_irq(&qdio->req_q_lock); |
| 1615 | if (req && !IS_ERR(req)) | ||
| 1616 | zfcp_dbf_rec_run_wka("fsowp_1", wka_port, req->req_id); | ||
| 1607 | return retval; | 1617 | return retval; |
| 1608 | } | 1618 | } |
| 1609 | 1619 | ||
| @@ -1628,7 +1638,7 @@ static void zfcp_fsf_close_wka_port_handler(struct zfcp_fsf_req *req) · 18 unmodified lines | |||
| 1628 | int zfcp_fsf_close_wka_port(struct zfcp_fc_wka_port *wka_port) | 1638 | int zfcp_fsf_close_wka_port(struct zfcp_fc_wka_port *wka_port) |
| 1629 | { | 1639 | { |
| 1630 | struct zfcp_qdio *qdio = wka_port->adapter->qdio; | 1640 | struct zfcp_qdio *qdio = wka_port->adapter->qdio; |
| 1631 | struct zfcp_fsf_req *req; | 1641 | struct zfcp_fsf_req *req = NULL; |
| 1632 | int retval = -EIO; | 1642 | int retval = -EIO; |
| 1633 | 1643 | ||
| 1634 | spin_lock_irq(&qdio->req_q_lock); | 1644 | spin_lock_irq(&qdio->req_q_lock); |
| @@ -1657,6 +1667,8 @@ int zfcp_fsf_close_wka_port(struct zfcp_fc_wka_port *wka_port) · 22 unmodified lines | |||
| 1657 | zfcp_fsf_req_free(req); | 1667 | zfcp_fsf_req_free(req); |
| 1658 | out: | 1668 | out: |
| 1659 | spin_unlock_irq(&qdio->req_q_lock); | 1669 | spin_unlock_irq(&qdio->req_q_lock); |
| 1670 | if (req && !IS_ERR(req)) | ||
| 1671 | zfcp_dbf_rec_run_wka("fscwp_1", wka_port, req->req_id); | ||
| 1660 | return retval; | 1672 | return retval; |
| 1661 | } | 1673 | } |
| 1662 | 1674 | ||
| @@ -3,7 +3,7 @@ · 2 unmodified lines | |||
| 3 | * | 3 | * |
| 4 | * Interface to the FSF support functions. | 4 | * Interface to the FSF support functions. |
| 5 | * | 5 | * |
| 6 | * Copyright IBM Corp. 2002, 2010 | 6 | * Copyright IBM Corp. 2002, 2015 |
| 7 | */ | 7 | */ |
| 8 | 8 | ||
| 9 | #ifndef FSF_H | 9 | #ifndef FSF_H |
| @@ -436,6 +436,7 @@ struct zfcp_blk_drv_data { · 426 unmodified lines | |||
| 436 | * @handler_data: data passed to handler function | 436 | * @handler_data: data passed to handler function |
| 437 | * @port: Optional pointer to port for zfcp internal ELS (only test link ADISC) | 437 | * @port: Optional pointer to port for zfcp internal ELS (only test link ADISC) |
| 438 | * @status: used to pass error status to calling function | 438 | * @status: used to pass error status to calling function |
| 439 | * @d_id: Destination ID of either open WKA port for CT or of D_ID for ELS | ||
| 439 | */ | 440 | */ |
| 440 | struct zfcp_fsf_ct_els { | 441 | struct zfcp_fsf_ct_els { |
| 441 | struct scatterlist *req; | 442 | struct scatterlist *req; |
| @@ -444,6 +445,7 @@ struct zfcp_fsf_ct_els { · 2 unmodified lines | |||
| 444 | void *handler_data; | 445 | void *handler_data; |
| 445 | struct zfcp_port *port; | 446 | struct zfcp_port *port; |
| 446 | int status; | 447 | int status; |
| 448 | u32 d_id; | ||
| 447 | }; | 449 | }; |
| 448 | 450 | ||
| 449 | #endif /* FSF_H */ | 451 | #endif /* FSF_H */ |
| @@ -3,7 +3,7 @@ · 2 unmodified lines | |||
| 3 | * | 3 | * |
| 4 | * Interface to Linux SCSI midlayer. | 4 | * Interface to Linux SCSI midlayer. |
| 5 | * | 5 | * |
| 6 | * Copyright IBM Corp. 2002, 2013 | 6 | * Copyright IBM Corp. 2002, 2015 |
| 7 | */ | 7 | */ |
| 8 | 8 | ||
| 9 | #define KMSG_COMPONENT "zfcp" | 9 | #define KMSG_COMPONENT "zfcp" |
| @@ -556,6 +556,9 @@ static void zfcp_scsi_rport_register(struct zfcp_port *port) · 546 unmodified lines | |||
| 556 | ids.port_id = port->d_id; | 556 | ids.port_id = port->d_id; |
| 557 | ids.roles = FC_RPORT_ROLE_FCP_TARGET; | 557 | ids.roles = FC_RPORT_ROLE_FCP_TARGET; |
| 558 | 558 | ||
| 559 | zfcp_dbf_rec_trig("scpaddy", port->adapter, port, NULL, | ||
| 560 | ZFCP_PSEUDO_ERP_ACTION_RPORT_ADD, | ||
| 561 | ZFCP_PSEUDO_ERP_ACTION_RPORT_ADD); | ||
| 559 | rport = fc_remote_port_add(port->adapter->scsi_host, 0, &ids); | 562 | rport = fc_remote_port_add(port->adapter->scsi_host, 0, &ids); |
| 560 | if (!rport) { | 563 | if (!rport) { |
| 561 | dev_err(&port->adapter->ccw_device->dev, | 564 | dev_err(&port->adapter->ccw_device->dev, |
| @@ -577,6 +580,9 @@ static void zfcp_scsi_rport_block(struct zfcp_port *port) · 15 unmodified lines | |||
| 577 | struct fc_rport *rport = port->rport; | 580 | struct fc_rport *rport = port->rport; |
| 578 | 581 | ||
| 579 | if (rport) { | 582 | if (rport) { |
| 583 | zfcp_dbf_rec_trig("scpdely", port->adapter, port, NULL, | ||
| 584 | ZFCP_PSEUDO_ERP_ACTION_RPORT_DEL, | ||
| 585 | ZFCP_PSEUDO_ERP_ACTION_RPORT_DEL); | ||
| 580 | fc_remote_port_delete(rport); | 586 | fc_remote_port_delete(rport); |
| 581 | port->rport = NULL; | 587 | port->rport = NULL; |
| 582 | } | 588 | } |
| @@ -396,18 +396,6 @@ config SCSI_3W_SAS · 395 unmodified lines | |||
| 396 | Please read the comments at the top of | 396 | Please read the comments at the top of |
| 397 | <file:drivers/scsi/3w-sas.c>. | 397 | <file:drivers/scsi/3w-sas.c>. |
| 398 | 398 | ||
| 399 | config SCSI_7000FASST | ||
| 400 | tristate "7000FASST SCSI support" | ||
| 401 | depends on ISA && SCSI && ISA_DMA_API | ||
| 402 | select CHECK_SIGNATURE | ||
| 403 | help | ||
| 404 | This driver supports the Western Digital 7000 SCSI host adapter | ||
| 405 | family. Some information is in the source: | ||
| 406 | <file:drivers/scsi/wd7000.c>. | ||
| 407 | |||
| 408 | To compile this driver as a module, choose M here: the | ||
| 409 | module will be called wd7000. | ||
| 410 | |||
| 411 | config SCSI_ACARD | 399 | config SCSI_ACARD |
| 412 | tristate "ACARD SCSI support" | 400 | tristate "ACARD SCSI support" |
| 413 | depends on PCI && SCSI | 401 | depends on PCI && SCSI |
| @@ -512,18 +500,6 @@ config SCSI_ADVANSYS · 98 unmodified lines | |||
| 512 | To compile this driver as a module, choose M here: the | 500 | To compile this driver as a module, choose M here: the |
| 513 | module will be called advansys. | 501 | module will be called advansys. |
| 514 | 502 | ||
| 515 | config SCSI_IN2000 | ||
| 516 | tristate "Always IN2000 SCSI support" | ||
| 517 | depends on ISA && SCSI | ||
| 518 | help | ||
| 519 | This is support for an ISA bus SCSI host adapter. You'll find more | ||
| 520 | information in <file:Documentation/scsi/in2000.txt>. If it doesn't work | ||
| 521 | out of the box, you may have to change the jumpers for IRQ or | ||
| 522 | address selection. | ||
| 523 | |||
| 524 | To compile this driver as a module, choose M here: the | ||
| 525 | module will be called in2000. | ||
| 526 | |||
| 527 | config SCSI_ARCMSR | 503 | config SCSI_ARCMSR |
| 528 | tristate "ARECA (ARC11xx/12xx/13xx/16xx) SATA/SAS RAID Host Adapter" | 504 | tristate "ARECA (ARC11xx/12xx/13xx/16xx) SATA/SAS RAID Host Adapter" |
| 529 | depends on PCI && SCSI | 505 | depends on PCI && SCSI |
| @@ -540,6 +516,7 @@ config SCSI_ARCMSR · 10 unmodified lines | |||
| 540 | source "drivers/scsi/esas2r/Kconfig" | 516 | source "drivers/scsi/esas2r/Kconfig" |
| 541 | source "drivers/scsi/megaraid/Kconfig.megaraid" | 517 | source "drivers/scsi/megaraid/Kconfig.megaraid" |
| 542 | source "drivers/scsi/mpt3sas/Kconfig" | 518 | source "drivers/scsi/mpt3sas/Kconfig" |
| 519 | source "drivers/scsi/smartpqi/Kconfig" | ||
| 543 | source "drivers/scsi/ufs/Kconfig" | 520 | source "drivers/scsi/ufs/Kconfig" |
| 544 | 521 | ||
| 545 | config SCSI_HPTIOP | 522 | config SCSI_HPTIOP |
| @@ -660,20 +637,6 @@ config SCSI_DMX3191D · 114 unmodified lines | |||
| 660 | To compile this driver as a module, choose M here: the | 637 | To compile this driver as a module, choose M here: the |
| 661 | module will be called dmx3191d. | 638 | module will be called dmx3191d. |
| 662 | 639 | ||
| 663 | config SCSI_DTC3280 | ||
| 664 | tristate "DTC3180/3280 SCSI support" | ||
| 665 | depends on ISA && SCSI | ||
| 666 | select SCSI_SPI_ATTRS | ||
| 667 | select CHECK_SIGNATURE | ||
| 668 | help | ||
| 669 | This is support for DTC 3180/3280 SCSI Host Adapters. Please read | ||
| 670 | the SCSI-HOWTO, available from | ||
| 671 | <http://www.tldp.org/docs.html#howto>, and the file | ||
| 672 | <file:Documentation/scsi/dtc3x80.txt>. | ||
| 673 | |||
| 674 | To compile this driver as a module, choose M here: the | ||
| 675 | module will be called dtc. | ||
| 676 | |||
| 677 | config SCSI_EATA | 640 | config SCSI_EATA |
| 678 | tristate "EATA ISA/EISA/PCI (DPT and generic EATA/DMA-compliant boards) support" | 641 | tristate "EATA ISA/EISA/PCI (DPT and generic EATA/DMA-compliant boards) support" |
| 679 | depends on (ISA || EISA || PCI) && SCSI && ISA_DMA_API | 642 | depends on (ISA || EISA || PCI) && SCSI && ISA_DMA_API |
| @@ -1248,20 +1211,6 @@ config SCSI_NCR53C8XX_NO_DISCONNECT · 568 unmodified lines | |||
| 1248 | not allow targets to disconnect is not reasonable if there is more | 1211 | not allow targets to disconnect is not reasonable if there is more |
| 1249 | than 1 device on a SCSI bus. The normal answer therefore is N. | 1212 | than 1 device on a SCSI bus. The normal answer therefore is N. |
| 1250 | 1213 | ||
| 1251 | config SCSI_PAS16 | ||
| 1252 | tristate "PAS16 SCSI support" | ||
| 1253 | depends on ISA && SCSI | ||
| 1254 | select SCSI_SPI_ATTRS | ||
| 1255 | ---help--- | ||
| 1256 | This is support for a SCSI host adapter. It is explained in section | ||
| 1257 | 3.10 of the SCSI-HOWTO, available from | ||
| 1258 | <http://www.tldp.org/docs.html#howto>. If it doesn't work out | ||
| 1259 | of the box, you may have to change some settings in | ||
| 1260 | <file:drivers/scsi/pas16.h>. | ||
| 1261 | |||
| 1262 | To compile this driver as a module, choose M here: the | ||
| 1263 | module will be called pas16. | ||
| 1264 | |||
| 1265 | config SCSI_QLOGIC_FAS | 1214 | config SCSI_QLOGIC_FAS |
| 1266 | tristate "Qlogic FAS SCSI support" | 1215 | tristate "Qlogic FAS SCSI support" |
| 1267 | depends on ISA && SCSI | 1216 | depends on ISA && SCSI |
| @@ -1382,89 +1331,6 @@ config SCSI_AM53C974 · 114 unmodified lines | |||
| 1382 | To compile this driver as a module, choose M here: the | 1331 | To compile this driver as a module, choose M here: the |
| 1383 | module will be called am53c974. | 1332 | module will be called am53c974. |
| 1384 | 1333 | ||
| 1385 | config SCSI_T128 | ||
| 1386 | tristate "Trantor T128/T128F/T228 SCSI support" | ||
| 1387 | depends on ISA && SCSI | ||
| 1388 | select SCSI_SPI_ATTRS | ||
| 1389 | select CHECK_SIGNATURE | ||
| 1390 | ---help--- | ||
| 1391 | This is support for a SCSI host adapter. It is explained in section | ||
| 1392 | 3.11 of the SCSI-HOWTO, available from | ||
| 1393 | <http://www.tldp.org/docs.html#howto>. If it doesn't work out | ||
| 1394 | of the box, you may have to change some settings in | ||
| 1395 | <file:drivers/scsi/t128.h>. Note that Trantor was purchased by | ||
| 1396 | Adaptec, and some former Trantor products are being sold under the | ||
| 1397 | Adaptec name. | ||
| 1398 | |||
| 1399 | To compile this driver as a module, choose M here: the | ||
| 1400 | module will be called t128. | ||
| 1401 | |||
| 1402 | config SCSI_U14_34F | ||
| 1403 | tristate "UltraStor 14F/34F support" | ||
| 1404 | depends on ISA && SCSI && ISA_DMA_API | ||
| 1405 | ---help--- | ||
| 1406 | This is support for the UltraStor 14F and 34F SCSI-2 host adapters. | ||
| 1407 | The source at <file:drivers/scsi/u14-34f.c> contains some | ||
| 1408 | information about this hardware. If the driver doesn't work out of | ||
| 1409 | the box, you may have to change some settings in | ||
| 1410 | <file: drivers/scsi/u14-34f.c>. Read the SCSI-HOWTO, available from | ||
| 1411 | <http://www.tldp.org/docs.html#howto>. Note that there is also | ||
| 1412 | another driver for the same hardware: "UltraStor SCSI support", | ||
| 1413 | below. You should say Y to both only if you want 24F support as | ||
| 1414 | well. | ||
| 1415 | |||
| 1416 | To compile this driver as a module, choose M here: the | ||
| 1417 | module will be called u14-34f. | ||
| 1418 | |||
| 1419 | config SCSI_U14_34F_TAGGED_QUEUE | ||
| 1420 | bool "enable tagged command queueing" | ||
| 1421 | depends on SCSI_U14_34F | ||
| 1422 | help | ||
| 1423 | This is a feature of SCSI-2 which improves performance: the host | ||
| 1424 | adapter can send several SCSI commands to a device's queue even if | ||
| 1425 | previous commands haven't finished yet. | ||
| 1426 | This is equivalent to the "u14-34f=tc:y" boot option. | ||
| 1427 | |||
| 1428 | config SCSI_U14_34F_LINKED_COMMANDS | ||
| 1429 | bool "enable elevator sorting" | ||
| 1430 | depends on SCSI_U14_34F | ||
| 1431 | help | ||
| 1432 | This option enables elevator sorting for all probed SCSI disks and | ||
| 1433 | CD-ROMs. It definitely reduces the average seek distance when doing | ||
| 1434 | random seeks, but this does not necessarily result in a noticeable | ||
| 1435 | performance improvement: your mileage may vary... | ||
| 1436 | This is equivalent to the "u14-34f=lc:y" boot option. | ||
| 1437 | |||
| 1438 | config SCSI_U14_34F_MAX_TAGS | ||
| 1439 | int "maximum number of queued commands" | ||
| 1440 | depends on SCSI_U14_34F | ||
| 1441 | default "8" | ||
| 1442 | help | ||
| 1443 | This specifies how many SCSI commands can be maximally queued for | ||
| 1444 | each probed SCSI device. You should reduce the default value of 8 | ||
| 1445 | only if you have disks with buggy or limited tagged command support. | ||
| 1446 | Minimum is 2 and maximum is 14. This value is also the window size | ||
| 1447 | used by the elevator sorting option above. The effective value used | ||
| 1448 | by the driver for each probed SCSI device is reported at boot time. | ||
| 1449 | This is equivalent to the "u14-34f=mq:8" boot option. | ||
| 1450 | |||
| 1451 | config SCSI_ULTRASTOR | ||
| 1452 | tristate "UltraStor SCSI support" | ||
| 1453 | depends on X86 && ISA && SCSI && ISA_DMA_API | ||
| 1454 | ---help--- | ||
| 1455 | This is support for the UltraStor 14F, 24F and 34F SCSI-2 host | ||
| 1456 | adapter family. This driver is explained in section 3.12 of the | ||
| 1457 | SCSI-HOWTO, available from | ||
| 1458 | <http://www.tldp.org/docs.html#howto>. If it doesn't work out | ||
| 1459 | of the box, you may have to change some settings in | ||
| 1460 | <file:drivers/scsi/ultrastor.h>. | ||
| 1461 | |||
| 1462 | Note that there is also another driver for the same hardware: | ||
| 1463 | "UltraStor 14F/34F support", above. | ||
| 1464 | |||
| 1465 | To compile this driver as a module, choose M here: the | ||
| 1466 | module will be called ultrastor. | ||
| 1467 | |||
| 1468 | config SCSI_NSP32 | 1334 | config SCSI_NSP32 |
| 1469 | tristate "Workbit NinjaSCSI-32Bi/UDE support" | 1335 | tristate "Workbit NinjaSCSI-32Bi/UDE support" |
| 1470 | depends on PCI && SCSI && !64BIT | 1336 | depends on PCI && SCSI && !64BIT |
| @@ -61,9 +61,7 @@ obj-$(CONFIG_SCSI_SIM710) += 53c700.o sim710.o · 60 unmodified lines | |||
| 61 | obj-$(CONFIG_SCSI_ADVANSYS) += advansys.o | 61 | obj-$(CONFIG_SCSI_ADVANSYS) += advansys.o |
| 62 | obj-$(CONFIG_SCSI_BUSLOGIC) += BusLogic.o | 62 | obj-$(CONFIG_SCSI_BUSLOGIC) += BusLogic.o |
| 63 | obj-$(CONFIG_SCSI_DPT_I2O) += dpt_i2o.o | 63 | obj-$(CONFIG_SCSI_DPT_I2O) += dpt_i2o.o |
| 64 | obj-$(CONFIG_SCSI_U14_34F) += u14-34f.o | ||
| 65 | obj-$(CONFIG_SCSI_ARCMSR) += arcmsr/ | 64 | obj-$(CONFIG_SCSI_ARCMSR) += arcmsr/ |
| 66 | obj-$(CONFIG_SCSI_ULTRASTOR) += ultrastor.o | ||
| 67 | obj-$(CONFIG_SCSI_AHA152X) += aha152x.o | 65 | obj-$(CONFIG_SCSI_AHA152X) += aha152x.o |
| 68 | obj-$(CONFIG_SCSI_AHA1542) += aha1542.o | 66 | obj-$(CONFIG_SCSI_AHA1542) += aha1542.o |
| 69 | obj-$(CONFIG_SCSI_AHA1740) += aha1740.o | 67 | obj-$(CONFIG_SCSI_AHA1740) += aha1740.o |
| @@ -75,7 +73,6 @@ obj-$(CONFIG_SCSI_PM8001) += pm8001/ · 5 unmodified lines | |||
| 75 | obj-$(CONFIG_SCSI_ISCI) += isci/ | 73 | obj-$(CONFIG_SCSI_ISCI) += isci/ |
| 76 | obj-$(CONFIG_SCSI_IPS) += ips.o | 74 | obj-$(CONFIG_SCSI_IPS) += ips.o |
| 77 | obj-$(CONFIG_SCSI_FUTURE_DOMAIN)+= fdomain.o | 75 | obj-$(CONFIG_SCSI_FUTURE_DOMAIN)+= fdomain.o |
| 78 | obj-$(CONFIG_SCSI_IN2000) += in2000.o | ||
| 79 | obj-$(CONFIG_SCSI_GENERIC_NCR5380) += g_NCR5380.o | 76 | obj-$(CONFIG_SCSI_GENERIC_NCR5380) += g_NCR5380.o |
| 80 | obj-$(CONFIG_SCSI_GENERIC_NCR5380_MMIO) += g_NCR5380_mmio.o | 77 | obj-$(CONFIG_SCSI_GENERIC_NCR5380_MMIO) += g_NCR5380_mmio.o |
| 81 | obj-$(CONFIG_SCSI_NCR53C406A) += NCR53c406a.o | 78 | obj-$(CONFIG_SCSI_NCR53C406A) += NCR53c406a.o |
| @@ -90,15 +87,12 @@ obj-$(CONFIG_SCSI_QLA_ISCSI) += libiscsi.o qla4xxx/ · 8 unmodified lines | |||
| 90 | obj-$(CONFIG_SCSI_LPFC) += lpfc/ | 87 | obj-$(CONFIG_SCSI_LPFC) += lpfc/ |
| 91 | obj-$(CONFIG_SCSI_BFA_FC) += bfa/ | 88 | obj-$(CONFIG_SCSI_BFA_FC) += bfa/ |
| 92 | obj-$(CONFIG_SCSI_CHELSIO_FCOE) += csiostor/ | 89 | obj-$(CONFIG_SCSI_CHELSIO_FCOE) += csiostor/ |
| 93 | obj-$(CONFIG_SCSI_PAS16) += pas16.o | ||
| 94 | obj-$(CONFIG_SCSI_T128) += t128.o | ||
| 95 | obj-$(CONFIG_SCSI_DMX3191D) += dmx3191d.o | 90 | obj-$(CONFIG_SCSI_DMX3191D) += dmx3191d.o |
| 96 | obj-$(CONFIG_SCSI_HPSA) += hpsa.o | 91 | obj-$(CONFIG_SCSI_HPSA) += hpsa.o |
| 97 | obj-$(CONFIG_SCSI_DTC3280) += dtc.o | 92 | obj-$(CONFIG_SCSI_SMARTPQI) += smartpqi/ |
| 98 | obj-$(CONFIG_SCSI_SYM53C8XX_2) += sym53c8xx_2/ | 93 | obj-$(CONFIG_SCSI_SYM53C8XX_2) += sym53c8xx_2/ |
| 99 | obj-$(CONFIG_SCSI_ZALON) += zalon7xx.o | 94 | obj-$(CONFIG_SCSI_ZALON) += zalon7xx.o |
| 100 | obj-$(CONFIG_SCSI_EATA_PIO) += eata_pio.o | 95 | obj-$(CONFIG_SCSI_EATA_PIO) += eata_pio.o |
| 101 | obj-$(CONFIG_SCSI_7000FASST) += wd7000.o | ||
| 102 | obj-$(CONFIG_SCSI_EATA) += eata.o | 96 | obj-$(CONFIG_SCSI_EATA) += eata.o |
| 103 | obj-$(CONFIG_SCSI_DC395x) += dc395x.o | 97 | obj-$(CONFIG_SCSI_DC395x) += dc395x.o |
| 104 | obj-$(CONFIG_SCSI_AM53C974) += esp_scsi.o am53c974.o | 98 | obj-$(CONFIG_SCSI_AM53C974) += esp_scsi.o am53c974.o |
| @@ -230,13 +230,6 @@ static int NCR5380_poll_politely2(struct Scsi_Host *instance, · 229 unmodified lines | |||
| 230 | return -ETIMEDOUT; | 230 | return -ETIMEDOUT; |
| 231 | } | 231 | } |
| 232 | 232 | ||
| 233 | static inline int NCR5380_poll_politely(struct Scsi_Host *instance, | ||
| 234 | int reg, int bit, int val, int wait) | ||
| 235 | { | ||
| 236 | return NCR5380_poll_politely2(instance, reg, bit, val, | ||
| 237 | reg, bit, val, wait); | ||
| 238 | } | ||
| 239 | |||
| 240 | #if NDEBUG | 233 | #if NDEBUG |
| 241 | static struct { | 234 | static struct { |
| 242 | unsigned char mask; | 235 | unsigned char mask; |
| @@ -1854,11 +1847,11 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) · 1611 unmodified lines | |||
| 1854 | /* XXX - need to source or sink data here, as appropriate */ | 1847 | /* XXX - need to source or sink data here, as appropriate */ |
| 1855 | } | 1848 | } |
| 1856 | } else { | 1849 | } else { |
| 1857 | /* Break up transfer into 3 ms chunks, | 1850 | /* Transfer a small chunk so that the |
| 1858 | * presuming 6 accesses per handshake. | 1851 | * irq mode lock is not held too long. |
| 1859 | */ | 1852 | */ |
| 1860 | transfersize = min((unsigned long)cmd->SCp.this_residual, | 1853 | transfersize = min(cmd->SCp.this_residual, |
| 1861 | hostdata->accesses_per_ms / 2); | 1854 | NCR5380_PIO_CHUNK_SIZE); |
| 1862 | len = transfersize; | 1855 | len = transfersize; |
| 1863 | NCR5380_transfer_pio(instance, &phase, &len, | 1856 | NCR5380_transfer_pio(instance, &phase, &len, |
| 1864 | (unsigned char **)&cmd->SCp.ptr); | 1857 | (unsigned char **)&cmd->SCp.ptr); |
| @@ -250,6 +250,8 @@ struct NCR5380_cmd { · 249 unmodified lines | |||
| 250 | 250 | ||
| 251 | #define NCR5380_CMD_SIZE (sizeof(struct NCR5380_cmd)) | 251 | #define NCR5380_CMD_SIZE (sizeof(struct NCR5380_cmd)) |
| 252 | 252 | ||
| 253 | #define NCR5380_PIO_CHUNK_SIZE 256 | ||
| 254 | |||
| 253 | static inline struct scsi_cmnd *NCR5380_to_scmd(struct NCR5380_cmd *ncmd_ptr) | 255 | static inline struct scsi_cmnd *NCR5380_to_scmd(struct NCR5380_cmd *ncmd_ptr) |
| 254 | { | 256 | { |
| 255 | return ((struct scsi_cmnd *)ncmd_ptr) - 1; | 257 | return ((struct scsi_cmnd *)ncmd_ptr) - 1; |
| @@ -292,8 +294,14 @@ static void NCR5380_reselect(struct Scsi_Host *instance); · 36 unmodified lines | |||
| 292 | static struct scsi_cmnd *NCR5380_select(struct Scsi_Host *, struct scsi_cmnd *); | 294 | static struct scsi_cmnd *NCR5380_select(struct Scsi_Host *, struct scsi_cmnd *); |
| 293 | static int NCR5380_transfer_dma(struct Scsi_Host *instance, unsigned char *phase, int *count, unsigned char **data); | 295 | static int NCR5380_transfer_dma(struct Scsi_Host *instance, unsigned char *phase, int *count, unsigned char **data); |
| 294 | static int NCR5380_transfer_pio(struct Scsi_Host *instance, unsigned char *phase, int *count, unsigned char **data); | 296 | static int NCR5380_transfer_pio(struct Scsi_Host *instance, unsigned char *phase, int *count, unsigned char **data); |
| 295 | static int NCR5380_poll_politely(struct Scsi_Host *, int, int, int, int); | ||
| 296 | static int NCR5380_poll_politely2(struct Scsi_Host *, int, int, int, int, int, int, int); | 297 | static int NCR5380_poll_politely2(struct Scsi_Host *, int, int, int, int, int, int, int); |
| 297 | 298 | ||
| 299 | static inline int NCR5380_poll_politely(struct Scsi_Host *instance, | ||
| 300 | int reg, int bit, int val, int wait) | ||
| 301 | { | ||
| 302 | return NCR5380_poll_politely2(instance, reg, bit, val, | ||
| 303 | reg, bit, val, wait); | ||
| 304 | } | ||
| 305 | |||
| 298 | #endif /* __KERNEL__ */ | 306 | #endif /* __KERNEL__ */ |
| 299 | #endif /* NCR5380_H */ | 307 | #endif /* NCR5380_H */ |
| @@ -613,7 +613,7 @@ static int aac_src_restart_adapter(struct aac_dev *dev, int bled) · 612 unmodified lines | |||
| 613 | * @dev: Adapter | 613 | * @dev: Adapter |
| 614 | * @comm: communications method | 614 | * @comm: communications method |
| 615 | */ | 615 | */ |
| 616 | int aac_src_select_comm(struct aac_dev *dev, int comm) | 616 | static int aac_src_select_comm(struct aac_dev *dev, int comm) |
| 617 | { | 617 | { |
| 618 | switch (comm) { | 618 | switch (comm) { |
| 619 | case AAC_COMM_MESSAGE: | 619 | case AAC_COMM_MESSAGE: |
| @@ -632,7 +632,7 @@ int asd_init_hw(struct asd_ha_struct *asd_ha) · 631 unmodified lines | |||
| 632 | pci_name(asd_ha->pcidev)); | 632 | pci_name(asd_ha->pcidev)); |
| 633 | return err; | 633 | return err; |
| 634 | } | 634 | } |
| 635 | pci_write_config_dword(asd_ha->pcidev, PCIC_HSTPCIX_CNTRL, | 635 | err = pci_write_config_dword(asd_ha->pcidev, PCIC_HSTPCIX_CNTRL, |
| 636 | v | SC_TMR_DIS); | 636 | v | SC_TMR_DIS); |
| 637 | if (err) { | 637 | if (err) { |
| 638 | asd_printk("couldn't disable split completion timer of %s\n", | 638 | asd_printk("couldn't disable split completion timer of %s\n", |
| @@ -2388,15 +2388,23 @@ static int arcmsr_iop_message_xfer(struct AdapterControlBlock *acb, · 2387 unmodified lines | |||
| 2388 | } | 2388 | } |
| 2389 | case ARCMSR_MESSAGE_WRITE_WQBUFFER: { | 2389 | case ARCMSR_MESSAGE_WRITE_WQBUFFER: { |
| 2390 | unsigned char *ver_addr; | 2390 | unsigned char *ver_addr; |
| 2391 | int32_t user_len, cnt2end; | 2391 | uint32_t user_len; |
| 2392 | int32_t cnt2end; | ||
| 2392 | uint8_t *pQbuffer, *ptmpuserbuffer; | 2393 | uint8_t *pQbuffer, *ptmpuserbuffer; |
| 2394 | |||
| 2395 | user_len = pcmdmessagefld->cmdmessage.Length; | ||
| 2396 | if (user_len > ARCMSR_API_DATA_BUFLEN) { | ||
| 2397 | retvalue = ARCMSR_MESSAGE_FAIL; | ||
| 2398 | goto message_out; | ||
| 2399 | } | ||
| 2400 | |||
| 2393 | ver_addr = kmalloc(ARCMSR_API_DATA_BUFLEN, GFP_ATOMIC); | 2401 | ver_addr = kmalloc(ARCMSR_API_DATA_BUFLEN, GFP_ATOMIC); |
| 2394 | if (!ver_addr) { | 2402 | if (!ver_addr) { |
| 2395 | retvalue = ARCMSR_MESSAGE_FAIL; | 2403 | retvalue = ARCMSR_MESSAGE_FAIL; |
| 2396 | goto message_out; | 2404 | goto message_out; |
| 2397 | } | 2405 | } |
| 2398 | ptmpuserbuffer = ver_addr; | 2406 | ptmpuserbuffer = ver_addr; |
| 2399 | user_len = pcmdmessagefld->cmdmessage.Length; | 2407 | |
| 2400 | memcpy(ptmpuserbuffer, | 2408 | memcpy(ptmpuserbuffer, |
| 2401 | pcmdmessagefld->messagedatabuffer, user_len); | 2409 | pcmdmessagefld->messagedatabuffer, user_len); |
| 2402 | spin_lock_irqsave(&acb->wqbuffer_lock, flags); | 2410 | spin_lock_irqsave(&acb->wqbuffer_lock, flags); |
| @@ -1,5 +1,5 @@ | |||
| 1 | /** | 1 | /** |
| 2 | * Copyright (C) 2005 - 2015 Emulex | 2 | * Copyright (C) 2005 - 2016 Broadcom |
| 3 | * All rights reserved. | 3 | * All rights reserved. |
| 4 | * | 4 | * |
| 5 | * This program is free software; you can redistribute it and/or | 5 | * This program is free software; you can redistribute it and/or |
| @@ -8,7 +8,7 @@ · 2 unmodified lines | |||
| 8 | * Public License is included in this distribution in the file called COPYING. | 8 | * Public License is included in this distribution in the file called COPYING. |
| 9 | * | 9 | * |
| 10 | * Contact Information: | 10 | * Contact Information: |
| 11 | * linux-drivers@avagotech.com | 11 | * linux-drivers@broadcom.com |
| 12 | * | 12 | * |
| 13 | * Emulex | 13 | * Emulex |
| 14 | * 3333 Susan Street | 14 | * 3333 Susan Street |
| @@ -89,7 +89,7 @@ struct be_aic_obj { /* Adaptive interrupt coalescing (AIC) info */ · 74 unmodified lines | |||
| 89 | u32 max_eqd; /* in usecs */ | 89 | u32 max_eqd; /* in usecs */ |
| 90 | u32 prev_eqd; /* in usecs */ | 90 | u32 prev_eqd; /* in usecs */ |
| 91 | u32 et_eqd; /* configured val when aic is off */ | 91 | u32 et_eqd; /* configured val when aic is off */ |
| 92 | ulong jiffs; | 92 | ulong jiffies; |
| 93 | u64 eq_prev; /* Used to calculate eqe */ | 93 | u64 eq_prev; /* Used to calculate eqe */ |
| 94 | }; | 94 | }; |
| 95 | 95 | ||
| @@ -100,7 +100,7 @@ struct be_eq_obj { · 4 unmodified lines | |||
| 100 | struct be_queue_info q; | 100 | struct be_queue_info q; |
| 101 | struct beiscsi_hba *phba; | 101 | struct beiscsi_hba *phba; |
| 102 | struct be_queue_info *cq; | 102 | struct be_queue_info *cq; |
| 103 | struct work_struct work_cqs; /* Work Item */ | 103 | struct work_struct mcc_work; /* Work Item */ |
| 104 | struct irq_poll iopoll; | 104 | struct irq_poll iopoll; |
| 105 | }; | 105 | }; |
| 106 | 106 | ||
| @@ -111,8 +111,11 @@ struct be_mcc_obj { · 4 unmodified lines | |||
| 111 | 111 | ||
| 112 | struct beiscsi_mcc_tag_state { | 112 | struct beiscsi_mcc_tag_state { |
| 113 | unsigned long tag_state; | 113 | unsigned long tag_state; |
| 114 | #define MCC_TAG_STATE_RUNNING 1 | 114 | #define MCC_TAG_STATE_RUNNING 0 |
| 115 | #define MCC_TAG_STATE_TIMEOUT 2 | 115 | #define MCC_TAG_STATE_TIMEOUT 1 |
| 116 | #define MCC_TAG_STATE_ASYNC 2 | ||
| 117 | #define MCC_TAG_STATE_IGNORE 3 | ||
| 118 | void (*cbfn)(struct beiscsi_hba *, unsigned int); | ||
| 116 | struct be_dma_mem tag_mem_state; | 119 | struct be_dma_mem tag_mem_state; |
| 117 | }; | 120 | }; |
| 118 | 121 | ||
| @@ -1,5 +1,5 @@ | |||
| 1 | /** | 1 | /** |
| 2 | * Copyright (C) 2005 - 2015 Emulex | 2 | * Copyright (C) 2005 - 2016 Broadcom |
| 3 | * All rights reserved. | 3 | * All rights reserved. |
| 4 | * | 4 | * |
| 5 | * This program is free software; you can redistribute it and/or | 5 | * This program is free software; you can redistribute it and/or |
| @@ -8,7 +8,7 @@ · 2 unmodified lines | |||
| 8 | * Public License is included in this distribution in the file called COPYING. | 8 | * Public License is included in this distribution in the file called COPYING. |
| 9 | * | 9 | * |
| 10 | * Contact Information: | 10 | * Contact Information: |
| 11 | * linux-drivers@avagotech.com | 11 | * linux-drivers@broadcom.com |
| 12 | * | 12 | * |
| 13 | * Emulex | 13 | * Emulex |
| 14 | * 3333 Susan Street | 14 | * 3333 Susan Street |
| @@ -21,110 +21,77 @@ · 6 unmodified lines | |||
| 21 | #include "be.h" | 21 | #include "be.h" |
| 22 | #include "be_mgmt.h" | 22 | #include "be_mgmt.h" |
| 23 | 23 | ||
| 24 | int beiscsi_pci_soft_reset(struct beiscsi_hba *phba) | 24 | /* UE Status Low CSR */ |
| 25 | { | 25 | static const char * const desc_ue_status_low[] = { |
| 26 | u32 sreset; | 26 | "CEV", |
| 27 | u8 *pci_reset_offset = 0; | 27 | "CTX", |
| 28 | u8 *pci_online0_offset = 0; | 28 | "DBUF", |
| 29 | u8 *pci_online1_offset = 0; | 29 | "ERX", |
| 30 | u32 pconline0 = 0; | 30 | "Host", |
| 31 | u32 pconline1 = 0; | 31 | "MPU", |
| 32 | u32 i; | 32 | "NDMA", |
| 33 | 33 | "PTC ", | |
| 34 | pci_reset_offset = (u8 *)phba->pci_va + BE2_SOFT_RESET; | 34 | "RDMA ", |
| 35 | pci_online0_offset = (u8 *)phba->pci_va + BE2_PCI_ONLINE0; | 35 | "RXF ", |
| 36 | pci_online1_offset = (u8 *)phba->pci_va + BE2_PCI_ONLINE1; | 36 | "RXIPS ", |
| 37 | sreset = readl((void *)pci_reset_offset); | 37 | "RXULP0 ", |
| 38 | sreset |= BE2_SET_RESET; | 38 | "RXULP1 ", |
| 39 | writel(sreset, (void *)pci_reset_offset); | 39 | "RXULP2 ", |
| 40 | 40 | "TIM ", | |
| 41 | i = 0; | 41 | "TPOST ", |
| 42 | while (sreset & BE2_SET_RESET) { | 42 | "TPRE ", |
| 43 | if (i > 64) | 43 | "TXIPS ", |
| 44 | break; | 44 | "TXULP0 ", |
| 45 | msleep(100); | 45 | "TXULP1 ", |
| 46 | sreset = readl((void *)pci_reset_offset); | 46 | "UC ", |
| 47 | i++; | 47 | "WDMA ", |
| 48 | } | 48 | "TXULP2 ", |
| 49 | 49 | "HOST1 ", | |
| 50 | if (sreset & BE2_SET_RESET) { | 50 | "P0_OB_LINK ", |
| 51 | printk(KERN_ERR DRV_NAME | 51 | "P1_OB_LINK ", |
| 52 | " Soft Reset did not deassert\n"); | 52 | "HOST_GPIO ", |
| 53 | return -EIO; | 53 | "MBOX ", |
| 54 | } | 54 | "AXGMAC0", |
| 55 | pconline1 = BE2_MPU_IRAM_ONLINE; | 55 | "AXGMAC1", |
| 56 | writel(pconline0, (void *)pci_online0_offset); | 56 | "JTAG", |
| 57 | writel(pconline1, (void *)pci_online1_offset); | 57 | "MPU_INTPEND" |
| 58 | 58 | }; | |
| 59 | sreset |= BE2_SET_RESET; | ||
| 60 | writel(sreset, (void *)pci_reset_offset); | ||
| 61 | |||
| 62 | i = 0; | ||
| 63 | while (sreset & BE2_SET_RESET) { | ||
| 64 | if (i > 64) | ||
| 65 | break; | ||
| 66 | msleep(1); | ||
| 67 | sreset = readl((void *)pci_reset_offset); | ||
| 68 | i++; | ||
| 69 | } | ||
| 70 | if (sreset & BE2_SET_RESET) { | ||
| 71 | printk(KERN_ERR DRV_NAME | ||
| 72 | " MPU Online Soft Reset did not deassert\n"); | ||
| 73 | return -EIO; | ||
| 74 | } | ||
| 75 | return 0; | ||
| 76 | } | ||
| 77 | |||
| 78 | int be_chk_reset_complete(struct beiscsi_hba *phba) | ||
| 79 | { | ||
| 80 | unsigned int num_loop; | ||
| 81 | u8 *mpu_sem = 0; | ||
| 82 | u32 status; | ||
| 83 | |||
| 84 | num_loop = 1000; | ||
| 85 | mpu_sem = (u8 *)phba->csr_va + MPU_EP_SEMAPHORE; | ||
| 86 | msleep(5000); | ||
| 87 | |||
| 88 | while (num_loop) { | ||
| 89 | status = readl((void *)mpu_sem); | ||
| 90 | |||
| 91 | if ((status & 0x80000000) || (status & 0x0000FFFF) == 0xC000) | ||
| 92 | break; | ||
| 93 | msleep(60); | ||
| 94 | num_loop--; | ||
| 95 | } | ||
| 96 | |||
| 97 | if ((status & 0x80000000) || (!num_loop)) { | ||
| 98 | beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, | ||
| 99 | "BC_%d : Failed in be_chk_reset_complete" | ||
| 100 | "status = 0x%x\n", status); | ||
| 101 | return -EIO; | ||
| 102 | } | ||
| 103 | |||
| 104 | return 0; | ||
| 105 | } | ||
| 106 | |||
| 107 | unsigned int alloc_mcc_tag(struct beiscsi_hba *phba) | ||
| 108 | { | ||
| 109 | unsigned int tag = 0; | ||
| 110 | 59 | ||
| 111 | spin_lock(&phba->ctrl.mcc_lock); | 60 | /* UE Status High CSR */ |
| 112 | if (phba->ctrl.mcc_tag_available) { | 61 | static const char * const desc_ue_status_hi[] = { |
| 113 | tag = phba->ctrl.mcc_tag[phba->ctrl.mcc_alloc_index]; | 62 | "LPCMEMHOST", |
| 114 | phba->ctrl.mcc_tag[phba->ctrl.mcc_alloc_index] = 0; | 63 | "MGMT_MAC", |
| 115 | phba->ctrl.mcc_tag_status[tag] = 0; | 64 | "PCS0ONLINE", |
| 116 | phba->ctrl.ptag_state[tag].tag_state = 0; | 65 | "MPU_IRAM", |
| 117 | } | 66 | "PCS1ONLINE", |
| 118 | if (tag) { | 67 | "PCTL0", |
| 119 | phba->ctrl.mcc_tag_available--; | 68 | "PCTL1", |
| 120 | if (phba->ctrl.mcc_alloc_index == (MAX_MCC_CMD - 1)) | 69 | "PMEM", |
| 121 | phba->ctrl.mcc_alloc_index = 0; | 70 | "RR", |
| 122 | else | 71 | "TXPB", |
| 123 | phba->ctrl.mcc_alloc_index++; | 72 | "RXPP", |
| 124 | } | 73 | "XAUI", |
| 125 | spin_unlock(&phba->ctrl.mcc_lock); | 74 | "TXP", |
| 126 | return tag; | 75 | "ARM", |
| 127 | } | 76 | "IPC", |
| 77 | "HOST2", | ||
| 78 | "HOST3", | ||
| 79 | "HOST4", | ||
| 80 | "HOST5", | ||
| 81 | "HOST6", | ||
| 82 | "HOST7", | ||
| 83 | "HOST8", | ||
| 84 | "HOST9", | ||
| 85 | "NETC", | ||
| 86 | "Unknown", | ||
| 87 | "Unknown", | ||
| 88 | "Unknown", | ||
| 89 | "Unknown", | ||
| 90 | "Unknown", | ||
| 91 | "Unknown", | ||
| 92 | "Unknown", | ||
| 93 | "Unknown" | ||
| 94 | }; | ||
| 128 | 95 | ||
| 129 | struct be_mcc_wrb *alloc_mcc_wrb(struct beiscsi_hba *phba, | 96 | struct be_mcc_wrb *alloc_mcc_wrb(struct beiscsi_hba *phba, |
| 130 | unsigned int *ref_tag) | 97 | unsigned int *ref_tag) |
| @@ -133,7 +100,7 @@ struct be_mcc_wrb *alloc_mcc_wrb(struct beiscsi_hba *phba, · 2 unmodified lines | |||
| 133 | struct be_mcc_wrb *wrb = NULL; | 100 | struct be_mcc_wrb *wrb = NULL; |
| 134 | unsigned int tag; | 101 | unsigned int tag; |
| 135 | 102 | ||
| 136 | spin_lock_bh(&phba->ctrl.mcc_lock); | 103 | spin_lock(&phba->ctrl.mcc_lock); |
| 137 | if (mccq->used == mccq->len) { | 104 | if (mccq->used == mccq->len) { |
| 138 | beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT | | 105 | beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT | |
| 139 | BEISCSI_LOG_CONFIG | BEISCSI_LOG_MBOX, | 106 | BEISCSI_LOG_CONFIG | BEISCSI_LOG_MBOX, |
| @@ -160,6 +127,7 @@ struct be_mcc_wrb *alloc_mcc_wrb(struct beiscsi_hba *phba, · 20 unmodified lines | |||
| 160 | phba->ctrl.mcc_tag[phba->ctrl.mcc_alloc_index] = 0; | 127 | phba->ctrl.mcc_tag[phba->ctrl.mcc_alloc_index] = 0; |
| 161 | phba->ctrl.mcc_tag_status[tag] = 0; | 128 | phba->ctrl.mcc_tag_status[tag] = 0; |
| 162 | phba->ctrl.ptag_state[tag].tag_state = 0; | 129 | phba->ctrl.ptag_state[tag].tag_state = 0; |
| 130 | phba->ctrl.ptag_state[tag].cbfn = NULL; | ||
| 163 | phba->ctrl.mcc_tag_available--; | 131 | phba->ctrl.mcc_tag_available--; |
| 164 | if (phba->ctrl.mcc_alloc_index == (MAX_MCC_CMD - 1)) | 132 | if (phba->ctrl.mcc_alloc_index == (MAX_MCC_CMD - 1)) |
| 165 | phba->ctrl.mcc_alloc_index = 0; | 133 | phba->ctrl.mcc_alloc_index = 0; |
| @@ -174,7 +142,7 @@ struct be_mcc_wrb *alloc_mcc_wrb(struct beiscsi_hba *phba, · 8 unmodified lines | |||
| 174 | mccq->used++; | 142 | mccq->used++; |
| 175 | 143 | ||
| 176 | alloc_failed: | 144 | alloc_failed: |
| 177 | spin_unlock_bh(&phba->ctrl.mcc_lock); | 145 | spin_unlock(&phba->ctrl.mcc_lock); |
| 178 | return wrb; | 146 | return wrb; |
| 179 | } | 147 | } |
| 180 | 148 | ||
| @@ -182,7 +150,7 @@ void free_mcc_wrb(struct be_ctrl_info *ctrl, unsigned int tag) · 1 unmodified line | |||
| 182 | { | 150 | { |
| 183 | struct be_queue_info *mccq = &ctrl->mcc_obj.q; | 151 | struct be_queue_info *mccq = &ctrl->mcc_obj.q; |
| 184 | 152 | ||
| 185 | spin_lock_bh(&ctrl->mcc_lock); | 153 | spin_lock(&ctrl->mcc_lock); |
| 186 | tag = tag & MCC_Q_CMD_TAG_MASK; | 154 | tag = tag & MCC_Q_CMD_TAG_MASK; |
| 187 | ctrl->mcc_tag[ctrl->mcc_free_index] = tag; | 155 | ctrl->mcc_tag[ctrl->mcc_free_index] = tag; |
| 188 | if (ctrl->mcc_free_index == (MAX_MCC_CMD - 1)) | 156 | if (ctrl->mcc_free_index == (MAX_MCC_CMD - 1)) |
| @@ -191,16 +159,71 @@ void free_mcc_wrb(struct be_ctrl_info *ctrl, unsigned int tag) · 2 unmodified lines | |||
| 191 | ctrl->mcc_free_index++; | 159 | ctrl->mcc_free_index++; |
| 192 | ctrl->mcc_tag_available++; | 160 | ctrl->mcc_tag_available++; |
| 193 | mccq->used--; | 161 | mccq->used--; |
| 194 | spin_unlock_bh(&ctrl->mcc_lock); | 162 | spin_unlock(&ctrl->mcc_lock); |
| 195 | } | 163 | } |
| 196 | 164 | ||
| 197 | /** | 165 | /* |
| 198 | * beiscsi_fail_session(): Closing session with appropriate error | 166 | * beiscsi_mcc_compl_status - Return the status of MCC completion |
| 199 | * @cls_session: ptr to session | 167 | * @phba: Driver private structure |
| 200 | **/ | 168 | * @tag: Tag for the MBX Command |
| 201 | void beiscsi_fail_session(struct iscsi_cls_session *cls_session) | 169 | * @wrb: the WRB used for the MBX Command |
| 170 | * @mbx_cmd_mem: ptr to memory allocated for MBX Cmd | ||
| 171 | * | ||
| 172 | * return | ||
| 173 | * Success: 0 | ||
| 174 | * Failure: Non-Zero | ||
| 175 | */ | ||
| 176 | int __beiscsi_mcc_compl_status(struct beiscsi_hba *phba, | ||
| 177 | unsigned int tag, | ||
| 178 | struct be_mcc_wrb **wrb, | ||
| 179 | struct be_dma_mem *mbx_cmd_mem) | ||
| 202 | { | 180 | { |
| 203 | iscsi_session_failure(cls_session->dd_data, ISCSI_ERR_CONN_FAILED); | 181 | struct be_queue_info *mccq = &phba->ctrl.mcc_obj.q; |
| 182 | uint16_t status = 0, addl_status = 0, wrb_num = 0; | ||
| 183 | struct be_cmd_resp_hdr *mbx_resp_hdr; | ||
| 184 | struct be_cmd_req_hdr *mbx_hdr; | ||
| 185 | struct be_mcc_wrb *temp_wrb; | ||
| 186 | uint32_t mcc_tag_status; | ||
| 187 | int rc = 0; | ||
| 188 | |||
| 189 | mcc_tag_status = phba->ctrl.mcc_tag_status[tag]; | ||
| 190 | status = (mcc_tag_status & CQE_STATUS_MASK); | ||
| 191 | addl_status = ((mcc_tag_status & CQE_STATUS_ADDL_MASK) >> | ||
| 192 | CQE_STATUS_ADDL_SHIFT); | ||
| 193 | |||
| 194 | if (mbx_cmd_mem) { | ||
| 195 | mbx_hdr = (struct be_cmd_req_hdr *)mbx_cmd_mem->va; | ||
| 196 | } else { | ||
| 197 | wrb_num = (mcc_tag_status & CQE_STATUS_WRB_MASK) >> | ||
| 198 | CQE_STATUS_WRB_SHIFT; | ||
| 199 | temp_wrb = (struct be_mcc_wrb *)queue_get_wrb(mccq, wrb_num); | ||
| 200 | mbx_hdr = embedded_payload(temp_wrb); | ||
| 201 | |||
| 202 | if (wrb) | ||
| 203 | *wrb = temp_wrb; | ||
| 204 | } | ||
| 205 | |||
| 206 | if (status || addl_status) { | ||
| 207 | beiscsi_log(phba, KERN_WARNING, | ||
| 208 | BEISCSI_LOG_INIT | BEISCSI_LOG_EH | | ||
| 209 | BEISCSI_LOG_CONFIG, | ||
| 210 | "BC_%d : MBX Cmd Failed for Subsys : %d Opcode : %d with Status : %d and Extd_Status : %d\n", | ||
| 211 | mbx_hdr->subsystem, mbx_hdr->opcode, | ||
| 212 | status, addl_status); | ||
| 213 | rc = -EIO; | ||
| 214 | if (status == MCC_STATUS_INSUFFICIENT_BUFFER) { | ||
| 215 | mbx_resp_hdr = (struct be_cmd_resp_hdr *)mbx_hdr; | ||
| 216 | beiscsi_log(phba, KERN_WARNING, | ||
| 217 | BEISCSI_LOG_INIT | BEISCSI_LOG_EH | | ||
| 218 | BEISCSI_LOG_CONFIG, | ||
| 219 | "BC_%d : Insufficient Buffer Error Resp_Len : %d Actual_Resp_Len : %d\n", | ||
| 220 | mbx_resp_hdr->response_length, | ||
| 221 | mbx_resp_hdr->actual_resp_len); | ||
| 222 | rc = -EAGAIN; | ||
| 223 | } | ||
| 224 | } | ||
| 225 | |||
| 226 | return rc; | ||
| 204 | } | 227 | } |
| 205 | 228 | ||
| 206 | /* | 229 | /* |
| @@ -217,26 +240,34 @@ void beiscsi_fail_session(struct iscsi_cls_session *cls_session) · 10 unmodified lines | |||
| 217 | * Failure: Non-Zero | 240 | * Failure: Non-Zero |
| 218 | **/ | 241 | **/ |
| 219 | int beiscsi_mccq_compl_wait(struct beiscsi_hba *phba, | 242 | int beiscsi_mccq_compl_wait(struct beiscsi_hba *phba, |
| 220 | uint32_t tag, struct be_mcc_wrb **wrb, | 243 | unsigned int tag, |
| 244 | struct be_mcc_wrb **wrb, | ||
| 221 | struct be_dma_mem *mbx_cmd_mem) | 245 | struct be_dma_mem *mbx_cmd_mem) |
| 222 | { | 246 | { |
| 223 | int rc = 0; | 247 | int rc = 0; |
| 224 | uint32_t mcc_tag_status; | ||
| 225 | uint16_t status = 0, addl_status = 0, wrb_num = 0; | ||
| 226 | struct be_mcc_wrb *temp_wrb; | ||
| 227 | struct be_cmd_req_hdr *mbx_hdr; | ||
| 228 | struct be_cmd_resp_hdr *mbx_resp_hdr; | ||
| 229 | struct be_queue_info *mccq = &phba->ctrl.mcc_obj.q; | ||
| 230 | 248 | ||
| 231 | if (beiscsi_error(phba)) | 249 | if (beiscsi_hba_in_error(phba)) { |
| 232 | return -EPERM; | 250 | clear_bit(MCC_TAG_STATE_RUNNING, |
| 251 | &phba->ctrl.ptag_state[tag].tag_state); | ||
| 252 | return -EIO; | ||
| 253 | } | ||
| 233 | 254 | ||
| 234 | /* wait for the mccq completion */ | 255 | /* wait for the mccq completion */ |
| 235 | rc = wait_event_interruptible_timeout( | 256 | rc = wait_event_interruptible_timeout(phba->ctrl.mcc_wait[tag], |
| 236 | phba->ctrl.mcc_wait[tag], | 257 | phba->ctrl.mcc_tag_status[tag], |
| 237 | phba->ctrl.mcc_tag_status[tag], | 258 | msecs_to_jiffies( |
| 238 | msecs_to_jiffies( | 259 | BEISCSI_HOST_MBX_TIMEOUT)); |
| 239 | BEISCSI_HOST_MBX_TIMEOUT)); | 260 | /** |
| 261 | * Return EIO if port is being disabled. Associated DMA memory, if any, | ||
| 262 | * is freed by the caller. When port goes offline, MCCQ is cleaned up | ||
| 263 | * so does WRB. | ||
| 264 | */ | ||
| 265 | if (!test_bit(BEISCSI_HBA_ONLINE, &phba->state)) { | ||
| 266 | clear_bit(MCC_TAG_STATE_RUNNING, | ||
| 267 | &phba->ctrl.ptag_state[tag].tag_state); | ||
| 268 | return -EIO; | ||
| 269 | } | ||
| 270 | |||
| 240 | /** | 271 | /** |
| 241 | * If MBOX cmd timeout expired, tag and resource allocated | 272 | * If MBOX cmd timeout expired, tag and resource allocated |
| 242 | * for cmd is not freed until FW returns completion. | 273 | * for cmd is not freed until FW returns completion. |
| @@ -270,47 +301,7 @@ int beiscsi_mccq_compl_wait(struct beiscsi_hba *phba, · 27 unmodified lines | |||
| 270 | return -EBUSY; | 301 | return -EBUSY; |
| 271 | } | 302 | } |
| 272 | 303 | ||
| 273 | rc = 0; | 304 | rc = __beiscsi_mcc_compl_status(phba, tag, wrb, mbx_cmd_mem); |
| 274 | mcc_tag_status = phba->ctrl.mcc_tag_status[tag]; | ||
| 275 | status = (mcc_tag_status & CQE_STATUS_MASK); | ||
| 276 | addl_status = ((mcc_tag_status & CQE_STATUS_ADDL_MASK) >> | ||
| 277 | CQE_STATUS_ADDL_SHIFT); | ||
| 278 | |||
| 279 | if (mbx_cmd_mem) { | ||
| 280 | mbx_hdr = (struct be_cmd_req_hdr *)mbx_cmd_mem->va; | ||
| 281 | } else { | ||
| 282 | wrb_num = (mcc_tag_status & CQE_STATUS_WRB_MASK) >> | ||
| 283 | CQE_STATUS_WRB_SHIFT; | ||
| 284 | temp_wrb = (struct be_mcc_wrb *)queue_get_wrb(mccq, wrb_num); | ||
| 285 | mbx_hdr = embedded_payload(temp_wrb); | ||
| 286 | |||
| 287 | if (wrb) | ||
| 288 | *wrb = temp_wrb; | ||
| 289 | } | ||
| 290 | |||
| 291 | if (status || addl_status) { | ||
| 292 | beiscsi_log(phba, KERN_WARNING, | ||
| 293 | BEISCSI_LOG_INIT | BEISCSI_LOG_EH | | ||
| 294 | BEISCSI_LOG_CONFIG, | ||
| 295 | "BC_%d : MBX Cmd Failed for " | ||
| 296 | "Subsys : %d Opcode : %d with " | ||
| 297 | "Status : %d and Extd_Status : %d\n", | ||
| 298 | mbx_hdr->subsystem, | ||
| 299 | mbx_hdr->opcode, | ||
| 300 | status, addl_status); | ||
| 301 | rc = -EIO; | ||
| 302 | if (status == MCC_STATUS_INSUFFICIENT_BUFFER) { | ||
| 303 | mbx_resp_hdr = (struct be_cmd_resp_hdr *) mbx_hdr; | ||
| 304 | beiscsi_log(phba, KERN_WARNING, | ||
| 305 | BEISCSI_LOG_INIT | BEISCSI_LOG_EH | | ||
| 306 | BEISCSI_LOG_CONFIG, | ||
| 307 | "BC_%d : Insufficient Buffer Error " | ||
| 308 | "Resp_Len : %d Actual_Resp_Len : %d\n", | ||
| 309 | mbx_resp_hdr->response_length, | ||
| 310 | mbx_resp_hdr->actual_resp_len); | ||
| 311 | rc = -EAGAIN; | ||
| 312 | } | ||
| 313 | } | ||
| 314 | 305 | ||
| 315 | free_mcc_wrb(&phba->ctrl, tag); | 306 | free_mcc_wrb(&phba->ctrl, tag); |
| 316 | return rc; | 307 | return rc; |
| @@ -330,11 +321,10 @@ int beiscsi_mccq_compl_wait(struct beiscsi_hba *phba, · 13 unmodified lines | |||
| 330 | static int beiscsi_process_mbox_compl(struct be_ctrl_info *ctrl, | 321 | static int beiscsi_process_mbox_compl(struct be_ctrl_info *ctrl, |
| 331 | struct be_mcc_compl *compl) | 322 | struct be_mcc_compl *compl) |
| 332 | { | 323 | { |
| 333 | u16 compl_status, extd_status; | ||
| 334 | struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem); | 324 | struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem); |
| 335 | struct beiscsi_hba *phba = pci_get_drvdata(ctrl->pdev); | 325 | struct beiscsi_hba *phba = pci_get_drvdata(ctrl->pdev); |
| 336 | struct be_cmd_req_hdr *hdr = embedded_payload(wrb); | 326 | struct be_cmd_req_hdr *hdr = embedded_payload(wrb); |
| 337 | struct be_cmd_resp_hdr *resp_hdr; | 327 | u16 compl_status, extd_status; |
| 338 | 328 | ||
| 339 | /** | 329 | /** |
| 340 | * To check if valid bit is set, check the entire word as we don't know | 330 | * To check if valid bit is set, check the entire word as we don't know |
| @@ -368,14 +358,7 @@ static int beiscsi_process_mbox_compl(struct be_ctrl_info *ctrl, · 27 unmodified lines | |||
| 368 | beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG | BEISCSI_LOG_MBOX, | 358 | beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG | BEISCSI_LOG_MBOX, |
| 369 | "BC_%d : error in cmd completion: Subsystem : %d Opcode : %d status(compl/extd)=%d/%d\n", | 359 | "BC_%d : error in cmd completion: Subsystem : %d Opcode : %d status(compl/extd)=%d/%d\n", |
| 370 | hdr->subsystem, hdr->opcode, compl_status, extd_status); | 360 | hdr->subsystem, hdr->opcode, compl_status, extd_status); |
| 371 | 361 | return compl_status; | |
| 372 | if (compl_status == MCC_STATUS_INSUFFICIENT_BUFFER) { | ||
| 373 | /* if status is insufficient buffer, check the length */ | ||
| 374 | resp_hdr = (struct be_cmd_resp_hdr *) hdr; | ||
| 375 | if (resp_hdr->response_length) | ||
| 376 | return 0; | ||
| 377 | } | ||
| 378 | return -EINVAL; | ||
| 379 | } | 362 | } |
| 380 | 363 | ||
| 381 | static void beiscsi_process_async_link(struct beiscsi_hba *phba, | 364 | static void beiscsi_process_async_link(struct beiscsi_hba *phba, |
| @@ -391,18 +374,19 @@ static void beiscsi_process_async_link(struct beiscsi_hba *phba, · 9 unmodified lines | |||
| 391 | * This has been newly introduced in SKH-R Firmware 10.0.338.45. | 374 | * This has been newly introduced in SKH-R Firmware 10.0.338.45. |
| 392 | **/ | 375 | **/ |
| 393 | if (evt->port_link_status & BE_ASYNC_LINK_UP_MASK) { | 376 | if (evt->port_link_status & BE_ASYNC_LINK_UP_MASK) { |
| 394 | phba->state = BE_ADAPTER_LINK_UP | BE_ADAPTER_CHECK_BOOT; | 377 | set_bit(BEISCSI_HBA_LINK_UP, &phba->state); |
| 395 | phba->get_boot = BE_GET_BOOT_RETRIES; | 378 | if (test_bit(BEISCSI_HBA_BOOT_FOUND, &phba->state)) |
| 379 | beiscsi_start_boot_work(phba, BE_BOOT_INVALID_SHANDLE); | ||
| 396 | __beiscsi_log(phba, KERN_ERR, | 380 | __beiscsi_log(phba, KERN_ERR, |
| 397 | "BC_%d : Link Up on Port %d tag 0x%x\n", | 381 | "BC_%d : Link Up on Port %d tag 0x%x\n", |
| 398 | evt->physical_port, evt->event_tag); | 382 | evt->physical_port, evt->event_tag); |
| 399 | } else { | 383 | } else { |
| 400 | phba->state = BE_ADAPTER_LINK_DOWN; | 384 | clear_bit(BEISCSI_HBA_LINK_UP, &phba->state); |
| 401 | __beiscsi_log(phba, KERN_ERR, | 385 | __beiscsi_log(phba, KERN_ERR, |
| 402 | "BC_%d : Link Down on Port %d tag 0x%x\n", | 386 | "BC_%d : Link Down on Port %d tag 0x%x\n", |
| 403 | evt->physical_port, evt->event_tag); | 387 | evt->physical_port, evt->event_tag); |
| 404 | iscsi_host_for_each_session(phba->shost, | 388 | iscsi_host_for_each_session(phba->shost, |
| 405 | beiscsi_fail_session); | 389 | beiscsi_session_fail); |
| 406 | } | 390 | } |
| 407 | } | 391 | } |
| 408 | 392 | ||
| @@ -482,8 +466,8 @@ void beiscsi_process_async_event(struct beiscsi_hba *phba, · 73 unmodified lines | |||
| 482 | beiscsi_process_async_link(phba, compl); | 466 | beiscsi_process_async_link(phba, compl); |
| 483 | break; | 467 | break; |
| 484 | case ASYNC_EVENT_CODE_ISCSI: | 468 | case ASYNC_EVENT_CODE_ISCSI: |
| 485 | phba->state |= BE_ADAPTER_CHECK_BOOT; | 469 | if (test_bit(BEISCSI_HBA_BOOT_FOUND, &phba->state)) |
| 486 | phba->get_boot = BE_GET_BOOT_RETRIES; | 470 | beiscsi_start_boot_work(phba, BE_BOOT_INVALID_SHANDLE); |
| 487 | sev = KERN_ERR; | 471 | sev = KERN_ERR; |
| 488 | break; | 472 | break; |
| 489 | case ASYNC_EVENT_CODE_SLI: | 473 | case ASYNC_EVENT_CODE_SLI: |
| @@ -519,6 +503,9 @@ int beiscsi_process_mcc_compl(struct be_ctrl_info *ctrl, · 29 unmodified lines | |||
| 519 | return 0; | 503 | return 0; |
| 520 | } | 504 | } |
| 521 | 505 | ||
| 506 | /* end MCC with this tag */ | ||
| 507 | clear_bit(MCC_TAG_STATE_RUNNING, &ctrl->ptag_state[tag].tag_state); | ||
| 508 | |||
| 522 | if (test_bit(MCC_TAG_STATE_TIMEOUT, &ctrl->ptag_state[tag].tag_state)) { | 509 | if (test_bit(MCC_TAG_STATE_TIMEOUT, &ctrl->ptag_state[tag].tag_state)) { |
| 523 | beiscsi_log(phba, KERN_WARNING, | 510 | beiscsi_log(phba, KERN_WARNING, |
| 524 | BEISCSI_LOG_MBOX | BEISCSI_LOG_INIT | | 511 | BEISCSI_LOG_MBOX | BEISCSI_LOG_INIT | |
| @@ -529,9 +516,11 @@ int beiscsi_process_mcc_compl(struct be_ctrl_info *ctrl, · 4 unmodified lines | |||
| 529 | * Only for non-embedded cmd, PCI resource is allocated. | 516 | * Only for non-embedded cmd, PCI resource is allocated. |
| 530 | **/ | 517 | **/ |
| 531 | tag_mem = &ctrl->ptag_state[tag].tag_mem_state; | 518 | tag_mem = &ctrl->ptag_state[tag].tag_mem_state; |
| 532 | if (tag_mem->size) | 519 | if (tag_mem->size) { |
| 533 | pci_free_consistent(ctrl->pdev, tag_mem->size, | 520 | pci_free_consistent(ctrl->pdev, tag_mem->size, |
| 534 | tag_mem->va, tag_mem->dma); | 521 | tag_mem->va, tag_mem->dma); |
| 522 | tag_mem->size = 0; | ||
| 523 | } | ||
| 535 | free_mcc_wrb(ctrl, tag); | 524 | free_mcc_wrb(ctrl, tag); |
| 536 | return 0; | 525 | return 0; |
| 537 | } | 526 | } |
| @@ -550,57 +539,25 @@ int beiscsi_process_mcc_compl(struct be_ctrl_info *ctrl, · 12 unmodified lines | |||
| 550 | CQE_STATUS_ADDL_MASK; | 539 | CQE_STATUS_ADDL_MASK; |
| 551 | ctrl->mcc_tag_status[tag] |= (compl_status & CQE_STATUS_MASK); | 540 | ctrl->mcc_tag_status[tag] |= (compl_status & CQE_STATUS_MASK); |
| 552 | 541 | ||
| 553 | /* write ordering forced in wake_up_interruptible */ | 542 | if (test_bit(MCC_TAG_STATE_ASYNC, &ctrl->ptag_state[tag].tag_state)) { |
| 554 | clear_bit(MCC_TAG_STATE_RUNNING, &ctrl->ptag_state[tag].tag_state); | 543 | if (ctrl->ptag_state[tag].cbfn) |
| 555 | wake_up_interruptible(&ctrl->mcc_wait[tag]); | 544 | ctrl->ptag_state[tag].cbfn(phba, tag); |
| 556 | return 0; | 545 | else |
| 557 | } | 546 | __beiscsi_log(phba, KERN_ERR, |
| 558 | 547 | "BC_%d : MBX ASYNC command with no callback\n"); | |
| 559 | /* | 548 | free_mcc_wrb(ctrl, tag); |
| 560 | * be_mcc_compl_poll()- Wait for MBX completion | ||
| 561 | * @phba: driver private structure | ||
| 562 | * | ||
| 563 | * Wait till no more pending mcc requests are present | ||
| 564 | * | ||
| 565 | * return | ||
| 566 | * Success: 0 | ||
| 567 | * Failure: Non-Zero | ||
| 568 | * | ||
| 569 | **/ | ||
| 570 | int be_mcc_compl_poll(struct beiscsi_hba *phba, unsigned int tag) | ||
| 571 | { | ||
| 572 | struct be_ctrl_info *ctrl = &phba->ctrl; | ||
| 573 | int i; | ||
| 574 | |||
| 575 | if (!test_bit(MCC_TAG_STATE_RUNNING, | ||
| 576 | &ctrl->ptag_state[tag].tag_state)) { | ||
| 577 | beiscsi_log(phba, KERN_ERR, | ||
| 578 | BEISCSI_LOG_CONFIG | BEISCSI_LOG_MBOX, | ||
| 579 | "BC_%d: tag %u state not running\n", tag); | ||
| 580 | return 0; | 549 | return 0; |
| 581 | } | 550 | } |
| 582 | for (i = 0; i < mcc_timeout; i++) { | ||
| 583 | if (beiscsi_error(phba)) | ||
| 584 | return -EIO; | ||
| 585 | 551 | ||
| 586 | beiscsi_process_mcc_cq(phba); | 552 | if (test_bit(MCC_TAG_STATE_IGNORE, &ctrl->ptag_state[tag].tag_state)) { |
| 587 | /* after polling, wrb and tag need to be released */ | 553 | /* just check completion status and free wrb */ |
| 588 | if (!test_bit(MCC_TAG_STATE_RUNNING, | 554 | __beiscsi_mcc_compl_status(phba, tag, NULL, NULL); |
| 589 | &ctrl->ptag_state[tag].tag_state)) { | 555 | free_mcc_wrb(ctrl, tag); |
| 590 | free_mcc_wrb(ctrl, tag); | ||
| 591 | break; | ||
| 592 | } | ||
| 593 | udelay(100); | ||
| 594 | } | ||
| 595 | |||
| 596 | if (i < mcc_timeout) | ||
| 597 | return 0; | 556 | return 0; |
| 557 | } | ||
| 598 | 558 | ||
| 599 | beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG | BEISCSI_LOG_MBOX, | 559 | wake_up_interruptible(&ctrl->mcc_wait[tag]); |
| 600 | "BC_%d : FW Timed Out\n"); | 560 | return 0; |
| 601 | phba->fw_timeout = true; | ||
| 602 | beiscsi_ue_detect(phba); | ||
| 603 | return -EBUSY; | ||
| 604 | } | 561 | } |
| 605 | 562 | ||
| 606 | void be_mcc_notify(struct beiscsi_hba *phba, unsigned int tag) | 563 | void be_mcc_notify(struct beiscsi_hba *phba, unsigned int tag) |
| @@ -642,7 +599,7 @@ static int be_mbox_db_ready_poll(struct be_ctrl_info *ctrl) · 35 unmodified lines | |||
| 642 | */ | 599 | */ |
| 643 | timeout = jiffies + msecs_to_jiffies(BEISCSI_MBX_RDY_BIT_TIMEOUT); | 600 | timeout = jiffies + msecs_to_jiffies(BEISCSI_MBX_RDY_BIT_TIMEOUT); |
| 644 | do { | 601 | do { |
| 645 | if (beiscsi_error(phba)) | 602 | if (beiscsi_hba_in_error(phba)) |
| 646 | return -EIO; | 603 | return -EIO; |
| 647 | 604 | ||
| 648 | ready = ioread32(db); | 605 | ready = ioread32(db); |
| @@ -655,16 +612,14 @@ static int be_mbox_db_ready_poll(struct be_ctrl_info *ctrl) · 6 unmodified lines | |||
| 655 | 612 | ||
| 656 | if (time_after(jiffies, timeout)) | 613 | if (time_after(jiffies, timeout)) |
| 657 | break; | 614 | break; |
| 658 | msleep(20); | 615 | /* 1ms sleep is enough in most cases */ |
| 616 | schedule_timeout_uninterruptible(msecs_to_jiffies(1)); | ||
| 659 | } while (!ready); | 617 | } while (!ready); |
| 660 | 618 | ||
| 661 | beiscsi_log(phba, KERN_ERR, | 619 | beiscsi_log(phba, KERN_ERR, |
| 662 | BEISCSI_LOG_CONFIG | BEISCSI_LOG_MBOX, | 620 | BEISCSI_LOG_CONFIG | BEISCSI_LOG_MBOX, |
| 663 | "BC_%d : FW Timed Out\n"); | 621 | "BC_%d : FW Timed Out\n"); |
| 664 | 622 | set_bit(BEISCSI_HBA_FW_TIMEOUT, &phba->state); | |
| 665 | phba->fw_timeout = true; | ||
| 666 | beiscsi_ue_detect(phba); | ||
| 667 | |||
| 668 | return -EBUSY; | 623 | return -EBUSY; |
| 669 | } | 624 | } |
| 670 | 625 | ||
| @@ -679,7 +634,7 @@ static int be_mbox_db_ready_poll(struct be_ctrl_info *ctrl) · 8 unmodified lines | |||
| 679 | * Success: 0 | 634 | * Success: 0 |
| 680 | * Failure: Non-Zero | 635 | * Failure: Non-Zero |
| 681 | **/ | 636 | **/ |
| 682 | int be_mbox_notify(struct be_ctrl_info *ctrl) | 637 | static int be_mbox_notify(struct be_ctrl_info *ctrl) |
| 683 | { | 638 | { |
| 684 | int status; | 639 | int status; |
| 685 | u32 val = 0; | 640 | u32 val = 0; |
| @@ -819,87 +774,6 @@ int beiscsi_cmd_eq_create(struct be_ctrl_info *ctrl, · 133 unmodified lines | |||
| 819 | return status; | 774 | return status; |
| 820 | } | 775 | } |
| 821 | 776 | ||
| 822 | /** | ||
| 823 | * be_cmd_fw_initialize()- Initialize FW | ||
| 824 | * @ctrl: Pointer to function control structure | ||
| 825 | * | ||
| 826 | * Send FW initialize pattern for the function. | ||
| 827 | * | ||
| 828 | * return | ||
| 829 | * Success: 0 | ||
| 830 | * Failure: Non-Zero value | ||
| 831 | **/ | ||
| 832 | int be_cmd_fw_initialize(struct be_ctrl_info *ctrl) | ||
| 833 | { | ||
| 834 | struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem); | ||
| 835 | struct beiscsi_hba *phba = pci_get_drvdata(ctrl->pdev); | ||
| 836 | int status; | ||
| 837 | u8 *endian_check; | ||
| 838 | |||
| 839 | mutex_lock(&ctrl->mbox_lock); | ||
| 840 | memset(wrb, 0, sizeof(*wrb)); | ||
| 841 | |||
| 842 | endian_check = (u8 *) wrb; | ||
| 843 | *endian_check++ = 0xFF; | ||
| 844 | *endian_check++ = 0x12; | ||
| 845 | *endian_check++ = 0x34; | ||
| 846 | *endian_check++ = 0xFF; | ||
| 847 | *endian_check++ = 0xFF; | ||
| 848 | *endian_check++ = 0x56; | ||
| 849 | *endian_check++ = 0x78; | ||
| 850 | *endian_check++ = 0xFF; | ||
| 851 | be_dws_cpu_to_le(wrb, sizeof(*wrb)); | ||
| 852 | |||
| 853 | status = be_mbox_notify(ctrl); | ||
| 854 | if (status) | ||
| 855 | beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, | ||
| 856 | "BC_%d : be_cmd_fw_initialize Failed\n"); | ||
| 857 | |||
| 858 | mutex_unlock(&ctrl->mbox_lock); | ||
| 859 | return status; | ||
| 860 | } | ||
| 861 | |||
| 862 | /** | ||
| 863 | * be_cmd_fw_uninit()- Uinitialize FW | ||
| 864 | * @ctrl: Pointer to function control structure | ||
| 865 | * | ||
| 866 | * Send FW uninitialize pattern for the function | ||
| 867 | * | ||
| 868 | * return | ||
| 869 | * Success: 0 | ||
| 870 | * Failure: Non-Zero value | ||
| 871 | **/ | ||
| 872 | int be_cmd_fw_uninit(struct be_ctrl_info *ctrl) | ||
| 873 | { | ||
| 874 | struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem); | ||
| 875 | struct beiscsi_hba *phba = pci_get_drvdata(ctrl->pdev); | ||
| 876 | int status; | ||
| 877 | u8 *endian_check; | ||
| 878 | |||
| 879 | mutex_lock(&ctrl->mbox_lock); | ||
| 880 | memset(wrb, 0, sizeof(*wrb)); | ||
| 881 | |||
| 882 | endian_check = (u8 *) wrb; | ||
| 883 | *endian_check++ = 0xFF; | ||
| 884 | *endian_check++ = 0xAA; | ||
| 885 | *endian_check++ = 0xBB; | ||
| 886 | *endian_check++ = 0xFF; | ||
| 887 | *endian_check++ = 0xFF; | ||
| 888 | *endian_check++ = 0xCC; | ||
| 889 | *endian_check++ = 0xDD; | ||
| 890 | *endian_check = 0xFF; | ||
| 891 | |||
| 892 | be_dws_cpu_to_le(wrb, sizeof(*wrb)); | ||
| 893 | |||
| 894 | status = be_mbox_notify(ctrl); | ||
| 895 | if (status) | ||
| 896 | beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, | ||
| 897 | "BC_%d : be_cmd_fw_uninit Failed\n"); | ||
| 898 | |||
| 899 | mutex_unlock(&ctrl->mbox_lock); | ||
| 900 | return status; | ||
| 901 | } | ||
| 902 | |||
| 903 | int beiscsi_cmd_cq_create(struct be_ctrl_info *ctrl, | 777 | int beiscsi_cmd_cq_create(struct be_ctrl_info *ctrl, |
| 904 | struct be_queue_info *cq, struct be_queue_info *eq, | 778 | struct be_queue_info *cq, struct be_queue_info *eq, |
| 905 | bool sol_evts, bool no_delay, int coalesce_wm) | 779 | bool sol_evts, bool no_delay, int coalesce_wm) |
| @@ -1343,25 +1217,6 @@ error: · 437 unmodified lines | |||
| 1343 | return status; | 1217 | return status; |
| 1344 | } | 1218 | } |
| 1345 | 1219 | ||
| 1346 | int beiscsi_cmd_reset_function(struct beiscsi_hba *phba) | ||
| 1347 | { | ||
| 1348 | struct be_ctrl_info *ctrl = &phba->ctrl; | ||
| 1349 | struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem); | ||
| 1350 | struct be_post_sgl_pages_req *req = embedded_payload(wrb); | ||
| 1351 | int status; | ||
| 1352 | |||
| 1353 | mutex_lock(&ctrl->mbox_lock); | ||
| 1354 | |||
| 1355 | req = embedded_payload(wrb); | ||
| 1356 | be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); | ||
| 1357 | be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, | ||
| 1358 | OPCODE_COMMON_FUNCTION_RESET, sizeof(*req)); | ||
| 1359 | status = be_mbox_notify(ctrl); | ||
| 1360 | |||
| 1361 | mutex_unlock(&ctrl->mbox_lock); | ||
| 1362 | return status; | ||
| 1363 | } | ||
| 1364 | |||
| 1365 | /** | 1220 | /** |
| 1366 | * be_cmd_set_vlan()- Configure VLAN paramters on the adapter | 1221 | * be_cmd_set_vlan()- Configure VLAN paramters on the adapter |
| 1367 | * @phba: device priv structure instance | 1222 | * @phba: device priv structure instance |
| @@ -1402,3 +1257,564 @@ int be_cmd_set_vlan(struct beiscsi_hba *phba, · 34 unmodified lines | |||
| 1402 | 1257 | ||
| 1403 | return tag; | 1258 | return tag; |
| 1404 | } | 1259 | } |
| 1260 | |||
| 1261 | int beiscsi_check_supported_fw(struct be_ctrl_info *ctrl, | ||
| 1262 | struct beiscsi_hba *phba) | ||
| 1263 | { | ||
| 1264 | struct be_dma_mem nonemb_cmd; | ||
| 1265 | struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem); | ||
| 1266 | struct be_mgmt_controller_attributes *req; | ||
| 1267 | struct be_sge *sge = nonembedded_sgl(wrb); | ||
| 1268 | int status = 0; | ||
| 1269 | |||
| 1270 | nonemb_cmd.va = pci_alloc_consistent(ctrl->pdev, | ||
| 1271 | sizeof(struct be_mgmt_controller_attributes), | ||
| 1272 | &nonemb_cmd.dma); | ||
| 1273 | if (nonemb_cmd.va == NULL) { | ||
| 1274 | beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, | ||
| 1275 | "BG_%d : pci_alloc_consistent failed in %s\n", | ||
| 1276 | __func__); | ||
| 1277 | return -ENOMEM; | ||
| 1278 | } | ||
| 1279 | nonemb_cmd.size = sizeof(struct be_mgmt_controller_attributes); | ||
| 1280 | req = nonemb_cmd.va; | ||
| 1281 | memset(req, 0, sizeof(*req)); | ||
| 1282 | mutex_lock(&ctrl->mbox_lock); | ||
| 1283 | memset(wrb, 0, sizeof(*wrb)); | ||
| 1284 | be_wrb_hdr_prepare(wrb, sizeof(*req), false, 1); | ||
| 1285 | be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, | ||
| 1286 | OPCODE_COMMON_GET_CNTL_ATTRIBUTES, sizeof(*req)); | ||
| 1287 | sge->pa_hi = cpu_to_le32(upper_32_bits(nonemb_cmd.dma)); | ||
| 1288 | sge->pa_lo = cpu_to_le32(nonemb_cmd.dma & 0xFFFFFFFF); | ||
| 1289 | sge->len = cpu_to_le32(nonemb_cmd.size); | ||
| 1290 | status = be_mbox_notify(ctrl); | ||
| 1291 | if (!status) { | ||
| 1292 | struct be_mgmt_controller_attributes_resp *resp = nonemb_cmd.va; | ||
| 1293 | |||
| 1294 | beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_INIT, | ||
| 1295 | "BG_%d : Firmware Version of CMD : %s\n" | ||
| 1296 | "Firmware Version is : %s\n" | ||
| 1297 | "Developer Build, not performing version check...\n", | ||
| 1298 | resp->params.hba_attribs | ||
| 1299 | .flashrom_version_string, | ||
| 1300 | resp->params.hba_attribs. | ||
| 1301 | firmware_version_string); | ||
| 1302 | |||
| 1303 | phba->fw_config.iscsi_features = | ||
| 1304 | resp->params.hba_attribs.iscsi_features; | ||
| 1305 | beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_INIT, | ||
| 1306 | "BM_%d : phba->fw_config.iscsi_features = %d\n", | ||
| 1307 | phba->fw_config.iscsi_features); | ||
| 1308 | memcpy(phba->fw_ver_str, resp->params.hba_attribs. | ||
| 1309 | firmware_version_string, BEISCSI_VER_STRLEN); | ||
| 1310 | } else | ||
| 1311 | beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, | ||
| 1312 | "BG_%d : Failed in beiscsi_check_supported_fw\n"); | ||
| 1313 | mutex_unlock(&ctrl->mbox_lock); | ||
| 1314 | if (nonemb_cmd.va) | ||
| 1315 | pci_free_consistent(ctrl->pdev, nonemb_cmd.size, | ||
| 1316 | nonemb_cmd.va, nonemb_cmd.dma); | ||
| 1317 | |||
| 1318 | return status; | ||
| 1319 | } | ||
| 1320 | |||
| 1321 | /** | ||
| 1322 | * beiscsi_get_fw_config()- Get the FW config for the function | ||
| 1323 | * @ctrl: ptr to Ctrl Info | ||
| 1324 | * @phba: ptr to the dev priv structure | ||
| 1325 | * | ||
| 1326 | * Get the FW config and resources available for the function. | ||
| 1327 | * The resources are created based on the count received here. | ||
| 1328 | * | ||
| 1329 | * return | ||
| 1330 | * Success: 0 | ||
| 1331 | * Failure: Non-Zero Value | ||
| 1332 | **/ | ||
| 1333 | int beiscsi_get_fw_config(struct be_ctrl_info *ctrl, | ||
| 1334 | struct beiscsi_hba *phba) | ||
| 1335 | { | ||
| 1336 | struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem); | ||
| 1337 | struct be_fw_cfg *pfw_cfg = embedded_payload(wrb); | ||
| 1338 | uint32_t cid_count, icd_count; | ||
| 1339 | int status = -EINVAL; | ||
| 1340 | uint8_t ulp_num = 0; | ||
| 1341 | |||
| 1342 | mutex_lock(&ctrl->mbox_lock); | ||
| 1343 | memset(wrb, 0, sizeof(*wrb)); | ||
| 1344 | be_wrb_hdr_prepare(wrb, sizeof(*pfw_cfg), true, 0); | ||
| 1345 | |||
| 1346 | be_cmd_hdr_prepare(&pfw_cfg->hdr, CMD_SUBSYSTEM_COMMON, | ||
| 1347 | OPCODE_COMMON_QUERY_FIRMWARE_CONFIG, | ||
| 1348 | EMBED_MBX_MAX_PAYLOAD_SIZE); | ||
| 1349 | |||
| 1350 | if (be_mbox_notify(ctrl)) { | ||
| 1351 | beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, | ||
| 1352 | "BG_%d : Failed in beiscsi_get_fw_config\n"); | ||
| 1353 | goto fail_init; | ||
| 1354 | } | ||
| 1355 | |||
| 1356 | /* FW response formats depend on port id */ | ||
| 1357 | phba->fw_config.phys_port = pfw_cfg->phys_port; | ||
| 1358 | if (phba->fw_config.phys_port >= BEISCSI_PHYS_PORT_MAX) { | ||
| 1359 | beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, | ||
| 1360 | "BG_%d : invalid physical port id %d\n", | ||
| 1361 | phba->fw_config.phys_port); | ||
| 1362 | goto fail_init; | ||
| 1363 | } | ||
| 1364 | |||
| 1365 | /* populate and check FW config against min and max values */ | ||
| 1366 | if (!is_chip_be2_be3r(phba)) { | ||
| 1367 | phba->fw_config.eqid_count = pfw_cfg->eqid_count; | ||
| 1368 | phba->fw_config.cqid_count = pfw_cfg->cqid_count; | ||
| 1369 | if (phba->fw_config.eqid_count == 0 || | ||
| 1370 | phba->fw_config.eqid_count > 2048) { | ||
| 1371 | beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, | ||
| 1372 | "BG_%d : invalid EQ count %d\n", | ||
| 1373 | phba->fw_config.eqid_count); | ||
| 1374 | goto fail_init; | ||
| 1375 | } | ||
| 1376 | if (phba->fw_config.cqid_count == 0 || | ||
| 1377 | phba->fw_config.cqid_count > 4096) { | ||
| 1378 | beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, | ||
| 1379 | "BG_%d : invalid CQ count %d\n", | ||
| 1380 | phba->fw_config.cqid_count); | ||
| 1381 | goto fail_init; | ||
| 1382 | } | ||
| 1383 | beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_INIT, | ||
| 1384 | "BG_%d : EQ_Count : %d CQ_Count : %d\n", | ||
| 1385 | phba->fw_config.eqid_count, | ||
| 1386 | phba->fw_config.cqid_count); | ||
| 1387 | } | ||
| 1388 | |||
| 1389 | /** | ||
| 1390 | * Check on which all ULP iSCSI Protocol is loaded. | ||
| 1391 | * Set the Bit for those ULP. This set flag is used | ||
| 1392 | * at all places in the code to check on which ULP | ||
| 1393 | * iSCSi Protocol is loaded | ||
| 1394 | **/ | ||
| 1395 | for (ulp_num = 0; ulp_num < BEISCSI_ULP_COUNT; ulp_num++) { | ||
| 1396 | if (pfw_cfg->ulp[ulp_num].ulp_mode & | ||
| 1397 | BEISCSI_ULP_ISCSI_INI_MODE) { | ||
| 1398 | set_bit(ulp_num, &phba->fw_config.ulp_supported); | ||
| 1399 | |||
| 1400 | /* Get the CID, ICD and Chain count for each ULP */ | ||
| 1401 | phba->fw_config.iscsi_cid_start[ulp_num] = | ||
| 1402 | pfw_cfg->ulp[ulp_num].sq_base; | ||
| 1403 | phba->fw_config.iscsi_cid_count[ulp_num] = | ||
| 1404 | pfw_cfg->ulp[ulp_num].sq_count; | ||
| 1405 | |||
| 1406 | phba->fw_config.iscsi_icd_start[ulp_num] = | ||
| 1407 | pfw_cfg->ulp[ulp_num].icd_base; | ||
| 1408 | phba->fw_config.iscsi_icd_count[ulp_num] = | ||
| 1409 | pfw_cfg->ulp[ulp_num].icd_count; | ||
| 1410 | |||
| 1411 | phba->fw_config.iscsi_chain_start[ulp_num] = | ||
| 1412 | pfw_cfg->chain_icd[ulp_num].chain_base; | ||
| 1413 | phba->fw_config.iscsi_chain_count[ulp_num] = | ||
| 1414 | pfw_cfg->chain_icd[ulp_num].chain_count; | ||
| 1415 | |||
| 1416 | beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_INIT, | ||
| 1417 | "BG_%d : Function loaded on ULP : %d\n" | ||
| 1418 | "\tiscsi_cid_count : %d\n" | ||
| 1419 | "\tiscsi_cid_start : %d\n" | ||
| 1420 | "\t iscsi_icd_count : %d\n" | ||
| 1421 | "\t iscsi_icd_start : %d\n", | ||
| 1422 | ulp_num, | ||
| 1423 | phba->fw_config. | ||
| 1424 | iscsi_cid_count[ulp_num], | ||
| 1425 | phba->fw_config. | ||
| 1426 | iscsi_cid_start[ulp_num], | ||
| 1427 | phba->fw_config. | ||
| 1428 | iscsi_icd_count[ulp_num], | ||
| 1429 | phba->fw_config. | ||
| 1430 | iscsi_icd_start[ulp_num]); | ||
| 1431 | } | ||
| 1432 | } | ||
| 1433 | |||
| 1434 | if (phba->fw_config.ulp_supported == 0) { | ||
| 1435 | beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, | ||
| 1436 | "BG_%d : iSCSI initiator mode not set: ULP0 %x ULP1 %x\n", | ||
| 1437 | pfw_cfg->ulp[BEISCSI_ULP0].ulp_mode, | ||
| 1438 | pfw_cfg->ulp[BEISCSI_ULP1].ulp_mode); | ||
| 1439 | goto fail_init; | ||
| 1440 | } | ||
| 1441 | |||
| 1442 | /** | ||
| 1443 | * ICD is shared among ULPs. Use icd_count of any one loaded ULP | ||
| 1444 | **/ | ||
| 1445 | for (ulp_num = 0; ulp_num < BEISCSI_ULP_COUNT; ulp_num++) | ||
| 1446 | if (test_bit(ulp_num, &phba->fw_config.ulp_supported)) | ||
| 1447 | break; | ||
| 1448 | icd_count = phba->fw_config.iscsi_icd_count[ulp_num]; | ||
| 1449 | if (icd_count == 0 || icd_count > 65536) { | ||
| 1450 | beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, | ||
| 1451 | "BG_%d: invalid ICD count %d\n", icd_count); | ||
| 1452 | goto fail_init; | ||
| 1453 | } | ||
| 1454 | |||
| 1455 | cid_count = BEISCSI_GET_CID_COUNT(phba, BEISCSI_ULP0) + | ||
| 1456 | BEISCSI_GET_CID_COUNT(phba, BEISCSI_ULP1); | ||
| 1457 | if (cid_count == 0 || cid_count > 4096) { | ||
| 1458 | beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, | ||
| 1459 | "BG_%d: invalid CID count %d\n", cid_count); | ||
| 1460 | goto fail_init; | ||
| 1461 | } | ||
| 1462 | |||
| 1463 | /** | ||
| 1464 | * Check FW is dual ULP aware i.e. can handle either | ||
| 1465 | * of the protocols. | ||
| 1466 | */ | ||
| 1467 | phba->fw_config.dual_ulp_aware = (pfw_cfg->function_mode & | ||
| 1468 | BEISCSI_FUNC_DUA_MODE); | ||
| 1469 | |||
| 1470 | beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_INIT, | ||
| 1471 | "BG_%d : DUA Mode : 0x%x\n", | ||
| 1472 | phba->fw_config.dual_ulp_aware); | ||
| 1473 | |||
| 1474 | /* all set, continue using this FW config */ | ||
| 1475 | status = 0; | ||
| 1476 | fail_init: | ||
| 1477 | mutex_unlock(&ctrl->mbox_lock); | ||
| 1478 | return status; | ||
| 1479 | } | ||
| 1480 | |||
| 1481 | /** | ||
| 1482 | * beiscsi_get_port_name()- Get port name for the function | ||
| 1483 | * @ctrl: ptr to Ctrl Info | ||
| 1484 | * @phba: ptr to the dev priv structure | ||
| 1485 | * | ||
| 1486 | * Get the alphanumeric character for port | ||
| 1487 | * | ||
| 1488 | **/ | ||
| 1489 | int beiscsi_get_port_name(struct be_ctrl_info *ctrl, struct beiscsi_hba *phba) | ||
| 1490 | { | ||
| 1491 | int ret = 0; | ||
| 1492 | struct be_mcc_wrb *wrb; | ||
| 1493 | struct be_cmd_get_port_name *ioctl; | ||
| 1494 | |||
| 1495 | mutex_lock(&ctrl->mbox_lock); | ||
| 1496 | wrb = wrb_from_mbox(&ctrl->mbox_mem); | ||
| 1497 | memset(wrb, 0, sizeof(*wrb)); | ||
| 1498 | ioctl = embedded_payload(wrb); | ||
| 1499 | |||
| 1500 | be_wrb_hdr_prepare(wrb, sizeof(*ioctl), true, 0); | ||
| 1501 | be_cmd_hdr_prepare(&ioctl->h.req_hdr, CMD_SUBSYSTEM_COMMON, | ||
| 1502 | OPCODE_COMMON_GET_PORT_NAME, | ||
| 1503 | EMBED_MBX_MAX_PAYLOAD_SIZE); | ||
| 1504 | ret = be_mbox_notify(ctrl); | ||
| 1505 | phba->port_name = 0; | ||
| 1506 | if (!ret) { | ||
| 1507 | phba->port_name = ioctl->p.resp.port_names >> | ||
| 1508 | (phba->fw_config.phys_port * 8) & 0xff; | ||
| 1509 | } else { | ||
| 1510 | beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_INIT, | ||
| 1511 | "BG_%d : GET_PORT_NAME ret 0x%x status 0x%x\n", | ||
| 1512 | ret, ioctl->h.resp_hdr.status); | ||
| 1513 | } | ||
| 1514 | |||
| 1515 | if (phba->port_name == 0) | ||
| 1516 | phba->port_name = '?'; | ||
| 1517 | |||
| 1518 | mutex_unlock(&ctrl->mbox_lock); | ||
| 1519 | return ret; | ||
| 1520 | } | ||
| 1521 | |||
| 1522 | int beiscsi_set_uer_feature(struct beiscsi_hba *phba) | ||
| 1523 | { | ||
| 1524 | struct be_ctrl_info *ctrl = &phba->ctrl; | ||
| 1525 | struct be_cmd_set_features *ioctl; | ||
| 1526 | struct be_mcc_wrb *wrb; | ||
| 1527 | int ret = 0; | ||
| 1528 | |||
| 1529 | mutex_lock(&ctrl->mbox_lock); | ||
| 1530 | wrb = wrb_from_mbox(&ctrl->mbox_mem); | ||
| 1531 | memset(wrb, 0, sizeof(*wrb)); | ||
| 1532 | ioctl = embedded_payload(wrb); | ||
| 1533 | |||
| 1534 | be_wrb_hdr_prepare(wrb, sizeof(*ioctl), true, 0); | ||
| 1535 | be_cmd_hdr_prepare(&ioctl->h.req_hdr, CMD_SUBSYSTEM_COMMON, | ||
| 1536 | OPCODE_COMMON_SET_FEATURES, | ||
| 1537 | EMBED_MBX_MAX_PAYLOAD_SIZE); | ||
| 1538 | ioctl->feature = BE_CMD_SET_FEATURE_UER; | ||
| 1539 | ioctl->param_len = sizeof(ioctl->param.req); | ||
| 1540 | ioctl->param.req.uer = BE_CMD_UER_SUPP_BIT; | ||
| 1541 | ret = be_mbox_notify(ctrl); | ||
| 1542 | if (!ret) { | ||
| 1543 | phba->ue2rp = ioctl->param.resp.ue2rp; | ||
| 1544 | set_bit(BEISCSI_HBA_UER_SUPP, &phba->state); | ||
| 1545 | beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_INIT, | ||
| 1546 | "BG_%d : HBA error recovery supported\n"); | ||
| 1547 | } else { | ||
| 1548 | /** | ||
| 1549 | * Check "MCC_STATUS_INVALID_LENGTH" for SKH. | ||
| 1550 | * Older FW versions return this error. | ||
| 1551 | */ | ||
| 1552 | if (ret == MCC_STATUS_ILLEGAL_REQUEST || | ||
| 1553 | ret == MCC_STATUS_INVALID_LENGTH) | ||
| 1554 | __beiscsi_log(phba, KERN_INFO, | ||
| 1555 | "BG_%d : HBA error recovery not supported\n"); | ||
| 1556 | } | ||
| 1557 | |||
| 1558 | mutex_unlock(&ctrl->mbox_lock); | ||
| 1559 | return ret; | ||
| 1560 | } | ||
| 1561 | |||
| 1562 | static u32 beiscsi_get_post_stage(struct beiscsi_hba *phba) | ||
| 1563 | { | ||
| 1564 | u32 sem; | ||
| 1565 | |||
| 1566 | if (is_chip_be2_be3r(phba)) | ||
| 1567 | sem = ioread32(phba->csr_va + SLIPORT_SEMAPHORE_OFFSET_BEx); | ||
| 1568 | else | ||
| 1569 | pci_read_config_dword(phba->pcidev, | ||
| 1570 | SLIPORT_SEMAPHORE_OFFSET_SH, &sem); | ||
| 1571 | return sem; | ||
| 1572 | } | ||
| 1573 | |||
| 1574 | int beiscsi_check_fw_rdy(struct beiscsi_hba *phba) | ||
| 1575 | { | ||
| 1576 | u32 loop, post, rdy = 0; | ||
| 1577 | |||
| 1578 | loop = 1000; | ||
| 1579 | while (loop--) { | ||
| 1580 | post = beiscsi_get_post_stage(phba); | ||
| 1581 | if (post & POST_ERROR_BIT) | ||
| 1582 | break; | ||
| 1583 | if ((post & POST_STAGE_MASK) == POST_STAGE_ARMFW_RDY) { | ||
| 1584 | rdy = 1; | ||
| 1585 | break; | ||
| 1586 | } | ||
| 1587 | msleep(60); | ||
| 1588 | } | ||
| 1589 | |||
| 1590 | if (!rdy) { | ||
| 1591 | __beiscsi_log(phba, KERN_ERR, | ||
| 1592 | "BC_%d : FW not ready 0x%x\n", post); | ||
| 1593 | } | ||
| 1594 | |||
| 1595 | return rdy; | ||
| 1596 | } | ||
| 1597 | |||
| 1598 | int beiscsi_cmd_function_reset(struct beiscsi_hba *phba) | ||
| 1599 | { | ||
| 1600 | struct be_ctrl_info *ctrl = &phba->ctrl; | ||
| 1601 | struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem); | ||
| 1602 | struct be_post_sgl_pages_req *req = embedded_payload(wrb); | ||
| 1603 | int status; | ||
| 1604 | |||
| 1605 | mutex_lock(&ctrl->mbox_lock); | ||
| 1606 | |||
| 1607 | req = embedded_payload(wrb); | ||
| 1608 | be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); | ||
| 1609 | be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, | ||
| 1610 | OPCODE_COMMON_FUNCTION_RESET, sizeof(*req)); | ||
| 1611 | status = be_mbox_notify(ctrl); | ||
| 1612 | |||
| 1613 | mutex_unlock(&ctrl->mbox_lock); | ||
| 1614 | return status; | ||
| 1615 | } | ||
| 1616 | |||
| 1617 | int beiscsi_cmd_special_wrb(struct be_ctrl_info *ctrl, u32 load) | ||
| 1618 | { | ||
| 1619 | struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem); | ||
| 1620 | struct beiscsi_hba *phba = pci_get_drvdata(ctrl->pdev); | ||
| 1621 | u8 *endian_check; | ||
| 1622 | int status; | ||
| 1623 | |||
| 1624 | mutex_lock(&ctrl->mbox_lock); | ||
| 1625 | memset(wrb, 0, sizeof(*wrb)); | ||
| 1626 | |||
| 1627 | endian_check = (u8 *) wrb; | ||
| 1628 | if (load) { | ||
| 1629 | /* to start communicating */ | ||
| 1630 | *endian_check++ = 0xFF; | ||
| 1631 | *endian_check++ = 0x12; | ||
| 1632 | *endian_check++ = 0x34; | ||
| 1633 | *endian_check++ = 0xFF; | ||
| 1634 | *endian_check++ = 0xFF; | ||
| 1635 | *endian_check++ = 0x56; | ||
| 1636 | *endian_check++ = 0x78; | ||
| 1637 | *endian_check++ = 0xFF; | ||
| 1638 | } else { | ||
| 1639 | /* to stop communicating */ | ||
| 1640 | *endian_check++ = 0xFF; | ||
| 1641 | *endian_check++ = 0xAA; | ||
| 1642 | *endian_check++ = 0xBB; | ||
| 1643 | *endian_check++ = 0xFF; | ||
| 1644 | *endian_check++ = 0xFF; | ||
| 1645 | *endian_check++ = 0xCC; | ||
| 1646 | *endian_check++ = 0xDD; | ||
| 1647 | *endian_check = 0xFF; | ||
| 1648 | } | ||
| 1649 | be_dws_cpu_to_le(wrb, sizeof(*wrb)); | ||
| 1650 | |||
| 1651 | status = be_mbox_notify(ctrl); | ||
| 1652 | if (status) | ||
| 1653 | beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_INIT, | ||
| 1654 | "BC_%d : special WRB message failed\n"); | ||
| 1655 | mutex_unlock(&ctrl->mbox_lock); | ||
| 1656 | return status; | ||
| 1657 | } | ||
| 1658 | |||
| 1659 | int beiscsi_init_sliport(struct beiscsi_hba *phba) | ||
| 1660 | { | ||
| 1661 | int status; | ||
| 1662 | |||
| 1663 | /* check POST stage before talking to FW */ | ||
| 1664 | status = beiscsi_check_fw_rdy(phba); | ||
| 1665 | if (!status) | ||
| 1666 | return -EIO; | ||
| 1667 | |||
| 1668 | /* clear all error states after checking FW rdy */ | ||
| 1669 | phba->state &= ~BEISCSI_HBA_IN_ERR; | ||
| 1670 | |||
| 1671 | /* check again UER support */ | ||
| 1672 | phba->state &= ~BEISCSI_HBA_UER_SUPP; | ||
| 1673 | |||
| 1674 | /* | ||
| 1675 | * SLI COMMON_FUNCTION_RESET completion is indicated by BMBX RDY bit. | ||
| 1676 | * It should clean up any stale info in FW for this fn. | ||
| 1677 | */ | ||
| 1678 | status = beiscsi_cmd_function_reset(phba); | ||
| 1679 | if (status) { | ||
| 1680 | beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, | ||
| 1681 | "BC_%d : SLI Function Reset failed\n"); | ||
| 1682 | return status; | ||
| 1683 | } | ||
| 1684 | |||
| 1685 | /* indicate driver is loading */ | ||
| 1686 | return beiscsi_cmd_special_wrb(&phba->ctrl, 1); | ||
| 1687 | } | ||
| 1688 | |||
| 1689 | /** | ||
| 1690 | * beiscsi_cmd_iscsi_cleanup()- Inform FW to cleanup EP data structures. | ||
| 1691 | * @phba: pointer to dev priv structure | ||
| 1692 | * @ulp: ULP number. | ||
| 1693 | * | ||
| 1694 | * return | ||
| 1695 | * Success: 0 | ||
| 1696 | * Failure: Non-Zero Value | ||
| 1697 | **/ | ||
| 1698 | int beiscsi_cmd_iscsi_cleanup(struct beiscsi_hba *phba, unsigned short ulp) | ||
| 1699 | { | ||
| 1700 | struct be_ctrl_info *ctrl = &phba->ctrl; | ||
| 1701 | struct iscsi_cleanup_req_v1 *req_v1; | ||
| 1702 | struct iscsi_cleanup_req *req; | ||
| 1703 | struct be_mcc_wrb *wrb; | ||
| 1704 | int status; | ||
| 1705 | |||
| 1706 | mutex_lock(&ctrl->mbox_lock); | ||
| 1707 | wrb = wrb_from_mbox(&ctrl->mbox_mem); | ||
| 1708 | req = embedded_payload(wrb); | ||
| 1709 | be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); | ||
| 1710 | be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ISCSI, | ||
| 1711 | OPCODE_COMMON_ISCSI_CLEANUP, sizeof(*req)); | ||
| 1712 | |||
| 1713 | /** | ||
| 1714 | * TODO: Check with FW folks the chute value to be set. | ||
| 1715 | * For now, use the ULP_MASK as the chute value. | ||
| 1716 | */ | ||
| 1717 | if (is_chip_be2_be3r(phba)) { | ||
| 1718 | req->chute = (1 << ulp); | ||
| 1719 | req->hdr_ring_id = HWI_GET_DEF_HDRQ_ID(phba, ulp); | ||
| 1720 | req->data_ring_id = HWI_GET_DEF_BUFQ_ID(phba, ulp); | ||
| 1721 | } else { | ||
| 1722 | req_v1 = (struct iscsi_cleanup_req_v1 *)req; | ||
| 1723 | req_v1->hdr.version = 1; | ||
| 1724 | req_v1->hdr_ring_id = cpu_to_le16(HWI_GET_DEF_HDRQ_ID(phba, | ||
| 1725 | ulp)); | ||
| 1726 | req_v1->data_ring_id = cpu_to_le16(HWI_GET_DEF_BUFQ_ID(phba, | ||
| 1727 | ulp)); | ||
| 1728 | } | ||
| 1729 | |||
| 1730 | status = be_mbox_notify(ctrl); | ||
| 1731 | if (status) | ||
| 1732 | beiscsi_log(phba, KERN_WARNING, BEISCSI_LOG_INIT, | ||
| 1733 | "BG_%d : %s failed %d\n", __func__, ulp); | ||
| 1734 | mutex_unlock(&ctrl->mbox_lock); | ||
| 1735 | return status; | ||
| 1736 | } | ||
| 1737 | |||
| 1738 | /* | ||
| 1739 | * beiscsi_detect_ue()- Detect Unrecoverable Error on adapter | ||
| 1740 | * @phba: Driver priv structure | ||
| 1741 | * | ||
| 1742 | * Read registers linked to UE and check for the UE status | ||
| 1743 | **/ | ||
| 1744 | int beiscsi_detect_ue(struct beiscsi_hba *phba) | ||
| 1745 | { | ||
| 1746 | uint32_t ue_mask_hi = 0, ue_mask_lo = 0; | ||
| 1747 | uint32_t ue_hi = 0, ue_lo = 0; | ||
| 1748 | uint8_t i = 0; | ||
| 1749 | int ret = 0; | ||
| 1750 | |||
| 1751 | pci_read_config_dword(phba->pcidev, | ||
| 1752 | PCICFG_UE_STATUS_LOW, &ue_lo); | ||
| 1753 | pci_read_config_dword(phba->pcidev, | ||
| 1754 | PCICFG_UE_STATUS_MASK_LOW, | ||
| 1755 | &ue_mask_lo); | ||
| 1756 | pci_read_config_dword(phba->pcidev, | ||
| 1757 | PCICFG_UE_STATUS_HIGH, | ||
| 1758 | &ue_hi); | ||
| 1759 | pci_read_config_dword(phba->pcidev, | ||
| 1760 | PCICFG_UE_STATUS_MASK_HI, | ||
| 1761 | &ue_mask_hi); | ||
| 1762 | |||
| 1763 | ue_lo = (ue_lo & ~ue_mask_lo); | ||
| 1764 | ue_hi = (ue_hi & ~ue_mask_hi); | ||
| 1765 | |||
| 1766 | |||
| 1767 | if (ue_lo || ue_hi) { | ||
| 1768 | set_bit(BEISCSI_HBA_IN_UE, &phba->state); | ||
| 1769 | __beiscsi_log(phba, KERN_ERR, | ||
| 1770 | "BC_%d : HBA error detected\n"); | ||
| 1771 | ret = 1; | ||
| 1772 | } | ||
| 1773 | |||
| 1774 | if (ue_lo) { | ||
| 1775 | for (i = 0; ue_lo; ue_lo >>= 1, i++) { | ||
| 1776 | if (ue_lo & 1) | ||
| 1777 | __beiscsi_log(phba, KERN_ERR, | ||
| 1778 | "BC_%d : UE_LOW %s bit set\n", | ||
| 1779 | desc_ue_status_low[i]); | ||
| 1780 | } | ||
| 1781 | } | ||
| 1782 | |||
| 1783 | if (ue_hi) { | ||
| 1784 | for (i = 0; ue_hi; ue_hi >>= 1, i++) { | ||
| 1785 | if (ue_hi & 1) | ||
| 1786 | __beiscsi_log(phba, KERN_ERR, | ||
| 1787 | "BC_%d : UE_HIGH %s bit set\n", | ||
| 1788 | desc_ue_status_hi[i]); | ||
| 1789 | } | ||
| 1790 | } | ||
| 1791 | return ret; | ||
| 1792 | } | ||
| 1793 | |||
| 1794 | /* | ||
| 1795 | * beiscsi_detect_tpe()- Detect Transient Parity Error on adapter | ||
| 1796 | * @phba: Driver priv structure | ||
| 1797 | * | ||
| 1798 | * Read SLIPORT SEMAPHORE register to check for UER | ||
| 1799 | * | ||
| 1800 | **/ | ||
| 1801 | int beiscsi_detect_tpe(struct beiscsi_hba *phba) | ||
| 1802 | { | ||
| 1803 | u32 post, status; | ||
| 1804 | int ret = 0; | ||
| 1805 | |||
| 1806 | post = beiscsi_get_post_stage(phba); | ||
| 1807 | status = post & POST_STAGE_MASK; | ||
| 1808 | if ((status & POST_ERR_RECOVERY_CODE_MASK) == | ||
| 1809 | POST_STAGE_RECOVERABLE_ERR) { | ||
| 1810 | set_bit(BEISCSI_HBA_IN_TPE, &phba->state); | ||
| 1811 | __beiscsi_log(phba, KERN_INFO, | ||
| 1812 | "BC_%d : HBA error recoverable: 0x%x\n", post); | ||
| 1813 | ret = 1; | ||
| 1814 | } else { | ||
| 1815 | __beiscsi_log(phba, KERN_INFO, | ||
| 1816 | "BC_%d : HBA in UE: 0x%x\n", post); | ||
| 1817 | } | ||
| 1818 | |||
| 1819 | return ret; | ||
| 1820 | } | ||
| @@ -1,5 +1,5 @@ | |||
| 1 | /** | 1 | /** |
| 2 | * Copyright (C) 2005 - 2015 Emulex | 2 | * Copyright (C) 2005 - 2016 Broadcom |
| 3 | * All rights reserved. | 3 | * All rights reserved. |
| 4 | * | 4 | * |
| 5 | * This program is free software; you can redistribute it and/or | 5 | * This program is free software; you can redistribute it and/or |
| @@ -8,7 +8,7 @@ · 2 unmodified lines | |||
| 8 | * Public License is included in this distribution in the file called COPYING. | 8 | * Public License is included in this distribution in the file called COPYING. |
| 9 | * | 9 | * |
| 10 | * Contact Information: | 10 | * Contact Information: |
| 11 | * linux-drivers@avagotech.com | 11 | * linux-drivers@broadcom.com |
| 12 | * | 12 | * |
| 13 | * Emulex | 13 | * Emulex |
| 14 | * 3333 Susan Street | 14 | * 3333 Susan Street |
| @@ -57,6 +57,7 @@ struct be_mcc_wrb { · 42 unmodified lines | |||
| 57 | #define MCC_STATUS_ILLEGAL_REQUEST 0x2 | 57 | #define MCC_STATUS_ILLEGAL_REQUEST 0x2 |
| 58 | #define MCC_STATUS_ILLEGAL_FIELD 0x3 | 58 | #define MCC_STATUS_ILLEGAL_FIELD 0x3 |
| 59 | #define MCC_STATUS_INSUFFICIENT_BUFFER 0x4 | 59 | #define MCC_STATUS_INSUFFICIENT_BUFFER 0x4 |
| 60 | #define MCC_STATUS_INVALID_LENGTH 0x74 | ||
| 60 | 61 | ||
| 61 | #define CQE_STATUS_COMPL_MASK 0xFFFF | 62 | #define CQE_STATUS_COMPL_MASK 0xFFFF |
| 62 | #define CQE_STATUS_COMPL_SHIFT 0 /* bits 0 - 15 */ | 63 | #define CQE_STATUS_COMPL_SHIFT 0 /* bits 0 - 15 */ |
| @@ -97,11 +98,23 @@ struct be_mcc_compl { · 34 unmodified lines | |||
| 97 | #define MPU_MAILBOX_DB_RDY_MASK 0x1 /* bit 0 */ | 98 | #define MPU_MAILBOX_DB_RDY_MASK 0x1 /* bit 0 */ |
| 98 | #define MPU_MAILBOX_DB_HI_MASK 0x2 /* bit 1 */ | 99 | #define MPU_MAILBOX_DB_HI_MASK 0x2 /* bit 1 */ |
| 99 | 100 | ||
| 100 | /********** MPU semphore ******************/ | 101 | /********** MPU semphore: used for SH & BE ******************/ |
| 101 | #define MPU_EP_SEMAPHORE_OFFSET 0xac | 102 | #define SLIPORT_SOFTRESET_OFFSET 0x5c /* CSR BAR offset */ |
| 102 | #define EP_SEMAPHORE_POST_STAGE_MASK 0x0000FFFF | 103 | #define SLIPORT_SEMAPHORE_OFFSET_BEx 0xac /* CSR BAR offset */ |
| 103 | #define EP_SEMAPHORE_POST_ERR_MASK 0x1 | 104 | #define SLIPORT_SEMAPHORE_OFFSET_SH 0x94 /* PCI-CFG offset */ |
| 104 | #define EP_SEMAPHORE_POST_ERR_SHIFT 31 | 105 | #define POST_STAGE_MASK 0x0000FFFF |
| 106 | #define POST_ERROR_BIT 0x80000000 | ||
| 107 | #define POST_ERR_RECOVERY_CODE_MASK 0xF000 | ||
| 108 | |||
| 109 | /* Soft Reset register masks */ | ||
| 110 | #define SLIPORT_SOFTRESET_SR_MASK 0x00000080 /* SR bit */ | ||
| 111 | |||
| 112 | /* MPU semphore POST stage values */ | ||
| 113 | #define POST_STAGE_AWAITING_HOST_RDY 0x1 /* FW awaiting goahead from host */ | ||
| 114 | #define POST_STAGE_HOST_RDY 0x2 /* Host has given go-ahed to FW */ | ||
| 115 | #define POST_STAGE_BE_RESET 0x3 /* Host wants to reset chip */ | ||
| 116 | #define POST_STAGE_ARMFW_RDY 0xC000 /* FW is done with POST */ | ||
| 117 | #define POST_STAGE_RECOVERABLE_ERR 0xE000 /* Recoverable err detected */ | ||
| 105 | 118 | ||
| 106 | /********** MCC door bell ************/ | 119 | /********** MCC door bell ************/ |
| 107 | #define DB_MCCQ_OFFSET 0x140 | 120 | #define DB_MCCQ_OFFSET 0x140 |
| @@ -109,9 +122,6 @@ struct be_mcc_compl { · 1 unmodified line | |||
| 109 | /* Number of entries posted */ | 122 | /* Number of entries posted */ |
| 110 | #define DB_MCCQ_NUM_POSTED_SHIFT 16 /* bits 16 - 29 */ | 123 | #define DB_MCCQ_NUM_POSTED_SHIFT 16 /* bits 16 - 29 */ |
| 111 | 124 | ||
| 112 | /* MPU semphore POST stage values */ | ||
| 113 | #define POST_STAGE_ARMFW_RDY 0xc000 /* FW is done with POST */ | ||
| 114 | |||
| 115 | /** | 125 | /** |
| 116 | * When the async bit of mcc_compl is set, the last 4 bytes of | 126 | * When the async bit of mcc_compl is set, the last 4 bytes of |
| 117 | * mcc_compl is interpreted as follows: | 127 | * mcc_compl is interpreted as follows: |
| @@ -217,6 +227,7 @@ struct be_mcc_mailbox { · 99 unmodified lines | |||
| 217 | #define OPCODE_COMMON_QUERY_FIRMWARE_CONFIG 58 | 227 | #define OPCODE_COMMON_QUERY_FIRMWARE_CONFIG 58 |
| 218 | #define OPCODE_COMMON_FUNCTION_RESET 61 | 228 | #define OPCODE_COMMON_FUNCTION_RESET 61 |
| 219 | #define OPCODE_COMMON_GET_PORT_NAME 77 | 229 | #define OPCODE_COMMON_GET_PORT_NAME 77 |
| 230 | #define OPCODE_COMMON_SET_FEATURES 191 | ||
| 220 | 231 | ||
| 221 | /** | 232 | /** |
| 222 | * LIST of opcodes that are common between Initiator and Target | 233 | * LIST of opcodes that are common between Initiator and Target |
| @@ -345,8 +356,8 @@ struct be_cmd_req_logout_fw_sess { · 122 unmodified lines | |||
| 345 | 356 | ||
| 346 | struct be_cmd_resp_logout_fw_sess { | 357 | struct be_cmd_resp_logout_fw_sess { |
| 347 | struct be_cmd_resp_hdr hdr; /* dw[4] */ | 358 | struct be_cmd_resp_hdr hdr; /* dw[4] */ |
| 348 | #define BEISCSI_MGMT_SESSION_CLOSE 0x20 | ||
| 349 | uint32_t session_status; | 359 | uint32_t session_status; |
| 360 | #define BE_SESS_STATUS_CLOSE 0x20 | ||
| 350 | } __packed; | 361 | } __packed; |
| 351 | 362 | ||
| 352 | struct mgmt_conn_login_options { | 363 | struct mgmt_conn_login_options { |
| @@ -365,6 +376,14 @@ struct ip_addr_format { · 12 unmodified lines | |||
| 365 | u16 size_of_structure; | 376 | u16 size_of_structure; |
| 366 | u8 reserved; | 377 | u8 reserved; |
| 367 | u8 ip_type; | 378 | u8 ip_type; |
| 379 | #define BEISCSI_IP_TYPE_V4 0x1 | ||
| 380 | #define BEISCSI_IP_TYPE_STATIC_V4 0x3 | ||
| 381 | #define BEISCSI_IP_TYPE_DHCP_V4 0x5 | ||
| 382 | /* type v4 values < type v6 values */ | ||
| 383 | #define BEISCSI_IP_TYPE_V6 0x10 | ||
| 384 | #define BEISCSI_IP_TYPE_ROUTABLE_V6 0x30 | ||
| 385 | #define BEISCSI_IP_TYPE_LINK_LOCAL_V6 0x50 | ||
| 386 | #define BEISCSI_IP_TYPE_AUTO_V6 0x90 | ||
| 368 | u8 addr[16]; | 387 | u8 addr[16]; |
| 369 | u32 rsvd0; | 388 | u32 rsvd0; |
| 370 | } __packed; | 389 | } __packed; |
| @@ -430,8 +449,13 @@ struct be_cmd_get_boot_target_req { · 59 unmodified lines | |||
| 430 | 449 | ||
| 431 | struct be_cmd_get_boot_target_resp { | 450 | struct be_cmd_get_boot_target_resp { |
| 432 | struct be_cmd_resp_hdr hdr; | 451 | struct be_cmd_resp_hdr hdr; |
| 433 | u32 boot_session_count; | 452 | u32 boot_session_count; |
| 434 | int boot_session_handle; | 453 | u32 boot_session_handle; |
| 454 | /** | ||
| 455 | * FW returns 0xffffffff if it couldn't establish connection with | ||
| 456 | * configured boot target. | ||
| 457 | */ | ||
| 458 | #define BE_BOOT_INVALID_SHANDLE 0xffffffff | ||
| 435 | }; | 459 | }; |
| 436 | 460 | ||
| 437 | struct be_cmd_reopen_session_req { | 461 | struct be_cmd_reopen_session_req { |
| @@ -699,16 +723,59 @@ struct be_cmd_get_nic_conf_resp { · 261 unmodified lines | |||
| 699 | u8 mac_address[ETH_ALEN]; | 723 | u8 mac_address[ETH_ALEN]; |
| 700 | } __packed; | 724 | } __packed; |
| 701 | 725 | ||
| 702 | #define BEISCSI_ALIAS_LEN 32 | 726 | /******************** Get HBA NAME *******************/ |
| 703 | 727 | ||
| 704 | struct be_cmd_hba_name { | 728 | struct be_cmd_hba_name { |
| 705 | struct be_cmd_req_hdr hdr; | 729 | struct be_cmd_req_hdr hdr; |
| 706 | u16 flags; | 730 | u16 flags; |
| 707 | u16 rsvd0; | 731 | u16 rsvd0; |
| 708 | u8 initiator_name[ISCSI_NAME_LEN]; | 732 | u8 initiator_name[ISCSI_NAME_LEN]; |
| 709 | u8 initiator_alias[BEISCSI_ALIAS_LEN]; | 733 | #define BE_INI_ALIAS_LEN 32 |
| 734 | u8 initiator_alias[BE_INI_ALIAS_LEN]; | ||
| 710 | } __packed; | 735 | } __packed; |
| 711 | 736 | ||
| 737 | /******************** COMMON SET Features *******************/ | ||
| 738 | #define BE_CMD_SET_FEATURE_UER 0x10 | ||
| 739 | #define BE_CMD_UER_SUPP_BIT 0x1 | ||
| 740 | struct be_uer_req { | ||
| 741 | u32 uer; | ||
| 742 | u32 rsvd; | ||
| 743 | }; | ||
| 744 | |||
| 745 | struct be_uer_resp { | ||
| 746 | u32 uer; | ||
| 747 | u16 ue2rp; | ||
| 748 | u16 ue2sr; | ||
| 749 | }; | ||
| 750 | |||
| 751 | struct be_cmd_set_features { | ||
| 752 | union { | ||
| 753 | struct be_cmd_req_hdr req_hdr; | ||
| 754 | struct be_cmd_resp_hdr resp_hdr; | ||
| 755 | } h; | ||
| 756 | u32 feature; | ||
| 757 | u32 param_len; | ||
| 758 | union { | ||
| 759 | struct be_uer_req req; | ||
| 760 | struct be_uer_resp resp; | ||
| 761 | u32 rsvd[2]; | ||
| 762 | } param; | ||
| 763 | } __packed; | ||
| 764 | |||
| 765 | int beiscsi_cmd_function_reset(struct beiscsi_hba *phba); | ||
| 766 | |||
| 767 | int beiscsi_cmd_special_wrb(struct be_ctrl_info *ctrl, u32 load); | ||
| 768 | |||
| 769 | int beiscsi_check_fw_rdy(struct beiscsi_hba *phba); | ||
| 770 | |||
| 771 | int beiscsi_init_sliport(struct beiscsi_hba *phba); | ||
| 772 | |||
| 773 | int beiscsi_cmd_iscsi_cleanup(struct beiscsi_hba *phba, unsigned short ulp_num); | ||
| 774 | |||
| 775 | int beiscsi_detect_ue(struct beiscsi_hba *phba); | ||
| 776 | |||
| 777 | int beiscsi_detect_tpe(struct beiscsi_hba *phba); | ||
| 778 | |||
| 712 | int beiscsi_cmd_eq_create(struct be_ctrl_info *ctrl, | 779 | int beiscsi_cmd_eq_create(struct be_ctrl_info *ctrl, |
| 713 | struct be_queue_info *eq, int eq_delay); | 780 | struct be_queue_info *eq, int eq_delay); |
| 714 | 781 | ||
| @@ -723,24 +790,21 @@ int beiscsi_cmd_mccq_create(struct beiscsi_hba *phba, · 8 unmodified lines | |||
| 723 | struct be_queue_info *mccq, | 790 | struct be_queue_info *mccq, |
| 724 | struct be_queue_info *cq); | 791 | struct be_queue_info *cq); |
| 725 | 792 | ||
| 726 | int be_poll_mcc(struct be_ctrl_info *ctrl); | ||
| 727 | int mgmt_check_supported_fw(struct be_ctrl_info *ctrl, | ||
| 728 | struct beiscsi_hba *phba); | ||
| 729 | unsigned int be_cmd_get_initname(struct beiscsi_hba *phba); | 793 | unsigned int be_cmd_get_initname(struct beiscsi_hba *phba); |
| 730 | 794 | ||
| 731 | void free_mcc_wrb(struct be_ctrl_info *ctrl, unsigned int tag); | 795 | void free_mcc_wrb(struct be_ctrl_info *ctrl, unsigned int tag); |
| 732 | 796 | ||
| 733 | int be_cmd_modify_eq_delay(struct beiscsi_hba *phba, struct be_set_eqd *, | 797 | int beiscsi_modify_eq_delay(struct beiscsi_hba *phba, struct be_set_eqd *, |
| 734 | int num); | 798 | int num); |
| 735 | int beiscsi_mccq_compl_wait(struct beiscsi_hba *phba, | 799 | int beiscsi_mccq_compl_wait(struct beiscsi_hba *phba, |
| 736 | uint32_t tag, struct be_mcc_wrb **wrb, | 800 | unsigned int tag, |
| 801 | struct be_mcc_wrb **wrb, | ||
| 737 | struct be_dma_mem *mbx_cmd_mem); | 802 | struct be_dma_mem *mbx_cmd_mem); |
| 738 | /*ISCSI Functuions */ | 803 | int __beiscsi_mcc_compl_status(struct beiscsi_hba *phba, |
| 739 | int be_cmd_fw_initialize(struct be_ctrl_info *ctrl); | 804 | unsigned int tag, |
| 740 | int be_cmd_fw_uninit(struct be_ctrl_info *ctrl); | 805 | struct be_mcc_wrb **wrb, |
| 741 | 806 | struct be_dma_mem *mbx_cmd_mem); | |
| 742 | struct be_mcc_wrb *wrb_from_mbox(struct be_dma_mem *mbox_mem); | 807 | struct be_mcc_wrb *wrb_from_mbox(struct be_dma_mem *mbox_mem); |
| 743 | int be_mcc_compl_poll(struct beiscsi_hba *phba, unsigned int tag); | ||
| 744 | void be_mcc_notify(struct beiscsi_hba *phba, unsigned int tag); | 808 | void be_mcc_notify(struct beiscsi_hba *phba, unsigned int tag); |
| 745 | struct be_mcc_wrb *alloc_mcc_wrb(struct beiscsi_hba *phba, | 809 | struct be_mcc_wrb *alloc_mcc_wrb(struct beiscsi_hba *phba, |
| 746 | unsigned int *ref_tag); | 810 | unsigned int *ref_tag); |
| @@ -749,9 +813,6 @@ void beiscsi_process_async_event(struct beiscsi_hba *phba, · 2 unmodified lines | |||
| 749 | int beiscsi_process_mcc_compl(struct be_ctrl_info *ctrl, | 813 | int beiscsi_process_mcc_compl(struct be_ctrl_info *ctrl, |
| 750 | struct be_mcc_compl *compl); | 814 | struct be_mcc_compl *compl); |
| 751 | 815 | ||
| 752 | |||
| 753 | int be_mbox_notify(struct be_ctrl_info *ctrl); | ||
| 754 | |||
| 755 | int be_cmd_create_default_pdu_queue(struct be_ctrl_info *ctrl, | 816 | int be_cmd_create_default_pdu_queue(struct be_ctrl_info *ctrl, |
| 756 | struct be_queue_info *cq, | 817 | struct be_queue_info *cq, |
| 757 | struct be_queue_info *dq, int length, | 818 | struct be_queue_info *dq, int length, |
| @@ -767,8 +828,6 @@ int be_cmd_iscsi_post_sgl_pages(struct be_ctrl_info *ctrl, · 9 unmodified lines | |||
| 767 | struct be_dma_mem *q_mem, u32 page_offset, | 828 | struct be_dma_mem *q_mem, u32 page_offset, |
| 768 | u32 num_pages); | 829 | u32 num_pages); |
| 769 | 830 | ||
| 770 | int beiscsi_cmd_reset_function(struct beiscsi_hba *phba); | ||
| 771 | |||
| 772 | int be_cmd_wrbq_create(struct be_ctrl_info *ctrl, struct be_dma_mem *q_mem, | 831 | int be_cmd_wrbq_create(struct be_ctrl_info *ctrl, struct be_dma_mem *q_mem, |
| 773 | struct be_queue_info *wrbq, | 832 | struct be_queue_info *wrbq, |
| 774 | struct hwi_wrb_context *pwrb_context, | 833 | struct hwi_wrb_context *pwrb_context, |
| @@ -777,6 +836,15 @@ int be_cmd_wrbq_create(struct be_ctrl_info *ctrl, struct be_dma_mem *q_mem, · 2 unmodified lines | |||
| 777 | /* Configuration Functions */ | 836 | /* Configuration Functions */ |
| 778 | int be_cmd_set_vlan(struct beiscsi_hba *phba, uint16_t vlan_tag); | 837 | int be_cmd_set_vlan(struct beiscsi_hba *phba, uint16_t vlan_tag); |
| 779 | 838 | ||
| 839 | int beiscsi_check_supported_fw(struct be_ctrl_info *ctrl, | ||
| 840 | struct beiscsi_hba *phba); | ||
| 841 | |||
| 842 | int beiscsi_get_fw_config(struct be_ctrl_info *ctrl, struct beiscsi_hba *phba); | ||
| 843 | |||
| 844 | int beiscsi_get_port_name(struct be_ctrl_info *ctrl, struct beiscsi_hba *phba); | ||
| 845 | |||
| 846 | int beiscsi_set_uer_feature(struct beiscsi_hba *phba); | ||
| 847 | |||
| 780 | struct be_default_pdu_context { | 848 | struct be_default_pdu_context { |
| 781 | u32 dw[4]; | 849 | u32 dw[4]; |
| 782 | } __packed; | 850 | } __packed; |
| @@ -999,7 +1067,16 @@ struct iscsi_cleanup_req { · 216 unmodified lines | |||
| 999 | u16 chute; | 1067 | u16 chute; |
| 1000 | u8 hdr_ring_id; | 1068 | u8 hdr_ring_id; |
| 1001 | u8 data_ring_id; | 1069 | u8 data_ring_id; |
| 1070 | } __packed; | ||
| 1002 | 1071 | ||
| 1072 | struct iscsi_cleanup_req_v1 { | ||
| 1073 | struct be_cmd_req_hdr hdr; | ||
| 1074 | u16 chute; | ||
| 1075 | u16 rsvd1; | ||
| 1076 | u16 hdr_ring_id; | ||
| 1077 | u16 rsvd2; | ||
| 1078 | u16 data_ring_id; | ||
| 1079 | u16 rsvd3; | ||
| 1003 | } __packed; | 1080 | } __packed; |
| 1004 | 1081 | ||
| 1005 | struct eq_delay { | 1082 | struct eq_delay { |
| @@ -1368,14 +1445,9 @@ struct be_cmd_get_port_name { · 362 unmodified lines | |||
| 1368 | * the cxn | 1445 | * the cxn |
| 1369 | */ | 1446 | */ |
| 1370 | 1447 | ||
| 1371 | int beiscsi_pci_soft_reset(struct beiscsi_hba *phba); | ||
| 1372 | int be_chk_reset_complete(struct beiscsi_hba *phba); | ||
| 1373 | |||
| 1374 | void be_wrb_hdr_prepare(struct be_mcc_wrb *wrb, int payload_len, | 1448 | void be_wrb_hdr_prepare(struct be_mcc_wrb *wrb, int payload_len, |
| 1375 | bool embedded, u8 sge_cnt); | 1449 | bool embedded, u8 sge_cnt); |
| 1376 | 1450 | ||
| 1377 | void be_cmd_hdr_prepare(struct be_cmd_req_hdr *req_hdr, | 1451 | void be_cmd_hdr_prepare(struct be_cmd_req_hdr *req_hdr, |
| 1378 | u8 subsystem, u8 opcode, int cmd_len); | 1452 | u8 subsystem, u8 opcode, int cmd_len); |
| 1379 | |||
| 1380 | void beiscsi_fail_session(struct iscsi_cls_session *cls_session); | ||
| 1381 | #endif /* !BEISCSI_CMDS_H */ | 1453 | #endif /* !BEISCSI_CMDS_H */ |
| @@ -1,5 +1,5 @@ | |||
| 1 | /** | 1 | /** |
| 2 | * Copyright (C) 2005 - 2015 Emulex | 2 | * Copyright (C) 2005 - 2016 Broadcom |
| 3 | * All rights reserved. | 3 | * All rights reserved. |
| 4 | * | 4 | * |
| 5 | * This program is free software; you can redistribute it and/or | 5 | * This program is free software; you can redistribute it and/or |
| @@ -7,10 +7,10 @@ · 1 unmodified line | |||
| 7 | * as published by the Free Software Foundation. The full GNU General | 7 | * as published by the Free Software Foundation. The full GNU General |
| 8 | * Public License is included in this distribution in the file called COPYING. | 8 | * Public License is included in this distribution in the file called COPYING. |
| 9 | * | 9 | * |
| 10 | * Written by: Jayamohan Kallickal (jayamohan.kallickal@avagotech.com) | 10 | * Written by: Jayamohan Kallickal (jayamohan.kallickal@broadcom.com) |
| 11 | * | 11 | * |
| 12 | * Contact Information: | 12 | * Contact Information: |
| 13 | * linux-drivers@avagotech.com | 13 | * linux-drivers@broadcom.com |
| 14 | * | 14 | * |
| 15 | * Emulex | 15 | * Emulex |
| 16 | * 3333 Susan Street | 16 | * 3333 Susan Street |
| @@ -52,22 +52,20 @@ struct iscsi_cls_session *beiscsi_session_create(struct iscsi_endpoint *ep, · 35 unmodified lines | |||
| 52 | 52 | ||
| 53 | 53 | ||
| 54 | if (!ep) { | 54 | if (!ep) { |
| 55 | printk(KERN_ERR | 55 | pr_err("beiscsi_session_create: invalid ep\n"); |
| 56 | "beiscsi_session_create: invalid ep\n"); | ||
| 57 | return NULL; | 56 | return NULL; |
| 58 | } | 57 | } |
| 59 | beiscsi_ep = ep->dd_data; | 58 | beiscsi_ep = ep->dd_data; |
| 60 | phba = beiscsi_ep->phba; | 59 | phba = beiscsi_ep->phba; |
| 61 | 60 | ||
| 62 | if (phba->state & BE_ADAPTER_PCI_ERR) { | 61 | if (!beiscsi_hba_is_online(phba)) { |
| 63 | beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG, | ||
| 64 | "BS_%d : PCI_ERROR Recovery\n"); | ||
| 65 | return NULL; | ||
| 66 | } else { | ||
| 67 | beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG, | 62 | beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG, |
| 68 | "BS_%d : In beiscsi_session_create\n"); | 63 | "BS_%d : HBA in error 0x%lx\n", phba->state); |
| 64 | return NULL; | ||
| 69 | } | 65 | } |
| 70 | 66 | ||
| 67 | beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG, | ||
| 68 | "BS_%d : In beiscsi_session_create\n"); | ||
| 71 | if (cmds_max > beiscsi_ep->phba->params.wrbs_per_cxn) { | 69 | if (cmds_max > beiscsi_ep->phba->params.wrbs_per_cxn) { |
| 72 | beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG, | 70 | beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG, |
| 73 | "BS_%d : Cannot handle %d cmds." | 71 | "BS_%d : Cannot handle %d cmds." |
| @@ -119,6 +117,16 @@ void beiscsi_session_destroy(struct iscsi_cls_session *cls_session) · 45 unmodified lines | |||
| 119 | iscsi_session_teardown(cls_session); | 117 | iscsi_session_teardown(cls_session); |
| 120 | } | 118 | } |
| 121 | 119 | ||
| 120 | /** | ||
| 121 | * beiscsi_session_fail(): Closing session with appropriate error | ||
| 122 | * @cls_session: ptr to session | ||
| 123 | **/ | ||
| 124 | void beiscsi_session_fail(struct iscsi_cls_session *cls_session) | ||
| 125 | { | ||
| 126 | iscsi_session_failure(cls_session->dd_data, ISCSI_ERR_CONN_FAILED); | ||
| 127 | } | ||
| 128 | |||
| 129 | |||
| 122 | /** | 130 | /** |
| 123 | * beiscsi_conn_create - create an instance of iscsi connection | 131 | * beiscsi_conn_create - create an instance of iscsi connection |
| 124 | * @cls_session: ptr to iscsi_cls_session | 132 | * @cls_session: ptr to iscsi_cls_session |
| @@ -237,7 +245,7 @@ int beiscsi_conn_bind(struct iscsi_cls_session *cls_session, · 112 unmodified lines | |||
| 237 | return beiscsi_bindconn_cid(phba, beiscsi_conn, beiscsi_ep->ep_cid); | 245 | return beiscsi_bindconn_cid(phba, beiscsi_conn, beiscsi_ep->ep_cid); |
| 238 | } | 246 | } |
| 239 | 247 | ||
| 240 | static int beiscsi_create_ipv4_iface(struct beiscsi_hba *phba) | 248 | static int beiscsi_iface_create_ipv4(struct beiscsi_hba *phba) |
| 241 | { | 249 | { |
| 242 | if (phba->ipv4_iface) | 250 | if (phba->ipv4_iface) |
| 243 | return 0; | 251 | return 0; |
| @@ -256,7 +264,7 @@ static int beiscsi_create_ipv4_iface(struct beiscsi_hba *phba) · 12 unmodified lines | |||
| 256 | return 0; | 264 | return 0; |
| 257 | } | 265 | } |
| 258 | 266 | ||
| 259 | static int beiscsi_create_ipv6_iface(struct beiscsi_hba *phba) | 267 | static int beiscsi_iface_create_ipv6(struct beiscsi_hba *phba) |
| 260 | { | 268 | { |
| 261 | if (phba->ipv6_iface) | 269 | if (phba->ipv6_iface) |
| 262 | return 0; | 270 | return 0; |
| @@ -275,79 +283,31 @@ static int beiscsi_create_ipv6_iface(struct beiscsi_hba *phba) · 12 unmodified lines | |||
| 275 | return 0; | 283 | return 0; |
| 276 | } | 284 | } |
| 277 | 285 | ||
| 278 | void beiscsi_create_def_ifaces(struct beiscsi_hba *phba) | 286 | void beiscsi_iface_create_default(struct beiscsi_hba *phba) |
| 279 | { | 287 | { |
| 280 | struct be_cmd_get_if_info_resp *if_info; | 288 | struct be_cmd_get_if_info_resp *if_info; |
| 281 | 289 | ||
| 282 | if (!mgmt_get_if_info(phba, BE2_IPV4, &if_info)) { | 290 | if (!beiscsi_if_get_info(phba, BEISCSI_IP_TYPE_V4, &if_info)) { |
| 283 | beiscsi_create_ipv4_iface(phba); | 291 | beiscsi_iface_create_ipv4(phba); |
| 284 | kfree(if_info); | 292 | kfree(if_info); |
| 285 | } | 293 | } |
| 286 | 294 | ||
| 287 | if (!mgmt_get_if_info(phba, BE2_IPV6, &if_info)) { | 295 | if (!beiscsi_if_get_info(phba, BEISCSI_IP_TYPE_V6, &if_info)) { |
| 288 | beiscsi_create_ipv6_iface(phba); | 296 | beiscsi_iface_create_ipv6(phba); |
| 289 | kfree(if_info); | 297 | kfree(if_info); |
| 290 | } | 298 | } |
| 291 | } | 299 | } |
| 292 | 300 | ||
| 293 | void beiscsi_destroy_def_ifaces(struct beiscsi_hba *phba) | 301 | void beiscsi_iface_destroy_default(struct beiscsi_hba *phba) |
| 294 | { | 302 | { |
| 295 | if (phba->ipv6_iface) | 303 | if (phba->ipv6_iface) { |
| 296 | iscsi_destroy_iface(phba->ipv6_iface); | 304 | iscsi_destroy_iface(phba->ipv6_iface); |
| 297 | if (phba->ipv4_iface) | 305 | phba->ipv6_iface = NULL; |
| 298 | iscsi_destroy_iface(phba->ipv4_iface); | ||
| 299 | } | ||
| 300 | |||
| 301 | static int | ||
| 302 | beiscsi_set_static_ip(struct Scsi_Host *shost, | ||
| 303 | struct iscsi_iface_param_info *iface_param, | ||
| 304 | void *data, uint32_t dt_len) | ||
| 305 | { | ||
| 306 | struct beiscsi_hba *phba = iscsi_host_priv(shost); | ||
| 307 | struct iscsi_iface_param_info *iface_ip = NULL; | ||
| 308 | struct iscsi_iface_param_info *iface_subnet = NULL; | ||
| 309 | struct nlattr *nla; | ||
| 310 | int ret; | ||
| 311 | |||
| 312 | |||
| 313 | switch (iface_param->param) { | ||
| 314 | case ISCSI_NET_PARAM_IPV4_BOOTPROTO: | ||
| 315 | nla = nla_find(data, dt_len, ISCSI_NET_PARAM_IPV4_ADDR); | ||
| 316 | if (nla) | ||
| 317 | iface_ip = nla_data(nla); | ||
| 318 | |||
| 319 | nla = nla_find(data, dt_len, ISCSI_NET_PARAM_IPV4_SUBNET); | ||
| 320 | if (nla) | ||
| 321 | iface_subnet = nla_data(nla); | ||
| 322 | break; | ||
| 323 | case ISCSI_NET_PARAM_IPV4_ADDR: | ||
| 324 | iface_ip = iface_param; | ||
| 325 | nla = nla_find(data, dt_len, ISCSI_NET_PARAM_IPV4_SUBNET); | ||
| 326 | if (nla) | ||
| 327 | iface_subnet = nla_data(nla); | ||
| 328 | break; | ||
| 329 | case ISCSI_NET_PARAM_IPV4_SUBNET: | ||
| 330 | iface_subnet = iface_param; | ||
| 331 | nla = nla_find(data, dt_len, ISCSI_NET_PARAM_IPV4_ADDR); | ||
| 332 | if (nla) | ||
| 333 | iface_ip = nla_data(nla); | ||
| 334 | break; | ||
| 335 | default: | ||
| 336 | beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG, | ||
| 337 | "BS_%d : Unsupported param %d\n", | ||
| 338 | iface_param->param); | ||
| 339 | } | 306 | } |
| 340 | 307 | if (phba->ipv4_iface) { | |
| 341 | if (!iface_ip || !iface_subnet) { | 308 | iscsi_destroy_iface(phba->ipv4_iface); |
| 342 | beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG, | 309 | phba->ipv4_iface = NULL; |
| 343 | "BS_%d : IP and Subnet Mask required\n"); | ||
| 344 | return -EINVAL; | ||
| 345 | } | 310 | } |
| 346 | |||
| 347 | ret = mgmt_set_ip(phba, iface_ip, iface_subnet, | ||
| 348 | ISCSI_BOOTPROTO_STATIC); | ||
| 349 | |||
| 350 | return ret; | ||
| 351 | } | 311 | } |
| 352 | 312 | ||
| 353 | /** | 313 | /** |
| @@ -363,137 +323,141 @@ beiscsi_set_static_ip(struct Scsi_Host *shost, · 9 unmodified lines | |||
| 363 | * Failure: Non-Zero Value | 323 | * Failure: Non-Zero Value |
| 364 | **/ | 324 | **/ |
| 365 | static int | 325 | static int |
| 366 | beiscsi_set_vlan_tag(struct Scsi_Host *shost, | 326 | beiscsi_iface_config_vlan(struct Scsi_Host *shost, |
| 367 | struct iscsi_iface_param_info *iface_param) | 327 | struct iscsi_iface_param_info *iface_param) |
| 368 | { | 328 | { |
| 369 | struct beiscsi_hba *phba = iscsi_host_priv(shost); | 329 | struct beiscsi_hba *phba = iscsi_host_priv(shost); |
| 370 | int ret; | 330 | int ret = -EPERM; |
| 371 | |||
| 372 | /* Get the Interface Handle */ | ||
| 373 | ret = mgmt_get_all_if_id(phba); | ||
| 374 | if (ret) { | ||
| 375 | beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG, | ||
| 376 | "BS_%d : Getting Interface Handle Failed\n"); | ||
| 377 | return ret; | ||
| 378 | } | ||
| 379 | 331 | ||
| 380 | switch (iface_param->param) { | 332 | switch (iface_param->param) { |
| 381 | case ISCSI_NET_PARAM_VLAN_ENABLED: | 333 | case ISCSI_NET_PARAM_VLAN_ENABLED: |
| 334 | ret = 0; | ||
| 382 | if (iface_param->value[0] != ISCSI_VLAN_ENABLE) | 335 | if (iface_param->value[0] != ISCSI_VLAN_ENABLE) |
| 383 | ret = mgmt_set_vlan(phba, BEISCSI_VLAN_DISABLE); | 336 | ret = beiscsi_if_set_vlan(phba, BEISCSI_VLAN_DISABLE); |
| 384 | break; | 337 | break; |
| 385 | case ISCSI_NET_PARAM_VLAN_TAG: | 338 | case ISCSI_NET_PARAM_VLAN_TAG: |
| 386 | ret = mgmt_set_vlan(phba, | 339 | ret = beiscsi_if_set_vlan(phba, |
| 387 | *((uint16_t *)iface_param->value)); | 340 | *((uint16_t *)iface_param->value)); |
| 388 | break; | 341 | break; |
| 389 | default: | ||
| 390 | beiscsi_log(phba, KERN_WARNING, BEISCSI_LOG_CONFIG, | ||
| 391 | "BS_%d : Unknown Param Type : %d\n", | ||
| 392 | iface_param->param); | ||
| 393 | return -ENOSYS; | ||
| 394 | } | 342 | } |
| 395 | return ret; | 343 | return ret; |
| 396 | } | 344 | } |
| 397 | 345 | ||
| 398 | 346 | ||
| 399 | static int | 347 | static int |
| 400 | beiscsi_set_ipv4(struct Scsi_Host *shost, | 348 | beiscsi_iface_config_ipv4(struct Scsi_Host *shost, |
| 401 | struct iscsi_iface_param_info *iface_param, | 349 | struct iscsi_iface_param_info *info, |
| 402 | void *data, uint32_t dt_len) | 350 | void *data, uint32_t dt_len) |
| 403 | { | 351 | { |
| 404 | struct beiscsi_hba *phba = iscsi_host_priv(shost); | 352 | struct beiscsi_hba *phba = iscsi_host_priv(shost); |
| 405 | int ret = 0; | 353 | u8 *ip = NULL, *subnet = NULL, *gw; |
| 354 | struct nlattr *nla; | ||
| 355 | int ret = -EPERM; | ||
| 406 | 356 | ||
| 407 | /* Check the param */ | 357 | /* Check the param */ |
| 408 | switch (iface_param->param) { | 358 | switch (info->param) { |
| 359 | case ISCSI_NET_PARAM_IFACE_ENABLE: | ||
| 360 | if (info->value[0] == ISCSI_IFACE_ENABLE) | ||
| 361 | ret = beiscsi_iface_create_ipv4(phba); | ||
| 362 | else { | ||
| 363 | iscsi_destroy_iface(phba->ipv4_iface); | ||
| 364 | phba->ipv4_iface = NULL; | ||
| 365 | } | ||
| 366 | break; | ||
| 409 | case ISCSI_NET_PARAM_IPV4_GW: | 367 | case ISCSI_NET_PARAM_IPV4_GW: |
| 410 | ret = mgmt_set_gateway(phba, iface_param); | 368 | gw = info->value; |
| 369 | ret = beiscsi_if_set_gw(phba, BEISCSI_IP_TYPE_V4, gw); | ||
| 411 | break; | 370 | break; |
| 412 | case ISCSI_NET_PARAM_IPV4_BOOTPROTO: | 371 | case ISCSI_NET_PARAM_IPV4_BOOTPROTO: |
| 413 | if (iface_param->value[0] == ISCSI_BOOTPROTO_DHCP) | 372 | if (info->value[0] == ISCSI_BOOTPROTO_DHCP) |
| 414 | ret = mgmt_set_ip(phba, iface_param, | 373 | ret = beiscsi_if_en_dhcp(phba, BEISCSI_IP_TYPE_V4); |
| 415 | NULL, ISCSI_BOOTPROTO_DHCP); | 374 | else if (info->value[0] == ISCSI_BOOTPROTO_STATIC) |
| 416 | else if (iface_param->value[0] == ISCSI_BOOTPROTO_STATIC) | 375 | /* release DHCP IP address */ |
| 417 | ret = beiscsi_set_static_ip(shost, iface_param, | 376 | ret = beiscsi_if_en_static(phba, BEISCSI_IP_TYPE_V4, |
| 418 | data, dt_len); | 377 | NULL, NULL); |
| 419 | else | 378 | else |
| 420 | beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG, | 379 | beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG, |
| 421 | "BS_%d : Invalid BOOTPROTO: %d\n", | 380 | "BS_%d : Invalid BOOTPROTO: %d\n", |
| 422 | iface_param->value[0]); | 381 | info->value[0]); |
| 423 | break; | 382 | break; |
| 424 | case ISCSI_NET_PARAM_IFACE_ENABLE: | ||
| 425 | if (iface_param->value[0] == ISCSI_IFACE_ENABLE) | ||
| 426 | ret = beiscsi_create_ipv4_iface(phba); | ||
| 427 | else | ||
| 428 | iscsi_destroy_iface(phba->ipv4_iface); | ||
| 429 | break; | ||
| 430 | case ISCSI_NET_PARAM_IPV4_SUBNET: | ||
| 431 | case ISCSI_NET_PARAM_IPV4_ADDR: | 383 | case ISCSI_NET_PARAM_IPV4_ADDR: |
| 432 | ret = beiscsi_set_static_ip(shost, iface_param, | 384 | ip = info->value; |
| 433 | data, dt_len); | 385 | nla = nla_find(data, dt_len, ISCSI_NET_PARAM_IPV4_SUBNET); |
| 386 | if (nla) { | ||
| 387 | info = nla_data(nla); | ||
| 388 | subnet = info->value; | ||
| 389 | } | ||
| 390 | ret = beiscsi_if_en_static(phba, BEISCSI_IP_TYPE_V4, | ||
| 391 | ip, subnet); | ||
| 434 | break; | 392 | break; |
| 435 | case ISCSI_NET_PARAM_VLAN_ENABLED: | 393 | case ISCSI_NET_PARAM_IPV4_SUBNET: |
| 436 | case ISCSI_NET_PARAM_VLAN_TAG: | 394 | /* |
| 437 | ret = beiscsi_set_vlan_tag(shost, iface_param); | 395 | * OPCODE_COMMON_ISCSI_NTWK_MODIFY_IP_ADDR ioctl needs IP |
| 396 | * and subnet both. Find IP to be applied for this subnet. | ||
| 397 | */ | ||
| 398 | subnet = info->value; | ||
| 399 | nla = nla_find(data, dt_len, ISCSI_NET_PARAM_IPV4_ADDR); | ||
| 400 | if (nla) { | ||
| 401 | info = nla_data(nla); | ||
| 402 | ip = info->value; | ||
| 403 | } | ||
| 404 | ret = beiscsi_if_en_static(phba, BEISCSI_IP_TYPE_V4, | ||
| 405 | ip, subnet); | ||
| 438 | break; | 406 | break; |
| 439 | default: | ||
| 440 | beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG, | ||
| 441 | "BS_%d : Param %d not supported\n", | ||
| 442 | iface_param->param); | ||
| 443 | } | 407 | } |
| 444 | 408 | ||
| 445 | return ret; | 409 | return ret; |
| 446 | } | 410 | } |
| 447 | 411 | ||
| 448 | static int | 412 | static int |
| 449 | beiscsi_set_ipv6(struct Scsi_Host *shost, | 413 | beiscsi_iface_config_ipv6(struct Scsi_Host *shost, |
| 450 | struct iscsi_iface_param_info *iface_param, | 414 | struct iscsi_iface_param_info *iface_param, |
| 451 | void *data, uint32_t dt_len) | 415 | void *data, uint32_t dt_len) |
| 452 | { | 416 | { |
| 453 | struct beiscsi_hba *phba = iscsi_host_priv(shost); | 417 | struct beiscsi_hba *phba = iscsi_host_priv(shost); |
| 454 | int ret = 0; | 418 | int ret = -EPERM; |
| 455 | 419 | ||
| 456 | switch (iface_param->param) { | 420 | switch (iface_param->param) { |
| 457 | case ISCSI_NET_PARAM_IFACE_ENABLE: | 421 | case ISCSI_NET_PARAM_IFACE_ENABLE: |
| 458 | if (iface_param->value[0] == ISCSI_IFACE_ENABLE) | 422 | if (iface_param->value[0] == ISCSI_IFACE_ENABLE) |
| 459 | ret = beiscsi_create_ipv6_iface(phba); | 423 | ret = beiscsi_iface_create_ipv6(phba); |
| 460 | else { | 424 | else { |
| 461 | iscsi_destroy_iface(phba->ipv6_iface); | 425 | iscsi_destroy_iface(phba->ipv6_iface); |
| 462 | ret = 0; | 426 | phba->ipv6_iface = NULL; |
| 463 | } | 427 | } |
| 464 | break; | 428 | break; |
| 465 | case ISCSI_NET_PARAM_IPV6_ADDR: | 429 | case ISCSI_NET_PARAM_IPV6_ADDR: |
| 466 | ret = mgmt_set_ip(phba, iface_param, NULL, | 430 | ret = beiscsi_if_en_static(phba, BEISCSI_IP_TYPE_V6, |
| 467 | ISCSI_BOOTPROTO_STATIC); | 431 | iface_param->value, NULL); |
| 468 | break; | 432 | break; |
| 469 | case ISCSI_NET_PARAM_VLAN_ENABLED: | ||
| 470 | case ISCSI_NET_PARAM_VLAN_TAG: | ||
| 471 | ret = beiscsi_set_vlan_tag(shost, iface_param); | ||
| 472 | break; | ||
| 473 | default: | ||
| 474 | beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG, | ||
| 475 | "BS_%d : Param %d not supported\n", | ||
| 476 | iface_param->param); | ||
| 477 | } | 433 | } |
| 478 | 434 | ||
| 479 | return ret; | 435 | return ret; |
| 480 | } | 436 | } |
| 481 | 437 | ||
| 482 | int be2iscsi_iface_set_param(struct Scsi_Host *shost, | 438 | int beiscsi_iface_set_param(struct Scsi_Host *shost, |
| 483 | void *data, uint32_t dt_len) | 439 | void *data, uint32_t dt_len) |
| 484 | { | 440 | { |
| 485 | struct iscsi_iface_param_info *iface_param = NULL; | 441 | struct iscsi_iface_param_info *iface_param = NULL; |
| 486 | struct beiscsi_hba *phba = iscsi_host_priv(shost); | 442 | struct beiscsi_hba *phba = iscsi_host_priv(shost); |
| 487 | struct nlattr *attrib; | 443 | struct nlattr *attrib; |
| 488 | uint32_t rm_len = dt_len; | 444 | uint32_t rm_len = dt_len; |
| 489 | int ret = 0 ; | 445 | int ret; |
| 490 | 446 | ||
| 491 | if (phba->state & BE_ADAPTER_PCI_ERR) { | 447 | if (!beiscsi_hba_is_online(phba)) { |
| 492 | beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG, | 448 | beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG, |
| 493 | "BS_%d : In PCI_ERROR Recovery\n"); | 449 | "BS_%d : HBA in error 0x%lx\n", phba->state); |
| 494 | return -EBUSY; | 450 | return -EBUSY; |
| 495 | } | 451 | } |
| 496 | 452 | ||
| 453 | /* update interface_handle */ | ||
| 454 | ret = beiscsi_if_get_handle(phba); | ||
| 455 | if (ret) { | ||
| 456 | beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG, | ||
| 457 | "BS_%d : Getting Interface Handle Failed\n"); | ||
| 458 | return ret; | ||
| 459 | } | ||
| 460 | |||
| 497 | nla_for_each_attr(attrib, data, dt_len, rm_len) { | 461 | nla_for_each_attr(attrib, data, dt_len, rm_len) { |
| 498 | iface_param = nla_data(attrib); | 462 | iface_param = nla_data(attrib); |
| 499 | 463 | ||
| @@ -512,40 +476,58 @@ int be2iscsi_iface_set_param(struct Scsi_Host *shost, · 12 unmodified lines | |||
| 512 | return -EINVAL; | 476 | return -EINVAL; |
| 513 | } | 477 | } |
| 514 | 478 | ||
| 515 | switch (iface_param->iface_type) { | 479 | beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG, |
| 516 | case ISCSI_IFACE_TYPE_IPV4: | 480 | "BS_%d : %s.0 set param %d", |
| 517 | ret = beiscsi_set_ipv4(shost, iface_param, | 481 | (iface_param->iface_type == ISCSI_IFACE_TYPE_IPV4) ? |
| 518 | data, dt_len); | 482 | "ipv4" : "ipv6", iface_param->param); |
| 519 | break; | 483 | |
| 520 | case ISCSI_IFACE_TYPE_IPV6: | 484 | ret = -EPERM; |
| 521 | ret = beiscsi_set_ipv6(shost, iface_param, | 485 | switch (iface_param->param) { |
| 522 | data, dt_len); | 486 | case ISCSI_NET_PARAM_VLAN_ENABLED: |
| 487 | case ISCSI_NET_PARAM_VLAN_TAG: | ||
| 488 | ret = beiscsi_iface_config_vlan(shost, iface_param); | ||
| 523 | break; | 489 | break; |
| 524 | default: | 490 | default: |
| 525 | beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG, | 491 | switch (iface_param->iface_type) { |
| 526 | "BS_%d : Invalid iface type :%d passed\n", | 492 | case ISCSI_IFACE_TYPE_IPV4: |
| 527 | iface_param->iface_type); | 493 | ret = beiscsi_iface_config_ipv4(shost, |
| 528 | break; | 494 | iface_param, |
| 495 | data, dt_len); | ||
| 496 | break; | ||
| 497 | case ISCSI_IFACE_TYPE_IPV6: | ||
| 498 | ret = beiscsi_iface_config_ipv6(shost, | ||
| 499 | iface_param, | ||
| 500 | data, dt_len); | ||
| 501 | break; | ||
| 502 | } | ||
| 529 | } | 503 | } |
| 530 | 504 | ||
| 505 | if (ret == -EPERM) { | ||
| 506 | __beiscsi_log(phba, KERN_ERR, | ||
| 507 | "BS_%d : %s.0 set param %d not permitted", | ||
| 508 | (iface_param->iface_type == | ||
| 509 | ISCSI_IFACE_TYPE_IPV4) ? "ipv4" : "ipv6", | ||
| 510 | iface_param->param); | ||
| 511 | ret = 0; | ||
| 512 | } | ||
| 531 | if (ret) | 513 | if (ret) |
| 532 | return ret; | 514 | break; |
| 533 | } | 515 | } |
| 534 | 516 | ||
| 535 | return ret; | 517 | return ret; |
| 536 | } | 518 | } |
| 537 | 519 | ||
| 538 | static int be2iscsi_get_if_param(struct beiscsi_hba *phba, | 520 | static int __beiscsi_iface_get_param(struct beiscsi_hba *phba, |
| 539 | struct iscsi_iface *iface, int param, | 521 | struct iscsi_iface *iface, |
| 540 | char *buf) | 522 | int param, char *buf) |
| 541 | { | 523 | { |
| 542 | struct be_cmd_get_if_info_resp *if_info; | 524 | struct be_cmd_get_if_info_resp *if_info; |
| 543 | int len, ip_type = BE2_IPV4; | 525 | int len, ip_type = BEISCSI_IP_TYPE_V4; |
| 544 | 526 | ||
| 545 | if (iface->iface_type == ISCSI_IFACE_TYPE_IPV6) | 527 | if (iface->iface_type == ISCSI_IFACE_TYPE_IPV6) |
| 546 | ip_type = BE2_IPV6; | 528 | ip_type = BEISCSI_IP_TYPE_V6; |
| 547 | 529 | ||
| 548 | len = mgmt_get_if_info(phba, ip_type, &if_info); | 530 | len = beiscsi_if_get_info(phba, ip_type, &if_info); |
| 549 | if (len) | 531 | if (len) |
| 550 | return len; | 532 | return len; |
| 551 | 533 | ||
| @@ -567,24 +549,24 @@ static int be2iscsi_get_if_param(struct beiscsi_hba *phba, · 15 unmodified lines | |||
| 567 | break; | 549 | break; |
| 568 | case ISCSI_NET_PARAM_VLAN_ENABLED: | 550 | case ISCSI_NET_PARAM_VLAN_ENABLED: |
| 569 | len = sprintf(buf, "%s\n", | 551 | len = sprintf(buf, "%s\n", |
| 570 | (if_info->vlan_priority == BEISCSI_VLAN_DISABLE) | 552 | (if_info->vlan_priority == BEISCSI_VLAN_DISABLE) ? |
| 571 | ? "Disabled\n" : "Enabled\n"); | 553 | "disable" : "enable"); |
| 572 | break; | 554 | break; |
| 573 | case ISCSI_NET_PARAM_VLAN_ID: | 555 | case ISCSI_NET_PARAM_VLAN_ID: |
| 574 | if (if_info->vlan_priority == BEISCSI_VLAN_DISABLE) | 556 | if (if_info->vlan_priority == BEISCSI_VLAN_DISABLE) |
| 575 | len = -EINVAL; | 557 | len = -EINVAL; |
| 576 | else | 558 | else |
| 577 | len = sprintf(buf, "%d\n", | 559 | len = sprintf(buf, "%d\n", |
| 578 | (if_info->vlan_priority & | 560 | (if_info->vlan_priority & |
| 579 | ISCSI_MAX_VLAN_ID)); | 561 | ISCSI_MAX_VLAN_ID)); |
| 580 | break; | 562 | break; |
| 581 | case ISCSI_NET_PARAM_VLAN_PRIORITY: | 563 | case ISCSI_NET_PARAM_VLAN_PRIORITY: |
| 582 | if (if_info->vlan_priority == BEISCSI_VLAN_DISABLE) | 564 | if (if_info->vlan_priority == BEISCSI_VLAN_DISABLE) |
| 583 | len = -EINVAL; | 565 | len = -EINVAL; |
| 584 | else | 566 | else |
| 585 | len = sprintf(buf, "%d\n", | 567 | len = sprintf(buf, "%d\n", |
| 586 | ((if_info->vlan_priority >> 13) & | 568 | ((if_info->vlan_priority >> 13) & |
| 587 | ISCSI_MAX_VLAN_PRIORITY)); | 569 | ISCSI_MAX_VLAN_PRIORITY)); |
| 588 | break; | 570 | break; |
| 589 | default: | 571 | default: |
| 590 | WARN_ON(1); | 572 | WARN_ON(1); |
| @@ -594,18 +576,20 @@ static int be2iscsi_get_if_param(struct beiscsi_hba *phba, · 3 unmodified lines | |||
| 594 | return len; | 576 | return len; |
| 595 | } | 577 | } |
| 596 | 578 | ||
| 597 | int be2iscsi_iface_get_param(struct iscsi_iface *iface, | 579 | int beiscsi_iface_get_param(struct iscsi_iface *iface, |
| 598 | enum iscsi_param_type param_type, | 580 | enum iscsi_param_type param_type, |
| 599 | int param, char *buf) | 581 | int param, char *buf) |
| 600 | { | 582 | { |
| 601 | struct Scsi_Host *shost = iscsi_iface_to_shost(iface); | 583 | struct Scsi_Host *shost = iscsi_iface_to_shost(iface); |
| 602 | struct beiscsi_hba *phba = iscsi_host_priv(shost); | 584 | struct beiscsi_hba *phba = iscsi_host_priv(shost); |
| 603 | struct be_cmd_get_def_gateway_resp gateway; | 585 | struct be_cmd_get_def_gateway_resp gateway; |
| 604 | int len = -ENOSYS; | 586 | int len = -EPERM; |
| 605 | 587 | ||
| 606 | if (phba->state & BE_ADAPTER_PCI_ERR) { | 588 | if (param_type != ISCSI_NET_PARAM) |
| 607 | beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG, | 589 | return 0; |
| 608 | "BS_%d : In PCI_ERROR Recovery\n"); | 590 | if (!beiscsi_hba_is_online(phba)) { |
| 591 | beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG, | ||
| 592 | "BS_%d : HBA in error 0x%lx\n", phba->state); | ||
| 609 | return -EBUSY; | 593 | return -EBUSY; |
| 610 | } | 594 | } |
| 611 | 595 | ||
| @@ -617,19 +601,22 @@ int be2iscsi_iface_get_param(struct iscsi_iface *iface, · 5 unmodified lines | |||
| 617 | case ISCSI_NET_PARAM_VLAN_ENABLED: | 601 | case ISCSI_NET_PARAM_VLAN_ENABLED: |
| 618 | case ISCSI_NET_PARAM_VLAN_ID: | 602 | case ISCSI_NET_PARAM_VLAN_ID: |
| 619 | case ISCSI_NET_PARAM_VLAN_PRIORITY: | 603 | case ISCSI_NET_PARAM_VLAN_PRIORITY: |
| 620 | len = be2iscsi_get_if_param(phba, iface, param, buf); | 604 | len = __beiscsi_iface_get_param(phba, iface, param, buf); |
| 621 | break; | 605 | break; |
| 622 | case ISCSI_NET_PARAM_IFACE_ENABLE: | 606 | case ISCSI_NET_PARAM_IFACE_ENABLE: |
| 623 | len = sprintf(buf, "enabled\n"); | 607 | if (iface->iface_type == ISCSI_IFACE_TYPE_IPV4) |
| 608 | len = sprintf(buf, "%s\n", | ||
| 609 | phba->ipv4_iface ? "enable" : "disable"); | ||
| 610 | else if (iface->iface_type == ISCSI_IFACE_TYPE_IPV6) | ||
| 611 | len = sprintf(buf, "%s\n", | ||
| 612 | phba->ipv6_iface ? "enable" : "disable"); | ||
| 624 | break; | 613 | break; |
| 625 | case ISCSI_NET_PARAM_IPV4_GW: | 614 | case ISCSI_NET_PARAM_IPV4_GW: |
| 626 | memset(&gateway, 0, sizeof(gateway)); | 615 | memset(&gateway, 0, sizeof(gateway)); |
| 627 | len = mgmt_get_gateway(phba, BE2_IPV4, &gateway); | 616 | len = beiscsi_if_get_gw(phba, BEISCSI_IP_TYPE_V4, &gateway); |
| 628 | if (!len) | 617 | if (!len) |
| 629 | len = sprintf(buf, "%pI4\n", &gateway.ip_addr.addr); | 618 | len = sprintf(buf, "%pI4\n", &gateway.ip_addr.addr); |
| 630 | break; | 619 | break; |
| 631 | default: | ||
| 632 | len = -ENOSYS; | ||
| 633 | } | 620 | } |
| 634 | 621 | ||
| 635 | return len; | 622 | return len; |
| @@ -647,7 +634,7 @@ int beiscsi_ep_get_param(struct iscsi_endpoint *ep, · 11 unmodified lines | |||
| 647 | enum iscsi_param param, char *buf) | 634 | enum iscsi_param param, char *buf) |
| 648 | { | 635 | { |
| 649 | struct beiscsi_endpoint *beiscsi_ep = ep->dd_data; | 636 | struct beiscsi_endpoint *beiscsi_ep = ep->dd_data; |
| 650 | int len = 0; | 637 | int len; |
| 651 | 638 | ||
| 652 | beiscsi_log(beiscsi_ep->phba, KERN_INFO, | 639 | beiscsi_log(beiscsi_ep->phba, KERN_INFO, |
| 653 | BEISCSI_LOG_CONFIG, | 640 | BEISCSI_LOG_CONFIG, |
| @@ -659,13 +646,13 @@ int beiscsi_ep_get_param(struct iscsi_endpoint *ep, · 5 unmodified lines | |||
| 659 | len = sprintf(buf, "%hu\n", beiscsi_ep->dst_tcpport); | 646 | len = sprintf(buf, "%hu\n", beiscsi_ep->dst_tcpport); |
| 660 | break; | 647 | break; |
| 661 | case ISCSI_PARAM_CONN_ADDRESS: | 648 | case ISCSI_PARAM_CONN_ADDRESS: |
| 662 | if (beiscsi_ep->ip_type == BE2_IPV4) | 649 | if (beiscsi_ep->ip_type == BEISCSI_IP_TYPE_V4) |
| 663 | len = sprintf(buf, "%pI4\n", &beiscsi_ep->dst_addr); | 650 | len = sprintf(buf, "%pI4\n", &beiscsi_ep->dst_addr); |
| 664 | else | 651 | else |
| 665 | len = sprintf(buf, "%pI6\n", &beiscsi_ep->dst6_addr); | 652 | len = sprintf(buf, "%pI6\n", &beiscsi_ep->dst6_addr); |
| 666 | break; | 653 | break; |
| 667 | default: | 654 | default: |
| 668 | return -ENOSYS; | 655 | len = -EPERM; |
| 669 | } | 656 | } |
| 670 | return len; | 657 | return len; |
| 671 | } | 658 | } |
| @@ -758,7 +745,7 @@ static void beiscsi_get_port_state(struct Scsi_Host *shost) · 86 unmodified lines | |||
| 758 | struct beiscsi_hba *phba = iscsi_host_priv(shost); | 745 | struct beiscsi_hba *phba = iscsi_host_priv(shost); |
| 759 | struct iscsi_cls_host *ihost = shost->shost_data; | 746 | struct iscsi_cls_host *ihost = shost->shost_data; |
| 760 | 747 | ||
| 761 | ihost->port_state = (phba->state & BE_ADAPTER_LINK_UP) ? | 748 | ihost->port_state = test_bit(BEISCSI_HBA_LINK_UP, &phba->state) ? |
| 762 | ISCSI_PORT_STATE_UP : ISCSI_PORT_STATE_DOWN; | 749 | ISCSI_PORT_STATE_UP : ISCSI_PORT_STATE_DOWN; |
| 763 | } | 750 | } |
| 764 | 751 | ||
| @@ -810,16 +797,13 @@ int beiscsi_get_host_param(struct Scsi_Host *shost, · 45 unmodified lines | |||
| 810 | struct beiscsi_hba *phba = iscsi_host_priv(shost); | 797 | struct beiscsi_hba *phba = iscsi_host_priv(shost); |
| 811 | int status = 0; | 798 | int status = 0; |
| 812 | 799 | ||
| 813 | 800 | if (!beiscsi_hba_is_online(phba)) { | |
| 814 | if (phba->state & BE_ADAPTER_PCI_ERR) { | ||
| 815 | beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG, | ||
| 816 | "BS_%d : In PCI_ERROR Recovery\n"); | ||
| 817 | return -EBUSY; | ||
| 818 | } else { | ||
| 819 | beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG, | 801 | beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG, |
| 820 | "BS_%d : In beiscsi_get_host_param," | 802 | "BS_%d : HBA in error 0x%lx\n", phba->state); |
| 821 | " param = %d\n", param); | 803 | return -EBUSY; |
| 822 | } | 804 | } |
| 805 | beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG, | ||
| 806 | "BS_%d : In beiscsi_get_host_param, param = %d\n", param); | ||
| 823 | 807 | ||
| 824 | switch (param) { | 808 | switch (param) { |
| 825 | case ISCSI_HOST_PARAM_HWADDRESS: | 809 | case ISCSI_HOST_PARAM_HWADDRESS: |
| @@ -961,15 +945,13 @@ int beiscsi_conn_start(struct iscsi_cls_conn *cls_conn) · 135 unmodified lines | |||
| 961 | 945 | ||
| 962 | phba = ((struct beiscsi_conn *)conn->dd_data)->phba; | 946 | phba = ((struct beiscsi_conn *)conn->dd_data)->phba; |
| 963 | 947 | ||
| 964 | if (phba->state & BE_ADAPTER_PCI_ERR) { | 948 | if (!beiscsi_hba_is_online(phba)) { |
| 965 | beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG, | 949 | beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG, |
| 966 | "BS_%d : In PCI_ERROR Recovery\n"); | 950 | "BS_%d : HBA in error 0x%lx\n", phba->state); |
| 967 | return -EBUSY; | 951 | return -EBUSY; |
| 968 | } else { | ||
| 969 | beiscsi_log(beiscsi_conn->phba, KERN_INFO, | ||
| 970 | BEISCSI_LOG_CONFIG, | ||
| 971 | "BS_%d : In beiscsi_conn_start\n"); | ||
| 972 | } | 952 | } |
| 953 | beiscsi_log(beiscsi_conn->phba, KERN_INFO, BEISCSI_LOG_CONFIG, | ||
| 954 | "BS_%d : In beiscsi_conn_start\n"); | ||
| 973 | 955 | ||
| 974 | memset(¶ms, 0, sizeof(struct beiscsi_offload_params)); | 956 | memset(¶ms, 0, sizeof(struct beiscsi_offload_params)); |
| 975 | beiscsi_ep = beiscsi_conn->ep; | 957 | beiscsi_ep = beiscsi_conn->ep; |
| @@ -1186,28 +1168,20 @@ beiscsi_ep_connect(struct Scsi_Host *shost, struct sockaddr *dst_addr, · 210 unmodified lines | |||
| 1186 | struct iscsi_endpoint *ep; | 1168 | struct iscsi_endpoint *ep; |
| 1187 | int ret; | 1169 | int ret; |
| 1188 | 1170 | ||
| 1189 | if (shost) | 1171 | if (!shost) { |
| 1190 | phba = iscsi_host_priv(shost); | ||
| 1191 | else { | ||
| 1192 | ret = -ENXIO; | 1172 | ret = -ENXIO; |
| 1193 | printk(KERN_ERR | 1173 | pr_err("beiscsi_ep_connect shost is NULL\n"); |
| 1194 | "beiscsi_ep_connect shost is NULL\n"); | ||
| 1195 | return ERR_PTR(ret); | 1174 | return ERR_PTR(ret); |
| 1196 | } | 1175 | } |
| 1197 | 1176 | ||
| 1198 | if (beiscsi_error(phba)) { | 1177 | phba = iscsi_host_priv(shost); |
| 1178 | if (!beiscsi_hba_is_online(phba)) { | ||
| 1199 | ret = -EIO; | 1179 | ret = -EIO; |
| 1200 | beiscsi_log(phba, KERN_WARNING, BEISCSI_LOG_CONFIG, | 1180 | beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG, |
| 1201 | "BS_%d : The FW state Not Stable!!!\n"); | 1181 | "BS_%d : HBA in error 0x%lx\n", phba->state); |
| 1202 | return ERR_PTR(ret); | 1182 | return ERR_PTR(ret); |
| 1203 | } | 1183 | } |
| 1204 | 1184 | if (!test_bit(BEISCSI_HBA_LINK_UP, &phba->state)) { | |
| 1205 | if (phba->state & BE_ADAPTER_PCI_ERR) { | ||
| 1206 | ret = -EBUSY; | ||
| 1207 | beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG, | ||
| 1208 | "BS_%d : In PCI_ERROR Recovery\n"); | ||
| 1209 | return ERR_PTR(ret); | ||
| 1210 | } else if (phba->state & BE_ADAPTER_LINK_DOWN) { | ||
| 1211 | ret = -EBUSY; | 1185 | ret = -EBUSY; |
| 1212 | beiscsi_log(phba, KERN_WARNING, BEISCSI_LOG_CONFIG, | 1186 | beiscsi_log(phba, KERN_WARNING, BEISCSI_LOG_CONFIG, |
| 1213 | "BS_%d : The Adapter Port state is Down!!!\n"); | 1187 | "BS_%d : The Adapter Port state is Down!!!\n"); |
| @@ -1361,9 +1335,9 @@ void beiscsi_ep_disconnect(struct iscsi_endpoint *ep) · 147 unmodified lines | |||
| 1361 | tcp_upload_flag = CONNECTION_UPLOAD_ABORT; | 1335 | tcp_upload_flag = CONNECTION_UPLOAD_ABORT; |
| 1362 | } | 1336 | } |
| 1363 | 1337 | ||
| 1364 | if (phba->state & BE_ADAPTER_PCI_ERR) { | 1338 | if (!beiscsi_hba_is_online(phba)) { |
| 1365 | beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG, | 1339 | beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG, |
| 1366 | "BS_%d : PCI_ERROR Recovery\n"); | 1340 | "BS_%d : HBA in error 0x%lx\n", phba->state); |
| 1367 | goto free_ep; | 1341 | goto free_ep; |
| 1368 | } | 1342 | } |
| 1369 | 1343 | ||
| @@ -1386,7 +1360,7 @@ free_ep: · 16 unmodified lines | |||
| 1386 | iscsi_destroy_endpoint(beiscsi_ep->openiscsi_ep); | 1360 | iscsi_destroy_endpoint(beiscsi_ep->openiscsi_ep); |
| 1387 | } | 1361 | } |
| 1388 | 1362 | ||
| 1389 | umode_t be2iscsi_attr_is_visible(int param_type, int param) | 1363 | umode_t beiscsi_attr_is_visible(int param_type, int param) |
| 1390 | { | 1364 | { |
| 1391 | switch (param_type) { | 1365 | switch (param_type) { |
| 1392 | case ISCSI_NET_PARAM: | 1366 | case ISCSI_NET_PARAM: |
| @@ -1,5 +1,5 @@ | |||
| 1 | /** | 1 | /** |
| 2 | * Copyright (C) 2005 - 2015 Avago Technologies | 2 | * Copyright (C) 2005 - 2016 Broadcom |
| 3 | * All rights reserved. | 3 | * All rights reserved. |
| 4 | * | 4 | * |
| 5 | * This program is free software; you can redistribute it and/or | 5 | * This program is free software; you can redistribute it and/or |
| @@ -7,10 +7,10 @@ · 1 unmodified line | |||
| 7 | * as published by the Free Software Foundation. The full GNU General | 7 | * as published by the Free Software Foundation. The full GNU General |
| 8 | * Public License is included in this distribution in the file called COPYING. | 8 | * Public License is included in this distribution in the file called COPYING. |
| 9 | * | 9 | * |
| 10 | * Written by: Jayamohan Kallickal (jayamohan.kallickal@avagotech.com) | 10 | * Written by: Jayamohan Kallickal (jayamohan.kallickal@broadcom.com) |
| 11 | * | 11 | * |
| 12 | * Contact Information: | 12 | * Contact Information: |
| 13 | * linux-drivers@avagotech.com | 13 | * linux-drivers@broadcom.com |
| 14 | * | 14 | * |
| 15 | * Avago Technologies | 15 | * Avago Technologies |
| 16 | * 3333 Susan Street | 16 | * 3333 Susan Street |
| @@ -23,25 +23,18 @@ · 6 unmodified lines | |||
| 23 | #include "be_main.h" | 23 | #include "be_main.h" |
| 24 | #include "be_mgmt.h" | 24 | #include "be_mgmt.h" |
| 25 | 25 | ||
| 26 | #define BE2_IPV4 0x1 | 26 | void beiscsi_iface_create_default(struct beiscsi_hba *phba); |
| 27 | #define BE2_IPV6 0x10 | ||
| 28 | #define BE2_DHCP_V4 0x05 | ||
| 29 | 27 | ||
| 30 | #define NON_BLOCKING 0x0 | 28 | void beiscsi_iface_destroy_default(struct beiscsi_hba *phba); |
| 31 | #define BLOCKING 0x1 | ||
| 32 | 29 | ||
| 33 | void beiscsi_create_def_ifaces(struct beiscsi_hba *phba); | 30 | int beiscsi_iface_get_param(struct iscsi_iface *iface, |
| 34 | |||
| 35 | void beiscsi_destroy_def_ifaces(struct beiscsi_hba *phba); | ||
| 36 | |||
| 37 | int be2iscsi_iface_get_param(struct iscsi_iface *iface, | ||
| 38 | enum iscsi_param_type param_type, | 31 | enum iscsi_param_type param_type, |
| 39 | int param, char *buf); | 32 | int param, char *buf); |
| 40 | 33 | ||
| 41 | int be2iscsi_iface_set_param(struct Scsi_Host *shost, | 34 | int beiscsi_iface_set_param(struct Scsi_Host *shost, |
| 42 | void *data, uint32_t count); | 35 | void *data, uint32_t count); |
| 43 | 36 | ||
| 44 | umode_t be2iscsi_attr_is_visible(int param_type, int param); | 37 | umode_t beiscsi_attr_is_visible(int param_type, int param); |
| 45 | 38 | ||
| 46 | void beiscsi_offload_connection(struct beiscsi_conn *beiscsi_conn, | 39 | void beiscsi_offload_connection(struct beiscsi_conn *beiscsi_conn, |
| 47 | struct beiscsi_offload_params *params); | 40 | struct beiscsi_offload_params *params); |
| @@ -57,6 +50,8 @@ struct iscsi_cls_session *beiscsi_session_create(struct iscsi_endpoint *ep, · 9 unmodified lines | |||
| 57 | 50 | ||
| 58 | void beiscsi_session_destroy(struct iscsi_cls_session *cls_session); | 51 | void beiscsi_session_destroy(struct iscsi_cls_session *cls_session); |
| 59 | 52 | ||
| 53 | void beiscsi_session_fail(struct iscsi_cls_session *cls_session); | ||
| 54 | |||
| 60 | struct iscsi_cls_conn *beiscsi_conn_create(struct iscsi_cls_session | 55 | struct iscsi_cls_conn *beiscsi_conn_create(struct iscsi_cls_session |
| 61 | *cls_session, uint32_t cid); | 56 | *cls_session, uint32_t cid); |
| 62 | 57 | ||
| @@ -1,5 +1,5 @@ | |||
| 1 | /** | 1 | /** |
| 2 | * Copyright (C) 2005 - 2015 Emulex | 2 | * Copyright (C) 2005 - 2016 Broadcom |
| 3 | * All rights reserved. | 3 | * All rights reserved. |
| 4 | * | 4 | * |
| 5 | * This program is free software; you can redistribute it and/or | 5 | * This program is free software; you can redistribute it and/or |
| @@ -7,10 +7,10 @@ · 1 unmodified line | |||
| 7 | * as published by the Free Software Foundation. The full GNU General | 7 | * as published by the Free Software Foundation. The full GNU General |
| 8 | * Public License is included in this distribution in the file called COPYING. | 8 | * Public License is included in this distribution in the file called COPYING. |
| 9 | * | 9 | * |
| 10 | * Written by: Jayamohan Kallickal (jayamohan.kallickal@avagotech.com) | 10 | * Written by: Jayamohan Kallickal (jayamohan.kallickal@broadcom.com) |
| 11 | * | 11 | * |
| 12 | * Contact Information: | 12 | * Contact Information: |
| 13 | * linux-drivers@avagotech.com | 13 | * linux-drivers@broadcom.com |
| 14 | * | 14 | * |
| 15 | * Emulex | 15 | * Emulex |
| 16 | * 3333 Susan Street | 16 | * 3333 Susan Street |
| @@ -374,170 +374,6 @@ static int beiscsi_eh_device_reset(struct scsi_cmnd *sc) · 357 unmodified lines | |||
| 374 | return iscsi_eh_device_reset(sc); | 374 | return iscsi_eh_device_reset(sc); |
| 375 | } | 375 | } |
| 376 | 376 | ||
| 377 | static ssize_t beiscsi_show_boot_tgt_info(void *data, int type, char *buf) | ||
| 378 | { | ||
| 379 | struct beiscsi_hba *phba = data; | ||
| 380 | struct mgmt_session_info *boot_sess = &phba->boot_sess; | ||
| 381 | struct mgmt_conn_info *boot_conn = &boot_sess->conn_list[0]; | ||
| 382 | char *str = buf; | ||
| 383 | int rc; | ||
| 384 | |||
| 385 | switch (type) { | ||
| 386 | case ISCSI_BOOT_TGT_NAME: | ||
| 387 | rc = sprintf(buf, "%.*s\n", | ||
| 388 | (int)strlen(boot_sess->target_name), | ||
| 389 | (char *)&boot_sess->target_name); | ||
| 390 | break; | ||
| 391 | case ISCSI_BOOT_TGT_IP_ADDR: | ||
| 392 | if (boot_conn->dest_ipaddr.ip_type == 0x1) | ||
| 393 | rc = sprintf(buf, "%pI4\n", | ||
| 394 | (char *)&boot_conn->dest_ipaddr.addr); | ||
| 395 | else | ||
| 396 | rc = sprintf(str, "%pI6\n", | ||
| 397 | (char *)&boot_conn->dest_ipaddr.addr); | ||
| 398 | break; | ||
| 399 | case ISCSI_BOOT_TGT_PORT: | ||
| 400 | rc = sprintf(str, "%d\n", boot_conn->dest_port); | ||
| 401 | break; | ||
| 402 | |||
| 403 | case ISCSI_BOOT_TGT_CHAP_NAME: | ||
| 404 | rc = sprintf(str, "%.*s\n", | ||
| 405 | boot_conn->negotiated_login_options.auth_data.chap. | ||
| 406 | target_chap_name_length, | ||
| 407 | (char *)&boot_conn->negotiated_login_options. | ||
| 408 | auth_data.chap.target_chap_name); | ||
| 409 | break; | ||
| 410 | case ISCSI_BOOT_TGT_CHAP_SECRET: | ||
| 411 | rc = sprintf(str, "%.*s\n", | ||
| 412 | boot_conn->negotiated_login_options.auth_data.chap. | ||
| 413 | target_secret_length, | ||
| 414 | (char *)&boot_conn->negotiated_login_options. | ||
| 415 | auth_data.chap.target_secret); | ||
| 416 | break; | ||
| 417 | case ISCSI_BOOT_TGT_REV_CHAP_NAME: | ||
| 418 | rc = sprintf(str, "%.*s\n", | ||
| 419 | boot_conn->negotiated_login_options.auth_data.chap. | ||
| 420 | intr_chap_name_length, | ||
| 421 | (char *)&boot_conn->negotiated_login_options. | ||
| 422 | auth_data.chap.intr_chap_name); | ||
| 423 | break; | ||
| 424 | case ISCSI_BOOT_TGT_REV_CHAP_SECRET: | ||
| 425 | rc = sprintf(str, "%.*s\n", | ||
| 426 | boot_conn->negotiated_login_options.auth_data.chap. | ||
| 427 | intr_secret_length, | ||
| 428 | (char *)&boot_conn->negotiated_login_options. | ||
| 429 | auth_data.chap.intr_secret); | ||
| 430 | break; | ||
| 431 | case ISCSI_BOOT_TGT_FLAGS: | ||
| 432 | rc = sprintf(str, "2\n"); | ||
| 433 | break; | ||
| 434 | case ISCSI_BOOT_TGT_NIC_ASSOC: | ||
| 435 | rc = sprintf(str, "0\n"); | ||
| 436 | break; | ||
| 437 | default: | ||
| 438 | rc = -ENOSYS; | ||
| 439 | break; | ||
| 440 | } | ||
| 441 | return rc; | ||
| 442 | } | ||
| 443 | |||
| 444 | static ssize_t beiscsi_show_boot_ini_info(void *data, int type, char *buf) | ||
| 445 | { | ||
| 446 | struct beiscsi_hba *phba = data; | ||
| 447 | char *str = buf; | ||
| 448 | int rc; | ||
| 449 | |||
| 450 | switch (type) { | ||
| 451 | case ISCSI_BOOT_INI_INITIATOR_NAME: | ||
| 452 | rc = sprintf(str, "%s\n", phba->boot_sess.initiator_iscsiname); | ||
| 453 | break; | ||
| 454 | default: | ||
| 455 | rc = -ENOSYS; | ||
| 456 | break; | ||
| 457 | } | ||
| 458 | return rc; | ||
| 459 | } | ||
| 460 | |||
| 461 | static ssize_t beiscsi_show_boot_eth_info(void *data, int type, char *buf) | ||
| 462 | { | ||
| 463 | struct beiscsi_hba *phba = data; | ||
| 464 | char *str = buf; | ||
| 465 | int rc; | ||
| 466 | |||
| 467 | switch (type) { | ||
| 468 | case ISCSI_BOOT_ETH_FLAGS: | ||
| 469 | rc = sprintf(str, "2\n"); | ||
| 470 | break; | ||
| 471 | case ISCSI_BOOT_ETH_INDEX: | ||
| 472 | rc = sprintf(str, "0\n"); | ||
| 473 | break; | ||
| 474 | case ISCSI_BOOT_ETH_MAC: | ||
| 475 | rc = beiscsi_get_macaddr(str, phba); | ||
| 476 | break; | ||
| 477 | default: | ||
| 478 | rc = -ENOSYS; | ||
| 479 | break; | ||
| 480 | } | ||
| 481 | return rc; | ||
| 482 | } | ||
| 483 | |||
| 484 | |||
| 485 | static umode_t beiscsi_tgt_get_attr_visibility(void *data, int type) | ||
| 486 | { | ||
| 487 | umode_t rc; | ||
| 488 | |||
| 489 | switch (type) { | ||
| 490 | case ISCSI_BOOT_TGT_NAME: | ||
| 491 | case ISCSI_BOOT_TGT_IP_ADDR: | ||
| 492 | case ISCSI_BOOT_TGT_PORT: | ||
| 493 | case ISCSI_BOOT_TGT_CHAP_NAME: | ||
| 494 | case ISCSI_BOOT_TGT_CHAP_SECRET: | ||
| 495 | case ISCSI_BOOT_TGT_REV_CHAP_NAME: | ||
| 496 | case ISCSI_BOOT_TGT_REV_CHAP_SECRET: | ||
| 497 | case ISCSI_BOOT_TGT_NIC_ASSOC: | ||
| 498 | case ISCSI_BOOT_TGT_FLAGS: | ||
| 499 | rc = S_IRUGO; | ||
| 500 | break; | ||
| 501 | default: | ||
| 502 | rc = 0; | ||
| 503 | break; | ||
| 504 | } | ||
| 505 | return rc; | ||
| 506 | } | ||
| 507 | |||
| 508 | static umode_t beiscsi_ini_get_attr_visibility(void *data, int type) | ||
| 509 | { | ||
| 510 | umode_t rc; | ||
| 511 | |||
| 512 | switch (type) { | ||
| 513 | case ISCSI_BOOT_INI_INITIATOR_NAME: | ||
| 514 | rc = S_IRUGO; | ||
| 515 | break; | ||
| 516 | default: | ||
| 517 | rc = 0; | ||
| 518 | break; | ||
| 519 | } | ||
| 520 | return rc; | ||
| 521 | } | ||
| 522 | |||
| 523 | |||
| 524 | static umode_t beiscsi_eth_get_attr_visibility(void *data, int type) | ||
| 525 | { | ||
| 526 | umode_t rc; | ||
| 527 | |||
| 528 | switch (type) { | ||
| 529 | case ISCSI_BOOT_ETH_FLAGS: | ||
| 530 | case ISCSI_BOOT_ETH_MAC: | ||
| 531 | case ISCSI_BOOT_ETH_INDEX: | ||
| 532 | rc = S_IRUGO; | ||
| 533 | break; | ||
| 534 | default: | ||
| 535 | rc = 0; | ||
| 536 | break; | ||
| 537 | } | ||
| 538 | return rc; | ||
| 539 | } | ||
| 540 | |||
| 541 | /*------------------- PCI Driver operations and data ----------------- */ | 377 | /*------------------- PCI Driver operations and data ----------------- */ |
| 542 | static const struct pci_device_id beiscsi_pci_id_table[] = { | 378 | static const struct pci_device_id beiscsi_pci_id_table[] = { |
| 543 | { PCI_DEVICE(BE_VENDOR_ID, BE_DEVICE_ID1) }, | 379 | { PCI_DEVICE(BE_VENDOR_ID, BE_DEVICE_ID1) }, |
| @@ -850,12 +686,11 @@ static void hwi_ring_eq_db(struct beiscsi_hba *phba, · 306 unmodified lines | |||
| 850 | static irqreturn_t be_isr_mcc(int irq, void *dev_id) | 686 | static irqreturn_t be_isr_mcc(int irq, void *dev_id) |
| 851 | { | 687 | { |
| 852 | struct beiscsi_hba *phba; | 688 | struct beiscsi_hba *phba; |
| 853 | struct be_eq_entry *eqe = NULL; | 689 | struct be_eq_entry *eqe; |
| 854 | struct be_queue_info *eq; | 690 | struct be_queue_info *eq; |
| 855 | struct be_queue_info *mcc; | 691 | struct be_queue_info *mcc; |
| 856 | unsigned int num_eq_processed; | 692 | unsigned int mcc_events; |
| 857 | struct be_eq_obj *pbe_eq; | 693 | struct be_eq_obj *pbe_eq; |
| 858 | unsigned long flags; | ||
| 859 | 694 | ||
| 860 | pbe_eq = dev_id; | 695 | pbe_eq = dev_id; |
| 861 | eq = &pbe_eq->q; | 696 | eq = &pbe_eq->q; |
| @@ -863,27 +698,23 @@ static irqreturn_t be_isr_mcc(int irq, void *dev_id) · 1 unmodified line | |||
| 863 | mcc = &phba->ctrl.mcc_obj.cq; | 698 | mcc = &phba->ctrl.mcc_obj.cq; |
| 864 | eqe = queue_tail_node(eq); | 699 | eqe = queue_tail_node(eq); |
| 865 | 700 | ||
| 866 | num_eq_processed = 0; | 701 | mcc_events = 0; |
| 867 | |||
| 868 | while (eqe->dw[offsetof(struct amap_eq_entry, valid) / 32] | 702 | while (eqe->dw[offsetof(struct amap_eq_entry, valid) / 32] |
| 869 | & EQE_VALID_MASK) { | 703 | & EQE_VALID_MASK) { |
| 870 | if (((eqe->dw[offsetof(struct amap_eq_entry, | 704 | if (((eqe->dw[offsetof(struct amap_eq_entry, |
| 871 | resource_id) / 32] & | 705 | resource_id) / 32] & |
| 872 | EQE_RESID_MASK) >> 16) == mcc->id) { | 706 | EQE_RESID_MASK) >> 16) == mcc->id) { |
| 873 | spin_lock_irqsave(&phba->isr_lock, flags); | 707 | mcc_events++; |
| 874 | pbe_eq->todo_mcc_cq = true; | ||
| 875 | spin_unlock_irqrestore(&phba->isr_lock, flags); | ||
| 876 | } | 708 | } |
| 877 | AMAP_SET_BITS(struct amap_eq_entry, valid, eqe, 0); | 709 | AMAP_SET_BITS(struct amap_eq_entry, valid, eqe, 0); |
| 878 | queue_tail_inc(eq); | 710 | queue_tail_inc(eq); |
| 879 | eqe = queue_tail_node(eq); | 711 | eqe = queue_tail_node(eq); |
| 880 | num_eq_processed++; | ||
| 881 | } | 712 | } |
| 882 | if (pbe_eq->todo_mcc_cq) | ||
| 883 | queue_work(phba->wq, &pbe_eq->work_cqs); | ||
| 884 | if (num_eq_processed) | ||
| 885 | hwi_ring_eq_db(phba, eq->id, 1, num_eq_processed, 1, 1); | ||
| 886 | 713 | ||
| 714 | if (mcc_events) { | ||
| 715 | queue_work(phba->wq, &pbe_eq->mcc_work); | ||
| 716 | hwi_ring_eq_db(phba, eq->id, 1, mcc_events, 1, 1); | ||
| 717 | } | ||
| 887 | return IRQ_HANDLED; | 718 | return IRQ_HANDLED; |
| 888 | } | 719 | } |
| 889 | 720 | ||
| @@ -902,7 +733,6 @@ static irqreturn_t be_isr_msix(int irq, void *dev_id) · 12 unmodified lines | |||
| 902 | eq = &pbe_eq->q; | 733 | eq = &pbe_eq->q; |
| 903 | 734 | ||
| 904 | phba = pbe_eq->phba; | 735 | phba = pbe_eq->phba; |
| 905 | |||
| 906 | /* disable interrupt till iopoll completes */ | 736 | /* disable interrupt till iopoll completes */ |
| 907 | hwi_ring_eq_db(phba, eq->id, 1, 0, 0, 1); | 737 | hwi_ring_eq_db(phba, eq->id, 1, 0, 0, 1); |
| 908 | irq_poll_sched(&pbe_eq->iopoll); | 738 | irq_poll_sched(&pbe_eq->iopoll); |
| @@ -920,14 +750,13 @@ static irqreturn_t be_isr(int irq, void *dev_id) · 11 unmodified lines | |||
| 920 | struct beiscsi_hba *phba; | 750 | struct beiscsi_hba *phba; |
| 921 | struct hwi_controller *phwi_ctrlr; | 751 | struct hwi_controller *phwi_ctrlr; |
| 922 | struct hwi_context_memory *phwi_context; | 752 | struct hwi_context_memory *phwi_context; |
| 923 | struct be_eq_entry *eqe = NULL; | 753 | struct be_eq_entry *eqe; |
| 924 | struct be_queue_info *eq; | 754 | struct be_queue_info *eq; |
| 925 | struct be_queue_info *mcc; | 755 | struct be_queue_info *mcc; |
| 926 | unsigned long flags, index; | 756 | unsigned int mcc_events, io_events; |
| 927 | unsigned int num_mcceq_processed, num_ioeq_processed; | ||
| 928 | struct be_ctrl_info *ctrl; | 757 | struct be_ctrl_info *ctrl; |
| 929 | struct be_eq_obj *pbe_eq; | 758 | struct be_eq_obj *pbe_eq; |
| 930 | int isr; | 759 | int isr, rearm; |
| 931 | 760 | ||
| 932 | phba = dev_id; | 761 | phba = dev_id; |
| 933 | ctrl = &phba->ctrl; | 762 | ctrl = &phba->ctrl; |
| @@ -942,44 +771,35 @@ static irqreturn_t be_isr(int irq, void *dev_id) · 8 unmodified lines | |||
| 942 | 771 | ||
| 943 | eq = &phwi_context->be_eq[0].q; | 772 | eq = &phwi_context->be_eq[0].q; |
| 944 | mcc = &phba->ctrl.mcc_obj.cq; | 773 | mcc = &phba->ctrl.mcc_obj.cq; |
| 945 | index = 0; | ||
| 946 | eqe = queue_tail_node(eq); | 774 | eqe = queue_tail_node(eq); |
| 947 | 775 | ||
| 948 | num_ioeq_processed = 0; | 776 | io_events = 0; |
| 949 | num_mcceq_processed = 0; | 777 | mcc_events = 0; |
| 950 | while (eqe->dw[offsetof(struct amap_eq_entry, valid) / 32] | 778 | while (eqe->dw[offsetof(struct amap_eq_entry, valid) / 32] |
| 951 | & EQE_VALID_MASK) { | 779 | & EQE_VALID_MASK) { |
| 952 | if (((eqe->dw[offsetof(struct amap_eq_entry, | 780 | if (((eqe->dw[offsetof(struct amap_eq_entry, |
| 953 | resource_id) / 32] & | 781 | resource_id) / 32] & EQE_RESID_MASK) >> 16) == mcc->id) |
| 954 | EQE_RESID_MASK) >> 16) == mcc->id) { | 782 | mcc_events++; |
| 955 | spin_lock_irqsave(&phba->isr_lock, flags); | 783 | else |
| 956 | pbe_eq->todo_mcc_cq = true; | 784 | io_events++; |
| 957 | spin_unlock_irqrestore(&phba->isr_lock, flags); | ||
| 958 | num_mcceq_processed++; | ||
| 959 | } else { | ||
| 960 | irq_poll_sched(&pbe_eq->iopoll); | ||
| 961 | num_ioeq_processed++; | ||
| 962 | } | ||
| 963 | AMAP_SET_BITS(struct amap_eq_entry, valid, eqe, 0); | 785 | AMAP_SET_BITS(struct amap_eq_entry, valid, eqe, 0); |
| 964 | queue_tail_inc(eq); | 786 | queue_tail_inc(eq); |
| 965 | eqe = queue_tail_node(eq); | 787 | eqe = queue_tail_node(eq); |
| 966 | } | 788 | } |
| 967 | if (num_ioeq_processed || num_mcceq_processed) { | 789 | if (!io_events && !mcc_events) |
| 968 | if (pbe_eq->todo_mcc_cq) | ||
| 969 | queue_work(phba->wq, &pbe_eq->work_cqs); | ||
| 970 | |||
| 971 | if ((num_mcceq_processed) && (!num_ioeq_processed)) | ||
| 972 | hwi_ring_eq_db(phba, eq->id, 0, | ||
| 973 | (num_ioeq_processed + | ||
| 974 | num_mcceq_processed) , 1, 1); | ||
| 975 | else | ||
| 976 | hwi_ring_eq_db(phba, eq->id, 0, | ||
| 977 | (num_ioeq_processed + | ||
| 978 | num_mcceq_processed), 0, 1); | ||
| 979 | |||
| 980 | return IRQ_HANDLED; | ||
| 981 | } else | ||
| 982 | return IRQ_NONE; | 790 | return IRQ_NONE; |
| 791 | |||
| 792 | /* no need to rearm if interrupt is only for IOs */ | ||
| 793 | rearm = 0; | ||
| 794 | if (mcc_events) { | ||
| 795 | queue_work(phba->wq, &pbe_eq->mcc_work); | ||
| 796 | /* rearm for MCCQ */ | ||
| 797 | rearm = 1; | ||
| 798 | } | ||
| 799 | if (io_events) | ||
| 800 | irq_poll_sched(&pbe_eq->iopoll); | ||
| 801 | hwi_ring_eq_db(phba, eq->id, 0, (io_events + mcc_events), rearm, 1); | ||
| 802 | return IRQ_HANDLED; | ||
| 983 | } | 803 | } |
| 984 | 804 | ||
| 985 | 805 | ||
| @@ -1077,57 +897,6 @@ void hwi_ring_cq_db(struct beiscsi_hba *phba, · 91 unmodified lines | |||
| 1077 | iowrite32(val, phba->db_va + DB_CQ_OFFSET); | 897 | iowrite32(val, phba->db_va + DB_CQ_OFFSET); |
| 1078 | } | 898 | } |
| 1079 | 899 | ||
| 1080 | static unsigned int | ||
| 1081 | beiscsi_process_async_pdu(struct beiscsi_conn *beiscsi_conn, | ||
| 1082 | struct beiscsi_hba *phba, | ||
| 1083 | struct pdu_base *ppdu, | ||
| 1084 | unsigned long pdu_len, | ||
| 1085 | void *pbuffer, unsigned long buf_len) | ||
| 1086 | { | ||
| 1087 | struct iscsi_conn *conn = beiscsi_conn->conn; | ||
| 1088 | struct iscsi_session *session = conn->session; | ||
| 1089 | struct iscsi_task *task; | ||
| 1090 | struct beiscsi_io_task *io_task; | ||
| 1091 | struct iscsi_hdr *login_hdr; | ||
| 1092 | |||
| 1093 | switch (ppdu->dw[offsetof(struct amap_pdu_base, opcode) / 32] & | ||
| 1094 | PDUBASE_OPCODE_MASK) { | ||
| 1095 | case ISCSI_OP_NOOP_IN: | ||
| 1096 | pbuffer = NULL; | ||
| 1097 | buf_len = 0; | ||
| 1098 | break; | ||
| 1099 | case ISCSI_OP_ASYNC_EVENT: | ||
| 1100 | break; | ||
| 1101 | case ISCSI_OP_REJECT: | ||
| 1102 | WARN_ON(!pbuffer); | ||
| 1103 | WARN_ON(!(buf_len == 48)); | ||
| 1104 | beiscsi_log(phba, KERN_ERR, | ||
| 1105 | BEISCSI_LOG_CONFIG | BEISCSI_LOG_IO, | ||
| 1106 | "BM_%d : In ISCSI_OP_REJECT\n"); | ||
| 1107 | break; | ||
| 1108 | case ISCSI_OP_LOGIN_RSP: | ||
| 1109 | case ISCSI_OP_TEXT_RSP: | ||
| 1110 | task = conn->login_task; | ||
| 1111 | io_task = task->dd_data; | ||
| 1112 | login_hdr = (struct iscsi_hdr *)ppdu; | ||
| 1113 | login_hdr->itt = io_task->libiscsi_itt; | ||
| 1114 | break; | ||
| 1115 | default: | ||
| 1116 | beiscsi_log(phba, KERN_WARNING, | ||
| 1117 | BEISCSI_LOG_IO | BEISCSI_LOG_CONFIG, | ||
| 1118 | "BM_%d : Unrecognized opcode 0x%x in async msg\n", | ||
| 1119 | (ppdu-> | ||
| 1120 | dw[offsetof(struct amap_pdu_base, opcode) / 32] | ||
| 1121 | & PDUBASE_OPCODE_MASK)); | ||
| 1122 | return 1; | ||
| 1123 | } | ||
| 1124 | |||
| 1125 | spin_lock_bh(&session->back_lock); | ||
| 1126 | __iscsi_complete_pdu(conn, (struct iscsi_hdr *)ppdu, pbuffer, buf_len); | ||
| 1127 | spin_unlock_bh(&session->back_lock); | ||
| 1128 | return 0; | ||
| 1129 | } | ||
| 1130 | |||
| 1131 | static struct sgl_handle *alloc_io_sgl_handle(struct beiscsi_hba *phba) | 900 | static struct sgl_handle *alloc_io_sgl_handle(struct beiscsi_hba *phba) |
| 1132 | { | 901 | { |
| 1133 | struct sgl_handle *psgl_handle; | 902 | struct sgl_handle *psgl_handle; |
| @@ -1199,6 +968,9 @@ beiscsi_get_wrb_handle(struct hwi_wrb_context *pwrb_context, · 65 unmodified lines | |||
| 1199 | pwrb_context->alloc_index++; | 968 | pwrb_context->alloc_index++; |
| 1200 | spin_unlock_bh(&pwrb_context->wrb_lock); | 969 | spin_unlock_bh(&pwrb_context->wrb_lock); |
| 1201 | 970 | ||
| 971 | if (pwrb_handle) | ||
| 972 | memset(pwrb_handle->pwrb, 0, sizeof(*pwrb_handle->pwrb)); | ||
| 973 | |||
| 1202 | return pwrb_handle; | 974 | return pwrb_handle; |
| 1203 | } | 975 | } |
| 1204 | 976 | ||
| @@ -1440,11 +1212,10 @@ hwi_complete_drvr_msgs(struct beiscsi_conn *beiscsi_conn, · 235 unmodified lines | |||
| 1440 | struct beiscsi_hba *phba, struct sol_cqe *psol) | 1212 | struct beiscsi_hba *phba, struct sol_cqe *psol) |
| 1441 | { | 1213 | { |
| 1442 | struct hwi_wrb_context *pwrb_context; | 1214 | struct hwi_wrb_context *pwrb_context; |
| 1443 | struct wrb_handle *pwrb_handle = NULL; | 1215 | uint16_t wrb_index, cid, cri_index; |
| 1444 | struct hwi_controller *phwi_ctrlr; | 1216 | struct hwi_controller *phwi_ctrlr; |
| 1217 | struct wrb_handle *pwrb_handle; | ||
| 1445 | struct iscsi_task *task; | 1218 | struct iscsi_task *task; |
| 1446 | struct beiscsi_io_task *io_task; | ||
| 1447 | uint16_t wrb_index, cid, cri_index; | ||
| 1448 | 1219 | ||
| 1449 | phwi_ctrlr = phba->phwi_ctrlr; | 1220 | phwi_ctrlr = phba->phwi_ctrlr; |
| 1450 | if (is_chip_be2_be3r(phba)) { | 1221 | if (is_chip_be2_be3r(phba)) { |
| @@ -1463,9 +1234,6 @@ hwi_complete_drvr_msgs(struct beiscsi_conn *beiscsi_conn, · 12 unmodified lines | |||
| 1463 | pwrb_context = &phwi_ctrlr->wrb_context[cri_index]; | 1234 | pwrb_context = &phwi_ctrlr->wrb_context[cri_index]; |
| 1464 | pwrb_handle = pwrb_context->pwrb_handle_basestd[wrb_index]; | 1235 | pwrb_handle = pwrb_context->pwrb_handle_basestd[wrb_index]; |
| 1465 | task = pwrb_handle->pio_handle; | 1236 | task = pwrb_handle->pio_handle; |
| 1466 | |||
| 1467 | io_task = task->dd_data; | ||
| 1468 | memset(io_task->pwrb_handle->pwrb, 0, sizeof(struct iscsi_wrb)); | ||
| 1469 | iscsi_put_task(task); | 1237 | iscsi_put_task(task); |
| 1470 | } | 1238 | } |
| 1471 | 1239 | ||
| @@ -1614,431 +1382,428 @@ static void hwi_complete_cmd(struct beiscsi_conn *beiscsi_conn, · 142 unmodified lines | |||
| 1614 | spin_unlock_bh(&session->back_lock); | 1382 | spin_unlock_bh(&session->back_lock); |
| 1615 | } | 1383 | } |
| 1616 | 1384 | ||
| 1617 | static struct list_head *hwi_get_async_busy_list(struct hwi_async_pdu_context | 1385 | /** |
| 1618 | *pasync_ctx, unsigned int is_header, | 1386 | * ASYNC PDUs include |
| 1619 | unsigned int host_write_ptr) | 1387 | * a. Unsolicited NOP-In (target initiated NOP-In) |
| 1388 | * b. ASYNC Messages | ||
| 1389 | * c. Reject PDU | ||
| 1390 | * d. Login response | ||
| 1391 | * These headers arrive unprocessed by the EP firmware. | ||
| 1392 | * iSCSI layer processes them. | ||
| 1393 | */ | ||
| 1394 | static unsigned int | ||
| 1395 | beiscsi_complete_pdu(struct beiscsi_conn *beiscsi_conn, | ||
| 1396 | struct pdu_base *phdr, void *pdata, unsigned int dlen) | ||
| 1620 | { | 1397 | { |
| 1621 | if (is_header) | 1398 | struct beiscsi_hba *phba = beiscsi_conn->phba; |
| 1622 | return &pasync_ctx->async_entry[host_write_ptr]. | 1399 | struct iscsi_conn *conn = beiscsi_conn->conn; |
| 1623 | header_busy_list; | 1400 | struct beiscsi_io_task *io_task; |
| 1624 | else | 1401 | struct iscsi_hdr *login_hdr; |
| 1625 | return &pasync_ctx->async_entry[host_write_ptr].data_busy_list; | 1402 | struct iscsi_task *task; |
| 1403 | u8 code; | ||
| 1404 | |||
| 1405 | code = AMAP_GET_BITS(struct amap_pdu_base, opcode, phdr); | ||
| 1406 | switch (code) { | ||
| 1407 | case ISCSI_OP_NOOP_IN: | ||
| 1408 | pdata = NULL; | ||
| 1409 | dlen = 0; | ||
| 1410 | break; | ||
| 1411 | case ISCSI_OP_ASYNC_EVENT: | ||
| 1412 | break; | ||
| 1413 | case ISCSI_OP_REJECT: | ||
| 1414 | WARN_ON(!pdata); | ||
| 1415 | WARN_ON(!(dlen == 48)); | ||
| 1416 | beiscsi_log(phba, KERN_ERR, | ||
| 1417 | BEISCSI_LOG_CONFIG | BEISCSI_LOG_IO, | ||
| 1418 | "BM_%d : In ISCSI_OP_REJECT\n"); | ||
| 1419 | break; | ||
| 1420 | case ISCSI_OP_LOGIN_RSP: | ||
| 1421 | case ISCSI_OP_TEXT_RSP: | ||
| 1422 | task = conn->login_task; | ||
| 1423 | io_task = task->dd_data; | ||
| 1424 | login_hdr = (struct iscsi_hdr *)phdr; | ||
| 1425 | login_hdr->itt = io_task->libiscsi_itt; | ||
| 1426 | break; | ||
| 1427 | default: | ||
| 1428 | beiscsi_log(phba, KERN_WARNING, | ||
| 1429 | BEISCSI_LOG_IO | BEISCSI_LOG_CONFIG, | ||
| 1430 | "BM_%d : unrecognized async PDU opcode 0x%x\n", | ||
| 1431 | code); | ||
| 1432 | return 1; | ||
| 1433 | } | ||
| 1434 | __iscsi_complete_pdu(conn, (struct iscsi_hdr *)phdr, pdata, dlen); | ||
| 1435 | return 0; | ||
| 1436 | } | ||
| 1437 | |||
| 1438 | static inline void | ||
| 1439 | beiscsi_hdl_put_handle(struct hd_async_context *pasync_ctx, | ||
| 1440 | struct hd_async_handle *pasync_handle) | ||
| 1441 | { | ||
| 1442 | if (pasync_handle->is_header) { | ||
| 1443 | list_add_tail(&pasync_handle->link, | ||
| 1444 | &pasync_ctx->async_header.free_list); | ||
| 1445 | pasync_ctx->async_header.free_entries++; | ||
| 1446 | } else { | ||
| 1447 | list_add_tail(&pasync_handle->link, | ||
| 1448 | &pasync_ctx->async_data.free_list); | ||
| 1449 | pasync_ctx->async_data.free_entries++; | ||
| 1450 | } | ||
| 1626 | } | 1451 | } |
| 1627 | 1452 | ||
| 1628 | static struct async_pdu_handle * | 1453 | static struct hd_async_handle * |
| 1629 | hwi_get_async_handle(struct beiscsi_hba *phba, | 1454 | beiscsi_hdl_get_handle(struct beiscsi_conn *beiscsi_conn, |
| 1630 | struct beiscsi_conn *beiscsi_conn, | 1455 | struct hd_async_context *pasync_ctx, |
| 1631 | struct hwi_async_pdu_context *pasync_ctx, | 1456 | struct i_t_dpdu_cqe *pdpdu_cqe) |
| 1632 | struct i_t_dpdu_cqe *pdpdu_cqe, unsigned int *pcq_index) | ||
| 1633 | { | 1457 | { |
| 1458 | struct beiscsi_hba *phba = beiscsi_conn->phba; | ||
| 1459 | struct hd_async_handle *pasync_handle; | ||
| 1634 | struct be_bus_address phys_addr; | 1460 | struct be_bus_address phys_addr; |
| 1635 | struct list_head *pbusy_list; | 1461 | u8 final, error = 0; |
| 1636 | struct async_pdu_handle *pasync_handle = NULL; | 1462 | u16 cid, code, ci; |
| 1637 | unsigned char is_header = 0; | 1463 | u32 dpl; |
| 1638 | unsigned int index, dpl; | ||
| 1639 | 1464 | ||
| 1465 | cid = beiscsi_conn->beiscsi_conn_cid; | ||
| 1466 | /** | ||
| 1467 | * This function is invoked to get the right async_handle structure | ||
| 1468 | * from a given DEF PDU CQ entry. | ||
| 1469 | * | ||
| 1470 | * - index in CQ entry gives the vertical index | ||
| 1471 | * - address in CQ entry is the offset where the DMA last ended | ||
| 1472 | * - final - no more notifications for this PDU | ||
| 1473 | */ | ||
| 1640 | if (is_chip_be2_be3r(phba)) { | 1474 | if (is_chip_be2_be3r(phba)) { |
| 1641 | dpl = AMAP_GET_BITS(struct amap_i_t_dpdu_cqe, | 1475 | dpl = AMAP_GET_BITS(struct amap_i_t_dpdu_cqe, |
| 1642 | dpl, pdpdu_cqe); | 1476 | dpl, pdpdu_cqe); |
| 1643 | index = AMAP_GET_BITS(struct amap_i_t_dpdu_cqe, | 1477 | ci = AMAP_GET_BITS(struct amap_i_t_dpdu_cqe, |
| 1644 | index, pdpdu_cqe); | 1478 | index, pdpdu_cqe); |
| 1479 | final = AMAP_GET_BITS(struct amap_i_t_dpdu_cqe, | ||
| 1480 | final, pdpdu_cqe); | ||
| 1645 | } else { | 1481 | } else { |
| 1646 | dpl = AMAP_GET_BITS(struct amap_i_t_dpdu_cqe_v2, | 1482 | dpl = AMAP_GET_BITS(struct amap_i_t_dpdu_cqe_v2, |
| 1647 | dpl, pdpdu_cqe); | 1483 | dpl, pdpdu_cqe); |
| 1648 | index = AMAP_GET_BITS(struct amap_i_t_dpdu_cqe_v2, | 1484 | ci = AMAP_GET_BITS(struct amap_i_t_dpdu_cqe_v2, |
| 1649 | index, pdpdu_cqe); | 1485 | index, pdpdu_cqe); |
| 1486 | final = AMAP_GET_BITS(struct amap_i_t_dpdu_cqe_v2, | ||
| 1487 | final, pdpdu_cqe); | ||
| 1650 | } | 1488 | } |
| 1651 | 1489 | ||
| 1652 | phys_addr.u.a32.address_lo = | 1490 | /** |
| 1653 | (pdpdu_cqe->dw[offsetof(struct amap_i_t_dpdu_cqe, | 1491 | * DB addr Hi/Lo is same for BE and SKH. |
| 1654 | db_addr_lo) / 32] - dpl); | 1492 | * Subtract the dataplacementlength to get to the base. |
| 1655 | phys_addr.u.a32.address_hi = | 1493 | */ |
| 1656 | pdpdu_cqe->dw[offsetof(struct amap_i_t_dpdu_cqe, | 1494 | phys_addr.u.a32.address_lo = AMAP_GET_BITS(struct amap_i_t_dpdu_cqe, |
| 1657 | db_addr_hi) / 32]; | 1495 | db_addr_lo, pdpdu_cqe); |
| 1658 | 1496 | phys_addr.u.a32.address_lo -= dpl; | |
| 1659 | phys_addr.u.a64.address = | 1497 | phys_addr.u.a32.address_hi = AMAP_GET_BITS(struct amap_i_t_dpdu_cqe, |
| 1660 | *((unsigned long long *)(&phys_addr.u.a64.address)); | 1498 | db_addr_hi, pdpdu_cqe); |
| 1661 | 1499 | ||
| 1662 | switch (pdpdu_cqe->dw[offsetof(struct amap_i_t_dpdu_cqe, code) / 32] | 1500 | code = AMAP_GET_BITS(struct amap_i_t_dpdu_cqe, code, pdpdu_cqe); |
| 1663 | & PDUCQE_CODE_MASK) { | 1501 | switch (code) { |
| 1664 | case UNSOL_HDR_NOTIFY: | 1502 | case UNSOL_HDR_NOTIFY: |
| 1665 | is_header = 1; | 1503 | pasync_handle = pasync_ctx->async_entry[ci].header; |
| 1666 | |||
| 1667 | pbusy_list = hwi_get_async_busy_list(pasync_ctx, | ||
| 1668 | is_header, index); | ||
| 1669 | break; | 1504 | break; |
| 1505 | case UNSOL_DATA_DIGEST_ERROR_NOTIFY: | ||
| 1506 | error = 1; | ||
| 1670 | case UNSOL_DATA_NOTIFY: | 1507 | case UNSOL_DATA_NOTIFY: |
| 1671 | pbusy_list = hwi_get_async_busy_list(pasync_ctx, | 1508 | pasync_handle = pasync_ctx->async_entry[ci].data; |
| 1672 | is_header, index); | ||
| 1673 | break; | 1509 | break; |
| 1510 | /* called only for above codes */ | ||
| 1674 | default: | 1511 | default: |
| 1675 | pbusy_list = NULL; | 1512 | pasync_handle = NULL; |
| 1676 | beiscsi_log(phba, KERN_WARNING, | 1513 | break; |
| 1677 | BEISCSI_LOG_IO | BEISCSI_LOG_CONFIG, | ||
| 1678 | "BM_%d : Unexpected code=%d\n", | ||
| 1679 | pdpdu_cqe->dw[offsetof(struct amap_i_t_dpdu_cqe, | ||
| 1680 | code) / 32] & PDUCQE_CODE_MASK); | ||
| 1681 | return NULL; | ||
| 1682 | } | 1514 | } |
| 1683 | 1515 | ||
| 1684 | WARN_ON(list_empty(pbusy_list)); | 1516 | if (!pasync_handle) { |
| 1685 | list_for_each_entry(pasync_handle, pbusy_list, link) { | 1517 | beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_ISCSI, |
| 1686 | if (pasync_handle->pa.u.a64.address == phys_addr.u.a64.address) | 1518 | "BM_%d : cid %d async PDU handle not found - code %d ci %d addr %llx\n", |
| 1687 | break; | 1519 | cid, code, ci, phys_addr.u.a64.address); |
| 1520 | return pasync_handle; | ||
| 1688 | } | 1521 | } |
| 1689 | 1522 | ||
| 1690 | WARN_ON(!pasync_handle); | 1523 | if (pasync_handle->pa.u.a64.address != phys_addr.u.a64.address || |
| 1524 | pasync_handle->index != ci) { | ||
| 1525 | /* driver bug - if ci does not match async handle index */ | ||
| 1526 | error = 1; | ||
| 1527 | beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_ISCSI, | ||
| 1528 | "BM_%d : cid %u async PDU handle mismatch - addr in %cQE %llx at %u:addr in CQE %llx ci %u\n", | ||
| 1529 | cid, pasync_handle->is_header ? 'H' : 'D', | ||
| 1530 | pasync_handle->pa.u.a64.address, | ||
| 1531 | pasync_handle->index, | ||
| 1532 | phys_addr.u.a64.address, ci); | ||
| 1533 | /* FW has stale address - attempt continuing by dropping */ | ||
| 1534 | } | ||
| 1691 | 1535 | ||
| 1692 | pasync_handle->cri = BE_GET_ASYNC_CRI_FROM_CID( | 1536 | /** |
| 1693 | beiscsi_conn->beiscsi_conn_cid); | 1537 | * Each CID is associated with unique CRI. |
| 1694 | pasync_handle->is_header = is_header; | 1538 | * ASYNC_CRI_FROM_CID mapping and CRI_FROM_CID are totaly different. |
| 1539 | **/ | ||
| 1540 | pasync_handle->cri = BE_GET_ASYNC_CRI_FROM_CID(cid); | ||
| 1541 | pasync_handle->is_final = final; | ||
| 1695 | pasync_handle->buffer_len = dpl; | 1542 | pasync_handle->buffer_len = dpl; |
| 1696 | *pcq_index = index; | 1543 | /* empty the slot */ |
| 1544 | if (pasync_handle->is_header) | ||
| 1545 | pasync_ctx->async_entry[ci].header = NULL; | ||
| 1546 | else | ||
| 1547 | pasync_ctx->async_entry[ci].data = NULL; | ||
| 1697 | 1548 | ||
| 1549 | /** | ||
| 1550 | * DEF PDU header and data buffers with errors should be simply | ||
| 1551 | * dropped as there are no consumers for it. | ||
| 1552 | */ | ||
| 1553 | if (error) { | ||
| 1554 | beiscsi_hdl_put_handle(pasync_ctx, pasync_handle); | ||
| 1555 | pasync_handle = NULL; | ||
| 1556 | } | ||
| 1698 | return pasync_handle; | 1557 | return pasync_handle; |
| 1699 | } | 1558 | } |
| 1700 | 1559 | ||
| 1701 | static unsigned int | 1560 | static void |
| 1702 | hwi_update_async_writables(struct beiscsi_hba *phba, | 1561 | beiscsi_hdl_purge_handles(struct beiscsi_hba *phba, |
| 1703 | struct hwi_async_pdu_context *pasync_ctx, | 1562 | struct hd_async_context *pasync_ctx, |
| 1704 | unsigned int is_header, unsigned int cq_index) | 1563 | u16 cri) |
| 1705 | { | 1564 | { |
| 1706 | struct list_head *pbusy_list; | 1565 | struct hd_async_handle *pasync_handle, *tmp_handle; |
| 1707 | struct async_pdu_handle *pasync_handle; | 1566 | struct list_head *plist; |
| 1708 | unsigned int num_entries, writables = 0; | ||
| 1709 | unsigned int *pep_read_ptr, *pwritables; | ||
| 1710 | |||
| 1711 | num_entries = pasync_ctx->num_entries; | ||
| 1712 | if (is_header) { | ||
| 1713 | pep_read_ptr = &pasync_ctx->async_header.ep_read_ptr; | ||
| 1714 | pwritables = &pasync_ctx->async_header.writables; | ||
| 1715 | } else { | ||
| 1716 | pep_read_ptr = &pasync_ctx->async_data.ep_read_ptr; | ||
| 1717 | pwritables = &pasync_ctx->async_data.writables; | ||
| 1718 | } | ||
| 1719 | |||
| 1720 | while ((*pep_read_ptr) != cq_index) { | ||
| 1721 | (*pep_read_ptr)++; | ||
| 1722 | *pep_read_ptr = (*pep_read_ptr) % num_entries; | ||
| 1723 | |||
| 1724 | pbusy_list = hwi_get_async_busy_list(pasync_ctx, is_header, | ||
| 1725 | *pep_read_ptr); | ||
| 1726 | if (writables == 0) | ||
| 1727 | WARN_ON(list_empty(pbusy_list)); | ||
| 1728 | |||
| 1729 | if (!list_empty(pbusy_list)) { | ||
| 1730 | pasync_handle = list_entry(pbusy_list->next, | ||
| 1731 | struct async_pdu_handle, | ||
| 1732 | link); | ||
| 1733 | WARN_ON(!pasync_handle); | ||
| 1734 | pasync_handle->consumed = 1; | ||
| 1735 | } | ||
| 1736 | |||
| 1737 | writables++; | ||
| 1738 | } | ||
| 1739 | 1567 | ||
| 1740 | if (!writables) { | 1568 | plist = &pasync_ctx->async_entry[cri].wq.list; |
| 1741 | beiscsi_log(phba, KERN_ERR, | 1569 | list_for_each_entry_safe(pasync_handle, tmp_handle, plist, link) { |
| 1742 | BEISCSI_LOG_CONFIG | BEISCSI_LOG_IO, | 1570 | list_del(&pasync_handle->link); |
| 1743 | "BM_%d : Duplicate notification received - index 0x%x!!\n", | 1571 | beiscsi_hdl_put_handle(pasync_ctx, pasync_handle); |
| 1744 | cq_index); | ||
| 1745 | WARN_ON(1); | ||
| 1746 | } | 1572 | } |
| 1747 | 1573 | ||
| 1748 | *pwritables = *pwritables + writables; | 1574 | INIT_LIST_HEAD(&pasync_ctx->async_entry[cri].wq.list); |
| 1749 | return 0; | 1575 | pasync_ctx->async_entry[cri].wq.hdr_len = 0; |
| 1576 | pasync_ctx->async_entry[cri].wq.bytes_received = 0; | ||
| 1577 | pasync_ctx->async_entry[cri].wq.bytes_needed = 0; | ||
| 1750 | } | 1578 | } |
| 1751 | 1579 | ||
| 1752 | static void hwi_free_async_msg(struct beiscsi_hba *phba, | 1580 | static unsigned int |
| 1753 | struct hwi_async_pdu_context *pasync_ctx, | 1581 | beiscsi_hdl_fwd_pdu(struct beiscsi_conn *beiscsi_conn, |
| 1754 | unsigned int cri) | 1582 | struct hd_async_context *pasync_ctx, |
| 1583 | u16 cri) | ||
| 1755 | { | 1584 | { |
| 1756 | struct async_pdu_handle *pasync_handle, *tmp_handle; | 1585 | struct iscsi_session *session = beiscsi_conn->conn->session; |
| 1586 | struct hd_async_handle *pasync_handle, *plast_handle; | ||
| 1587 | struct beiscsi_hba *phba = beiscsi_conn->phba; | ||
| 1588 | void *phdr = NULL, *pdata = NULL; | ||
| 1589 | u32 dlen = 0, status = 0; | ||
| 1757 | struct list_head *plist; | 1590 | struct list_head *plist; |
| 1758 | 1591 | ||
| 1759 | plist = &pasync_ctx->async_entry[cri].wait_queue.list; | 1592 | plist = &pasync_ctx->async_entry[cri].wq.list; |
| 1760 | list_for_each_entry_safe(pasync_handle, tmp_handle, plist, link) { | 1593 | plast_handle = NULL; |
| 1761 | list_del(&pasync_handle->link); | 1594 | list_for_each_entry(pasync_handle, plist, link) { |
| 1762 | 1595 | plast_handle = pasync_handle; | |
| 1763 | if (pasync_handle->is_header) { | 1596 | /* get the header, the first entry */ |
| 1764 | list_add_tail(&pasync_handle->link, | 1597 | if (!phdr) { |
| 1765 | &pasync_ctx->async_header.free_list); | 1598 | phdr = pasync_handle->pbuffer; |
| 1766 | pasync_ctx->async_header.free_entries++; | 1599 | continue; |
| 1767 | } else { | ||
| 1768 | list_add_tail(&pasync_handle->link, | ||
| 1769 | &pasync_ctx->async_data.free_list); | ||
| 1770 | pasync_ctx->async_data.free_entries++; | ||
| 1771 | } | 1600 | } |
| 1601 | /* use first buffer to collect all the data */ | ||
| 1602 | if (!pdata) { | ||
| 1603 | pdata = pasync_handle->pbuffer; | ||
| 1604 | dlen = pasync_handle->buffer_len; | ||
| 1605 | continue; | ||
| 1606 | } | ||
| 1607 | memcpy(pdata + dlen, pasync_handle->pbuffer, | ||
| 1608 | pasync_handle->buffer_len); | ||
| 1609 | dlen += pasync_handle->buffer_len; | ||
| 1772 | } | 1610 | } |
| 1773 | 1611 | ||
| 1774 | INIT_LIST_HEAD(&pasync_ctx->async_entry[cri].wait_queue.list); | 1612 | if (!plast_handle->is_final) { |
| 1775 | pasync_ctx->async_entry[cri].wait_queue.hdr_received = 0; | 1613 | /* last handle should have final PDU notification from FW */ |
| 1776 | pasync_ctx->async_entry[cri].wait_queue.bytes_received = 0; | 1614 | beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_ISCSI, |
| 1615 | "BM_%d : cid %u %p fwd async PDU with last handle missing - HL%u:DN%u:DR%u\n", | ||
| 1616 | beiscsi_conn->beiscsi_conn_cid, plast_handle, | ||
| 1617 | pasync_ctx->async_entry[cri].wq.hdr_len, | ||
| 1618 | pasync_ctx->async_entry[cri].wq.bytes_needed, | ||
| 1619 | pasync_ctx->async_entry[cri].wq.bytes_received); | ||
| 1620 | } | ||
| 1621 | spin_lock_bh(&session->back_lock); | ||
| 1622 | status = beiscsi_complete_pdu(beiscsi_conn, phdr, pdata, dlen); | ||
| 1623 | spin_unlock_bh(&session->back_lock); | ||
| 1624 | beiscsi_hdl_purge_handles(phba, pasync_ctx, cri); | ||
| 1625 | return status; | ||
| 1777 | } | 1626 | } |
| 1778 | 1627 | ||
| 1779 | static struct phys_addr * | 1628 | static unsigned int |
| 1780 | hwi_get_ring_address(struct hwi_async_pdu_context *pasync_ctx, | 1629 | beiscsi_hdl_gather_pdu(struct beiscsi_conn *beiscsi_conn, |
| 1781 | unsigned int is_header, unsigned int host_write_ptr) | 1630 | struct hd_async_context *pasync_ctx, |
| 1631 | struct hd_async_handle *pasync_handle) | ||
| 1782 | { | 1632 | { |
| 1783 | struct phys_addr *pasync_sge = NULL; | 1633 | unsigned int bytes_needed = 0, status = 0; |
| 1634 | u16 cri = pasync_handle->cri; | ||
| 1635 | struct cri_wait_queue *wq; | ||
| 1636 | struct beiscsi_hba *phba; | ||
| 1637 | struct pdu_base *ppdu; | ||
| 1638 | char *err = ""; | ||
| 1784 | 1639 | ||
| 1785 | if (is_header) | 1640 | phba = beiscsi_conn->phba; |
| 1786 | pasync_sge = pasync_ctx->async_header.ring_base; | 1641 | wq = &pasync_ctx->async_entry[cri].wq; |
| 1787 | else | 1642 | if (pasync_handle->is_header) { |
| 1788 | pasync_sge = pasync_ctx->async_data.ring_base; | 1643 | /* check if PDU hdr is rcv'd when old hdr not completed */ |
| 1644 | if (wq->hdr_len) { | ||
| 1645 | err = "incomplete"; | ||
| 1646 | goto drop_pdu; | ||
| 1647 | } | ||
| 1648 | ppdu = pasync_handle->pbuffer; | ||
| 1649 | bytes_needed = AMAP_GET_BITS(struct amap_pdu_base, | ||
| 1650 | data_len_hi, ppdu); | ||
| 1651 | bytes_needed <<= 16; | ||
| 1652 | bytes_needed |= be16_to_cpu(AMAP_GET_BITS(struct amap_pdu_base, | ||
| 1653 | data_len_lo, ppdu)); | ||
| 1654 | wq->hdr_len = pasync_handle->buffer_len; | ||
| 1655 | wq->bytes_received = 0; | ||
| 1656 | wq->bytes_needed = bytes_needed; | ||
| 1657 | list_add_tail(&pasync_handle->link, &wq->list); | ||
| 1658 | if (!bytes_needed) | ||
| 1659 | status = beiscsi_hdl_fwd_pdu(beiscsi_conn, | ||
| 1660 | pasync_ctx, cri); | ||
| 1661 | } else { | ||
| 1662 | /* check if data received has header and is needed */ | ||
| 1663 | if (!wq->hdr_len || !wq->bytes_needed) { | ||
| 1664 | err = "header less"; | ||
| 1665 | goto drop_pdu; | ||
| 1666 | } | ||
| 1667 | wq->bytes_received += pasync_handle->buffer_len; | ||
| 1668 | /* Something got overwritten? Better catch it here. */ | ||
| 1669 | if (wq->bytes_received > wq->bytes_needed) { | ||
| 1670 | err = "overflow"; | ||
| 1671 | goto drop_pdu; | ||
| 1672 | } | ||
| 1673 | list_add_tail(&pasync_handle->link, &wq->list); | ||
| 1674 | if (wq->bytes_received == wq->bytes_needed) | ||
| 1675 | status = beiscsi_hdl_fwd_pdu(beiscsi_conn, | ||
| 1676 | pasync_ctx, cri); | ||
| 1677 | } | ||
| 1678 | return status; | ||
| 1789 | 1679 | ||
| 1790 | return pasync_sge + host_write_ptr; | 1680 | drop_pdu: |
| 1681 | beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_ISCSI, | ||
| 1682 | "BM_%d : cid %u async PDU %s - def-%c:HL%u:DN%u:DR%u\n", | ||
| 1683 | beiscsi_conn->beiscsi_conn_cid, err, | ||
| 1684 | pasync_handle->is_header ? 'H' : 'D', | ||
| 1685 | wq->hdr_len, wq->bytes_needed, | ||
| 1686 | pasync_handle->buffer_len); | ||
| 1687 | /* discard this handle */ | ||
| 1688 | beiscsi_hdl_put_handle(pasync_ctx, pasync_handle); | ||
| 1689 | /* free all the other handles in cri_wait_queue */ | ||
| 1690 | beiscsi_hdl_purge_handles(phba, pasync_ctx, cri); | ||
| 1691 | /* try continuing */ | ||
| 1692 | return status; | ||
| 1791 | } | 1693 | } |
| 1792 | 1694 | ||
| 1793 | static void hwi_post_async_buffers(struct beiscsi_hba *phba, | 1695 | static void |
| 1794 | unsigned int is_header, uint8_t ulp_num) | 1696 | beiscsi_hdq_post_handles(struct beiscsi_hba *phba, |
| 1697 | u8 header, u8 ulp_num) | ||
| 1795 | { | 1698 | { |
| 1699 | struct hd_async_handle *pasync_handle, *tmp, **slot; | ||
| 1700 | struct hd_async_context *pasync_ctx; | ||
| 1796 | struct hwi_controller *phwi_ctrlr; | 1701 | struct hwi_controller *phwi_ctrlr; |
| 1797 | struct hwi_async_pdu_context *pasync_ctx; | 1702 | struct list_head *hfree_list; |
| 1798 | struct async_pdu_handle *pasync_handle; | ||
| 1799 | struct list_head *pfree_link, *pbusy_list; | ||
| 1800 | struct phys_addr *pasync_sge; | 1703 | struct phys_addr *pasync_sge; |
| 1801 | unsigned int ring_id, num_entries; | 1704 | u32 ring_id, doorbell = 0; |
| 1802 | unsigned int host_write_num, doorbell_offset; | 1705 | u16 index, num_entries; |
| 1803 | unsigned int writables; | 1706 | u32 doorbell_offset; |
| 1804 | unsigned int i = 0; | 1707 | u16 prod = 0, cons; |
| 1805 | u32 doorbell = 0; | ||
| 1806 | 1708 | ||
| 1807 | phwi_ctrlr = phba->phwi_ctrlr; | 1709 | phwi_ctrlr = phba->phwi_ctrlr; |
| 1808 | pasync_ctx = HWI_GET_ASYNC_PDU_CTX(phwi_ctrlr, ulp_num); | 1710 | pasync_ctx = HWI_GET_ASYNC_PDU_CTX(phwi_ctrlr, ulp_num); |
| 1809 | num_entries = pasync_ctx->num_entries; | 1711 | num_entries = pasync_ctx->num_entries; |
| 1810 | 1712 | if (header) { | |
| 1811 | if (is_header) { | 1713 | cons = pasync_ctx->async_header.free_entries; |
| 1812 | writables = min(pasync_ctx->async_header.writables, | 1714 | hfree_list = &pasync_ctx->async_header.free_list; |
| 1813 | pasync_ctx->async_header.free_entries); | ||
| 1814 | pfree_link = pasync_ctx->async_header.free_list.next; | ||
| 1815 | host_write_num = pasync_ctx->async_header.host_write_ptr; | ||
| 1816 | ring_id = phwi_ctrlr->default_pdu_hdr[ulp_num].id; | 1715 | ring_id = phwi_ctrlr->default_pdu_hdr[ulp_num].id; |
| 1817 | doorbell_offset = phwi_ctrlr->default_pdu_hdr[ulp_num]. | 1716 | doorbell_offset = phwi_ctrlr->default_pdu_hdr[ulp_num]. |
| 1818 | doorbell_offset; | 1717 | doorbell_offset; |
| 1819 | } else { | 1718 | } else { |
| 1820 | writables = min(pasync_ctx->async_data.writables, | 1719 | cons = pasync_ctx->async_data.free_entries; |
| 1821 | pasync_ctx->async_data.free_entries); | 1720 | hfree_list = &pasync_ctx->async_data.free_list; |
| 1822 | pfree_link = pasync_ctx->async_data.free_list.next; | ||
| 1823 | host_write_num = pasync_ctx->async_data.host_write_ptr; | ||
| 1824 | ring_id = phwi_ctrlr->default_pdu_data[ulp_num].id; | 1721 | ring_id = phwi_ctrlr->default_pdu_data[ulp_num].id; |
| 1825 | doorbell_offset = phwi_ctrlr->default_pdu_data[ulp_num]. | 1722 | doorbell_offset = phwi_ctrlr->default_pdu_data[ulp_num]. |
| 1826 | doorbell_offset; | 1723 | doorbell_offset; |
| 1827 | } | 1724 | } |
| 1725 | /* number of entries posted must be in multiples of 8 */ | ||
| 1726 | if (cons % 8) | ||
| 1727 | return; | ||
| 1828 | 1728 | ||
| 1829 | writables = (writables / 8) * 8; | 1729 | list_for_each_entry_safe(pasync_handle, tmp, hfree_list, link) { |
| 1830 | if (writables) { | 1730 | list_del_init(&pasync_handle->link); |
| 1831 | for (i = 0; i < writables; i++) { | 1731 | pasync_handle->is_final = 0; |
| 1832 | pbusy_list = | 1732 | pasync_handle->buffer_len = 0; |
| 1833 | hwi_get_async_busy_list(pasync_ctx, is_header, | ||
| 1834 | host_write_num); | ||
| 1835 | pasync_handle = | ||
| 1836 | list_entry(pfree_link, struct async_pdu_handle, | ||
| 1837 | link); | ||
| 1838 | WARN_ON(!pasync_handle); | ||
| 1839 | pasync_handle->consumed = 0; | ||
| 1840 | |||
| 1841 | pfree_link = pfree_link->next; | ||
| 1842 | |||
| 1843 | pasync_sge = hwi_get_ring_address(pasync_ctx, | ||
| 1844 | is_header, host_write_num); | ||
| 1845 | |||
| 1846 | pasync_sge->hi = pasync_handle->pa.u.a32.address_lo; | ||
| 1847 | pasync_sge->lo = pasync_handle->pa.u.a32.address_hi; | ||
| 1848 | |||
| 1849 | list_move(&pasync_handle->link, pbusy_list); | ||
| 1850 | |||
| 1851 | host_write_num++; | ||
| 1852 | host_write_num = host_write_num % num_entries; | ||
| 1853 | } | ||
| 1854 | |||
| 1855 | if (is_header) { | ||
| 1856 | pasync_ctx->async_header.host_write_ptr = | ||
| 1857 | host_write_num; | ||
| 1858 | pasync_ctx->async_header.free_entries -= writables; | ||
| 1859 | pasync_ctx->async_header.writables -= writables; | ||
| 1860 | pasync_ctx->async_header.busy_entries += writables; | ||
| 1861 | } else { | ||
| 1862 | pasync_ctx->async_data.host_write_ptr = host_write_num; | ||
| 1863 | pasync_ctx->async_data.free_entries -= writables; | ||
| 1864 | pasync_ctx->async_data.writables -= writables; | ||
| 1865 | pasync_ctx->async_data.busy_entries += writables; | ||
| 1866 | } | ||
| 1867 | |||
| 1868 | doorbell |= ring_id & DB_DEF_PDU_RING_ID_MASK; | ||
| 1869 | doorbell |= 1 << DB_DEF_PDU_REARM_SHIFT; | ||
| 1870 | doorbell |= 0 << DB_DEF_PDU_EVENT_SHIFT; | ||
| 1871 | doorbell |= (writables & DB_DEF_PDU_CQPROC_MASK) | ||
| 1872 | << DB_DEF_PDU_CQPROC_SHIFT; | ||
| 1873 | |||
| 1874 | iowrite32(doorbell, phba->db_va + doorbell_offset); | ||
| 1875 | } | ||
| 1876 | } | ||
| 1877 | |||
| 1878 | static void hwi_flush_default_pdu_buffer(struct beiscsi_hba *phba, | ||
| 1879 | struct beiscsi_conn *beiscsi_conn, | ||
| 1880 | struct i_t_dpdu_cqe *pdpdu_cqe) | ||
| 1881 | { | ||
| 1882 | struct hwi_controller *phwi_ctrlr; | ||
| 1883 | struct hwi_async_pdu_context *pasync_ctx; | ||
| 1884 | struct async_pdu_handle *pasync_handle = NULL; | ||
| 1885 | unsigned int cq_index = -1; | ||
| 1886 | uint16_t cri_index = BE_GET_CRI_FROM_CID( | ||
| 1887 | beiscsi_conn->beiscsi_conn_cid); | ||
| 1888 | |||
| 1889 | phwi_ctrlr = phba->phwi_ctrlr; | ||
| 1890 | pasync_ctx = HWI_GET_ASYNC_PDU_CTX(phwi_ctrlr, | ||
| 1891 | BEISCSI_GET_ULP_FROM_CRI(phwi_ctrlr, | ||
| 1892 | cri_index)); | ||
| 1893 | |||
| 1894 | pasync_handle = hwi_get_async_handle(phba, beiscsi_conn, pasync_ctx, | ||
| 1895 | pdpdu_cqe, &cq_index); | ||
| 1896 | BUG_ON(pasync_handle->is_header != 0); | ||
| 1897 | if (pasync_handle->consumed == 0) | ||
| 1898 | hwi_update_async_writables(phba, pasync_ctx, | ||
| 1899 | pasync_handle->is_header, cq_index); | ||
| 1900 | |||
| 1901 | hwi_free_async_msg(phba, pasync_ctx, pasync_handle->cri); | ||
| 1902 | hwi_post_async_buffers(phba, pasync_handle->is_header, | ||
| 1903 | BEISCSI_GET_ULP_FROM_CRI(phwi_ctrlr, | ||
| 1904 | cri_index)); | ||
| 1905 | } | ||
| 1906 | |||
| 1907 | static unsigned int | ||
| 1908 | hwi_fwd_async_msg(struct beiscsi_conn *beiscsi_conn, | ||
| 1909 | struct beiscsi_hba *phba, | ||
| 1910 | struct hwi_async_pdu_context *pasync_ctx, unsigned short cri) | ||
| 1911 | { | ||
| 1912 | struct list_head *plist; | ||
| 1913 | struct async_pdu_handle *pasync_handle; | ||
| 1914 | void *phdr = NULL; | ||
| 1915 | unsigned int hdr_len = 0, buf_len = 0; | ||
| 1916 | unsigned int status, index = 0, offset = 0; | ||
| 1917 | void *pfirst_buffer = NULL; | ||
| 1918 | unsigned int num_buf = 0; | ||
| 1919 | |||
| 1920 | plist = &pasync_ctx->async_entry[cri].wait_queue.list; | ||
| 1921 | 1733 | ||
| 1922 | list_for_each_entry(pasync_handle, plist, link) { | 1734 | /* handles can be consumed out of order, use index in handle */ |
| 1923 | if (index == 0) { | 1735 | index = pasync_handle->index; |
| 1924 | phdr = pasync_handle->pbuffer; | 1736 | WARN_ON(pasync_handle->is_header != header); |
| 1925 | hdr_len = pasync_handle->buffer_len; | 1737 | if (header) |
| 1926 | } else { | 1738 | slot = &pasync_ctx->async_entry[index].header; |
| 1927 | buf_len = pasync_handle->buffer_len; | 1739 | else |
| 1928 | if (!num_buf) { | 1740 | slot = &pasync_ctx->async_entry[index].data; |
| 1929 | pfirst_buffer = pasync_handle->pbuffer; | 1741 | /** |
| 1930 | num_buf++; | 1742 | * The slot just tracks handle's hold and release, so |
| 1931 | } | 1743 | * overwriting at the same index won't do any harm but |
| 1932 | memcpy(pfirst_buffer + offset, | 1744 | * needs to be caught. |
| 1933 | pasync_handle->pbuffer, buf_len); | 1745 | */ |
| 1934 | offset += buf_len; | 1746 | if (*slot != NULL) { |
| 1747 | beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_ISCSI, | ||
| 1748 | "BM_%d : async PDU %s slot at %u not empty\n", | ||
| 1749 | header ? "header" : "data", index); | ||
| 1935 | } | 1750 | } |
| 1936 | index++; | 1751 | /** |
| 1752 | * We use same freed index as in completion to post so this | ||
| 1753 | * operation is not required for refills. Its required only | ||
| 1754 | * for ring creation. | ||
| 1755 | */ | ||
| 1756 | if (header) | ||
| 1757 | pasync_sge = pasync_ctx->async_header.ring_base; | ||
| 1758 | else | ||
| 1759 | pasync_sge = pasync_ctx->async_data.ring_base; | ||
| 1760 | pasync_sge += index; | ||
| 1761 | /* if its a refill then address is same; hi is lo */ | ||
| 1762 | WARN_ON(pasync_sge->hi && | ||
| 1763 | pasync_sge->hi != pasync_handle->pa.u.a32.address_lo); | ||
| 1764 | WARN_ON(pasync_sge->lo && | ||
| 1765 | pasync_sge->lo != pasync_handle->pa.u.a32.address_hi); | ||
| 1766 | pasync_sge->hi = pasync_handle->pa.u.a32.address_lo; | ||
| 1767 | pasync_sge->lo = pasync_handle->pa.u.a32.address_hi; | ||
| 1768 | |||
| 1769 | *slot = pasync_handle; | ||
| 1770 | if (++prod == cons) | ||
| 1771 | break; | ||
| 1937 | } | 1772 | } |
| 1773 | if (header) | ||
| 1774 | pasync_ctx->async_header.free_entries -= prod; | ||
| 1775 | else | ||
| 1776 | pasync_ctx->async_data.free_entries -= prod; | ||
| 1938 | 1777 | ||
| 1939 | status = beiscsi_process_async_pdu(beiscsi_conn, phba, | 1778 | doorbell |= ring_id & DB_DEF_PDU_RING_ID_MASK; |
| 1940 | phdr, hdr_len, pfirst_buffer, | 1779 | doorbell |= 1 << DB_DEF_PDU_REARM_SHIFT; |
| 1941 | offset); | 1780 | doorbell |= 0 << DB_DEF_PDU_EVENT_SHIFT; |
| 1942 | 1781 | doorbell |= (prod & DB_DEF_PDU_CQPROC_MASK) << DB_DEF_PDU_CQPROC_SHIFT; | |
| 1943 | hwi_free_async_msg(phba, pasync_ctx, cri); | 1782 | iowrite32(doorbell, phba->db_va + doorbell_offset); |
| 1944 | return 0; | ||
| 1945 | } | ||
| 1946 | |||
| 1947 | static unsigned int | ||
| 1948 | hwi_gather_async_pdu(struct beiscsi_conn *beiscsi_conn, | ||
| 1949 | struct beiscsi_hba *phba, | ||
| 1950 | struct async_pdu_handle *pasync_handle) | ||
| 1951 | { | ||
| 1952 | struct hwi_async_pdu_context *pasync_ctx; | ||
| 1953 | struct hwi_controller *phwi_ctrlr; | ||
| 1954 | unsigned int bytes_needed = 0, status = 0; | ||
| 1955 | unsigned short cri = pasync_handle->cri; | ||
| 1956 | struct pdu_base *ppdu; | ||
| 1957 | |||
| 1958 | phwi_ctrlr = phba->phwi_ctrlr; | ||
| 1959 | pasync_ctx = HWI_GET_ASYNC_PDU_CTX(phwi_ctrlr, | ||
| 1960 | BEISCSI_GET_ULP_FROM_CRI(phwi_ctrlr, | ||
| 1961 | BE_GET_CRI_FROM_CID(beiscsi_conn-> | ||
| 1962 | beiscsi_conn_cid))); | ||
| 1963 | |||
| 1964 | list_del(&pasync_handle->link); | ||
| 1965 | if (pasync_handle->is_header) { | ||
| 1966 | pasync_ctx->async_header.busy_entries--; | ||
| 1967 | if (pasync_ctx->async_entry[cri].wait_queue.hdr_received) { | ||
| 1968 | hwi_free_async_msg(phba, pasync_ctx, cri); | ||
| 1969 | BUG(); | ||
| 1970 | } | ||
| 1971 | |||
| 1972 | pasync_ctx->async_entry[cri].wait_queue.bytes_received = 0; | ||
| 1973 | pasync_ctx->async_entry[cri].wait_queue.hdr_received = 1; | ||
| 1974 | pasync_ctx->async_entry[cri].wait_queue.hdr_len = | ||
| 1975 | (unsigned short)pasync_handle->buffer_len; | ||
| 1976 | list_add_tail(&pasync_handle->link, | ||
| 1977 | &pasync_ctx->async_entry[cri].wait_queue.list); | ||
| 1978 | |||
| 1979 | ppdu = pasync_handle->pbuffer; | ||
| 1980 | bytes_needed = ((((ppdu->dw[offsetof(struct amap_pdu_base, | ||
| 1981 | data_len_hi) / 32] & PDUBASE_DATALENHI_MASK) << 8) & | ||
| 1982 | 0xFFFF0000) | ((be16_to_cpu((ppdu-> | ||
| 1983 | dw[offsetof(struct amap_pdu_base, data_len_lo) / 32] | ||
| 1984 | & PDUBASE_DATALENLO_MASK) >> 16)) & 0x0000FFFF)); | ||
| 1985 | |||
| 1986 | if (status == 0) { | ||
| 1987 | pasync_ctx->async_entry[cri].wait_queue.bytes_needed = | ||
| 1988 | bytes_needed; | ||
| 1989 | |||
| 1990 | if (bytes_needed == 0) | ||
| 1991 | status = hwi_fwd_async_msg(beiscsi_conn, phba, | ||
| 1992 | pasync_ctx, cri); | ||
| 1993 | } | ||
| 1994 | } else { | ||
| 1995 | pasync_ctx->async_data.busy_entries--; | ||
| 1996 | if (pasync_ctx->async_entry[cri].wait_queue.hdr_received) { | ||
| 1997 | list_add_tail(&pasync_handle->link, | ||
| 1998 | &pasync_ctx->async_entry[cri].wait_queue. | ||
| 1999 | list); | ||
| 2000 | pasync_ctx->async_entry[cri].wait_queue. | ||
| 2001 | bytes_received += | ||
| 2002 | (unsigned short)pasync_handle->buffer_len; | ||
| 2003 | |||
| 2004 | if (pasync_ctx->async_entry[cri].wait_queue. | ||
| 2005 | bytes_received >= | ||
| 2006 | pasync_ctx->async_entry[cri].wait_queue. | ||
| 2007 | bytes_needed) | ||
| 2008 | status = hwi_fwd_async_msg(beiscsi_conn, phba, | ||
| 2009 | pasync_ctx, cri); | ||
| 2010 | } | ||
| 2011 | } | ||
| 2012 | return status; | ||
| 2013 | } | 1783 | } |
| 2014 | 1784 | ||
| 2015 | static void hwi_process_default_pdu_ring(struct beiscsi_conn *beiscsi_conn, | 1785 | static void |
| 2016 | struct beiscsi_hba *phba, | 1786 | beiscsi_hdq_process_compl(struct beiscsi_conn *beiscsi_conn, |
| 2017 | struct i_t_dpdu_cqe *pdpdu_cqe) | 1787 | struct i_t_dpdu_cqe *pdpdu_cqe) |
| 2018 | { | 1788 | { |
| 1789 | struct beiscsi_hba *phba = beiscsi_conn->phba; | ||
| 1790 | struct hd_async_handle *pasync_handle = NULL; | ||
| 1791 | struct hd_async_context *pasync_ctx; | ||
| 2019 | struct hwi_controller *phwi_ctrlr; | 1792 | struct hwi_controller *phwi_ctrlr; |
| 2020 | struct hwi_async_pdu_context *pasync_ctx; | 1793 | u16 cid_cri; |
| 2021 | struct async_pdu_handle *pasync_handle = NULL; | 1794 | u8 ulp_num; |
| 2022 | unsigned int cq_index = -1; | ||
| 2023 | uint16_t cri_index = BE_GET_CRI_FROM_CID( | ||
| 2024 | beiscsi_conn->beiscsi_conn_cid); | ||
| 2025 | 1795 | ||
| 2026 | phwi_ctrlr = phba->phwi_ctrlr; | 1796 | phwi_ctrlr = phba->phwi_ctrlr; |
| 2027 | pasync_ctx = HWI_GET_ASYNC_PDU_CTX(phwi_ctrlr, | 1797 | cid_cri = BE_GET_CRI_FROM_CID(beiscsi_conn->beiscsi_conn_cid); |
| 2028 | BEISCSI_GET_ULP_FROM_CRI(phwi_ctrlr, | 1798 | ulp_num = BEISCSI_GET_ULP_FROM_CRI(phwi_ctrlr, cid_cri); |
| 2029 | cri_index)); | 1799 | pasync_ctx = HWI_GET_ASYNC_PDU_CTX(phwi_ctrlr, ulp_num); |
| 2030 | 1800 | pasync_handle = beiscsi_hdl_get_handle(beiscsi_conn, pasync_ctx, | |
| 2031 | pasync_handle = hwi_get_async_handle(phba, beiscsi_conn, pasync_ctx, | 1801 | pdpdu_cqe); |
| 2032 | pdpdu_cqe, &cq_index); | 1802 | if (!pasync_handle) |
| 2033 | 1803 | return; | |
| 2034 | if (pasync_handle->consumed == 0) | ||
| 2035 | hwi_update_async_writables(phba, pasync_ctx, | ||
| 2036 | pasync_handle->is_header, cq_index); | ||
| 2037 | 1804 | ||
| 2038 | hwi_gather_async_pdu(beiscsi_conn, phba, pasync_handle); | 1805 | beiscsi_hdl_gather_pdu(beiscsi_conn, pasync_ctx, pasync_handle); |
| 2039 | hwi_post_async_buffers(phba, pasync_handle->is_header, | 1806 | beiscsi_hdq_post_handles(phba, pasync_handle->is_header, ulp_num); |
| 2040 | BEISCSI_GET_ULP_FROM_CRI( | ||
| 2041 | phwi_ctrlr, cri_index)); | ||
| 2042 | } | 1807 | } |
| 2043 | 1808 | ||
| 2044 | void beiscsi_process_mcc_cq(struct beiscsi_hba *phba) | 1809 | void beiscsi_process_mcc_cq(struct beiscsi_hba *phba) |
| @@ -2051,6 +1816,9 @@ void beiscsi_process_mcc_cq(struct beiscsi_hba *phba) · 6 unmodified lines | |||
| 2051 | mcc_compl = queue_tail_node(mcc_cq); | 1816 | mcc_compl = queue_tail_node(mcc_cq); |
| 2052 | mcc_compl->flags = le32_to_cpu(mcc_compl->flags); | 1817 | mcc_compl->flags = le32_to_cpu(mcc_compl->flags); |
| 2053 | while (mcc_compl->flags & CQE_FLAGS_VALID_MASK) { | 1818 | while (mcc_compl->flags & CQE_FLAGS_VALID_MASK) { |
| 1819 | if (beiscsi_hba_in_error(phba)) | ||
| 1820 | return; | ||
| 1821 | |||
| 2054 | if (num_processed >= 32) { | 1822 | if (num_processed >= 32) { |
| 2055 | hwi_ring_cq_db(phba, mcc_cq->id, | 1823 | hwi_ring_cq_db(phba, mcc_cq->id, |
| 2056 | num_processed, 0); | 1824 | num_processed, 0); |
| @@ -2073,6 +1841,19 @@ void beiscsi_process_mcc_cq(struct beiscsi_hba *phba) · 16 unmodified lines | |||
| 2073 | hwi_ring_cq_db(phba, mcc_cq->id, num_processed, 1); | 1841 | hwi_ring_cq_db(phba, mcc_cq->id, num_processed, 1); |
| 2074 | } | 1842 | } |
| 2075 | 1843 | ||
| 1844 | static void beiscsi_mcc_work(struct work_struct *work) | ||
| 1845 | { | ||
| 1846 | struct be_eq_obj *pbe_eq; | ||
| 1847 | struct beiscsi_hba *phba; | ||
| 1848 | |||
| 1849 | pbe_eq = container_of(work, struct be_eq_obj, mcc_work); | ||
| 1850 | phba = pbe_eq->phba; | ||
| 1851 | beiscsi_process_mcc_cq(phba); | ||
| 1852 | /* rearm EQ for further interrupts */ | ||
| 1853 | if (!beiscsi_hba_in_error(phba)) | ||
| 1854 | hwi_ring_eq_db(phba, pbe_eq->q.id, 0, 0, 1, 1); | ||
| 1855 | } | ||
| 1856 | |||
| 2076 | /** | 1857 | /** |
| 2077 | * beiscsi_process_cq()- Process the Completion Queue | 1858 | * beiscsi_process_cq()- Process the Completion Queue |
| 2078 | * @pbe_eq: Event Q on which the Completion has come | 1859 | * @pbe_eq: Event Q on which the Completion has come |
| @@ -2101,6 +1882,9 @@ unsigned int beiscsi_process_cq(struct be_eq_obj *pbe_eq, int budget) · 22 unmodified lines | |||
| 2101 | 1882 | ||
| 2102 | while (sol->dw[offsetof(struct amap_sol_cqe, valid) / 32] & | 1883 | while (sol->dw[offsetof(struct amap_sol_cqe, valid) / 32] & |
| 2103 | CQE_VALID_MASK) { | 1884 | CQE_VALID_MASK) { |
| 1885 | if (beiscsi_hba_in_error(phba)) | ||
| 1886 | return 0; | ||
| 1887 | |||
| 2104 | be_dws_le_to_cpu(sol, sizeof(struct sol_cqe)); | 1888 | be_dws_le_to_cpu(sol, sizeof(struct sol_cqe)); |
| 2105 | 1889 | ||
| 2106 | code = (sol->dw[offsetof(struct amap_sol_cqe, code) / | 1890 | code = (sol->dw[offsetof(struct amap_sol_cqe, code) / |
| @@ -2165,8 +1949,8 @@ unsigned int beiscsi_process_cq(struct be_eq_obj *pbe_eq, int budget) · 58 unmodified lines | |||
| 2165 | cqe_desc[code], code, cid); | 1949 | cqe_desc[code], code, cid); |
| 2166 | 1950 | ||
| 2167 | spin_lock_bh(&phba->async_pdu_lock); | 1951 | spin_lock_bh(&phba->async_pdu_lock); |
| 2168 | hwi_process_default_pdu_ring(beiscsi_conn, phba, | 1952 | beiscsi_hdq_process_compl(beiscsi_conn, |
| 2169 | (struct i_t_dpdu_cqe *)sol); | 1953 | (struct i_t_dpdu_cqe *)sol); |
| 2170 | spin_unlock_bh(&phba->async_pdu_lock); | 1954 | spin_unlock_bh(&phba->async_pdu_lock); |
| 2171 | break; | 1955 | break; |
| 2172 | case UNSOL_DATA_NOTIFY: | 1956 | case UNSOL_DATA_NOTIFY: |
| @@ -2176,8 +1960,8 @@ unsigned int beiscsi_process_cq(struct be_eq_obj *pbe_eq, int budget) · 3 unmodified lines | |||
| 2176 | cqe_desc[code], code, cid); | 1960 | cqe_desc[code], code, cid); |
| 2177 | 1961 | ||
| 2178 | spin_lock_bh(&phba->async_pdu_lock); | 1962 | spin_lock_bh(&phba->async_pdu_lock); |
| 2179 | hwi_process_default_pdu_ring(beiscsi_conn, phba, | 1963 | beiscsi_hdq_process_compl(beiscsi_conn, |
| 2180 | (struct i_t_dpdu_cqe *)sol); | 1964 | (struct i_t_dpdu_cqe *)sol); |
| 2181 | spin_unlock_bh(&phba->async_pdu_lock); | 1965 | spin_unlock_bh(&phba->async_pdu_lock); |
| 2182 | break; | 1966 | break; |
| 2183 | case CXN_INVALIDATE_INDEX_NOTIFY: | 1967 | case CXN_INVALIDATE_INDEX_NOTIFY: |
| @@ -2213,8 +1997,9 @@ unsigned int beiscsi_process_cq(struct be_eq_obj *pbe_eq, int budget) · 29 unmodified lines | |||
| 2213 | "BM_%d : Dropping %s[%d] on DPDU ring on CID : %d\n", | 1997 | "BM_%d : Dropping %s[%d] on DPDU ring on CID : %d\n", |
| 2214 | cqe_desc[code], code, cid); | 1998 | cqe_desc[code], code, cid); |
| 2215 | spin_lock_bh(&phba->async_pdu_lock); | 1999 | spin_lock_bh(&phba->async_pdu_lock); |
| 2216 | hwi_flush_default_pdu_buffer(phba, beiscsi_conn, | 2000 | /* driver consumes the entry and drops the contents */ |
| 2217 | (struct i_t_dpdu_cqe *) sol); | 2001 | beiscsi_hdq_process_compl(beiscsi_conn, |
| 2002 | (struct i_t_dpdu_cqe *)sol); | ||
| 2218 | spin_unlock_bh(&phba->async_pdu_lock); | 2003 | spin_unlock_bh(&phba->async_pdu_lock); |
| 2219 | break; | 2004 | break; |
| 2220 | case CXN_KILLED_PDU_SIZE_EXCEEDS_DSL: | 2005 | case CXN_KILLED_PDU_SIZE_EXCEEDS_DSL: |
| @@ -2262,60 +2047,32 @@ proc_next_cqe: · 41 unmodified lines | |||
| 2262 | return total; | 2047 | return total; |
| 2263 | } | 2048 | } |
| 2264 | 2049 | ||
| 2265 | void beiscsi_process_all_cqs(struct work_struct *work) | ||
| 2266 | { | ||
| 2267 | unsigned long flags; | ||
| 2268 | struct hwi_controller *phwi_ctrlr; | ||
| 2269 | struct hwi_context_memory *phwi_context; | ||
| 2270 | struct beiscsi_hba *phba; | ||
| 2271 | struct be_eq_obj *pbe_eq = | ||
| 2272 | container_of(work, struct be_eq_obj, work_cqs); | ||
| 2273 | |||
| 2274 | phba = pbe_eq->phba; | ||
| 2275 | phwi_ctrlr = phba->phwi_ctrlr; | ||
| 2276 | phwi_context = phwi_ctrlr->phwi_ctxt; | ||
| 2277 | |||
| 2278 | if (pbe_eq->todo_mcc_cq) { | ||
| 2279 | spin_lock_irqsave(&phba->isr_lock, flags); | ||
| 2280 | pbe_eq->todo_mcc_cq = false; | ||
| 2281 | spin_unlock_irqrestore(&phba->isr_lock, flags); | ||
| 2282 | beiscsi_process_mcc_cq(phba); | ||
| 2283 | } | ||
| 2284 | |||
| 2285 | if (pbe_eq->todo_cq) { | ||
| 2286 | spin_lock_irqsave(&phba->isr_lock, flags); | ||
| 2287 | pbe_eq->todo_cq = false; | ||
| 2288 | spin_unlock_irqrestore(&phba->isr_lock, flags); | ||
| 2289 | beiscsi_process_cq(pbe_eq, BE2_MAX_NUM_CQ_PROC); | ||
| 2290 | } | ||
| 2291 | |||
| 2292 | /* rearm EQ for further interrupts */ | ||
| 2293 | hwi_ring_eq_db(phba, pbe_eq->q.id, 0, 0, 1, 1); | ||
| 2294 | } | ||
| 2295 | |||
| 2296 | static int be_iopoll(struct irq_poll *iop, int budget) | 2050 | static int be_iopoll(struct irq_poll *iop, int budget) |
| 2297 | { | 2051 | { |
| 2298 | unsigned int ret, num_eq_processed; | 2052 | unsigned int ret, io_events; |
| 2299 | struct beiscsi_hba *phba; | 2053 | struct beiscsi_hba *phba; |
| 2300 | struct be_eq_obj *pbe_eq; | 2054 | struct be_eq_obj *pbe_eq; |
| 2301 | struct be_eq_entry *eqe = NULL; | 2055 | struct be_eq_entry *eqe = NULL; |
| 2302 | struct be_queue_info *eq; | 2056 | struct be_queue_info *eq; |
| 2303 | 2057 | ||
| 2304 | num_eq_processed = 0; | ||
| 2305 | pbe_eq = container_of(iop, struct be_eq_obj, iopoll); | 2058 | pbe_eq = container_of(iop, struct be_eq_obj, iopoll); |
| 2306 | phba = pbe_eq->phba; | 2059 | phba = pbe_eq->phba; |
| 2060 | if (beiscsi_hba_in_error(phba)) { | ||
| 2061 | irq_poll_complete(iop); | ||
| 2062 | return 0; | ||
| 2063 | } | ||
| 2064 | |||
| 2065 | io_events = 0; | ||
| 2307 | eq = &pbe_eq->q; | 2066 | eq = &pbe_eq->q; |
| 2308 | eqe = queue_tail_node(eq); | 2067 | eqe = queue_tail_node(eq); |
| 2309 | |||
| 2310 | while (eqe->dw[offsetof(struct amap_eq_entry, valid) / 32] & | 2068 | while (eqe->dw[offsetof(struct amap_eq_entry, valid) / 32] & |
| 2311 | EQE_VALID_MASK) { | 2069 | EQE_VALID_MASK) { |
| 2312 | AMAP_SET_BITS(struct amap_eq_entry, valid, eqe, 0); | 2070 | AMAP_SET_BITS(struct amap_eq_entry, valid, eqe, 0); |
| 2313 | queue_tail_inc(eq); | 2071 | queue_tail_inc(eq); |
| 2314 | eqe = queue_tail_node(eq); | 2072 | eqe = queue_tail_node(eq); |
| 2315 | num_eq_processed++; | 2073 | io_events++; |
| 2316 | } | 2074 | } |
| 2317 | 2075 | hwi_ring_eq_db(phba, eq->id, 1, io_events, 0, 1); | |
| 2318 | hwi_ring_eq_db(phba, eq->id, 1, num_eq_processed, 0, 1); | ||
| 2319 | 2076 | ||
| 2320 | ret = beiscsi_process_cq(pbe_eq, budget); | 2077 | ret = beiscsi_process_cq(pbe_eq, budget); |
| 2321 | pbe_eq->cq_count += ret; | 2078 | pbe_eq->cq_count += ret; |
| @@ -2325,7 +2082,8 @@ static int be_iopoll(struct irq_poll *iop, int budget) · 3 unmodified lines | |||
| 2325 | BEISCSI_LOG_CONFIG | BEISCSI_LOG_IO, | 2082 | BEISCSI_LOG_CONFIG | BEISCSI_LOG_IO, |
| 2326 | "BM_%d : rearm pbe_eq->q.id =%d ret %d\n", | 2083 | "BM_%d : rearm pbe_eq->q.id =%d ret %d\n", |
| 2327 | pbe_eq->q.id, ret); | 2084 | pbe_eq->q.id, ret); |
| 2328 | hwi_ring_eq_db(phba, pbe_eq->q.id, 0, 0, 1, 1); | 2085 | if (!beiscsi_hba_in_error(phba)) |
| 2086 | hwi_ring_eq_db(phba, pbe_eq->q.id, 0, 0, 1, 1); | ||
| 2329 | } | 2087 | } |
| 2330 | return ret; | 2088 | return ret; |
| 2331 | } | 2089 | } |
| @@ -2691,20 +2449,20 @@ static void beiscsi_find_mem_req(struct beiscsi_hba *phba) · 359 unmodified lines | |||
| 2691 | (ulp_num * MEM_DESCR_OFFSET)); | 2449 | (ulp_num * MEM_DESCR_OFFSET)); |
| 2692 | phba->mem_req[mem_descr_index] = | 2450 | phba->mem_req[mem_descr_index] = |
| 2693 | BEISCSI_GET_CID_COUNT(phba, ulp_num) * | 2451 | BEISCSI_GET_CID_COUNT(phba, ulp_num) * |
| 2694 | sizeof(struct async_pdu_handle); | 2452 | sizeof(struct hd_async_handle); |
| 2695 | 2453 | ||
| 2696 | mem_descr_index = (HWI_MEM_ASYNC_DATA_HANDLE_ULP0 + | 2454 | mem_descr_index = (HWI_MEM_ASYNC_DATA_HANDLE_ULP0 + |
| 2697 | (ulp_num * MEM_DESCR_OFFSET)); | 2455 | (ulp_num * MEM_DESCR_OFFSET)); |
| 2698 | phba->mem_req[mem_descr_index] = | 2456 | phba->mem_req[mem_descr_index] = |
| 2699 | BEISCSI_GET_CID_COUNT(phba, ulp_num) * | 2457 | BEISCSI_GET_CID_COUNT(phba, ulp_num) * |
| 2700 | sizeof(struct async_pdu_handle); | 2458 | sizeof(struct hd_async_handle); |
| 2701 | 2459 | ||
| 2702 | mem_descr_index = (HWI_MEM_ASYNC_PDU_CONTEXT_ULP0 + | 2460 | mem_descr_index = (HWI_MEM_ASYNC_PDU_CONTEXT_ULP0 + |
| 2703 | (ulp_num * MEM_DESCR_OFFSET)); | 2461 | (ulp_num * MEM_DESCR_OFFSET)); |
| 2704 | phba->mem_req[mem_descr_index] = | 2462 | phba->mem_req[mem_descr_index] = |
| 2705 | sizeof(struct hwi_async_pdu_context) + | 2463 | sizeof(struct hd_async_context) + |
| 2706 | (BEISCSI_GET_CID_COUNT(phba, ulp_num) * | 2464 | (BEISCSI_GET_CID_COUNT(phba, ulp_num) * |
| 2707 | sizeof(struct hwi_async_entry)); | 2465 | sizeof(struct hd_async_entry)); |
| 2708 | } | 2466 | } |
| 2709 | } | 2467 | } |
| 2710 | } | 2468 | } |
| @@ -2963,35 +2721,34 @@ static int hwi_init_async_pdu_ctx(struct beiscsi_hba *phba) · 252 unmodified lines | |||
| 2963 | uint8_t ulp_num; | 2721 | uint8_t ulp_num; |
| 2964 | struct hwi_controller *phwi_ctrlr; | 2722 | struct hwi_controller *phwi_ctrlr; |
| 2965 | struct hba_parameters *p = &phba->params; | 2723 | struct hba_parameters *p = &phba->params; |
| 2966 | struct hwi_async_pdu_context *pasync_ctx; | 2724 | struct hd_async_context *pasync_ctx; |
| 2967 | struct async_pdu_handle *pasync_header_h, *pasync_data_h; | 2725 | struct hd_async_handle *pasync_header_h, *pasync_data_h; |
| 2968 | unsigned int index, idx, num_per_mem, num_async_data; | 2726 | unsigned int index, idx, num_per_mem, num_async_data; |
| 2969 | struct be_mem_descriptor *mem_descr; | 2727 | struct be_mem_descriptor *mem_descr; |
| 2970 | 2728 | ||
| 2971 | for (ulp_num = 0; ulp_num < BEISCSI_ULP_COUNT; ulp_num++) { | 2729 | for (ulp_num = 0; ulp_num < BEISCSI_ULP_COUNT; ulp_num++) { |
| 2972 | if (test_bit(ulp_num, &phba->fw_config.ulp_supported)) { | 2730 | if (test_bit(ulp_num, &phba->fw_config.ulp_supported)) { |
| 2973 | 2731 | /* get async_ctx for each ULP */ | |
| 2974 | mem_descr = (struct be_mem_descriptor *)phba->init_mem; | 2732 | mem_descr = (struct be_mem_descriptor *)phba->init_mem; |
| 2975 | mem_descr += (HWI_MEM_ASYNC_PDU_CONTEXT_ULP0 + | 2733 | mem_descr += (HWI_MEM_ASYNC_PDU_CONTEXT_ULP0 + |
| 2976 | (ulp_num * MEM_DESCR_OFFSET)); | 2734 | (ulp_num * MEM_DESCR_OFFSET)); |
| 2977 | 2735 | ||
| 2978 | phwi_ctrlr = phba->phwi_ctrlr; | 2736 | phwi_ctrlr = phba->phwi_ctrlr; |
| 2979 | phwi_ctrlr->phwi_ctxt->pasync_ctx[ulp_num] = | 2737 | phwi_ctrlr->phwi_ctxt->pasync_ctx[ulp_num] = |
| 2980 | (struct hwi_async_pdu_context *) | 2738 | (struct hd_async_context *) |
| 2981 | mem_descr->mem_array[0].virtual_address; | 2739 | mem_descr->mem_array[0].virtual_address; |
| 2982 | 2740 | ||
| 2983 | pasync_ctx = phwi_ctrlr->phwi_ctxt->pasync_ctx[ulp_num]; | 2741 | pasync_ctx = phwi_ctrlr->phwi_ctxt->pasync_ctx[ulp_num]; |
| 2984 | memset(pasync_ctx, 0, sizeof(*pasync_ctx)); | 2742 | memset(pasync_ctx, 0, sizeof(*pasync_ctx)); |
| 2985 | 2743 | ||
| 2986 | pasync_ctx->async_entry = | 2744 | pasync_ctx->async_entry = |
| 2987 | (struct hwi_async_entry *) | 2745 | (struct hd_async_entry *) |
| 2988 | ((long unsigned int)pasync_ctx + | 2746 | ((long unsigned int)pasync_ctx + |
| 2989 | sizeof(struct hwi_async_pdu_context)); | 2747 | sizeof(struct hd_async_context)); |
| 2990 | 2748 | ||
| 2991 | pasync_ctx->num_entries = BEISCSI_GET_CID_COUNT(phba, | 2749 | pasync_ctx->num_entries = BEISCSI_GET_CID_COUNT(phba, |
| 2992 | ulp_num); | 2750 | ulp_num); |
| 2993 | pasync_ctx->buffer_size = p->defpdu_hdr_sz; | 2751 | /* setup header buffers */ |
| 2994 | |||
| 2995 | mem_descr = (struct be_mem_descriptor *)phba->init_mem; | 2752 | mem_descr = (struct be_mem_descriptor *)phba->init_mem; |
| 2996 | mem_descr += HWI_MEM_ASYNC_HEADER_BUF_ULP0 + | 2753 | mem_descr += HWI_MEM_ASYNC_HEADER_BUF_ULP0 + |
| 2997 | (ulp_num * MEM_DESCR_OFFSET); | 2754 | (ulp_num * MEM_DESCR_OFFSET); |
| @@ -3008,6 +2765,7 @@ static int hwi_init_async_pdu_ctx(struct beiscsi_hba *phba) · 10 unmodified lines | |||
| 3008 | "BM_%d : No Virtual address for ULP : %d\n", | 2765 | "BM_%d : No Virtual address for ULP : %d\n", |
| 3009 | ulp_num); | 2766 | ulp_num); |
| 3010 | 2767 | ||
| 2768 | pasync_ctx->async_header.buffer_size = p->defpdu_hdr_sz; | ||
| 3011 | pasync_ctx->async_header.va_base = | 2769 | pasync_ctx->async_header.va_base = |
| 3012 | mem_descr->mem_array[0].virtual_address; | 2770 | mem_descr->mem_array[0].virtual_address; |
| 3013 | 2771 | ||
| @@ -3015,6 +2773,7 @@ static int hwi_init_async_pdu_ctx(struct beiscsi_hba *phba) · 1 unmodified line | |||
| 3015 | mem_descr->mem_array[0]. | 2773 | mem_descr->mem_array[0]. |
| 3016 | bus_address.u.a64.address; | 2774 | bus_address.u.a64.address; |
| 3017 | 2775 | ||
| 2776 | /* setup header buffer sgls */ | ||
| 3018 | mem_descr = (struct be_mem_descriptor *)phba->init_mem; | 2777 | mem_descr = (struct be_mem_descriptor *)phba->init_mem; |
| 3019 | mem_descr += HWI_MEM_ASYNC_HEADER_RING_ULP0 + | 2778 | mem_descr += HWI_MEM_ASYNC_HEADER_RING_ULP0 + |
| 3020 | (ulp_num * MEM_DESCR_OFFSET); | 2779 | (ulp_num * MEM_DESCR_OFFSET); |
| @@ -3034,6 +2793,7 @@ static int hwi_init_async_pdu_ctx(struct beiscsi_hba *phba) · 13 unmodified lines | |||
| 3034 | pasync_ctx->async_header.ring_base = | 2793 | pasync_ctx->async_header.ring_base = |
| 3035 | mem_descr->mem_array[0].virtual_address; | 2794 | mem_descr->mem_array[0].virtual_address; |
| 3036 | 2795 | ||
| 2796 | /* setup header buffer handles */ | ||
| 3037 | mem_descr = (struct be_mem_descriptor *)phba->init_mem; | 2797 | mem_descr = (struct be_mem_descriptor *)phba->init_mem; |
| 3038 | mem_descr += HWI_MEM_ASYNC_HEADER_HANDLE_ULP0 + | 2798 | mem_descr += HWI_MEM_ASYNC_HEADER_HANDLE_ULP0 + |
| 3039 | (ulp_num * MEM_DESCR_OFFSET); | 2799 | (ulp_num * MEM_DESCR_OFFSET); |
| @@ -3052,9 +2812,9 @@ static int hwi_init_async_pdu_ctx(struct beiscsi_hba *phba) · 12 unmodified lines | |||
| 3052 | 2812 | ||
| 3053 | pasync_ctx->async_header.handle_base = | 2813 | pasync_ctx->async_header.handle_base = |
| 3054 | mem_descr->mem_array[0].virtual_address; | 2814 | mem_descr->mem_array[0].virtual_address; |
| 3055 | pasync_ctx->async_header.writables = 0; | ||
| 3056 | INIT_LIST_HEAD(&pasync_ctx->async_header.free_list); | 2815 | INIT_LIST_HEAD(&pasync_ctx->async_header.free_list); |
| 3057 | 2816 | ||
| 2817 | /* setup data buffer sgls */ | ||
| 3058 | mem_descr = (struct be_mem_descriptor *)phba->init_mem; | 2818 | mem_descr = (struct be_mem_descriptor *)phba->init_mem; |
| 3059 | mem_descr += HWI_MEM_ASYNC_DATA_RING_ULP0 + | 2819 | mem_descr += HWI_MEM_ASYNC_DATA_RING_ULP0 + |
| 3060 | (ulp_num * MEM_DESCR_OFFSET); | 2820 | (ulp_num * MEM_DESCR_OFFSET); |
| @@ -3074,6 +2834,7 @@ static int hwi_init_async_pdu_ctx(struct beiscsi_hba *phba) · 13 unmodified lines | |||
| 3074 | pasync_ctx->async_data.ring_base = | 2834 | pasync_ctx->async_data.ring_base = |
| 3075 | mem_descr->mem_array[0].virtual_address; | 2835 | mem_descr->mem_array[0].virtual_address; |
| 3076 | 2836 | ||
| 2837 | /* setup data buffer handles */ | ||
| 3077 | mem_descr = (struct be_mem_descriptor *)phba->init_mem; | 2838 | mem_descr = (struct be_mem_descriptor *)phba->init_mem; |
| 3078 | mem_descr += HWI_MEM_ASYNC_DATA_HANDLE_ULP0 + | 2839 | mem_descr += HWI_MEM_ASYNC_DATA_HANDLE_ULP0 + |
| 3079 | (ulp_num * MEM_DESCR_OFFSET); | 2840 | (ulp_num * MEM_DESCR_OFFSET); |
| @@ -3085,16 +2846,16 @@ static int hwi_init_async_pdu_ctx(struct beiscsi_hba *phba) · 5 unmodified lines | |||
| 3085 | 2846 | ||
| 3086 | pasync_ctx->async_data.handle_base = | 2847 | pasync_ctx->async_data.handle_base = |
| 3087 | mem_descr->mem_array[0].virtual_address; | 2848 | mem_descr->mem_array[0].virtual_address; |
| 3088 | pasync_ctx->async_data.writables = 0; | ||
| 3089 | INIT_LIST_HEAD(&pasync_ctx->async_data.free_list); | 2849 | INIT_LIST_HEAD(&pasync_ctx->async_data.free_list); |
| 3090 | 2850 | ||
| 3091 | pasync_header_h = | 2851 | pasync_header_h = |
| 3092 | (struct async_pdu_handle *) | 2852 | (struct hd_async_handle *) |
| 3093 | pasync_ctx->async_header.handle_base; | 2853 | pasync_ctx->async_header.handle_base; |
| 3094 | pasync_data_h = | 2854 | pasync_data_h = |
| 3095 | (struct async_pdu_handle *) | 2855 | (struct hd_async_handle *) |
| 3096 | pasync_ctx->async_data.handle_base; | 2856 | pasync_ctx->async_data.handle_base; |
| 3097 | 2857 | ||
| 2858 | /* setup data buffers */ | ||
| 3098 | mem_descr = (struct be_mem_descriptor *)phba->init_mem; | 2859 | mem_descr = (struct be_mem_descriptor *)phba->init_mem; |
| 3099 | mem_descr += HWI_MEM_ASYNC_DATA_BUF_ULP0 + | 2860 | mem_descr += HWI_MEM_ASYNC_DATA_BUF_ULP0 + |
| 3100 | (ulp_num * MEM_DESCR_OFFSET); | 2861 | (ulp_num * MEM_DESCR_OFFSET); |
| @@ -3112,6 +2873,7 @@ static int hwi_init_async_pdu_ctx(struct beiscsi_hba *phba) · 11 unmodified lines | |||
| 3112 | ulp_num); | 2873 | ulp_num); |
| 3113 | 2874 | ||
| 3114 | idx = 0; | 2875 | idx = 0; |
| 2876 | pasync_ctx->async_data.buffer_size = p->defpdu_data_sz; | ||
| 3115 | pasync_ctx->async_data.va_base = | 2877 | pasync_ctx->async_data.va_base = |
| 3116 | mem_descr->mem_array[idx].virtual_address; | 2878 | mem_descr->mem_array[idx].virtual_address; |
| 3117 | pasync_ctx->async_data.pa_base.u.a64.address = | 2879 | pasync_ctx->async_data.pa_base.u.a64.address = |
| @@ -3125,7 +2887,8 @@ static int hwi_init_async_pdu_ctx(struct beiscsi_hba *phba) · 7 unmodified lines | |||
| 3125 | for (index = 0; index < BEISCSI_GET_CID_COUNT | 2887 | for (index = 0; index < BEISCSI_GET_CID_COUNT |
| 3126 | (phba, ulp_num); index++) { | 2888 | (phba, ulp_num); index++) { |
| 3127 | pasync_header_h->cri = -1; | 2889 | pasync_header_h->cri = -1; |
| 3128 | pasync_header_h->index = (char)index; | 2890 | pasync_header_h->is_header = 1; |
| 2891 | pasync_header_h->index = index; | ||
| 3129 | INIT_LIST_HEAD(&pasync_header_h->link); | 2892 | INIT_LIST_HEAD(&pasync_header_h->link); |
| 3130 | pasync_header_h->pbuffer = | 2893 | pasync_header_h->pbuffer = |
| 3131 | (void *)((unsigned long) | 2894 | (void *)((unsigned long) |
| @@ -3142,14 +2905,13 @@ static int hwi_init_async_pdu_ctx(struct beiscsi_hba *phba) · 10 unmodified lines | |||
| 3142 | free_list); | 2905 | free_list); |
| 3143 | pasync_header_h++; | 2906 | pasync_header_h++; |
| 3144 | pasync_ctx->async_header.free_entries++; | 2907 | pasync_ctx->async_header.free_entries++; |
| 3145 | pasync_ctx->async_header.writables++; | ||
| 3146 | |||
| 3147 | INIT_LIST_HEAD(&pasync_ctx->async_entry[index]. | ||
| 3148 | wait_queue.list); | ||
| 3149 | INIT_LIST_HEAD(&pasync_ctx->async_entry[index]. | 2908 | INIT_LIST_HEAD(&pasync_ctx->async_entry[index]. |
| 3150 | header_busy_list); | 2909 | wq.list); |
| 2910 | pasync_ctx->async_entry[index].header = NULL; | ||
| 2911 | |||
| 3151 | pasync_data_h->cri = -1; | 2912 | pasync_data_h->cri = -1; |
| 3152 | pasync_data_h->index = (char)index; | 2913 | pasync_data_h->is_header = 0; |
| 2914 | pasync_data_h->index = index; | ||
| 3153 | INIT_LIST_HEAD(&pasync_data_h->link); | 2915 | INIT_LIST_HEAD(&pasync_data_h->link); |
| 3154 | 2916 | ||
| 3155 | if (!num_async_data) { | 2917 | if (!num_async_data) { |
| @@ -3184,16 +2946,8 @@ static int hwi_init_async_pdu_ctx(struct beiscsi_hba *phba) · 28 unmodified lines | |||
| 3184 | free_list); | 2946 | free_list); |
| 3185 | pasync_data_h++; | 2947 | pasync_data_h++; |
| 3186 | pasync_ctx->async_data.free_entries++; | 2948 | pasync_ctx->async_data.free_entries++; |
| 3187 | pasync_ctx->async_data.writables++; | 2949 | pasync_ctx->async_entry[index].data = NULL; |
| 3188 | |||
| 3189 | INIT_LIST_HEAD(&pasync_ctx->async_entry[index]. | ||
| 3190 | data_busy_list); | ||
| 3191 | } | 2950 | } |
| 3192 | |||
| 3193 | pasync_ctx->async_header.host_write_ptr = 0; | ||
| 3194 | pasync_ctx->async_header.ep_read_ptr = -1; | ||
| 3195 | pasync_ctx->async_data.host_write_ptr = 0; | ||
| 3196 | pasync_ctx->async_data.ep_read_ptr = -1; | ||
| 3197 | } | 2951 | } |
| 3198 | } | 2952 | } |
| 3199 | 2953 | ||
| @@ -3265,8 +3019,8 @@ static int be_fill_queue(struct be_queue_info *q, · 65 unmodified lines | |||
| 3265 | static int beiscsi_create_eqs(struct beiscsi_hba *phba, | 3019 | static int beiscsi_create_eqs(struct beiscsi_hba *phba, |
| 3266 | struct hwi_context_memory *phwi_context) | 3020 | struct hwi_context_memory *phwi_context) |
| 3267 | { | 3021 | { |
| 3022 | int ret = -ENOMEM, eq_for_mcc; | ||
| 3268 | unsigned int i, num_eq_pages; | 3023 | unsigned int i, num_eq_pages; |
| 3269 | int ret = 0, eq_for_mcc; | ||
| 3270 | struct be_queue_info *eq; | 3024 | struct be_queue_info *eq; |
| 3271 | struct be_dma_mem *mem; | 3025 | struct be_dma_mem *mem; |
| 3272 | void *eq_vaddress; | 3026 | void *eq_vaddress; |
| @@ -3284,8 +3038,8 @@ static int beiscsi_create_eqs(struct beiscsi_hba *phba, · 11 unmodified lines | |||
| 3284 | mem = &eq->dma_mem; | 3038 | mem = &eq->dma_mem; |
| 3285 | phwi_context->be_eq[i].phba = phba; | 3039 | phwi_context->be_eq[i].phba = phba; |
| 3286 | eq_vaddress = pci_alloc_consistent(phba->pcidev, | 3040 | eq_vaddress = pci_alloc_consistent(phba->pcidev, |
| 3287 | num_eq_pages * PAGE_SIZE, | 3041 | num_eq_pages * PAGE_SIZE, |
| 3288 | &paddr); | 3042 | &paddr); |
| 3289 | if (!eq_vaddress) | 3043 | if (!eq_vaddress) |
| 3290 | goto create_eq_error; | 3044 | goto create_eq_error; |
| 3291 | 3045 | ||
| @@ -3313,6 +3067,7 @@ static int beiscsi_create_eqs(struct beiscsi_hba *phba, · 21 unmodified lines | |||
| 3313 | phwi_context->be_eq[i].q.id); | 3067 | phwi_context->be_eq[i].q.id); |
| 3314 | } | 3068 | } |
| 3315 | return 0; | 3069 | return 0; |
| 3070 | |||
| 3316 | create_eq_error: | 3071 | create_eq_error: |
| 3317 | for (i = 0; i < (phba->num_cpus + eq_for_mcc); i++) { | 3072 | for (i = 0; i < (phba->num_cpus + eq_for_mcc); i++) { |
| 3318 | eq = &phwi_context->be_eq[i].q; | 3073 | eq = &phwi_context->be_eq[i].q; |
| @@ -3329,11 +3084,11 @@ static int beiscsi_create_cqs(struct beiscsi_hba *phba, · 10 unmodified lines | |||
| 3329 | struct hwi_context_memory *phwi_context) | 3084 | struct hwi_context_memory *phwi_context) |
| 3330 | { | 3085 | { |
| 3331 | unsigned int i, num_cq_pages; | 3086 | unsigned int i, num_cq_pages; |
| 3332 | int ret = 0; | ||
| 3333 | struct be_queue_info *cq, *eq; | 3087 | struct be_queue_info *cq, *eq; |
| 3334 | struct be_dma_mem *mem; | 3088 | struct be_dma_mem *mem; |
| 3335 | struct be_eq_obj *pbe_eq; | 3089 | struct be_eq_obj *pbe_eq; |
| 3336 | void *cq_vaddress; | 3090 | void *cq_vaddress; |
| 3091 | int ret = -ENOMEM; | ||
| 3337 | dma_addr_t paddr; | 3092 | dma_addr_t paddr; |
| 3338 | 3093 | ||
| 3339 | num_cq_pages = PAGES_REQUIRED(phba->params.num_cq_entries * \ | 3094 | num_cq_pages = PAGES_REQUIRED(phba->params.num_cq_entries * \ |
| @@ -3347,10 +3102,11 @@ static int beiscsi_create_cqs(struct beiscsi_hba *phba, · 7 unmodified lines | |||
| 3347 | pbe_eq->phba = phba; | 3102 | pbe_eq->phba = phba; |
| 3348 | mem = &cq->dma_mem; | 3103 | mem = &cq->dma_mem; |
| 3349 | cq_vaddress = pci_alloc_consistent(phba->pcidev, | 3104 | cq_vaddress = pci_alloc_consistent(phba->pcidev, |
| 3350 | num_cq_pages * PAGE_SIZE, | 3105 | num_cq_pages * PAGE_SIZE, |
| 3351 | &paddr); | 3106 | &paddr); |
| 3352 | if (!cq_vaddress) | 3107 | if (!cq_vaddress) |
| 3353 | goto create_cq_error; | 3108 | goto create_cq_error; |
| 3109 | |||
| 3354 | ret = be_fill_queue(cq, phba->params.num_cq_entries, | 3110 | ret = be_fill_queue(cq, phba->params.num_cq_entries, |
| 3355 | sizeof(struct sol_cqe), cq_vaddress); | 3111 | sizeof(struct sol_cqe), cq_vaddress); |
| 3356 | if (ret) { | 3112 | if (ret) { |
| @@ -3385,7 +3141,6 @@ create_cq_error: · 28 unmodified lines | |||
| 3385 | mem->va, mem->dma); | 3141 | mem->va, mem->dma); |
| 3386 | } | 3142 | } |
| 3387 | return ret; | 3143 | return ret; |
| 3388 | |||
| 3389 | } | 3144 | } |
| 3390 | 3145 | ||
| 3391 | static int | 3146 | static int |
| @@ -3437,7 +3192,6 @@ beiscsi_create_def_hdr(struct beiscsi_hba *phba, · 45 unmodified lines | |||
| 3437 | "BM_%d : iscsi hdr def pdu id for ULP : %d is %d\n", | 3192 | "BM_%d : iscsi hdr def pdu id for ULP : %d is %d\n", |
| 3438 | ulp_num, | 3193 | ulp_num, |
| 3439 | phwi_context->be_def_hdrq[ulp_num].id); | 3194 | phwi_context->be_def_hdrq[ulp_num].id); |
| 3440 | hwi_post_async_buffers(phba, BEISCSI_DEFQ_HDR, ulp_num); | ||
| 3441 | return 0; | 3195 | return 0; |
| 3442 | } | 3196 | } |
| 3443 | 3197 | ||
| @@ -3492,11 +3246,9 @@ beiscsi_create_def_data(struct beiscsi_hba *phba, · 48 unmodified lines | |||
| 3492 | ulp_num, | 3246 | ulp_num, |
| 3493 | phwi_context->be_def_dataq[ulp_num].id); | 3247 | phwi_context->be_def_dataq[ulp_num].id); |
| 3494 | 3248 | ||
| 3495 | hwi_post_async_buffers(phba, BEISCSI_DEFQ_DATA, ulp_num); | ||
| 3496 | beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_INIT, | 3249 | beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_INIT, |
| 3497 | "BM_%d : DEFAULT PDU DATA RING CREATED" | 3250 | "BM_%d : DEFAULT PDU DATA RING CREATED" |
| 3498 | "on ULP : %d\n", ulp_num); | 3251 | "on ULP : %d\n", ulp_num); |
| 3499 | |||
| 3500 | return 0; | 3252 | return 0; |
| 3501 | } | 3253 | } |
| 3502 | 3254 | ||
| @@ -3716,10 +3468,53 @@ static void free_wrb_handles(struct beiscsi_hba *phba) · 213 unmodified lines | |||
| 3716 | 3468 | ||
| 3717 | static void be_mcc_queues_destroy(struct beiscsi_hba *phba) | 3469 | static void be_mcc_queues_destroy(struct beiscsi_hba *phba) |
| 3718 | { | 3470 | { |
| 3719 | struct be_queue_info *q; | ||
| 3720 | struct be_ctrl_info *ctrl = &phba->ctrl; | 3471 | struct be_ctrl_info *ctrl = &phba->ctrl; |
| 3472 | struct be_dma_mem *ptag_mem; | ||
| 3473 | struct be_queue_info *q; | ||
| 3474 | int i, tag; | ||
| 3721 | 3475 | ||
| 3722 | q = &phba->ctrl.mcc_obj.q; | 3476 | q = &phba->ctrl.mcc_obj.q; |
| 3477 | for (i = 0; i < MAX_MCC_CMD; i++) { | ||
| 3478 | tag = i + 1; | ||
| 3479 | if (!test_bit(MCC_TAG_STATE_RUNNING, | ||
| 3480 | &ctrl->ptag_state[tag].tag_state)) | ||
| 3481 | continue; | ||
| 3482 | |||
| 3483 | if (test_bit(MCC_TAG_STATE_TIMEOUT, | ||
| 3484 | &ctrl->ptag_state[tag].tag_state)) { | ||
| 3485 | ptag_mem = &ctrl->ptag_state[tag].tag_mem_state; | ||
| 3486 | if (ptag_mem->size) { | ||
| 3487 | pci_free_consistent(ctrl->pdev, | ||
| 3488 | ptag_mem->size, | ||
| 3489 | ptag_mem->va, | ||
| 3490 | ptag_mem->dma); | ||
| 3491 | ptag_mem->size = 0; | ||
| 3492 | } | ||
| 3493 | continue; | ||
| 3494 | } | ||
| 3495 | /** | ||
| 3496 | * If MCC is still active and waiting then wake up the process. | ||
| 3497 | * We are here only because port is going offline. The process | ||
| 3498 | * sees that (BEISCSI_HBA_ONLINE is cleared) and EIO error is | ||
| 3499 | * returned for the operation and allocated memory cleaned up. | ||
| 3500 | */ | ||
| 3501 | if (waitqueue_active(&ctrl->mcc_wait[tag])) { | ||
| 3502 | ctrl->mcc_tag_status[tag] = MCC_STATUS_FAILED; | ||
| 3503 | ctrl->mcc_tag_status[tag] |= CQE_VALID_MASK; | ||
| 3504 | wake_up_interruptible(&ctrl->mcc_wait[tag]); | ||
| 3505 | /* | ||
| 3506 | * Control tag info gets reinitialized in enable | ||
| 3507 | * so wait for the process to clear running state. | ||
| 3508 | */ | ||
| 3509 | while (test_bit(MCC_TAG_STATE_RUNNING, | ||
| 3510 | &ctrl->ptag_state[tag].tag_state)) | ||
| 3511 | schedule_timeout_uninterruptible(HZ); | ||
| 3512 | } | ||
| 3513 | /** | ||
| 3514 | * For MCC with tag_states MCC_TAG_STATE_ASYNC and | ||
| 3515 | * MCC_TAG_STATE_IGNORE nothing needs to done. | ||
| 3516 | */ | ||
| 3517 | } | ||
| 3723 | if (q->created) { | 3518 | if (q->created) { |
| 3724 | beiscsi_cmd_q_destroy(ctrl, q, QTYPE_MCCQ); | 3519 | beiscsi_cmd_q_destroy(ctrl, q, QTYPE_MCCQ); |
| 3725 | be_queue_free(phba, q); | 3520 | be_queue_free(phba, q); |
| @@ -3732,68 +3527,6 @@ static void be_mcc_queues_destroy(struct beiscsi_hba *phba) · 6 unmodified lines | |||
| 3732 | } | 3527 | } |
| 3733 | } | 3528 | } |
| 3734 | 3529 | ||
| 3735 | static void hwi_cleanup(struct beiscsi_hba *phba) | ||
| 3736 | { | ||
| 3737 | struct be_queue_info *q; | ||
| 3738 | struct be_ctrl_info *ctrl = &phba->ctrl; | ||
| 3739 | struct hwi_controller *phwi_ctrlr; | ||
| 3740 | struct hwi_context_memory *phwi_context; | ||
| 3741 | struct hwi_async_pdu_context *pasync_ctx; | ||
| 3742 | int i, eq_for_mcc, ulp_num; | ||
| 3743 | |||
| 3744 | phwi_ctrlr = phba->phwi_ctrlr; | ||
| 3745 | phwi_context = phwi_ctrlr->phwi_ctxt; | ||
| 3746 | |||
| 3747 | be_cmd_iscsi_remove_template_hdr(ctrl); | ||
| 3748 | |||
| 3749 | for (i = 0; i < phba->params.cxns_per_ctrl; i++) { | ||
| 3750 | q = &phwi_context->be_wrbq[i]; | ||
| 3751 | if (q->created) | ||
| 3752 | beiscsi_cmd_q_destroy(ctrl, q, QTYPE_WRBQ); | ||
| 3753 | } | ||
| 3754 | kfree(phwi_context->be_wrbq); | ||
| 3755 | free_wrb_handles(phba); | ||
| 3756 | |||
| 3757 | for (ulp_num = 0; ulp_num < BEISCSI_ULP_COUNT; ulp_num++) { | ||
| 3758 | if (test_bit(ulp_num, &phba->fw_config.ulp_supported)) { | ||
| 3759 | |||
| 3760 | q = &phwi_context->be_def_hdrq[ulp_num]; | ||
| 3761 | if (q->created) | ||
| 3762 | beiscsi_cmd_q_destroy(ctrl, q, QTYPE_DPDUQ); | ||
| 3763 | |||
| 3764 | q = &phwi_context->be_def_dataq[ulp_num]; | ||
| 3765 | if (q->created) | ||
| 3766 | beiscsi_cmd_q_destroy(ctrl, q, QTYPE_DPDUQ); | ||
| 3767 | |||
| 3768 | pasync_ctx = phwi_ctrlr->phwi_ctxt->pasync_ctx[ulp_num]; | ||
| 3769 | } | ||
| 3770 | } | ||
| 3771 | |||
| 3772 | beiscsi_cmd_q_destroy(ctrl, NULL, QTYPE_SGL); | ||
| 3773 | |||
| 3774 | for (i = 0; i < (phba->num_cpus); i++) { | ||
| 3775 | q = &phwi_context->be_cq[i]; | ||
| 3776 | if (q->created) { | ||
| 3777 | be_queue_free(phba, q); | ||
| 3778 | beiscsi_cmd_q_destroy(ctrl, q, QTYPE_CQ); | ||
| 3779 | } | ||
| 3780 | } | ||
| 3781 | |||
| 3782 | be_mcc_queues_destroy(phba); | ||
| 3783 | if (phba->msix_enabled) | ||
| 3784 | eq_for_mcc = 1; | ||
| 3785 | else | ||
| 3786 | eq_for_mcc = 0; | ||
| 3787 | for (i = 0; i < (phba->num_cpus + eq_for_mcc); i++) { | ||
| 3788 | q = &phwi_context->be_eq[i].q; | ||
| 3789 | if (q->created) { | ||
| 3790 | be_queue_free(phba, q); | ||
| 3791 | beiscsi_cmd_q_destroy(ctrl, q, QTYPE_EQ); | ||
| 3792 | } | ||
| 3793 | } | ||
| 3794 | be_cmd_fw_uninit(ctrl); | ||
| 3795 | } | ||
| 3796 | |||
| 3797 | static int be_mcc_queues_create(struct beiscsi_hba *phba, | 3530 | static int be_mcc_queues_create(struct beiscsi_hba *phba, |
| 3798 | struct hwi_context_memory *phwi_context) | 3531 | struct hwi_context_memory *phwi_context) |
| 3799 | { | 3532 | { |
| @@ -3875,7 +3608,119 @@ static void find_num_cpus(struct beiscsi_hba *phba) · 75 unmodified lines | |||
| 3875 | } | 3608 | } |
| 3876 | } | 3609 | } |
| 3877 | 3610 | ||
| 3878 | static int hwi_init_port(struct beiscsi_hba *phba) | 3611 | static void hwi_purge_eq(struct beiscsi_hba *phba) |
| 3612 | { | ||
| 3613 | struct hwi_controller *phwi_ctrlr; | ||
| 3614 | struct hwi_context_memory *phwi_context; | ||
| 3615 | struct be_queue_info *eq; | ||
| 3616 | struct be_eq_entry *eqe = NULL; | ||
| 3617 | int i, eq_msix; | ||
| 3618 | unsigned int num_processed; | ||
| 3619 | |||
| 3620 | if (beiscsi_hba_in_error(phba)) | ||
| 3621 | return; | ||
| 3622 | |||
| 3623 | phwi_ctrlr = phba->phwi_ctrlr; | ||
| 3624 | phwi_context = phwi_ctrlr->phwi_ctxt; | ||
| 3625 | if (phba->msix_enabled) | ||
| 3626 | eq_msix = 1; | ||
| 3627 | else | ||
| 3628 | eq_msix = 0; | ||
| 3629 | |||
| 3630 | for (i = 0; i < (phba->num_cpus + eq_msix); i++) { | ||
| 3631 | eq = &phwi_context->be_eq[i].q; | ||
| 3632 | eqe = queue_tail_node(eq); | ||
| 3633 | num_processed = 0; | ||
| 3634 | while (eqe->dw[offsetof(struct amap_eq_entry, valid) / 32] | ||
| 3635 | & EQE_VALID_MASK) { | ||
| 3636 | AMAP_SET_BITS(struct amap_eq_entry, valid, eqe, 0); | ||
| 3637 | queue_tail_inc(eq); | ||
| 3638 | eqe = queue_tail_node(eq); | ||
| 3639 | num_processed++; | ||
| 3640 | } | ||
| 3641 | |||
| 3642 | if (num_processed) | ||
| 3643 | hwi_ring_eq_db(phba, eq->id, 1, num_processed, 1, 1); | ||
| 3644 | } | ||
| 3645 | } | ||
| 3646 | |||
| 3647 | static void hwi_cleanup_port(struct beiscsi_hba *phba) | ||
| 3648 | { | ||
| 3649 | struct be_queue_info *q; | ||
| 3650 | struct be_ctrl_info *ctrl = &phba->ctrl; | ||
| 3651 | struct hwi_controller *phwi_ctrlr; | ||
| 3652 | struct hwi_context_memory *phwi_context; | ||
| 3653 | struct hd_async_context *pasync_ctx; | ||
| 3654 | int i, eq_for_mcc, ulp_num; | ||
| 3655 | |||
| 3656 | for (ulp_num = 0; ulp_num < BEISCSI_ULP_COUNT; ulp_num++) | ||
| 3657 | if (test_bit(ulp_num, &phba->fw_config.ulp_supported)) | ||
| 3658 | beiscsi_cmd_iscsi_cleanup(phba, ulp_num); | ||
| 3659 | |||
| 3660 | /** | ||
| 3661 | * Purge all EQ entries that may have been left out. This is to | ||
| 3662 | * workaround a problem we've seen occasionally where driver gets an | ||
| 3663 | * interrupt with EQ entry bit set after stopping the controller. | ||
| 3664 | */ | ||
| 3665 | hwi_purge_eq(phba); | ||
| 3666 | |||
| 3667 | phwi_ctrlr = phba->phwi_ctrlr; | ||
| 3668 | phwi_context = phwi_ctrlr->phwi_ctxt; | ||
| 3669 | |||
| 3670 | be_cmd_iscsi_remove_template_hdr(ctrl); | ||
| 3671 | |||
| 3672 | for (i = 0; i < phba->params.cxns_per_ctrl; i++) { | ||
| 3673 | q = &phwi_context->be_wrbq[i]; | ||
| 3674 | if (q->created) | ||
| 3675 | beiscsi_cmd_q_destroy(ctrl, q, QTYPE_WRBQ); | ||
| 3676 | } | ||
| 3677 | kfree(phwi_context->be_wrbq); | ||
| 3678 | free_wrb_handles(phba); | ||
| 3679 | |||
| 3680 | for (ulp_num = 0; ulp_num < BEISCSI_ULP_COUNT; ulp_num++) { | ||
| 3681 | if (test_bit(ulp_num, &phba->fw_config.ulp_supported)) { | ||
| 3682 | |||
| 3683 | q = &phwi_context->be_def_hdrq[ulp_num]; | ||
| 3684 | if (q->created) | ||
| 3685 | beiscsi_cmd_q_destroy(ctrl, q, QTYPE_DPDUQ); | ||
| 3686 | |||
| 3687 | q = &phwi_context->be_def_dataq[ulp_num]; | ||
| 3688 | if (q->created) | ||
| 3689 | beiscsi_cmd_q_destroy(ctrl, q, QTYPE_DPDUQ); | ||
| 3690 | |||
| 3691 | pasync_ctx = phwi_ctrlr->phwi_ctxt->pasync_ctx[ulp_num]; | ||
| 3692 | } | ||
| 3693 | } | ||
| 3694 | |||
| 3695 | beiscsi_cmd_q_destroy(ctrl, NULL, QTYPE_SGL); | ||
| 3696 | |||
| 3697 | for (i = 0; i < (phba->num_cpus); i++) { | ||
| 3698 | q = &phwi_context->be_cq[i]; | ||
| 3699 | if (q->created) { | ||
| 3700 | be_queue_free(phba, q); | ||
| 3701 | beiscsi_cmd_q_destroy(ctrl, q, QTYPE_CQ); | ||
| 3702 | } | ||
| 3703 | } | ||
| 3704 | |||
| 3705 | be_mcc_queues_destroy(phba); | ||
| 3706 | if (phba->msix_enabled) | ||
| 3707 | eq_for_mcc = 1; | ||
| 3708 | else | ||
| 3709 | eq_for_mcc = 0; | ||
| 3710 | for (i = 0; i < (phba->num_cpus + eq_for_mcc); i++) { | ||
| 3711 | q = &phwi_context->be_eq[i].q; | ||
| 3712 | if (q->created) { | ||
| 3713 | be_queue_free(phba, q); | ||
| 3714 | beiscsi_cmd_q_destroy(ctrl, q, QTYPE_EQ); | ||
| 3715 | } | ||
| 3716 | } | ||
| 3717 | /* this ensures complete FW cleanup */ | ||
| 3718 | beiscsi_cmd_function_reset(phba); | ||
| 3719 | /* last communication, indicate driver is unloading */ | ||
| 3720 | beiscsi_cmd_special_wrb(&phba->ctrl, 0); | ||
| 3721 | } | ||
| 3722 | |||
| 3723 | static int hwi_init_port(struct beiscsi_hba *phba) | ||
| 3879 | { | 3724 | { |
| 3880 | struct hwi_controller *phwi_ctrlr; | 3725 | struct hwi_controller *phwi_ctrlr; |
| 3881 | struct hwi_context_memory *phwi_context; | 3726 | struct hwi_context_memory *phwi_context; |
| @@ -3887,9 +3732,8 @@ static int hwi_init_port(struct beiscsi_hba *phba) · 5 unmodified lines | |||
| 3887 | phwi_context = phwi_ctrlr->phwi_ctxt; | 3732 | phwi_context = phwi_ctrlr->phwi_ctxt; |
| 3888 | phwi_context->max_eqd = 128; | 3733 | phwi_context->max_eqd = 128; |
| 3889 | phwi_context->min_eqd = 0; | 3734 | phwi_context->min_eqd = 0; |
| 3890 | phwi_context->cur_eqd = 0; | 3735 | phwi_context->cur_eqd = 32; |
| 3891 | be_cmd_fw_initialize(&phba->ctrl); | 3736 | /* set port optic state to unknown */ |
| 3892 | /* set optic state to unknown */ | ||
| 3893 | phba->optic_state = 0xff; | 3737 | phba->optic_state = 0xff; |
| 3894 | 3738 | ||
| 3895 | status = beiscsi_create_eqs(phba, phwi_context); | 3739 | status = beiscsi_create_eqs(phba, phwi_context); |
| @@ -3903,7 +3747,7 @@ static int hwi_init_port(struct beiscsi_hba *phba) · 7 unmodified lines | |||
| 3903 | if (status != 0) | 3747 | if (status != 0) |
| 3904 | goto error; | 3748 | goto error; |
| 3905 | 3749 | ||
| 3906 | status = mgmt_check_supported_fw(ctrl, phba); | 3750 | status = beiscsi_check_supported_fw(ctrl, phba); |
| 3907 | if (status != 0) { | 3751 | if (status != 0) { |
| 3908 | beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, | 3752 | beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, |
| 3909 | "BM_%d : Unsupported fw version\n"); | 3753 | "BM_%d : Unsupported fw version\n"); |
| @@ -3919,7 +3763,6 @@ static int hwi_init_port(struct beiscsi_hba *phba) · 9 unmodified lines | |||
| 3919 | 3763 | ||
| 3920 | for (ulp_num = 0; ulp_num < BEISCSI_ULP_COUNT; ulp_num++) { | 3764 | for (ulp_num = 0; ulp_num < BEISCSI_ULP_COUNT; ulp_num++) { |
| 3921 | if (test_bit(ulp_num, &phba->fw_config.ulp_supported)) { | 3765 | if (test_bit(ulp_num, &phba->fw_config.ulp_supported)) { |
| 3922 | |||
| 3923 | def_pdu_ring_sz = | 3766 | def_pdu_ring_sz = |
| 3924 | BEISCSI_GET_CID_COUNT(phba, ulp_num) * | 3767 | BEISCSI_GET_CID_COUNT(phba, ulp_num) * |
| 3925 | sizeof(struct phys_addr); | 3768 | sizeof(struct phys_addr); |
| @@ -3945,6 +3788,15 @@ static int hwi_init_port(struct beiscsi_hba *phba) · 19 unmodified lines | |||
| 3945 | ulp_num); | 3788 | ulp_num); |
| 3946 | goto error; | 3789 | goto error; |
| 3947 | } | 3790 | } |
| 3791 | /** | ||
| 3792 | * Now that the default PDU rings have been created, | ||
| 3793 | * let EP know about it. | ||
| 3794 | * Call beiscsi_cmd_iscsi_cleanup before posting? | ||
| 3795 | */ | ||
| 3796 | beiscsi_hdq_post_handles(phba, BEISCSI_DEFQ_HDR, | ||
| 3797 | ulp_num); | ||
| 3798 | beiscsi_hdq_post_handles(phba, BEISCSI_DEFQ_DATA, | ||
| 3799 | ulp_num); | ||
| 3948 | } | 3800 | } |
| 3949 | } | 3801 | } |
| 3950 | 3802 | ||
| @@ -3973,7 +3825,7 @@ static int hwi_init_port(struct beiscsi_hba *phba) · 22 unmodified lines | |||
| 3973 | 3825 | ||
| 3974 | if (test_bit(ulp_num, &phba->fw_config.ulp_supported)) { | 3826 | if (test_bit(ulp_num, &phba->fw_config.ulp_supported)) { |
| 3975 | uint16_t cri = 0; | 3827 | uint16_t cri = 0; |
| 3976 | struct hwi_async_pdu_context *pasync_ctx; | 3828 | struct hd_async_context *pasync_ctx; |
| 3977 | 3829 | ||
| 3978 | pasync_ctx = HWI_GET_ASYNC_PDU_CTX( | 3830 | pasync_ctx = HWI_GET_ASYNC_PDU_CTX( |
| 3979 | phwi_ctrlr, ulp_num); | 3831 | phwi_ctrlr, ulp_num); |
| @@ -3985,6 +3837,14 @@ static int hwi_init_port(struct beiscsi_hba *phba) · 5 unmodified lines | |||
| 3985 | phwi_ctrlr->wrb_context[cri].cid] = | 3837 | phwi_ctrlr->wrb_context[cri].cid] = |
| 3986 | async_arr_idx++; | 3838 | async_arr_idx++; |
| 3987 | } | 3839 | } |
| 3840 | /** | ||
| 3841 | * Now that the default PDU rings have been created, | ||
| 3842 | * let EP know about it. | ||
| 3843 | */ | ||
| 3844 | beiscsi_hdq_post_handles(phba, BEISCSI_DEFQ_HDR, | ||
| 3845 | ulp_num); | ||
| 3846 | beiscsi_hdq_post_handles(phba, BEISCSI_DEFQ_DATA, | ||
| 3847 | ulp_num); | ||
| 3988 | } | 3848 | } |
| 3989 | } | 3849 | } |
| 3990 | 3850 | ||
| @@ -3995,7 +3855,7 @@ static int hwi_init_port(struct beiscsi_hba *phba) · 4 unmodified lines | |||
| 3995 | error: | 3855 | error: |
| 3996 | beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, | 3856 | beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, |
| 3997 | "BM_%d : hwi_init_port failed"); | 3857 | "BM_%d : hwi_init_port failed"); |
| 3998 | hwi_cleanup(phba); | 3858 | hwi_cleanup_port(phba); |
| 3999 | return status; | 3859 | return status; |
| 4000 | } | 3860 | } |
| 4001 | 3861 | ||
| @@ -4354,149 +4214,6 @@ static void hwi_disable_intr(struct beiscsi_hba *phba) · 352 unmodified lines | |||
| 4354 | "BM_%d : In hwi_disable_intr, Already Disabled\n"); | 4214 | "BM_%d : In hwi_disable_intr, Already Disabled\n"); |
| 4355 | } | 4215 | } |
| 4356 | 4216 | ||
| 4357 | /** | ||
| 4358 | * beiscsi_get_boot_info()- Get the boot session info | ||
| 4359 | * @phba: The device priv structure instance | ||
| 4360 | * | ||
| 4361 | * Get the boot target info and store in driver priv structure | ||
| 4362 | * | ||
| 4363 | * return values | ||
| 4364 | * Success: 0 | ||
| 4365 | * Failure: Non-Zero Value | ||
| 4366 | **/ | ||
| 4367 | static int beiscsi_get_boot_info(struct beiscsi_hba *phba) | ||
| 4368 | { | ||
| 4369 | struct be_cmd_get_session_resp *session_resp; | ||
| 4370 | struct be_dma_mem nonemb_cmd; | ||
| 4371 | unsigned int tag; | ||
| 4372 | unsigned int s_handle; | ||
| 4373 | int ret = -ENOMEM; | ||
| 4374 | |||
| 4375 | /* Get the session handle of the boot target */ | ||
| 4376 | ret = be_mgmt_get_boot_shandle(phba, &s_handle); | ||
| 4377 | if (ret) { | ||
| 4378 | beiscsi_log(phba, KERN_ERR, | ||
| 4379 | BEISCSI_LOG_INIT | BEISCSI_LOG_CONFIG, | ||
| 4380 | "BM_%d : No boot session\n"); | ||
| 4381 | |||
| 4382 | if (ret == -ENXIO) | ||
| 4383 | phba->get_boot = 0; | ||
| 4384 | |||
| 4385 | |||
| 4386 | return ret; | ||
| 4387 | } | ||
| 4388 | phba->get_boot = 0; | ||
| 4389 | nonemb_cmd.va = pci_zalloc_consistent(phba->ctrl.pdev, | ||
| 4390 | sizeof(*session_resp), | ||
| 4391 | &nonemb_cmd.dma); | ||
| 4392 | if (nonemb_cmd.va == NULL) { | ||
| 4393 | beiscsi_log(phba, KERN_ERR, | ||
| 4394 | BEISCSI_LOG_INIT | BEISCSI_LOG_CONFIG, | ||
| 4395 | "BM_%d : Failed to allocate memory for" | ||
| 4396 | "beiscsi_get_session_info\n"); | ||
| 4397 | |||
| 4398 | return -ENOMEM; | ||
| 4399 | } | ||
| 4400 | |||
| 4401 | tag = mgmt_get_session_info(phba, s_handle, | ||
| 4402 | &nonemb_cmd); | ||
| 4403 | if (!tag) { | ||
| 4404 | beiscsi_log(phba, KERN_ERR, | ||
| 4405 | BEISCSI_LOG_INIT | BEISCSI_LOG_CONFIG, | ||
| 4406 | "BM_%d : beiscsi_get_session_info" | ||
| 4407 | " Failed\n"); | ||
| 4408 | |||
| 4409 | goto boot_freemem; | ||
| 4410 | } | ||
| 4411 | |||
| 4412 | ret = beiscsi_mccq_compl_wait(phba, tag, NULL, &nonemb_cmd); | ||
| 4413 | if (ret) { | ||
| 4414 | beiscsi_log(phba, KERN_ERR, | ||
| 4415 | BEISCSI_LOG_INIT | BEISCSI_LOG_CONFIG, | ||
| 4416 | "BM_%d : beiscsi_get_session_info Failed"); | ||
| 4417 | |||
| 4418 | if (ret != -EBUSY) | ||
| 4419 | goto boot_freemem; | ||
| 4420 | else | ||
| 4421 | return ret; | ||
| 4422 | } | ||
| 4423 | |||
| 4424 | session_resp = nonemb_cmd.va ; | ||
| 4425 | |||
| 4426 | memcpy(&phba->boot_sess, &session_resp->session_info, | ||
| 4427 | sizeof(struct mgmt_session_info)); | ||
| 4428 | |||
| 4429 | beiscsi_logout_fw_sess(phba, | ||
| 4430 | phba->boot_sess.session_handle); | ||
| 4431 | ret = 0; | ||
| 4432 | |||
| 4433 | boot_freemem: | ||
| 4434 | pci_free_consistent(phba->ctrl.pdev, nonemb_cmd.size, | ||
| 4435 | nonemb_cmd.va, nonemb_cmd.dma); | ||
| 4436 | return ret; | ||
| 4437 | } | ||
| 4438 | |||
| 4439 | static void beiscsi_boot_release(void *data) | ||
| 4440 | { | ||
| 4441 | struct beiscsi_hba *phba = data; | ||
| 4442 | |||
| 4443 | scsi_host_put(phba->shost); | ||
| 4444 | } | ||
| 4445 | |||
| 4446 | static int beiscsi_setup_boot_info(struct beiscsi_hba *phba) | ||
| 4447 | { | ||
| 4448 | struct iscsi_boot_kobj *boot_kobj; | ||
| 4449 | |||
| 4450 | /* it has been created previously */ | ||
| 4451 | if (phba->boot_kset) | ||
| 4452 | return 0; | ||
| 4453 | |||
| 4454 | /* get boot info using mgmt cmd */ | ||
| 4455 | if (beiscsi_get_boot_info(phba)) | ||
| 4456 | /* Try to see if we can carry on without this */ | ||
| 4457 | return 0; | ||
| 4458 | |||
| 4459 | phba->boot_kset = iscsi_boot_create_host_kset(phba->shost->host_no); | ||
| 4460 | if (!phba->boot_kset) | ||
| 4461 | return -ENOMEM; | ||
| 4462 | |||
| 4463 | /* get a ref because the show function will ref the phba */ | ||
| 4464 | if (!scsi_host_get(phba->shost)) | ||
| 4465 | goto free_kset; | ||
| 4466 | boot_kobj = iscsi_boot_create_target(phba->boot_kset, 0, phba, | ||
| 4467 | beiscsi_show_boot_tgt_info, | ||
| 4468 | beiscsi_tgt_get_attr_visibility, | ||
| 4469 | beiscsi_boot_release); | ||
| 4470 | if (!boot_kobj) | ||
| 4471 | goto put_shost; | ||
| 4472 | |||
| 4473 | if (!scsi_host_get(phba->shost)) | ||
| 4474 | goto free_kset; | ||
| 4475 | boot_kobj = iscsi_boot_create_initiator(phba->boot_kset, 0, phba, | ||
| 4476 | beiscsi_show_boot_ini_info, | ||
| 4477 | beiscsi_ini_get_attr_visibility, | ||
| 4478 | beiscsi_boot_release); | ||
| 4479 | if (!boot_kobj) | ||
| 4480 | goto put_shost; | ||
| 4481 | |||
| 4482 | if (!scsi_host_get(phba->shost)) | ||
| 4483 | goto free_kset; | ||
| 4484 | boot_kobj = iscsi_boot_create_ethernet(phba->boot_kset, 0, phba, | ||
| 4485 | beiscsi_show_boot_eth_info, | ||
| 4486 | beiscsi_eth_get_attr_visibility, | ||
| 4487 | beiscsi_boot_release); | ||
| 4488 | if (!boot_kobj) | ||
| 4489 | goto put_shost; | ||
| 4490 | return 0; | ||
| 4491 | |||
| 4492 | put_shost: | ||
| 4493 | scsi_host_put(phba->shost); | ||
| 4494 | free_kset: | ||
| 4495 | iscsi_boot_destroy_kset(phba->boot_kset); | ||
| 4496 | phba->boot_kset = NULL; | ||
| 4497 | return -ENOMEM; | ||
| 4498 | } | ||
| 4499 | |||
| 4500 | static int beiscsi_init_port(struct beiscsi_hba *phba) | 4217 | static int beiscsi_init_port(struct beiscsi_hba *phba) |
| 4501 | { | 4218 | { |
| 4502 | int ret; | 4219 | int ret; |
| @@ -4516,7 +4233,8 @@ static int beiscsi_init_port(struct beiscsi_hba *phba) · 13 unmodified lines | |||
| 4516 | goto do_cleanup_ctrlr; | 4233 | goto do_cleanup_ctrlr; |
| 4517 | } | 4234 | } |
| 4518 | 4235 | ||
| 4519 | if (hba_setup_cid_tbls(phba)) { | 4236 | ret = hba_setup_cid_tbls(phba); |
| 4237 | if (ret < 0) { | ||
| 4520 | beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, | 4238 | beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, |
| 4521 | "BM_%d : Failed in hba_setup_cid_tbls\n"); | 4239 | "BM_%d : Failed in hba_setup_cid_tbls\n"); |
| 4522 | kfree(phba->io_sgl_hndl_base); | 4240 | kfree(phba->io_sgl_hndl_base); |
| @@ -4527,61 +4245,15 @@ static int beiscsi_init_port(struct beiscsi_hba *phba) · 4 unmodified lines | |||
| 4527 | return ret; | 4245 | return ret; |
| 4528 | 4246 | ||
| 4529 | do_cleanup_ctrlr: | 4247 | do_cleanup_ctrlr: |
| 4530 | hwi_cleanup(phba); | 4248 | hwi_cleanup_port(phba); |
| 4531 | return ret; | 4249 | return ret; |
| 4532 | } | 4250 | } |
| 4533 | 4251 | ||
| 4534 | static void hwi_purge_eq(struct beiscsi_hba *phba) | 4252 | static void beiscsi_cleanup_port(struct beiscsi_hba *phba) |
| 4535 | { | ||
| 4536 | struct hwi_controller *phwi_ctrlr; | ||
| 4537 | struct hwi_context_memory *phwi_context; | ||
| 4538 | struct be_queue_info *eq; | ||
| 4539 | struct be_eq_entry *eqe = NULL; | ||
| 4540 | int i, eq_msix; | ||
| 4541 | unsigned int num_processed; | ||
| 4542 | |||
| 4543 | phwi_ctrlr = phba->phwi_ctrlr; | ||
| 4544 | phwi_context = phwi_ctrlr->phwi_ctxt; | ||
| 4545 | if (phba->msix_enabled) | ||
| 4546 | eq_msix = 1; | ||
| 4547 | else | ||
| 4548 | eq_msix = 0; | ||
| 4549 | |||
| 4550 | for (i = 0; i < (phba->num_cpus + eq_msix); i++) { | ||
| 4551 | eq = &phwi_context->be_eq[i].q; | ||
| 4552 | eqe = queue_tail_node(eq); | ||
| 4553 | num_processed = 0; | ||
| 4554 | while (eqe->dw[offsetof(struct amap_eq_entry, valid) / 32] | ||
| 4555 | & EQE_VALID_MASK) { | ||
| 4556 | AMAP_SET_BITS(struct amap_eq_entry, valid, eqe, 0); | ||
| 4557 | queue_tail_inc(eq); | ||
| 4558 | eqe = queue_tail_node(eq); | ||
| 4559 | num_processed++; | ||
| 4560 | } | ||
| 4561 | |||
| 4562 | if (num_processed) | ||
| 4563 | hwi_ring_eq_db(phba, eq->id, 1, num_processed, 1, 1); | ||
| 4564 | } | ||
| 4565 | } | ||
| 4566 | |||
| 4567 | static void beiscsi_clean_port(struct beiscsi_hba *phba) | ||
| 4568 | { | 4253 | { |
| 4569 | int mgmt_status, ulp_num; | ||
| 4570 | struct ulp_cid_info *ptr_cid_info = NULL; | 4254 | struct ulp_cid_info *ptr_cid_info = NULL; |
| 4255 | int ulp_num; | ||
| 4571 | 4256 | ||
| 4572 | for (ulp_num = 0; ulp_num < BEISCSI_ULP_COUNT; ulp_num++) { | ||
| 4573 | if (test_bit(ulp_num, (void *)&phba->fw_config.ulp_supported)) { | ||
| 4574 | mgmt_status = mgmt_epfw_cleanup(phba, ulp_num); | ||
| 4575 | if (mgmt_status) | ||
| 4576 | beiscsi_log(phba, KERN_WARNING, | ||
| 4577 | BEISCSI_LOG_INIT, | ||
| 4578 | "BM_%d : mgmt_epfw_cleanup FAILED" | ||
| 4579 | " for ULP_%d\n", ulp_num); | ||
| 4580 | } | ||
| 4581 | } | ||
| 4582 | |||
| 4583 | hwi_purge_eq(phba); | ||
| 4584 | hwi_cleanup(phba); | ||
| 4585 | kfree(phba->io_sgl_hndl_base); | 4257 | kfree(phba->io_sgl_hndl_base); |
| 4586 | kfree(phba->eh_sgl_hndl_base); | 4258 | kfree(phba->eh_sgl_hndl_base); |
| 4587 | kfree(phba->ep_array); | 4259 | kfree(phba->ep_array); |
| @@ -4598,7 +4270,6 @@ static void beiscsi_clean_port(struct beiscsi_hba *phba) · 10 unmodified lines | |||
| 4598 | } | 4270 | } |
| 4599 | } | 4271 | } |
| 4600 | } | 4272 | } |
| 4601 | |||
| 4602 | } | 4273 | } |
| 4603 | 4274 | ||
| 4604 | /** | 4275 | /** |
| @@ -4625,16 +4296,12 @@ beiscsi_free_mgmt_task_handles(struct beiscsi_conn *beiscsi_conn, · 20 unmodified lines | |||
| 4625 | io_task = task->dd_data; | 4296 | io_task = task->dd_data; |
| 4626 | 4297 | ||
| 4627 | if (io_task->pwrb_handle) { | 4298 | if (io_task->pwrb_handle) { |
| 4628 | memset(io_task->pwrb_handle->pwrb, 0, | 4299 | free_wrb_handle(phba, pwrb_context, io_task->pwrb_handle); |
| 4629 | sizeof(struct iscsi_wrb)); | ||
| 4630 | free_wrb_handle(phba, pwrb_context, | ||
| 4631 | io_task->pwrb_handle); | ||
| 4632 | io_task->pwrb_handle = NULL; | 4300 | io_task->pwrb_handle = NULL; |
| 4633 | } | 4301 | } |
| 4634 | 4302 | ||
| 4635 | if (io_task->psgl_handle) { | 4303 | if (io_task->psgl_handle) { |
| 4636 | free_mgmt_sgl_handle(phba, | 4304 | free_mgmt_sgl_handle(phba, io_task->psgl_handle); |
| 4637 | io_task->psgl_handle); | ||
| 4638 | io_task->psgl_handle = NULL; | 4305 | io_task->psgl_handle = NULL; |
| 4639 | } | 4306 | } |
| 4640 | 4307 | ||
| @@ -4671,6 +4338,7 @@ static void beiscsi_cleanup_task(struct iscsi_task *task) · 30 unmodified lines | |||
| 4671 | pci_pool_free(beiscsi_sess->bhs_pool, io_task->cmd_bhs, | 4338 | pci_pool_free(beiscsi_sess->bhs_pool, io_task->cmd_bhs, |
| 4672 | io_task->bhs_pa.u.a64.address); | 4339 | io_task->bhs_pa.u.a64.address); |
| 4673 | io_task->cmd_bhs = NULL; | 4340 | io_task->cmd_bhs = NULL; |
| 4341 | task->hdr = NULL; | ||
| 4674 | } | 4342 | } |
| 4675 | 4343 | ||
| 4676 | if (task->sc) { | 4344 | if (task->sc) { |
| @@ -4686,7 +4354,8 @@ static void beiscsi_cleanup_task(struct iscsi_task *task) · 9 unmodified lines | |||
| 4686 | } | 4354 | } |
| 4687 | 4355 | ||
| 4688 | if (io_task->scsi_cmnd) { | 4356 | if (io_task->scsi_cmnd) { |
| 4689 | scsi_dma_unmap(io_task->scsi_cmnd); | 4357 | if (io_task->num_sg) |
| 4358 | scsi_dma_unmap(io_task->scsi_cmnd); | ||
| 4690 | io_task->scsi_cmnd = NULL; | 4359 | io_task->scsi_cmnd = NULL; |
| 4691 | } | 4360 | } |
| 4692 | } else { | 4361 | } else { |
| @@ -5051,7 +4720,6 @@ static int beiscsi_mtask(struct iscsi_task *task) · 358 unmodified lines | |||
| 5051 | 4720 | ||
| 5052 | cid = beiscsi_conn->beiscsi_conn_cid; | 4721 | cid = beiscsi_conn->beiscsi_conn_cid; |
| 5053 | pwrb = io_task->pwrb_handle->pwrb; | 4722 | pwrb = io_task->pwrb_handle->pwrb; |
| 5054 | memset(pwrb, 0, sizeof(*pwrb)); | ||
| 5055 | 4723 | ||
| 5056 | if (is_chip_be2_be3r(phba)) { | 4724 | if (is_chip_be2_be3r(phba)) { |
| 5057 | AMAP_SET_BITS(struct amap_iscsi_wrb, cmdsn_itt, pwrb, | 4725 | AMAP_SET_BITS(struct amap_iscsi_wrb, cmdsn_itt, pwrb, |
| @@ -5165,6 +4833,15 @@ static int beiscsi_task_xmit(struct iscsi_task *task) · 107 unmodified lines | |||
| 5165 | int num_sg; | 4833 | int num_sg; |
| 5166 | unsigned int writedir = 0, xferlen = 0; | 4834 | unsigned int writedir = 0, xferlen = 0; |
| 5167 | 4835 | ||
| 4836 | phba = io_task->conn->phba; | ||
| 4837 | /** | ||
| 4838 | * HBA in error includes BEISCSI_HBA_FW_TIMEOUT. IO path might be | ||
| 4839 | * operational if FW still gets heartbeat from EP FW. Is management | ||
| 4840 | * path really needed to continue further? | ||
| 4841 | */ | ||
| 4842 | if (!beiscsi_hba_is_online(phba)) | ||
| 4843 | return -EIO; | ||
| 4844 | |||
| 5168 | if (!io_task->conn->login_in_progress) | 4845 | if (!io_task->conn->login_in_progress) |
| 5169 | task->hdr->exp_statsn = 0; | 4846 | task->hdr->exp_statsn = 0; |
| 5170 | 4847 | ||
| @@ -5172,8 +4849,8 @@ static int beiscsi_task_xmit(struct iscsi_task *task) · 1 unmodified line | |||
| 5172 | return beiscsi_mtask(task); | 4849 | return beiscsi_mtask(task); |
| 5173 | 4850 | ||
| 5174 | io_task->scsi_cmnd = sc; | 4851 | io_task->scsi_cmnd = sc; |
| 4852 | io_task->num_sg = 0; | ||
| 5175 | num_sg = scsi_dma_map(sc); | 4853 | num_sg = scsi_dma_map(sc); |
| 5176 | phba = io_task->conn->phba; | ||
| 5177 | if (num_sg < 0) { | 4854 | if (num_sg < 0) { |
| 5178 | beiscsi_log(phba, KERN_ERR, | 4855 | beiscsi_log(phba, KERN_ERR, |
| 5179 | BEISCSI_LOG_IO | BEISCSI_LOG_ISCSI, | 4856 | BEISCSI_LOG_IO | BEISCSI_LOG_ISCSI, |
| @@ -5184,6 +4861,11 @@ static int beiscsi_task_xmit(struct iscsi_task *task) · 4 unmodified lines | |||
| 5184 | 4861 | ||
| 5185 | return num_sg; | 4862 | return num_sg; |
| 5186 | } | 4863 | } |
| 4864 | /** | ||
| 4865 | * For scsi cmd task, check num_sg before unmapping in cleanup_task. | ||
| 4866 | * For management task, cleanup_task checks mtask_addr before unmapping. | ||
| 4867 | */ | ||
| 4868 | io_task->num_sg = num_sg; | ||
| 5187 | xferlen = scsi_bufflen(sc); | 4869 | xferlen = scsi_bufflen(sc); |
| 5188 | sg = scsi_sglist(sc); | 4870 | sg = scsi_sglist(sc); |
| 5189 | if (sc->sc_data_direction == DMA_TO_DEVICE) | 4871 | if (sc->sc_data_direction == DMA_TO_DEVICE) |
| @@ -5213,6 +4895,12 @@ static int beiscsi_bsg_request(struct bsg_job *job) · 23 unmodified lines | |||
| 5213 | shost = iscsi_job_to_shost(job); | 4895 | shost = iscsi_job_to_shost(job); |
| 5214 | phba = iscsi_host_priv(shost); | 4896 | phba = iscsi_host_priv(shost); |
| 5215 | 4897 | ||
| 4898 | if (!beiscsi_hba_is_online(phba)) { | ||
| 4899 | beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG, | ||
| 4900 | "BM_%d : HBA in error 0x%lx\n", phba->state); | ||
| 4901 | return -ENXIO; | ||
| 4902 | } | ||
| 4903 | |||
| 5216 | switch (bsg_req->msgcode) { | 4904 | switch (bsg_req->msgcode) { |
| 5217 | case ISCSI_BSG_HST_VENDOR: | 4905 | case ISCSI_BSG_HST_VENDOR: |
| 5218 | nonemb_cmd.va = pci_alloc_consistent(phba->ctrl.pdev, | 4906 | nonemb_cmd.va = pci_alloc_consistent(phba->ctrl.pdev, |
| @@ -5240,6 +4928,14 @@ static int beiscsi_bsg_request(struct bsg_job *job) · 21 unmodified lines | |||
| 5240 | phba->ctrl.mcc_tag_status[tag], | 4928 | phba->ctrl.mcc_tag_status[tag], |
| 5241 | msecs_to_jiffies( | 4929 | msecs_to_jiffies( |
| 5242 | BEISCSI_HOST_MBX_TIMEOUT)); | 4930 | BEISCSI_HOST_MBX_TIMEOUT)); |
| 4931 | |||
| 4932 | if (!test_bit(BEISCSI_HBA_ONLINE, &phba->state)) { | ||
| 4933 | clear_bit(MCC_TAG_STATE_RUNNING, | ||
| 4934 | &phba->ctrl.ptag_state[tag].tag_state); | ||
| 4935 | pci_free_consistent(phba->ctrl.pdev, nonemb_cmd.size, | ||
| 4936 | nonemb_cmd.va, nonemb_cmd.dma); | ||
| 4937 | return -EIO; | ||
| 4938 | } | ||
| 5243 | extd_status = (phba->ctrl.mcc_tag_status[tag] & | 4939 | extd_status = (phba->ctrl.mcc_tag_status[tag] & |
| 5244 | CQE_STATUS_ADDL_MASK) >> CQE_STATUS_ADDL_SHIFT; | 4940 | CQE_STATUS_ADDL_MASK) >> CQE_STATUS_ADDL_SHIFT; |
| 5245 | status = phba->ctrl.mcc_tag_status[tag] & CQE_STATUS_MASK; | 4941 | status = phba->ctrl.mcc_tag_status[tag] & CQE_STATUS_MASK; |
| @@ -5283,106 +4979,294 @@ void beiscsi_hba_attrs_init(struct beiscsi_hba *phba) · 37 unmodified lines | |||
| 5283 | beiscsi_log_enable_init(phba, beiscsi_log_enable); | 4979 | beiscsi_log_enable_init(phba, beiscsi_log_enable); |
| 5284 | } | 4980 | } |
| 5285 | 4981 | ||
| 5286 | /* | 4982 | void beiscsi_start_boot_work(struct beiscsi_hba *phba, unsigned int s_handle) |
| 5287 | * beiscsi_quiesce()- Cleanup Driver resources | ||
| 5288 | * @phba: Instance Priv structure | ||
| 5289 | * @unload_state:i Clean or EEH unload state | ||
| 5290 | * | ||
| 5291 | * Free the OS and HW resources held by the driver | ||
| 5292 | **/ | ||
| 5293 | static void beiscsi_quiesce(struct beiscsi_hba *phba, | ||
| 5294 | uint32_t unload_state) | ||
| 5295 | { | 4983 | { |
| 5296 | struct hwi_controller *phwi_ctrlr; | 4984 | if (phba->boot_struct.boot_kset) |
| 5297 | struct hwi_context_memory *phwi_context; | 4985 | return; |
| 5298 | struct be_eq_obj *pbe_eq; | ||
| 5299 | unsigned int i, msix_vec; | ||
| 5300 | 4986 | ||
| 5301 | phwi_ctrlr = phba->phwi_ctrlr; | 4987 | /* skip if boot work is already in progress */ |
| 5302 | phwi_context = phwi_ctrlr->phwi_ctxt; | 4988 | if (test_and_set_bit(BEISCSI_HBA_BOOT_WORK, &phba->state)) |
| 5303 | hwi_disable_intr(phba); | 4989 | return; |
| 5304 | if (phba->msix_enabled) { | ||
| 5305 | for (i = 0; i <= phba->num_cpus; i++) { | ||
| 5306 | msix_vec = phba->msix_entries[i].vector; | ||
| 5307 | free_irq(msix_vec, &phwi_context->be_eq[i]); | ||
| 5308 | kfree(phba->msi_name[i]); | ||
| 5309 | } | ||
| 5310 | } else | ||
| 5311 | if (phba->pcidev->irq) | ||
| 5312 | free_irq(phba->pcidev->irq, phba); | ||
| 5313 | pci_disable_msix(phba->pcidev); | ||
| 5314 | cancel_delayed_work_sync(&phba->beiscsi_hw_check_task); | ||
| 5315 | 4990 | ||
| 5316 | for (i = 0; i < phba->num_cpus; i++) { | 4991 | phba->boot_struct.retry = 3; |
| 5317 | pbe_eq = &phwi_context->be_eq[i]; | 4992 | phba->boot_struct.tag = 0; |
| 5318 | irq_poll_disable(&pbe_eq->iopoll); | 4993 | phba->boot_struct.s_handle = s_handle; |
| 4994 | phba->boot_struct.action = BEISCSI_BOOT_GET_SHANDLE; | ||
| 4995 | schedule_work(&phba->boot_work); | ||
| 4996 | } | ||
| 4997 | |||
| 4998 | static ssize_t beiscsi_show_boot_tgt_info(void *data, int type, char *buf) | ||
| 4999 | { | ||
| 5000 | struct beiscsi_hba *phba = data; | ||
| 5001 | struct mgmt_session_info *boot_sess = &phba->boot_struct.boot_sess; | ||
| 5002 | struct mgmt_conn_info *boot_conn = &boot_sess->conn_list[0]; | ||
| 5003 | char *str = buf; | ||
| 5004 | int rc = -EPERM; | ||
| 5005 | |||
| 5006 | switch (type) { | ||
| 5007 | case ISCSI_BOOT_TGT_NAME: | ||
| 5008 | rc = sprintf(buf, "%.*s\n", | ||
| 5009 | (int)strlen(boot_sess->target_name), | ||
| 5010 | (char *)&boot_sess->target_name); | ||
| 5011 | break; | ||
| 5012 | case ISCSI_BOOT_TGT_IP_ADDR: | ||
| 5013 | if (boot_conn->dest_ipaddr.ip_type == BEISCSI_IP_TYPE_V4) | ||
| 5014 | rc = sprintf(buf, "%pI4\n", | ||
| 5015 | (char *)&boot_conn->dest_ipaddr.addr); | ||
| 5016 | else | ||
| 5017 | rc = sprintf(str, "%pI6\n", | ||
| 5018 | (char *)&boot_conn->dest_ipaddr.addr); | ||
| 5019 | break; | ||
| 5020 | case ISCSI_BOOT_TGT_PORT: | ||
| 5021 | rc = sprintf(str, "%d\n", boot_conn->dest_port); | ||
| 5022 | break; | ||
| 5023 | |||
| 5024 | case ISCSI_BOOT_TGT_CHAP_NAME: | ||
| 5025 | rc = sprintf(str, "%.*s\n", | ||
| 5026 | boot_conn->negotiated_login_options.auth_data.chap. | ||
| 5027 | target_chap_name_length, | ||
| 5028 | (char *)&boot_conn->negotiated_login_options. | ||
| 5029 | auth_data.chap.target_chap_name); | ||
| 5030 | break; | ||
| 5031 | case ISCSI_BOOT_TGT_CHAP_SECRET: | ||
| 5032 | rc = sprintf(str, "%.*s\n", | ||
| 5033 | boot_conn->negotiated_login_options.auth_data.chap. | ||
| 5034 | target_secret_length, | ||
| 5035 | (char *)&boot_conn->negotiated_login_options. | ||
| 5036 | auth_data.chap.target_secret); | ||
| 5037 | break; | ||
| 5038 | case ISCSI_BOOT_TGT_REV_CHAP_NAME: | ||
| 5039 | rc = sprintf(str, "%.*s\n", | ||
| 5040 | boot_conn->negotiated_login_options.auth_data.chap. | ||
| 5041 | intr_chap_name_length, | ||
| 5042 | (char *)&boot_conn->negotiated_login_options. | ||
| 5043 | auth_data.chap.intr_chap_name); | ||
| 5044 | break; | ||
| 5045 | case ISCSI_BOOT_TGT_REV_CHAP_SECRET: | ||
| 5046 | rc = sprintf(str, "%.*s\n", | ||
| 5047 | boot_conn->negotiated_login_options.auth_data.chap. | ||
| 5048 | intr_secret_length, | ||
| 5049 | (char *)&boot_conn->negotiated_login_options. | ||
| 5050 | auth_data.chap.intr_secret); | ||
| 5051 | break; | ||
| 5052 | case ISCSI_BOOT_TGT_FLAGS: | ||
| 5053 | rc = sprintf(str, "2\n"); | ||
| 5054 | break; | ||
| 5055 | case ISCSI_BOOT_TGT_NIC_ASSOC: | ||
| 5056 | rc = sprintf(str, "0\n"); | ||
| 5057 | break; | ||
| 5319 | } | 5058 | } |
| 5059 | return rc; | ||
| 5060 | } | ||
| 5320 | 5061 | ||
| 5321 | if (unload_state == BEISCSI_CLEAN_UNLOAD) { | 5062 | static ssize_t beiscsi_show_boot_ini_info(void *data, int type, char *buf) |
| 5322 | destroy_workqueue(phba->wq); | 5063 | { |
| 5323 | beiscsi_clean_port(phba); | 5064 | struct beiscsi_hba *phba = data; |
| 5324 | beiscsi_free_mem(phba); | 5065 | char *str = buf; |
| 5066 | int rc = -EPERM; | ||
| 5325 | 5067 | ||
| 5326 | beiscsi_unmap_pci_function(phba); | 5068 | switch (type) { |
| 5327 | pci_free_consistent(phba->pcidev, | 5069 | case ISCSI_BOOT_INI_INITIATOR_NAME: |
| 5328 | phba->ctrl.mbox_mem_alloced.size, | 5070 | rc = sprintf(str, "%s\n", |
| 5329 | phba->ctrl.mbox_mem_alloced.va, | 5071 | phba->boot_struct.boot_sess.initiator_iscsiname); |
| 5330 | phba->ctrl.mbox_mem_alloced.dma); | 5072 | break; |
| 5331 | } else { | ||
| 5332 | hwi_purge_eq(phba); | ||
| 5333 | hwi_cleanup(phba); | ||
| 5334 | } | 5073 | } |
| 5074 | return rc; | ||
| 5075 | } | ||
| 5076 | |||
| 5077 | static ssize_t beiscsi_show_boot_eth_info(void *data, int type, char *buf) | ||
| 5078 | { | ||
| 5079 | struct beiscsi_hba *phba = data; | ||
| 5080 | char *str = buf; | ||
| 5081 | int rc = -EPERM; | ||
| 5335 | 5082 | ||
| 5083 | switch (type) { | ||
| 5084 | case ISCSI_BOOT_ETH_FLAGS: | ||
| 5085 | rc = sprintf(str, "2\n"); | ||
| 5086 | break; | ||
| 5087 | case ISCSI_BOOT_ETH_INDEX: | ||
| 5088 | rc = sprintf(str, "0\n"); | ||
| 5089 | break; | ||
| 5090 | case ISCSI_BOOT_ETH_MAC: | ||
| 5091 | rc = beiscsi_get_macaddr(str, phba); | ||
| 5092 | break; | ||
| 5093 | } | ||
| 5094 | return rc; | ||
| 5336 | } | 5095 | } |
| 5337 | 5096 | ||
| 5338 | static void beiscsi_remove(struct pci_dev *pcidev) | 5097 | static umode_t beiscsi_tgt_get_attr_visibility(void *data, int type) |
| 5339 | { | 5098 | { |
| 5340 | struct beiscsi_hba *phba = NULL; | 5099 | umode_t rc = 0; |
| 5341 | 5100 | ||
| 5342 | phba = pci_get_drvdata(pcidev); | 5101 | switch (type) { |
| 5343 | if (!phba) { | 5102 | case ISCSI_BOOT_TGT_NAME: |
| 5344 | dev_err(&pcidev->dev, "beiscsi_remove called with no phba\n"); | 5103 | case ISCSI_BOOT_TGT_IP_ADDR: |
| 5345 | return; | 5104 | case ISCSI_BOOT_TGT_PORT: |
| 5105 | case ISCSI_BOOT_TGT_CHAP_NAME: | ||
| 5106 | case ISCSI_BOOT_TGT_CHAP_SECRET: | ||
| 5107 | case ISCSI_BOOT_TGT_REV_CHAP_NAME: | ||
| 5108 | case ISCSI_BOOT_TGT_REV_CHAP_SECRET: | ||
| 5109 | case ISCSI_BOOT_TGT_NIC_ASSOC: | ||
| 5110 | case ISCSI_BOOT_TGT_FLAGS: | ||
| 5111 | rc = S_IRUGO; | ||
| 5112 | break; | ||
| 5346 | } | 5113 | } |
| 5114 | return rc; | ||
| 5115 | } | ||
| 5347 | 5116 | ||
| 5348 | beiscsi_destroy_def_ifaces(phba); | 5117 | static umode_t beiscsi_ini_get_attr_visibility(void *data, int type) |
| 5349 | iscsi_boot_destroy_kset(phba->boot_kset); | 5118 | { |
| 5350 | iscsi_host_remove(phba->shost); | 5119 | umode_t rc = 0; |
| 5351 | beiscsi_quiesce(phba, BEISCSI_CLEAN_UNLOAD); | 5120 | |
| 5352 | pci_dev_put(phba->pcidev); | 5121 | switch (type) { |
| 5353 | iscsi_host_free(phba->shost); | 5122 | case ISCSI_BOOT_INI_INITIATOR_NAME: |
| 5354 | pci_disable_pcie_error_reporting(pcidev); | 5123 | rc = S_IRUGO; |
| 5355 | pci_set_drvdata(pcidev, NULL); | 5124 | break; |
| 5356 | pci_release_regions(pcidev); | 5125 | } |
| 5357 | pci_disable_device(pcidev); | 5126 | return rc; |
| 5358 | } | 5127 | } |
| 5359 | 5128 | ||
| 5360 | static void beiscsi_msix_enable(struct beiscsi_hba *phba) | 5129 | static umode_t beiscsi_eth_get_attr_visibility(void *data, int type) |
| 5361 | { | 5130 | { |
| 5362 | int i, status; | 5131 | umode_t rc = 0; |
| 5363 | 5132 | ||
| 5364 | for (i = 0; i <= phba->num_cpus; i++) | 5133 | switch (type) { |
| 5365 | phba->msix_entries[i].entry = i; | 5134 | case ISCSI_BOOT_ETH_FLAGS: |
| 5135 | case ISCSI_BOOT_ETH_MAC: | ||
| 5136 | case ISCSI_BOOT_ETH_INDEX: | ||
| 5137 | rc = S_IRUGO; | ||
| 5138 | break; | ||
| 5139 | } | ||
| 5140 | return rc; | ||
| 5141 | } | ||
| 5366 | 5142 | ||
| 5367 | status = pci_enable_msix_range(phba->pcidev, phba->msix_entries, | 5143 | static void beiscsi_boot_kobj_release(void *data) |
| 5368 | phba->num_cpus + 1, phba->num_cpus + 1); | 5144 | { |
| 5369 | if (status > 0) | 5145 | struct beiscsi_hba *phba = data; |
| 5370 | phba->msix_enabled = true; | 5146 | |
| 5147 | scsi_host_put(phba->shost); | ||
| 5148 | } | ||
| 5149 | |||
| 5150 | static int beiscsi_boot_create_kset(struct beiscsi_hba *phba) | ||
| 5151 | { | ||
| 5152 | struct boot_struct *bs = &phba->boot_struct; | ||
| 5153 | struct iscsi_boot_kobj *boot_kobj; | ||
| 5154 | |||
| 5155 | if (bs->boot_kset) { | ||
| 5156 | __beiscsi_log(phba, KERN_ERR, | ||
| 5157 | "BM_%d: boot_kset already created\n"); | ||
| 5158 | return 0; | ||
| 5159 | } | ||
| 5160 | |||
| 5161 | bs->boot_kset = iscsi_boot_create_host_kset(phba->shost->host_no); | ||
| 5162 | if (!bs->boot_kset) { | ||
| 5163 | __beiscsi_log(phba, KERN_ERR, | ||
| 5164 | "BM_%d: boot_kset alloc failed\n"); | ||
| 5165 | return -ENOMEM; | ||
| 5166 | } | ||
| 5167 | |||
| 5168 | /* get shost ref because the show function will refer phba */ | ||
| 5169 | if (!scsi_host_get(phba->shost)) | ||
| 5170 | goto free_kset; | ||
| 5171 | |||
| 5172 | boot_kobj = iscsi_boot_create_target(bs->boot_kset, 0, phba, | ||
| 5173 | beiscsi_show_boot_tgt_info, | ||
| 5174 | beiscsi_tgt_get_attr_visibility, | ||
| 5175 | beiscsi_boot_kobj_release); | ||
| 5176 | if (!boot_kobj) | ||
| 5177 | goto put_shost; | ||
| 5178 | |||
| 5179 | if (!scsi_host_get(phba->shost)) | ||
| 5180 | goto free_kset; | ||
| 5181 | |||
| 5182 | boot_kobj = iscsi_boot_create_initiator(bs->boot_kset, 0, phba, | ||
| 5183 | beiscsi_show_boot_ini_info, | ||
| 5184 | beiscsi_ini_get_attr_visibility, | ||
| 5185 | beiscsi_boot_kobj_release); | ||
| 5186 | if (!boot_kobj) | ||
| 5187 | goto put_shost; | ||
| 5188 | |||
| 5189 | if (!scsi_host_get(phba->shost)) | ||
| 5190 | goto free_kset; | ||
| 5191 | |||
| 5192 | boot_kobj = iscsi_boot_create_ethernet(bs->boot_kset, 0, phba, | ||
| 5193 | beiscsi_show_boot_eth_info, | ||
| 5194 | beiscsi_eth_get_attr_visibility, | ||
| 5195 | beiscsi_boot_kobj_release); | ||
| 5196 | if (!boot_kobj) | ||
| 5197 | goto put_shost; | ||
| 5198 | |||
| 5199 | return 0; | ||
| 5200 | |||
| 5201 | put_shost: | ||
| 5202 | scsi_host_put(phba->shost); | ||
| 5203 | free_kset: | ||
| 5204 | iscsi_boot_destroy_kset(bs->boot_kset); | ||
| 5205 | bs->boot_kset = NULL; | ||
| 5206 | return -ENOMEM; | ||
| 5207 | } | ||
| 5208 | |||
| 5209 | static void beiscsi_boot_work(struct work_struct *work) | ||
| 5210 | { | ||
| 5211 | struct beiscsi_hba *phba = | ||
| 5212 | container_of(work, struct beiscsi_hba, boot_work); | ||
| 5213 | struct boot_struct *bs = &phba->boot_struct; | ||
| 5214 | unsigned int tag = 0; | ||
| 5371 | 5215 | ||
| 5372 | return; | 5216 | if (!beiscsi_hba_is_online(phba)) |
| 5217 | return; | ||
| 5218 | |||
| 5219 | beiscsi_log(phba, KERN_INFO, | ||
| 5220 | BEISCSI_LOG_CONFIG | BEISCSI_LOG_MBOX, | ||
| 5221 | "BM_%d : %s action %d\n", | ||
| 5222 | __func__, phba->boot_struct.action); | ||
| 5223 | |||
| 5224 | switch (phba->boot_struct.action) { | ||
| 5225 | case BEISCSI_BOOT_REOPEN_SESS: | ||
| 5226 | tag = beiscsi_boot_reopen_sess(phba); | ||
| 5227 | break; | ||
| 5228 | case BEISCSI_BOOT_GET_SHANDLE: | ||
| 5229 | tag = __beiscsi_boot_get_shandle(phba, 1); | ||
| 5230 | break; | ||
| 5231 | case BEISCSI_BOOT_GET_SINFO: | ||
| 5232 | tag = beiscsi_boot_get_sinfo(phba); | ||
| 5233 | break; | ||
| 5234 | case BEISCSI_BOOT_LOGOUT_SESS: | ||
| 5235 | tag = beiscsi_boot_logout_sess(phba); | ||
| 5236 | break; | ||
| 5237 | case BEISCSI_BOOT_CREATE_KSET: | ||
| 5238 | beiscsi_boot_create_kset(phba); | ||
| 5239 | /** | ||
| 5240 | * updated boot_kset is made visible to all before | ||
| 5241 | * ending the boot work. | ||
| 5242 | */ | ||
| 5243 | mb(); | ||
| 5244 | clear_bit(BEISCSI_HBA_BOOT_WORK, &phba->state); | ||
| 5245 | return; | ||
| 5246 | } | ||
| 5247 | if (!tag) { | ||
| 5248 | if (bs->retry--) | ||
| 5249 | schedule_work(&phba->boot_work); | ||
| 5250 | else | ||
| 5251 | clear_bit(BEISCSI_HBA_BOOT_WORK, &phba->state); | ||
| 5252 | } | ||
| 5373 | } | 5253 | } |
| 5374 | 5254 | ||
| 5375 | static void be_eqd_update(struct beiscsi_hba *phba) | 5255 | static void beiscsi_eqd_update_work(struct work_struct *work) |
| 5376 | { | 5256 | { |
| 5257 | struct hwi_context_memory *phwi_context; | ||
| 5377 | struct be_set_eqd set_eqd[MAX_CPUS]; | 5258 | struct be_set_eqd set_eqd[MAX_CPUS]; |
| 5378 | struct be_aic_obj *aic; | ||
| 5379 | struct be_eq_obj *pbe_eq; | ||
| 5380 | struct hwi_controller *phwi_ctrlr; | 5259 | struct hwi_controller *phwi_ctrlr; |
| 5381 | struct hwi_context_memory *phwi_context; | 5260 | struct be_eq_obj *pbe_eq; |
| 5261 | struct beiscsi_hba *phba; | ||
| 5262 | unsigned int pps, delta; | ||
| 5263 | struct be_aic_obj *aic; | ||
| 5382 | int eqd, i, num = 0; | 5264 | int eqd, i, num = 0; |
| 5383 | ulong now; | 5265 | unsigned long now; |
| 5384 | u32 pps, delta; | 5266 | |
| 5385 | unsigned int tag; | 5267 | phba = container_of(work, struct beiscsi_hba, eqd_update.work); |
| 5268 | if (!beiscsi_hba_is_online(phba)) | ||
| 5269 | return; | ||
| 5386 | 5270 | ||
| 5387 | phwi_ctrlr = phba->phwi_ctrlr; | 5271 | phwi_ctrlr = phba->phwi_ctrlr; |
| 5388 | phwi_context = phwi_ctrlr->phwi_ctxt; | 5272 | phwi_context = phwi_ctrlr->phwi_ctxt; |
| @@ -5391,13 +5275,13 @@ static void be_eqd_update(struct beiscsi_hba *phba) · 2 unmodified lines | |||
| 5391 | aic = &phba->aic_obj[i]; | 5275 | aic = &phba->aic_obj[i]; |
| 5392 | pbe_eq = &phwi_context->be_eq[i]; | 5276 | pbe_eq = &phwi_context->be_eq[i]; |
| 5393 | now = jiffies; | 5277 | now = jiffies; |
| 5394 | if (!aic->jiffs || time_before(now, aic->jiffs) || | 5278 | if (!aic->jiffies || time_before(now, aic->jiffies) || |
| 5395 | pbe_eq->cq_count < aic->eq_prev) { | 5279 | pbe_eq->cq_count < aic->eq_prev) { |
| 5396 | aic->jiffs = now; | 5280 | aic->jiffies = now; |
| 5397 | aic->eq_prev = pbe_eq->cq_count; | 5281 | aic->eq_prev = pbe_eq->cq_count; |
| 5398 | continue; | 5282 | continue; |
| 5399 | } | 5283 | } |
| 5400 | delta = jiffies_to_msecs(now - aic->jiffs); | 5284 | delta = jiffies_to_msecs(now - aic->jiffies); |
| 5401 | pps = (((u32)(pbe_eq->cq_count - aic->eq_prev) * 1000) / delta); | 5285 | pps = (((u32)(pbe_eq->cq_count - aic->eq_prev) * 1000) / delta); |
| 5402 | eqd = (pps / 1500) << 2; | 5286 | eqd = (pps / 1500) << 2; |
| 5403 | 5287 | ||
| @@ -5406,7 +5290,7 @@ static void be_eqd_update(struct beiscsi_hba *phba) · 2 unmodified lines | |||
| 5406 | eqd = min_t(u32, eqd, phwi_context->max_eqd); | 5290 | eqd = min_t(u32, eqd, phwi_context->max_eqd); |
| 5407 | eqd = max_t(u32, eqd, phwi_context->min_eqd); | 5291 | eqd = max_t(u32, eqd, phwi_context->min_eqd); |
| 5408 | 5292 | ||
| 5409 | aic->jiffs = now; | 5293 | aic->jiffies = now; |
| 5410 | aic->eq_prev = pbe_eq->cq_count; | 5294 | aic->eq_prev = pbe_eq->cq_count; |
| 5411 | 5295 | ||
| 5412 | if (eqd != aic->prev_eqd) { | 5296 | if (eqd != aic->prev_eqd) { |
| @@ -5416,53 +5300,242 @@ static void be_eqd_update(struct beiscsi_hba *phba) · 3 unmodified lines | |||
| 5416 | num++; | 5300 | num++; |
| 5417 | } | 5301 | } |
| 5418 | } | 5302 | } |
| 5419 | if (num) { | 5303 | if (num) |
| 5420 | tag = be_cmd_modify_eq_delay(phba, set_eqd, num); | 5304 | /* completion of this is ignored */ |
| 5421 | if (tag) | 5305 | beiscsi_modify_eq_delay(phba, set_eqd, num); |
| 5422 | beiscsi_mccq_compl_wait(phba, tag, NULL, NULL); | 5306 | |
| 5307 | schedule_delayed_work(&phba->eqd_update, | ||
| 5308 | msecs_to_jiffies(BEISCSI_EQD_UPDATE_INTERVAL)); | ||
| 5309 | } | ||
| 5310 | |||
| 5311 | static void beiscsi_msix_enable(struct beiscsi_hba *phba) | ||
| 5312 | { | ||
| 5313 | int i, status; | ||
| 5314 | |||
| 5315 | for (i = 0; i <= phba->num_cpus; i++) | ||
| 5316 | phba->msix_entries[i].entry = i; | ||
| 5317 | |||
| 5318 | status = pci_enable_msix_range(phba->pcidev, phba->msix_entries, | ||
| 5319 | phba->num_cpus + 1, phba->num_cpus + 1); | ||
| 5320 | if (status > 0) | ||
| 5321 | phba->msix_enabled = true; | ||
| 5322 | } | ||
| 5323 | |||
| 5324 | static void beiscsi_hw_tpe_check(unsigned long ptr) | ||
| 5325 | { | ||
| 5326 | struct beiscsi_hba *phba; | ||
| 5327 | u32 wait; | ||
| 5328 | |||
| 5329 | phba = (struct beiscsi_hba *)ptr; | ||
| 5330 | /* if not TPE, do nothing */ | ||
| 5331 | if (!beiscsi_detect_tpe(phba)) | ||
| 5332 | return; | ||
| 5333 | |||
| 5334 | /* wait default 4000ms before recovering */ | ||
| 5335 | wait = 4000; | ||
| 5336 | if (phba->ue2rp > BEISCSI_UE_DETECT_INTERVAL) | ||
| 5337 | wait = phba->ue2rp - BEISCSI_UE_DETECT_INTERVAL; | ||
| 5338 | queue_delayed_work(phba->wq, &phba->recover_port, | ||
| 5339 | msecs_to_jiffies(wait)); | ||
| 5340 | } | ||
| 5341 | |||
| 5342 | static void beiscsi_hw_health_check(unsigned long ptr) | ||
| 5343 | { | ||
| 5344 | struct beiscsi_hba *phba; | ||
| 5345 | |||
| 5346 | phba = (struct beiscsi_hba *)ptr; | ||
| 5347 | beiscsi_detect_ue(phba); | ||
| 5348 | if (beiscsi_detect_ue(phba)) { | ||
| 5349 | __beiscsi_log(phba, KERN_ERR, | ||
| 5350 | "BM_%d : port in error: %lx\n", phba->state); | ||
| 5351 | /* sessions are no longer valid, so first fail the sessions */ | ||
| 5352 | queue_work(phba->wq, &phba->sess_work); | ||
| 5353 | |||
| 5354 | /* detect UER supported */ | ||
| 5355 | if (!test_bit(BEISCSI_HBA_UER_SUPP, &phba->state)) | ||
| 5356 | return; | ||
| 5357 | /* modify this timer to check TPE */ | ||
| 5358 | phba->hw_check.function = beiscsi_hw_tpe_check; | ||
| 5423 | } | 5359 | } |
| 5360 | |||
| 5361 | mod_timer(&phba->hw_check, | ||
| 5362 | jiffies + msecs_to_jiffies(BEISCSI_UE_DETECT_INTERVAL)); | ||
| 5424 | } | 5363 | } |
| 5425 | 5364 | ||
| 5426 | static void be_check_boot_session(struct beiscsi_hba *phba) | 5365 | /* |
| 5366 | * beiscsi_enable_port()- Enables the disabled port. | ||
| 5367 | * Only port resources freed in disable function are reallocated. | ||
| 5368 | * This is called in HBA error handling path. | ||
| 5369 | * | ||
| 5370 | * @phba: Instance of driver private structure | ||
| 5371 | * | ||
| 5372 | **/ | ||
| 5373 | static int beiscsi_enable_port(struct beiscsi_hba *phba) | ||
| 5427 | { | 5374 | { |
| 5428 | if (beiscsi_setup_boot_info(phba)) | 5375 | struct hwi_context_memory *phwi_context; |
| 5429 | beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, | 5376 | struct hwi_controller *phwi_ctrlr; |
| 5430 | "BM_%d : Could not set up " | 5377 | struct be_eq_obj *pbe_eq; |
| 5431 | "iSCSI boot info on async event.\n"); | 5378 | int ret, i; |
| 5379 | |||
| 5380 | if (test_bit(BEISCSI_HBA_ONLINE, &phba->state)) { | ||
| 5381 | __beiscsi_log(phba, KERN_ERR, | ||
| 5382 | "BM_%d : %s : port is online %lx\n", | ||
| 5383 | __func__, phba->state); | ||
| 5384 | return 0; | ||
| 5385 | } | ||
| 5386 | |||
| 5387 | ret = beiscsi_init_sliport(phba); | ||
| 5388 | if (ret) | ||
| 5389 | return ret; | ||
| 5390 | |||
| 5391 | if (enable_msix) | ||
| 5392 | find_num_cpus(phba); | ||
| 5393 | else | ||
| 5394 | phba->num_cpus = 1; | ||
| 5395 | if (enable_msix) { | ||
| 5396 | beiscsi_msix_enable(phba); | ||
| 5397 | if (!phba->msix_enabled) | ||
| 5398 | phba->num_cpus = 1; | ||
| 5399 | } | ||
| 5400 | |||
| 5401 | beiscsi_get_params(phba); | ||
| 5402 | /* Re-enable UER. If different TPE occurs then it is recoverable. */ | ||
| 5403 | beiscsi_set_uer_feature(phba); | ||
| 5404 | |||
| 5405 | phba->shost->max_id = phba->params.cxns_per_ctrl; | ||
| 5406 | phba->shost->can_queue = phba->params.ios_per_ctrl; | ||
| 5407 | ret = hwi_init_controller(phba); | ||
| 5408 | if (ret) { | ||
| 5409 | __beiscsi_log(phba, KERN_ERR, | ||
| 5410 | "BM_%d : init controller failed %d\n", ret); | ||
| 5411 | goto disable_msix; | ||
| 5412 | } | ||
| 5413 | |||
| 5414 | for (i = 0; i < MAX_MCC_CMD; i++) { | ||
| 5415 | init_waitqueue_head(&phba->ctrl.mcc_wait[i + 1]); | ||
| 5416 | phba->ctrl.mcc_tag[i] = i + 1; | ||
| 5417 | phba->ctrl.mcc_tag_status[i + 1] = 0; | ||
| 5418 | phba->ctrl.mcc_tag_available++; | ||
| 5419 | } | ||
| 5420 | |||
| 5421 | phwi_ctrlr = phba->phwi_ctrlr; | ||
| 5422 | phwi_context = phwi_ctrlr->phwi_ctxt; | ||
| 5423 | for (i = 0; i < phba->num_cpus; i++) { | ||
| 5424 | pbe_eq = &phwi_context->be_eq[i]; | ||
| 5425 | irq_poll_init(&pbe_eq->iopoll, be_iopoll_budget, be_iopoll); | ||
| 5426 | } | ||
| 5427 | |||
| 5428 | i = (phba->msix_enabled) ? i : 0; | ||
| 5429 | /* Work item for MCC handling */ | ||
| 5430 | pbe_eq = &phwi_context->be_eq[i]; | ||
| 5431 | INIT_WORK(&pbe_eq->mcc_work, beiscsi_mcc_work); | ||
| 5432 | |||
| 5433 | ret = beiscsi_init_irqs(phba); | ||
| 5434 | if (ret < 0) { | ||
| 5435 | __beiscsi_log(phba, KERN_ERR, | ||
| 5436 | "BM_%d : setup IRQs failed %d\n", ret); | ||
| 5437 | goto cleanup_port; | ||
| 5438 | } | ||
| 5439 | hwi_enable_intr(phba); | ||
| 5440 | /* port operational: clear all error bits */ | ||
| 5441 | set_bit(BEISCSI_HBA_ONLINE, &phba->state); | ||
| 5442 | __beiscsi_log(phba, KERN_INFO, | ||
| 5443 | "BM_%d : port online: 0x%lx\n", phba->state); | ||
| 5444 | |||
| 5445 | /* start hw_check timer and eqd_update work */ | ||
| 5446 | schedule_delayed_work(&phba->eqd_update, | ||
| 5447 | msecs_to_jiffies(BEISCSI_EQD_UPDATE_INTERVAL)); | ||
| 5448 | |||
| 5449 | /** | ||
| 5450 | * Timer function gets modified for TPE detection. | ||
| 5451 | * Always reinit to do health check first. | ||
| 5452 | */ | ||
| 5453 | phba->hw_check.function = beiscsi_hw_health_check; | ||
| 5454 | mod_timer(&phba->hw_check, | ||
| 5455 | jiffies + msecs_to_jiffies(BEISCSI_UE_DETECT_INTERVAL)); | ||
| 5456 | return 0; | ||
| 5457 | |||
| 5458 | cleanup_port: | ||
| 5459 | for (i = 0; i < phba->num_cpus; i++) { | ||
| 5460 | pbe_eq = &phwi_context->be_eq[i]; | ||
| 5461 | irq_poll_disable(&pbe_eq->iopoll); | ||
| 5462 | } | ||
| 5463 | hwi_cleanup_port(phba); | ||
| 5464 | |||
| 5465 | disable_msix: | ||
| 5466 | if (phba->msix_enabled) | ||
| 5467 | pci_disable_msix(phba->pcidev); | ||
| 5468 | |||
| 5469 | return ret; | ||
| 5432 | } | 5470 | } |
| 5433 | 5471 | ||
| 5434 | /* | 5472 | /* |
| 5435 | * beiscsi_hw_health_check()- Check adapter health | 5473 | * beiscsi_disable_port()- Disable port and cleanup driver resources. |
| 5436 | * @work: work item to check HW health | 5474 | * This is called in HBA error handling and driver removal. |
| 5475 | * @phba: Instance Priv structure | ||
| 5476 | * @unload: indicate driver is unloading | ||
| 5437 | * | 5477 | * |
| 5438 | * Check if adapter in an unrecoverable state or not. | 5478 | * Free the OS and HW resources held by the driver |
| 5439 | **/ | 5479 | **/ |
| 5440 | static void | 5480 | static void beiscsi_disable_port(struct beiscsi_hba *phba, int unload) |
| 5441 | beiscsi_hw_health_check(struct work_struct *work) | ||
| 5442 | { | 5481 | { |
| 5443 | struct beiscsi_hba *phba = | 5482 | struct hwi_context_memory *phwi_context; |
| 5444 | container_of(work, struct beiscsi_hba, | 5483 | struct hwi_controller *phwi_ctrlr; |
| 5445 | beiscsi_hw_check_task.work); | 5484 | struct be_eq_obj *pbe_eq; |
| 5485 | unsigned int i, msix_vec; | ||
| 5446 | 5486 | ||
| 5447 | be_eqd_update(phba); | 5487 | if (!test_and_clear_bit(BEISCSI_HBA_ONLINE, &phba->state)) |
| 5488 | return; | ||
| 5448 | 5489 | ||
| 5449 | if (phba->state & BE_ADAPTER_CHECK_BOOT) { | 5490 | phwi_ctrlr = phba->phwi_ctrlr; |
| 5450 | if ((phba->get_boot > 0) && (!phba->boot_kset)) { | 5491 | phwi_context = phwi_ctrlr->phwi_ctxt; |
| 5451 | phba->get_boot--; | 5492 | hwi_disable_intr(phba); |
| 5452 | if (!(phba->get_boot % BE_GET_BOOT_TO)) | 5493 | if (phba->msix_enabled) { |
| 5453 | be_check_boot_session(phba); | 5494 | for (i = 0; i <= phba->num_cpus; i++) { |
| 5454 | } else { | 5495 | msix_vec = phba->msix_entries[i].vector; |
| 5455 | phba->state &= ~BE_ADAPTER_CHECK_BOOT; | 5496 | free_irq(msix_vec, &phwi_context->be_eq[i]); |
| 5456 | phba->get_boot = 0; | 5497 | kfree(phba->msi_name[i]); |
| 5457 | } | 5498 | } |
| 5499 | } else | ||
| 5500 | if (phba->pcidev->irq) | ||
| 5501 | free_irq(phba->pcidev->irq, phba); | ||
| 5502 | pci_disable_msix(phba->pcidev); | ||
| 5503 | |||
| 5504 | for (i = 0; i < phba->num_cpus; i++) { | ||
| 5505 | pbe_eq = &phwi_context->be_eq[i]; | ||
| 5506 | irq_poll_disable(&pbe_eq->iopoll); | ||
| 5507 | } | ||
| 5508 | cancel_delayed_work_sync(&phba->eqd_update); | ||
| 5509 | cancel_work_sync(&phba->boot_work); | ||
| 5510 | /* WQ might be running cancel queued mcc_work if we are not exiting */ | ||
| 5511 | if (!unload && beiscsi_hba_in_error(phba)) { | ||
| 5512 | pbe_eq = &phwi_context->be_eq[i]; | ||
| 5513 | cancel_work_sync(&pbe_eq->mcc_work); | ||
| 5458 | } | 5514 | } |
| 5515 | hwi_cleanup_port(phba); | ||
| 5516 | } | ||
| 5459 | 5517 | ||
| 5460 | beiscsi_ue_detect(phba); | 5518 | static void beiscsi_sess_work(struct work_struct *work) |
| 5519 | { | ||
| 5520 | struct beiscsi_hba *phba; | ||
| 5461 | 5521 | ||
| 5462 | schedule_delayed_work(&phba->beiscsi_hw_check_task, | 5522 | phba = container_of(work, struct beiscsi_hba, sess_work); |
| 5463 | msecs_to_jiffies(1000)); | 5523 | /* |
| 5524 | * This work gets scheduled only in case of HBA error. | ||
| 5525 | * Old sessions are gone so need to be re-established. | ||
| 5526 | * iscsi_session_failure needs process context hence this work. | ||
| 5527 | */ | ||
| 5528 | iscsi_host_for_each_session(phba->shost, beiscsi_session_fail); | ||
| 5464 | } | 5529 | } |
| 5465 | 5530 | ||
| 5531 | static void beiscsi_recover_port(struct work_struct *work) | ||
| 5532 | { | ||
| 5533 | struct beiscsi_hba *phba; | ||
| 5534 | |||
| 5535 | phba = container_of(work, struct beiscsi_hba, recover_port.work); | ||
| 5536 | beiscsi_disable_port(phba, 0); | ||
| 5537 | beiscsi_enable_port(phba); | ||
| 5538 | } | ||
| 5466 | 5539 | ||
| 5467 | static pci_ers_result_t beiscsi_eeh_err_detected(struct pci_dev *pdev, | 5540 | static pci_ers_result_t beiscsi_eeh_err_detected(struct pci_dev *pdev, |
| 5468 | pci_channel_state_t state) | 5541 | pci_channel_state_t state) |
| @@ -5470,12 +5543,18 @@ static pci_ers_result_t beiscsi_eeh_err_detected(struct pci_dev *pdev, · 1 unmodified line | |||
| 5470 | struct beiscsi_hba *phba = NULL; | 5543 | struct beiscsi_hba *phba = NULL; |
| 5471 | 5544 | ||
| 5472 | phba = (struct beiscsi_hba *)pci_get_drvdata(pdev); | 5545 | phba = (struct beiscsi_hba *)pci_get_drvdata(pdev); |
| 5473 | phba->state |= BE_ADAPTER_PCI_ERR; | 5546 | set_bit(BEISCSI_HBA_PCI_ERR, &phba->state); |
| 5474 | 5547 | ||
| 5475 | beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, | 5548 | beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, |
| 5476 | "BM_%d : EEH error detected\n"); | 5549 | "BM_%d : EEH error detected\n"); |
| 5477 | 5550 | ||
| 5478 | beiscsi_quiesce(phba, BEISCSI_EEH_UNLOAD); | 5551 | /* first stop UE detection when PCI error detected */ |
| 5552 | del_timer_sync(&phba->hw_check); | ||
| 5553 | cancel_delayed_work_sync(&phba->recover_port); | ||
| 5554 | |||
| 5555 | /* sessions are no longer valid, so first fail the sessions */ | ||
| 5556 | iscsi_host_for_each_session(phba->shost, beiscsi_session_fail); | ||
| 5557 | beiscsi_disable_port(phba, 0); | ||
| 5479 | 5558 | ||
| 5480 | if (state == pci_channel_io_perm_failure) { | 5559 | if (state == pci_channel_io_perm_failure) { |
| 5481 | beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, | 5560 | beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, |
| @@ -5515,9 +5594,8 @@ static pci_ers_result_t beiscsi_eeh_reset(struct pci_dev *pdev) · 33 unmodified lines | |||
| 5515 | pci_set_power_state(pdev, PCI_D0); | 5594 | pci_set_power_state(pdev, PCI_D0); |
| 5516 | pci_restore_state(pdev); | 5595 | pci_restore_state(pdev); |
| 5517 | 5596 | ||
| 5518 | /* Wait for the CHIP Reset to complete */ | 5597 | status = beiscsi_check_fw_rdy(phba); |
| 5519 | status = be_chk_reset_complete(phba); | 5598 | if (status) { |
| 5520 | if (!status) { | ||
| 5521 | beiscsi_log(phba, KERN_WARNING, BEISCSI_LOG_INIT, | 5599 | beiscsi_log(phba, KERN_WARNING, BEISCSI_LOG_INIT, |
| 5522 | "BM_%d : EEH Reset Completed\n"); | 5600 | "BM_%d : EEH Reset Completed\n"); |
| 5523 | } else { | 5601 | } else { |
| @@ -5532,87 +5610,16 @@ static pci_ers_result_t beiscsi_eeh_reset(struct pci_dev *pdev) · 8 unmodified lines | |||
| 5532 | 5610 | ||
| 5533 | static void beiscsi_eeh_resume(struct pci_dev *pdev) | 5611 | static void beiscsi_eeh_resume(struct pci_dev *pdev) |
| 5534 | { | 5612 | { |
| 5535 | int ret = 0, i; | 5613 | struct beiscsi_hba *phba; |
| 5536 | struct be_eq_obj *pbe_eq; | 5614 | int ret; |
| 5537 | struct beiscsi_hba *phba = NULL; | ||
| 5538 | struct hwi_controller *phwi_ctrlr; | ||
| 5539 | struct hwi_context_memory *phwi_context; | ||
| 5540 | 5615 | ||
| 5541 | phba = (struct beiscsi_hba *)pci_get_drvdata(pdev); | 5616 | phba = (struct beiscsi_hba *)pci_get_drvdata(pdev); |
| 5542 | pci_save_state(pdev); | 5617 | pci_save_state(pdev); |
| 5543 | 5618 | ||
| 5544 | if (enable_msix) | 5619 | ret = beiscsi_enable_port(phba); |
| 5545 | find_num_cpus(phba); | 5620 | if (ret) |
| 5546 | else | 5621 | __beiscsi_log(phba, KERN_ERR, |
| 5547 | phba->num_cpus = 1; | 5622 | "BM_%d : AER EEH resume failed\n"); |
| 5548 | |||
| 5549 | if (enable_msix) { | ||
| 5550 | beiscsi_msix_enable(phba); | ||
| 5551 | if (!phba->msix_enabled) | ||
| 5552 | phba->num_cpus = 1; | ||
| 5553 | } | ||
| 5554 | |||
| 5555 | ret = beiscsi_cmd_reset_function(phba); | ||
| 5556 | if (ret) { | ||
| 5557 | beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, | ||
| 5558 | "BM_%d : Reset Failed\n"); | ||
| 5559 | goto ret_err; | ||
| 5560 | } | ||
| 5561 | |||
| 5562 | ret = be_chk_reset_complete(phba); | ||
| 5563 | if (ret) { | ||
| 5564 | beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, | ||
| 5565 | "BM_%d : Failed to get out of reset.\n"); | ||
| 5566 | goto ret_err; | ||
| 5567 | } | ||
| 5568 | |||
| 5569 | beiscsi_get_params(phba); | ||
| 5570 | phba->shost->max_id = phba->params.cxns_per_ctrl; | ||
| 5571 | phba->shost->can_queue = phba->params.ios_per_ctrl; | ||
| 5572 | ret = hwi_init_controller(phba); | ||
| 5573 | if (ret) { | ||
| 5574 | beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, | ||
| 5575 | "BM_%d : beiscsi_eeh_resume -" | ||
| 5576 | "Failed to initialize beiscsi_hba.\n"); | ||
| 5577 | goto ret_err; | ||
| 5578 | } | ||
| 5579 | |||
| 5580 | for (i = 0; i < MAX_MCC_CMD; i++) { | ||
| 5581 | init_waitqueue_head(&phba->ctrl.mcc_wait[i + 1]); | ||
| 5582 | phba->ctrl.mcc_tag[i] = i + 1; | ||
| 5583 | phba->ctrl.mcc_tag_status[i + 1] = 0; | ||
| 5584 | phba->ctrl.mcc_tag_available++; | ||
| 5585 | } | ||
| 5586 | |||
| 5587 | phwi_ctrlr = phba->phwi_ctrlr; | ||
| 5588 | phwi_context = phwi_ctrlr->phwi_ctxt; | ||
| 5589 | |||
| 5590 | for (i = 0; i < phba->num_cpus; i++) { | ||
| 5591 | pbe_eq = &phwi_context->be_eq[i]; | ||
| 5592 | irq_poll_init(&pbe_eq->iopoll, be_iopoll_budget, | ||
| 5593 | be_iopoll); | ||
| 5594 | } | ||
| 5595 | |||
| 5596 | i = (phba->msix_enabled) ? i : 0; | ||
| 5597 | /* Work item for MCC handling */ | ||
| 5598 | pbe_eq = &phwi_context->be_eq[i]; | ||
| 5599 | INIT_WORK(&pbe_eq->work_cqs, beiscsi_process_all_cqs); | ||
| 5600 | |||
| 5601 | ret = beiscsi_init_irqs(phba); | ||
| 5602 | if (ret < 0) { | ||
| 5603 | beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, | ||
| 5604 | "BM_%d : beiscsi_eeh_resume - " | ||
| 5605 | "Failed to beiscsi_init_irqs\n"); | ||
| 5606 | goto ret_err; | ||
| 5607 | } | ||
| 5608 | |||
| 5609 | hwi_enable_intr(phba); | ||
| 5610 | phba->state &= ~BE_ADAPTER_PCI_ERR; | ||
| 5611 | |||
| 5612 | return; | ||
| 5613 | ret_err: | ||
| 5614 | beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, | ||
| 5615 | "BM_%d : AER EEH Resume Failed\n"); | ||
| 5616 | } | 5623 | } |
| 5617 | 5624 | ||
| 5618 | static int beiscsi_dev_probe(struct pci_dev *pcidev, | 5625 | static int beiscsi_dev_probe(struct pci_dev *pcidev, |
| @@ -5622,7 +5629,8 @@ static int beiscsi_dev_probe(struct pci_dev *pcidev, · 3 unmodified lines | |||
| 5622 | struct hwi_controller *phwi_ctrlr; | 5629 | struct hwi_controller *phwi_ctrlr; |
| 5623 | struct hwi_context_memory *phwi_context; | 5630 | struct hwi_context_memory *phwi_context; |
| 5624 | struct be_eq_obj *pbe_eq; | 5631 | struct be_eq_obj *pbe_eq; |
| 5625 | int ret = 0, i; | 5632 | unsigned int s_handle; |
| 5633 | int ret, i; | ||
| 5626 | 5634 | ||
| 5627 | ret = beiscsi_enable_pci(pcidev); | 5635 | ret = beiscsi_enable_pci(pcidev); |
| 5628 | if (ret < 0) { | 5636 | if (ret < 0) { |
| @@ -5635,6 +5643,7 @@ static int beiscsi_dev_probe(struct pci_dev *pcidev, · 6 unmodified lines | |||
| 5635 | if (!phba) { | 5643 | if (!phba) { |
| 5636 | dev_err(&pcidev->dev, | 5644 | dev_err(&pcidev->dev, |
| 5637 | "beiscsi_dev_probe - Failed in beiscsi_hba_alloc\n"); | 5645 | "beiscsi_dev_probe - Failed in beiscsi_hba_alloc\n"); |
| 5646 | ret = -ENOMEM; | ||
| 5638 | goto disable_pci; | 5647 | goto disable_pci; |
| 5639 | } | 5648 | } |
| 5640 | 5649 | ||
| @@ -5650,10 +5659,8 @@ static int beiscsi_dev_probe(struct pci_dev *pcidev, · 9 unmodified lines | |||
| 5650 | /* Initialize Driver configuration Paramters */ | 5659 | /* Initialize Driver configuration Paramters */ |
| 5651 | beiscsi_hba_attrs_init(phba); | 5660 | beiscsi_hba_attrs_init(phba); |
| 5652 | 5661 | ||
| 5653 | phba->fw_timeout = false; | ||
| 5654 | phba->mac_addr_set = false; | 5662 | phba->mac_addr_set = false; |
| 5655 | 5663 | ||
| 5656 | |||
| 5657 | switch (pcidev->device) { | 5664 | switch (pcidev->device) { |
| 5658 | case BE_DEVICE_ID1: | 5665 | case BE_DEVICE_ID1: |
| 5659 | case OC_DEVICE_ID1: | 5666 | case OC_DEVICE_ID1: |
| @@ -5677,39 +5684,26 @@ static int beiscsi_dev_probe(struct pci_dev *pcidev, · 17 unmodified lines | |||
| 5677 | ret = be_ctrl_init(phba, pcidev); | 5684 | ret = be_ctrl_init(phba, pcidev); |
| 5678 | if (ret) { | 5685 | if (ret) { |
| 5679 | beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, | 5686 | beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, |
| 5680 | "BM_%d : beiscsi_dev_probe-" | 5687 | "BM_%d : be_ctrl_init failed\n"); |
| 5681 | "Failed in be_ctrl_init\n"); | ||
| 5682 | goto hba_free; | 5688 | goto hba_free; |
| 5683 | } | 5689 | } |
| 5684 | 5690 | ||
| 5685 | /* | 5691 | ret = beiscsi_init_sliport(phba); |
| 5686 | * FUNCTION_RESET should clean up any stale info in FW for this fn | 5692 | if (ret) |
| 5687 | */ | ||
| 5688 | ret = beiscsi_cmd_reset_function(phba); | ||
| 5689 | if (ret) { | ||
| 5690 | beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, | ||
| 5691 | "BM_%d : Reset Failed\n"); | ||
| 5692 | goto hba_free; | ||
| 5693 | } | ||
| 5694 | ret = be_chk_reset_complete(phba); | ||
| 5695 | if (ret) { | ||
| 5696 | beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, | ||
| 5697 | "BM_%d : Failed to get out of reset.\n"); | ||
| 5698 | goto hba_free; | 5693 | goto hba_free; |
| 5699 | } | ||
| 5700 | 5694 | ||
| 5701 | spin_lock_init(&phba->io_sgl_lock); | 5695 | spin_lock_init(&phba->io_sgl_lock); |
| 5702 | spin_lock_init(&phba->mgmt_sgl_lock); | 5696 | spin_lock_init(&phba->mgmt_sgl_lock); |
| 5703 | spin_lock_init(&phba->isr_lock); | ||
| 5704 | spin_lock_init(&phba->async_pdu_lock); | 5697 | spin_lock_init(&phba->async_pdu_lock); |
| 5705 | ret = mgmt_get_fw_config(&phba->ctrl, phba); | 5698 | ret = beiscsi_get_fw_config(&phba->ctrl, phba); |
| 5706 | if (ret != 0) { | 5699 | if (ret != 0) { |
| 5707 | beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, | 5700 | beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, |
| 5708 | "BM_%d : Error getting fw config\n"); | 5701 | "BM_%d : Error getting fw config\n"); |
| 5709 | goto free_port; | 5702 | goto free_port; |
| 5710 | } | 5703 | } |
| 5711 | mgmt_get_port_name(&phba->ctrl, phba); | 5704 | beiscsi_get_port_name(&phba->ctrl, phba); |
| 5712 | beiscsi_get_params(phba); | 5705 | beiscsi_get_params(phba); |
| 5706 | beiscsi_set_uer_feature(phba); | ||
| 5713 | 5707 | ||
| 5714 | if (enable_msix) | 5708 | if (enable_msix) |
| 5715 | find_num_cpus(phba); | 5709 | find_num_cpus(phba); |
| @@ -5754,25 +5748,24 @@ static int beiscsi_dev_probe(struct pci_dev *pcidev, · 38 unmodified lines | |||
| 5754 | beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, | 5748 | beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, |
| 5755 | "BM_%d : beiscsi_dev_probe-" | 5749 | "BM_%d : beiscsi_dev_probe-" |
| 5756 | "Failed to allocate work queue\n"); | 5750 | "Failed to allocate work queue\n"); |
| 5751 | ret = -ENOMEM; | ||
| 5757 | goto free_twq; | 5752 | goto free_twq; |
| 5758 | } | 5753 | } |
| 5759 | 5754 | ||
| 5760 | INIT_DELAYED_WORK(&phba->beiscsi_hw_check_task, | 5755 | INIT_DELAYED_WORK(&phba->eqd_update, beiscsi_eqd_update_work); |
| 5761 | beiscsi_hw_health_check); | ||
| 5762 | 5756 | ||
| 5763 | phwi_ctrlr = phba->phwi_ctrlr; | 5757 | phwi_ctrlr = phba->phwi_ctrlr; |
| 5764 | phwi_context = phwi_ctrlr->phwi_ctxt; | 5758 | phwi_context = phwi_ctrlr->phwi_ctxt; |
| 5765 | 5759 | ||
| 5766 | for (i = 0; i < phba->num_cpus; i++) { | 5760 | for (i = 0; i < phba->num_cpus; i++) { |
| 5767 | pbe_eq = &phwi_context->be_eq[i]; | 5761 | pbe_eq = &phwi_context->be_eq[i]; |
| 5768 | irq_poll_init(&pbe_eq->iopoll, be_iopoll_budget, | 5762 | irq_poll_init(&pbe_eq->iopoll, be_iopoll_budget, be_iopoll); |
| 5769 | be_iopoll); | ||
| 5770 | } | 5763 | } |
| 5771 | 5764 | ||
| 5772 | i = (phba->msix_enabled) ? i : 0; | 5765 | i = (phba->msix_enabled) ? i : 0; |
| 5773 | /* Work item for MCC handling */ | 5766 | /* Work item for MCC handling */ |
| 5774 | pbe_eq = &phwi_context->be_eq[i]; | 5767 | pbe_eq = &phwi_context->be_eq[i]; |
| 5775 | INIT_WORK(&pbe_eq->work_cqs, beiscsi_process_all_cqs); | 5768 | INIT_WORK(&pbe_eq->mcc_work, beiscsi_mcc_work); |
| 5776 | 5769 | ||
| 5777 | ret = beiscsi_init_irqs(phba); | 5770 | ret = beiscsi_init_irqs(phba); |
| 5778 | if (ret < 0) { | 5771 | if (ret < 0) { |
| @@ -5783,22 +5776,42 @@ static int beiscsi_dev_probe(struct pci_dev *pcidev, · 4 unmodified lines | |||
| 5783 | } | 5776 | } |
| 5784 | hwi_enable_intr(phba); | 5777 | hwi_enable_intr(phba); |
| 5785 | 5778 | ||
| 5786 | if (iscsi_host_add(phba->shost, &phba->pcidev->dev)) | 5779 | ret = iscsi_host_add(phba->shost, &phba->pcidev->dev); |
| 5780 | if (ret) | ||
| 5787 | goto free_blkenbld; | 5781 | goto free_blkenbld; |
| 5788 | 5782 | ||
| 5789 | if (beiscsi_setup_boot_info(phba)) | 5783 | /* set online bit after port is operational */ |
| 5790 | /* | 5784 | set_bit(BEISCSI_HBA_ONLINE, &phba->state); |
| 5791 | * log error but continue, because we may not be using | 5785 | __beiscsi_log(phba, KERN_INFO, |
| 5792 | * iscsi boot. | 5786 | "BM_%d : port online: 0x%lx\n", phba->state); |
| 5787 | |||
| 5788 | INIT_WORK(&phba->boot_work, beiscsi_boot_work); | ||
| 5789 | ret = beiscsi_boot_get_shandle(phba, &s_handle); | ||
| 5790 | if (ret > 0) { | ||
| 5791 | beiscsi_start_boot_work(phba, s_handle); | ||
| 5792 | /** | ||
| 5793 | * Set this bit after starting the work to let | ||
| 5794 | * probe handle it first. | ||
| 5795 | * ASYNC event can too schedule this work. | ||
| 5793 | */ | 5796 | */ |
| 5794 | beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, | 5797 | set_bit(BEISCSI_HBA_BOOT_FOUND, &phba->state); |
| 5795 | "BM_%d : Could not set up " | 5798 | } |
| 5796 | "iSCSI boot info.\n"); | ||
| 5797 | 5799 | ||
| 5798 | beiscsi_create_def_ifaces(phba); | 5800 | beiscsi_iface_create_default(phba); |
| 5799 | schedule_delayed_work(&phba->beiscsi_hw_check_task, | 5801 | schedule_delayed_work(&phba->eqd_update, |
| 5800 | msecs_to_jiffies(1000)); | 5802 | msecs_to_jiffies(BEISCSI_EQD_UPDATE_INTERVAL)); |
| 5801 | 5803 | ||
| 5804 | INIT_WORK(&phba->sess_work, beiscsi_sess_work); | ||
| 5805 | INIT_DELAYED_WORK(&phba->recover_port, beiscsi_recover_port); | ||
| 5806 | /** | ||
| 5807 | * Start UE detection here. UE before this will cause stall in probe | ||
| 5808 | * and eventually fail the probe. | ||
| 5809 | */ | ||
| 5810 | init_timer(&phba->hw_check); | ||
| 5811 | phba->hw_check.function = beiscsi_hw_health_check; | ||
| 5812 | phba->hw_check.data = (unsigned long)phba; | ||
| 5813 | mod_timer(&phba->hw_check, | ||
| 5814 | jiffies + msecs_to_jiffies(BEISCSI_UE_DETECT_INTERVAL)); | ||
| 5802 | beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_INIT, | 5815 | beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_INIT, |
| 5803 | "\n\n\n BM_%d : SUCCESS - DRIVER LOADED\n\n\n"); | 5816 | "\n\n\n BM_%d : SUCCESS - DRIVER LOADED\n\n\n"); |
| 5804 | return 0; | 5817 | return 0; |
| @@ -5810,7 +5823,8 @@ free_blkenbld: · 5 unmodified lines | |||
| 5810 | irq_poll_disable(&pbe_eq->iopoll); | 5823 | irq_poll_disable(&pbe_eq->iopoll); |
| 5811 | } | 5824 | } |
| 5812 | free_twq: | 5825 | free_twq: |
| 5813 | beiscsi_clean_port(phba); | 5826 | hwi_cleanup_port(phba); |
| 5827 | beiscsi_cleanup_port(phba); | ||
| 5814 | beiscsi_free_mem(phba); | 5828 | beiscsi_free_mem(phba); |
| 5815 | free_port: | 5829 | free_port: |
| 5816 | pci_free_consistent(phba->pcidev, | 5830 | pci_free_consistent(phba->pcidev, |
| @@ -5830,6 +5844,49 @@ disable_pci: · 13 unmodified lines | |||
| 5830 | return ret; | 5844 | return ret; |
| 5831 | } | 5845 | } |
| 5832 | 5846 | ||
| 5847 | static void beiscsi_remove(struct pci_dev *pcidev) | ||
| 5848 | { | ||
| 5849 | struct beiscsi_hba *phba = NULL; | ||
| 5850 | |||
| 5851 | phba = pci_get_drvdata(pcidev); | ||
| 5852 | if (!phba) { | ||
| 5853 | dev_err(&pcidev->dev, "beiscsi_remove called with no phba\n"); | ||
| 5854 | return; | ||
| 5855 | } | ||
| 5856 | |||
| 5857 | /* first stop UE detection before unloading */ | ||
| 5858 | del_timer_sync(&phba->hw_check); | ||
| 5859 | cancel_delayed_work_sync(&phba->recover_port); | ||
| 5860 | cancel_work_sync(&phba->sess_work); | ||
| 5861 | |||
| 5862 | beiscsi_iface_destroy_default(phba); | ||
| 5863 | iscsi_host_remove(phba->shost); | ||
| 5864 | beiscsi_disable_port(phba, 1); | ||
| 5865 | |||
| 5866 | /* after cancelling boot_work */ | ||
| 5867 | iscsi_boot_destroy_kset(phba->boot_struct.boot_kset); | ||
| 5868 | |||
| 5869 | /* free all resources */ | ||
| 5870 | destroy_workqueue(phba->wq); | ||
| 5871 | beiscsi_cleanup_port(phba); | ||
| 5872 | beiscsi_free_mem(phba); | ||
| 5873 | |||
| 5874 | /* ctrl uninit */ | ||
| 5875 | beiscsi_unmap_pci_function(phba); | ||
| 5876 | pci_free_consistent(phba->pcidev, | ||
| 5877 | phba->ctrl.mbox_mem_alloced.size, | ||
| 5878 | phba->ctrl.mbox_mem_alloced.va, | ||
| 5879 | phba->ctrl.mbox_mem_alloced.dma); | ||
| 5880 | |||
| 5881 | pci_dev_put(phba->pcidev); | ||
| 5882 | iscsi_host_free(phba->shost); | ||
| 5883 | pci_disable_pcie_error_reporting(pcidev); | ||
| 5884 | pci_set_drvdata(pcidev, NULL); | ||
| 5885 | pci_release_regions(pcidev); | ||
| 5886 | pci_disable_device(pcidev); | ||
| 5887 | } | ||
| 5888 | |||
| 5889 | |||
| 5833 | static struct pci_error_handlers beiscsi_eeh_handlers = { | 5890 | static struct pci_error_handlers beiscsi_eeh_handlers = { |
| 5834 | .error_detected = beiscsi_eeh_err_detected, | 5891 | .error_detected = beiscsi_eeh_err_detected, |
| 5835 | .slot_reset = beiscsi_eeh_reset, | 5892 | .slot_reset = beiscsi_eeh_reset, |
| @@ -5846,9 +5903,9 @@ struct iscsi_transport beiscsi_iscsi_transport = { · 10 unmodified lines | |||
| 5846 | .create_conn = beiscsi_conn_create, | 5903 | .create_conn = beiscsi_conn_create, |
| 5847 | .bind_conn = beiscsi_conn_bind, | 5904 | .bind_conn = beiscsi_conn_bind, |
| 5848 | .destroy_conn = iscsi_conn_teardown, | 5905 | .destroy_conn = iscsi_conn_teardown, |
| 5849 | .attr_is_visible = be2iscsi_attr_is_visible, | 5906 | .attr_is_visible = beiscsi_attr_is_visible, |
| 5850 | .set_iface_param = be2iscsi_iface_set_param, | 5907 | .set_iface_param = beiscsi_iface_set_param, |
| 5851 | .get_iface_param = be2iscsi_iface_get_param, | 5908 | .get_iface_param = beiscsi_iface_get_param, |
| 5852 | .set_param = beiscsi_set_param, | 5909 | .set_param = beiscsi_set_param, |
| 5853 | .get_conn_param = iscsi_conn_get_param, | 5910 | .get_conn_param = iscsi_conn_get_param, |
| 5854 | .get_session_param = iscsi_session_get_param, | 5911 | .get_session_param = iscsi_session_get_param, |
| @@ -5877,7 +5934,6 @@ static struct pci_driver beiscsi_pci_driver = { · 22 unmodified lines | |||
| 5877 | .err_handler = &beiscsi_eeh_handlers | 5934 | .err_handler = &beiscsi_eeh_handlers |
| 5878 | }; | 5935 | }; |
| 5879 | 5936 | ||
| 5880 | |||
| 5881 | static int __init beiscsi_module_init(void) | 5937 | static int __init beiscsi_module_init(void) |
| 5882 | { | 5938 | { |
| 5883 | int ret; | 5939 | int ret; |
| @@ -1,5 +1,5 @@ | |||
| 1 | /** | 1 | /** |
| 2 | * Copyright (C) 2005 - 2015 Emulex | 2 | * Copyright (C) 2005 - 2016 Broadcom |
| 3 | * All rights reserved. | 3 | * All rights reserved. |
| 4 | * | 4 | * |
| 5 | * This program is free software; you can redistribute it and/or | 5 | * This program is free software; you can redistribute it and/or |
| @@ -7,10 +7,10 @@ · 1 unmodified line | |||
| 7 | * as published by the Free Software Foundation. The full GNU General | 7 | * as published by the Free Software Foundation. The full GNU General |
| 8 | * Public License is included in this distribution in the file called COPYING. | 8 | * Public License is included in this distribution in the file called COPYING. |
| 9 | * | 9 | * |
| 10 | * Written by: Jayamohan Kallickal (jayamohan.kallickal@avagotech.com) | 10 | * Written by: Jayamohan Kallickal (jayamohan.kallickal@broadcom.com) |
| 11 | * | 11 | * |
| 12 | * Contact Information: | 12 | * Contact Information: |
| 13 | * linux-drivers@avagotech.com | 13 | * linux-drivers@broadcom.com |
| 14 | * | 14 | * |
| 15 | * Emulex | 15 | * Emulex |
| 16 | * 3333 Susan Street | 16 | * 3333 Susan Street |
| @@ -36,7 +36,7 @@ · 19 unmodified lines | |||
| 36 | #include <scsi/scsi_transport_iscsi.h> | 36 | #include <scsi/scsi_transport_iscsi.h> |
| 37 | 37 | ||
| 38 | #define DRV_NAME "be2iscsi" | 38 | #define DRV_NAME "be2iscsi" |
| 39 | #define BUILD_STR "11.0.0.0" | 39 | #define BUILD_STR "11.2.0.0" |
| 40 | #define BE_NAME "Emulex OneConnect" \ | 40 | #define BE_NAME "Emulex OneConnect" \ |
| 41 | "Open-iSCSI Driver version" BUILD_STR | 41 | "Open-iSCSI Driver version" BUILD_STR |
| 42 | #define DRV_DESC BE_NAME " " "Driver" | 42 | #define DRV_DESC BE_NAME " " "Driver" |
| @@ -82,36 +82,12 @@ · 39 unmodified lines | |||
| 82 | #define BEISCSI_MAX_FRAGS_INIT 192 | 82 | #define BEISCSI_MAX_FRAGS_INIT 192 |
| 83 | #define BE_NUM_MSIX_ENTRIES 1 | 83 | #define BE_NUM_MSIX_ENTRIES 1 |
| 84 | 84 | ||
| 85 | #define MPU_EP_CONTROL 0 | ||
| 86 | #define MPU_EP_SEMAPHORE 0xac | ||
| 87 | #define BE2_SOFT_RESET 0x5c | ||
| 88 | #define BE2_PCI_ONLINE0 0xb0 | ||
| 89 | #define BE2_PCI_ONLINE1 0xb4 | ||
| 90 | #define BE2_SET_RESET 0x80 | ||
| 91 | #define BE2_MPU_IRAM_ONLINE 0x00000080 | ||
| 92 | |||
| 93 | #define BE_SENSE_INFO_SIZE 258 | 85 | #define BE_SENSE_INFO_SIZE 258 |
| 94 | #define BE_ISCSI_PDU_HEADER_SIZE 64 | 86 | #define BE_ISCSI_PDU_HEADER_SIZE 64 |
| 95 | #define BE_MIN_MEM_SIZE 16384 | 87 | #define BE_MIN_MEM_SIZE 16384 |
| 96 | #define MAX_CMD_SZ 65536 | 88 | #define MAX_CMD_SZ 65536 |
| 97 | #define IIOC_SCSI_DATA 0x05 /* Write Operation */ | 89 | #define IIOC_SCSI_DATA 0x05 /* Write Operation */ |
| 98 | 90 | ||
| 99 | #define INVALID_SESS_HANDLE 0xFFFFFFFF | ||
| 100 | |||
| 101 | /** | ||
| 102 | * Adapter States | ||
| 103 | **/ | ||
| 104 | #define BE_ADAPTER_LINK_UP 0x001 | ||
| 105 | #define BE_ADAPTER_LINK_DOWN 0x002 | ||
| 106 | #define BE_ADAPTER_PCI_ERR 0x004 | ||
| 107 | #define BE_ADAPTER_CHECK_BOOT 0x008 | ||
| 108 | |||
| 109 | |||
| 110 | #define BEISCSI_CLEAN_UNLOAD 0x01 | ||
| 111 | #define BEISCSI_EEH_UNLOAD 0x02 | ||
| 112 | |||
| 113 | #define BE_GET_BOOT_RETRIES 45 | ||
| 114 | #define BE_GET_BOOT_TO 20 | ||
| 115 | /** | 91 | /** |
| 116 | * hardware needs the async PDU buffers to be posted in multiples of 8 | 92 | * hardware needs the async PDU buffers to be posted in multiples of 8 |
| 117 | * So have atleast 8 of them by default | 93 | * So have atleast 8 of them by default |
| @@ -378,7 +354,6 @@ struct beiscsi_hba { · 260 unmodified lines | |||
| 378 | struct sgl_handle **eh_sgl_hndl_base; | 354 | struct sgl_handle **eh_sgl_hndl_base; |
| 379 | spinlock_t io_sgl_lock; | 355 | spinlock_t io_sgl_lock; |
| 380 | spinlock_t mgmt_sgl_lock; | 356 | spinlock_t mgmt_sgl_lock; |
| 381 | spinlock_t isr_lock; | ||
| 382 | spinlock_t async_pdu_lock; | 357 | spinlock_t async_pdu_lock; |
| 383 | unsigned int age; | 358 | unsigned int age; |
| 384 | struct list_head hba_queue; | 359 | struct list_head hba_queue; |
| @@ -390,7 +365,6 @@ struct beiscsi_hba { · 5 unmodified lines | |||
| 390 | struct ulp_cid_info *cid_array_info[BEISCSI_ULP_COUNT]; | 365 | struct ulp_cid_info *cid_array_info[BEISCSI_ULP_COUNT]; |
| 391 | struct iscsi_endpoint **ep_array; | 366 | struct iscsi_endpoint **ep_array; |
| 392 | struct beiscsi_conn **conn_table; | 367 | struct beiscsi_conn **conn_table; |
| 393 | struct iscsi_boot_kset *boot_kset; | ||
| 394 | struct Scsi_Host *shost; | 368 | struct Scsi_Host *shost; |
| 395 | struct iscsi_iface *ipv4_iface; | 369 | struct iscsi_iface *ipv4_iface; |
| 396 | struct iscsi_iface *ipv6_iface; | 370 | struct iscsi_iface *ipv6_iface; |
| @@ -418,12 +392,33 @@ struct beiscsi_hba { · 21 unmodified lines | |||
| 418 | unsigned long ulp_supported; | 392 | unsigned long ulp_supported; |
| 419 | } fw_config; | 393 | } fw_config; |
| 420 | 394 | ||
| 421 | unsigned int state; | 395 | unsigned long state; |
| 396 | #define BEISCSI_HBA_ONLINE 0 | ||
| 397 | #define BEISCSI_HBA_LINK_UP 1 | ||
| 398 | #define BEISCSI_HBA_BOOT_FOUND 2 | ||
| 399 | #define BEISCSI_HBA_BOOT_WORK 3 | ||
| 400 | #define BEISCSI_HBA_UER_SUPP 4 | ||
| 401 | #define BEISCSI_HBA_PCI_ERR 5 | ||
| 402 | #define BEISCSI_HBA_FW_TIMEOUT 6 | ||
| 403 | #define BEISCSI_HBA_IN_UE 7 | ||
| 404 | #define BEISCSI_HBA_IN_TPE 8 | ||
| 405 | |||
| 406 | /* error bits */ | ||
| 407 | #define BEISCSI_HBA_IN_ERR ((1 << BEISCSI_HBA_PCI_ERR) | \ | ||
| 408 | (1 << BEISCSI_HBA_FW_TIMEOUT) | \ | ||
| 409 | (1 << BEISCSI_HBA_IN_UE) | \ | ||
| 410 | (1 << BEISCSI_HBA_IN_TPE)) | ||
| 411 | |||
| 422 | u8 optic_state; | 412 | u8 optic_state; |
| 423 | int get_boot; | 413 | struct delayed_work eqd_update; |
| 424 | bool fw_timeout; | 414 | /* update EQ delay timer every 1000ms */ |
| 425 | bool ue_detected; | 415 | #define BEISCSI_EQD_UPDATE_INTERVAL 1000 |
| 426 | struct delayed_work beiscsi_hw_check_task; | 416 | struct timer_list hw_check; |
| 417 | /* check for UE every 1000ms */ | ||
| 418 | #define BEISCSI_UE_DETECT_INTERVAL 1000 | ||
| 419 | u32 ue2rp; | ||
| 420 | struct delayed_work recover_port; | ||
| 421 | struct work_struct sess_work; | ||
| 427 | 422 | ||
| 428 | bool mac_addr_set; | 423 | bool mac_addr_set; |
| 429 | u8 mac_address[ETH_ALEN]; | 424 | u8 mac_address[ETH_ALEN]; |
| @@ -435,7 +430,6 @@ struct beiscsi_hba { · 5 unmodified lines | |||
| 435 | struct be_ctrl_info ctrl; | 430 | struct be_ctrl_info ctrl; |
| 436 | unsigned int generation; | 431 | unsigned int generation; |
| 437 | unsigned int interface_handle; | 432 | unsigned int interface_handle; |
| 438 | struct mgmt_session_info boot_sess; | ||
| 439 | struct invalidate_command_table inv_tbl[128]; | 433 | struct invalidate_command_table inv_tbl[128]; |
| 440 | 434 | ||
| 441 | struct be_aic_obj aic_obj[MAX_CPUS]; | 435 | struct be_aic_obj aic_obj[MAX_CPUS]; |
| @@ -444,8 +438,29 @@ struct beiscsi_hba { · 2 unmodified lines | |||
| 444 | struct scatterlist *sg, | 438 | struct scatterlist *sg, |
| 445 | uint32_t num_sg, uint32_t xferlen, | 439 | uint32_t num_sg, uint32_t xferlen, |
| 446 | uint32_t writedir); | 440 | uint32_t writedir); |
| 441 | struct boot_struct { | ||
| 442 | int retry; | ||
| 443 | unsigned int tag; | ||
| 444 | unsigned int s_handle; | ||
| 445 | struct be_dma_mem nonemb_cmd; | ||
| 446 | enum { | ||
| 447 | BEISCSI_BOOT_REOPEN_SESS = 1, | ||
| 448 | BEISCSI_BOOT_GET_SHANDLE, | ||
| 449 | BEISCSI_BOOT_GET_SINFO, | ||
| 450 | BEISCSI_BOOT_LOGOUT_SESS, | ||
| 451 | BEISCSI_BOOT_CREATE_KSET, | ||
| 452 | } action; | ||
| 453 | struct mgmt_session_info boot_sess; | ||
| 454 | struct iscsi_boot_kset *boot_kset; | ||
| 455 | } boot_struct; | ||
| 456 | struct work_struct boot_work; | ||
| 447 | }; | 457 | }; |
| 448 | 458 | ||
| 459 | #define beiscsi_hba_in_error(phba) ((phba)->state & BEISCSI_HBA_IN_ERR) | ||
| 460 | #define beiscsi_hba_is_online(phba) \ | ||
| 461 | (!beiscsi_hba_in_error((phba)) && \ | ||
| 462 | test_bit(BEISCSI_HBA_ONLINE, &phba->state)) | ||
| 463 | |||
| 449 | struct beiscsi_session { | 464 | struct beiscsi_session { |
| 450 | struct pci_pool *bhs_pool; | 465 | struct pci_pool *bhs_pool; |
| 451 | }; | 466 | }; |
| @@ -508,6 +523,7 @@ struct beiscsi_io_task { · 56 unmodified lines | |||
| 508 | struct sgl_handle *psgl_handle; | 523 | struct sgl_handle *psgl_handle; |
| 509 | struct beiscsi_conn *conn; | 524 | struct beiscsi_conn *conn; |
| 510 | struct scsi_cmnd *scsi_cmnd; | 525 | struct scsi_cmnd *scsi_cmnd; |
| 526 | int num_sg; | ||
| 511 | struct hwi_wrb_context *pwrb_context; | 527 | struct hwi_wrb_context *pwrb_context; |
| 512 | unsigned int cmd_sn; | 528 | unsigned int cmd_sn; |
| 513 | unsigned int flags; | 529 | unsigned int flags; |
| @@ -592,80 +608,81 @@ struct amap_beiscsi_offload_params { · 78 unmodified lines | |||
| 592 | u8 max_recv_data_segment_length[32]; | 608 | u8 max_recv_data_segment_length[32]; |
| 593 | }; | 609 | }; |
| 594 | 610 | ||
| 595 | /* void hwi_complete_drvr_msgs(struct beiscsi_conn *beiscsi_conn, | 611 | struct hd_async_handle { |
| 596 | struct beiscsi_hba *phba, struct sol_cqe *psol);*/ | ||
| 597 | |||
| 598 | struct async_pdu_handle { | ||
| 599 | struct list_head link; | 612 | struct list_head link; |
| 600 | struct be_bus_address pa; | 613 | struct be_bus_address pa; |
| 601 | void *pbuffer; | 614 | void *pbuffer; |
| 602 | unsigned int consumed; | 615 | u32 buffer_len; |
| 603 | unsigned char index; | 616 | u16 index; |
| 604 | unsigned char is_header; | 617 | u16 cri; |
| 605 | unsigned short cri; | 618 | u8 is_header; |
| 606 | unsigned long buffer_len; | 619 | u8 is_final; |
| 607 | }; | 620 | }; |
| 608 | 621 | ||
| 609 | struct hwi_async_entry { | 622 | /** |
| 610 | struct { | 623 | * This has list of async PDUs that are waiting to be processed. |
| 611 | unsigned char hdr_received; | 624 | * Buffers live in this list for a brief duration before they get |
| 612 | unsigned char hdr_len; | 625 | * processed and posted back to hardware. |
| 613 | unsigned short bytes_received; | 626 | * Note that we don't really need one cri_wait_queue per async_entry. |
| 627 | * We need one cri_wait_queue per CRI. Its easier to manage if this | ||
| 628 | * is tagged along with the async_entry. | ||
| 629 | */ | ||
| 630 | struct hd_async_entry { | ||
| 631 | struct cri_wait_queue { | ||
| 632 | unsigned short hdr_len; | ||
| 633 | unsigned int bytes_received; | ||
| 614 | unsigned int bytes_needed; | 634 | unsigned int bytes_needed; |
| 615 | struct list_head list; | 635 | struct list_head list; |
| 616 | } wait_queue; | 636 | } wq; |
| 617 | 637 | /* handles posted to FW resides here */ | |
| 618 | struct list_head header_busy_list; | 638 | struct hd_async_handle *header; |
| 619 | struct list_head data_busy_list; | 639 | struct hd_async_handle *data; |
| 620 | }; | 640 | }; |
| 621 | 641 | ||
| 622 | struct hwi_async_pdu_context { | 642 | struct hd_async_buf_context { |
| 623 | struct { | 643 | struct be_bus_address pa_base; |
| 624 | struct be_bus_address pa_base; | 644 | void *va_base; |
| 625 | void *va_base; | 645 | void *ring_base; |
| 626 | void *ring_base; | 646 | struct hd_async_handle *handle_base; |
| 627 | struct async_pdu_handle *handle_base; | 647 | u16 free_entries; |
| 628 | 648 | u32 buffer_size; | |
| 629 | unsigned int host_write_ptr; | 649 | /** |
| 630 | unsigned int ep_read_ptr; | 650 | * Once iSCSI layer finishes processing an async PDU, the |
| 631 | unsigned int writables; | 651 | * handles used for the PDU are added to this list. |
| 632 | 652 | * They are posted back to FW in groups of 8. | |
| 633 | unsigned int free_entries; | 653 | */ |
| 634 | unsigned int busy_entries; | 654 | struct list_head free_list; |
| 635 | 655 | }; | |
| 636 | struct list_head free_list; | ||
| 637 | } async_header; | ||
| 638 | 656 | ||
| 639 | struct { | 657 | /** |
| 640 | struct be_bus_address pa_base; | 658 | * hd_async_context is declared for each ULP supporting iSCSI function. |
| 641 | void *va_base; | 659 | */ |
| 642 | void *ring_base; | 660 | struct hd_async_context { |
| 643 | struct async_pdu_handle *handle_base; | 661 | struct hd_async_buf_context async_header; |
| 644 | 662 | struct hd_async_buf_context async_data; | |
| 645 | unsigned int host_write_ptr; | 663 | u16 num_entries; |
| 646 | unsigned int ep_read_ptr; | 664 | /** |
| 647 | unsigned int writables; | 665 | * When unsol PDU is in, it needs to be chained till all the bytes are |
| 648 | 666 | * received and then processing is done. hd_async_entry is created | |
| 649 | unsigned int free_entries; | 667 | * based on the cid_count for each ULP. When unsol PDU comes in based |
| 650 | unsigned int busy_entries; | 668 | * on the conn_id it needs to be added to the correct async_entry wq. |
| 651 | struct list_head free_list; | 669 | * Below defined cid_to_async_cri_map is used to reterive the |
| 652 | } async_data; | 670 | * async_cri_map for a particular connection. |
| 653 | 671 | * | |
| 654 | unsigned int buffer_size; | 672 | * This array is initialized after beiscsi_create_wrb_rings returns. |
| 655 | unsigned int num_entries; | 673 | * |
| 674 | * - this method takes more memory space, fixed to 2K | ||
| 675 | * - any support for connections greater than this the array size needs | ||
| 676 | * to be incremented | ||
| 677 | */ | ||
| 656 | #define BE_GET_ASYNC_CRI_FROM_CID(cid) (pasync_ctx->cid_to_async_cri_map[cid]) | 678 | #define BE_GET_ASYNC_CRI_FROM_CID(cid) (pasync_ctx->cid_to_async_cri_map[cid]) |
| 657 | unsigned short cid_to_async_cri_map[BE_MAX_SESSION]; | 679 | unsigned short cid_to_async_cri_map[BE_MAX_SESSION]; |
| 658 | /** | 680 | /** |
| 659 | * This is a varying size list! Do not add anything | 681 | * This is a variable size array. Don`t add anything after this field!! |
| 660 | * after this entry!! | ||
| 661 | */ | 682 | */ |
| 662 | struct hwi_async_entry *async_entry; | 683 | struct hd_async_entry *async_entry; |
| 663 | }; | 684 | }; |
| 664 | 685 | ||
| 665 | #define PDUCQE_CODE_MASK 0x0000003F | ||
| 666 | #define PDUCQE_DPL_MASK 0xFFFF0000 | ||
| 667 | #define PDUCQE_INDEX_MASK 0x0000FFFF | ||
| 668 | |||
| 669 | struct i_t_dpdu_cqe { | 686 | struct i_t_dpdu_cqe { |
| 670 | u32 dw[4]; | 687 | u32 dw[4]; |
| 671 | } __packed; | 688 | } __packed; |
| @@ -845,7 +862,6 @@ struct wrb_handle *alloc_wrb_handle(struct beiscsi_hba *phba, unsigned int cid, · 173 unmodified lines | |||
| 845 | void | 862 | void |
| 846 | free_mgmt_sgl_handle(struct beiscsi_hba *phba, struct sgl_handle *psgl_handle); | 863 | free_mgmt_sgl_handle(struct beiscsi_hba *phba, struct sgl_handle *psgl_handle); |
| 847 | 864 | ||
| 848 | void beiscsi_process_all_cqs(struct work_struct *work); | ||
| 849 | void beiscsi_free_mgmt_task_handles(struct beiscsi_conn *beiscsi_conn, | 865 | void beiscsi_free_mgmt_task_handles(struct beiscsi_conn *beiscsi_conn, |
| 850 | struct iscsi_task *task); | 866 | struct iscsi_task *task); |
| 851 | 867 | ||
| @@ -856,11 +872,6 @@ void hwi_ring_cq_db(struct beiscsi_hba *phba, · 4 unmodified lines | |||
| 856 | unsigned int beiscsi_process_cq(struct be_eq_obj *pbe_eq, int budget); | 872 | unsigned int beiscsi_process_cq(struct be_eq_obj *pbe_eq, int budget); |
| 857 | void beiscsi_process_mcc_cq(struct beiscsi_hba *phba); | 873 | void beiscsi_process_mcc_cq(struct beiscsi_hba *phba); |
| 858 | 874 | ||
| 859 | static inline bool beiscsi_error(struct beiscsi_hba *phba) | ||
| 860 | { | ||
| 861 | return phba->ue_detected || phba->fw_timeout; | ||
| 862 | } | ||
| 863 | |||
| 864 | struct pdu_nop_out { | 875 | struct pdu_nop_out { |
| 865 | u32 dw[12]; | 876 | u32 dw[12]; |
| 866 | }; | 877 | }; |
| @@ -1067,11 +1078,18 @@ struct hwi_context_memory { · 200 unmodified lines | |||
| 1067 | struct be_queue_info be_cq[MAX_CPUS - 1]; | 1078 | struct be_queue_info be_cq[MAX_CPUS - 1]; |
| 1068 | 1079 | ||
| 1069 | struct be_queue_info *be_wrbq; | 1080 | struct be_queue_info *be_wrbq; |
| 1081 | /** | ||
| 1082 | * Create array of ULP number for below entries as DEFQ | ||
| 1083 | * will be created for both ULP if iSCSI Protocol is | ||
| 1084 | * loaded on both ULP. | ||
| 1085 | */ | ||
| 1070 | struct be_queue_info be_def_hdrq[BEISCSI_ULP_COUNT]; | 1086 | struct be_queue_info be_def_hdrq[BEISCSI_ULP_COUNT]; |
| 1071 | struct be_queue_info be_def_dataq[BEISCSI_ULP_COUNT]; | 1087 | struct be_queue_info be_def_dataq[BEISCSI_ULP_COUNT]; |
| 1072 | struct hwi_async_pdu_context *pasync_ctx[BEISCSI_ULP_COUNT]; | 1088 | struct hd_async_context *pasync_ctx[BEISCSI_ULP_COUNT]; |
| 1073 | }; | 1089 | }; |
| 1074 | 1090 | ||
| 1091 | void beiscsi_start_boot_work(struct beiscsi_hba *phba, unsigned int s_handle); | ||
| 1092 | |||
| 1075 | /* Logging related definitions */ | 1093 | /* Logging related definitions */ |
| 1076 | #define BEISCSI_LOG_INIT 0x0001 /* Initialization events */ | 1094 | #define BEISCSI_LOG_INIT 0x0001 /* Initialization events */ |
| 1077 | #define BEISCSI_LOG_MBOX 0x0002 /* Mailbox Events */ | 1095 | #define BEISCSI_LOG_MBOX 0x0002 /* Mailbox Events */ |
| @@ -1,5 +1,5 @@ | |||
| 1 | /** | 1 | /** |
| 2 | * Copyright (C) 2005 - 2015 Emulex | 2 | * Copyright (C) 2005 - 2016 Broadcom |
| 3 | * All rights reserved. | 3 | * All rights reserved. |
| 4 | * | 4 | * |
| 5 | * This program is free software; you can redistribute it and/or | 5 | * This program is free software; you can redistribute it and/or |
| @@ -7,10 +7,10 @@ · 1 unmodified line | |||
| 7 | * as published by the Free Software Foundation. The full GNU General | 7 | * as published by the Free Software Foundation. The full GNU General |
| 8 | * Public License is included in this distribution in the file called COPYING. | 8 | * Public License is included in this distribution in the file called COPYING. |
| 9 | * | 9 | * |
| 10 | * Written by: Jayamohan Kallickal (jayamohan.kallickal@avagotech.com) | 10 | * Written by: Jayamohan Kallickal (jayamohan.kallickal@broadcom.com) |
| 11 | * | 11 | * |
| 12 | * Contact Information: | 12 | * Contact Information: |
| 13 | * linux-drivers@avagotech.com | 13 | * linux-drivers@broadcom.com |
| 14 | * | 14 | * |
| 15 | * Emulex | 15 | * Emulex |
| 16 | * 3333 Susan Street | 16 | * 3333 Susan Street |
| @@ -24,139 +24,9 @@ · 7 unmodified lines | |||
| 24 | #include "be_iscsi.h" | 24 | #include "be_iscsi.h" |
| 25 | #include "be_main.h" | 25 | #include "be_main.h" |
| 26 | 26 | ||
| 27 | /* UE Status Low CSR */ | 27 | int beiscsi_modify_eq_delay(struct beiscsi_hba *phba, |
| 28 | static const char * const desc_ue_status_low[] = { | 28 | struct be_set_eqd *set_eqd, |
| 29 | "CEV", | 29 | int num) |
| 30 | "CTX", | ||
| 31 | "DBUF", | ||
| 32 | "ERX", | ||
| 33 | "Host", | ||
| 34 | "MPU", | ||
| 35 | "NDMA", | ||
| 36 | "PTC ", | ||
| 37 | "RDMA ", | ||
| 38 | "RXF ", | ||
| 39 | "RXIPS ", | ||
| 40 | "RXULP0 ", | ||
| 41 | "RXULP1 ", | ||
| 42 | "RXULP2 ", | ||
| 43 | "TIM ", | ||
| 44 | "TPOST ", | ||
| 45 | "TPRE ", | ||
| 46 | "TXIPS ", | ||
| 47 | "TXULP0 ", | ||
| 48 | "TXULP1 ", | ||
| 49 | "UC ", | ||
| 50 | "WDMA ", | ||
| 51 | "TXULP2 ", | ||
| 52 | "HOST1 ", | ||
| 53 | "P0_OB_LINK ", | ||
| 54 | "P1_OB_LINK ", | ||
| 55 | "HOST_GPIO ", | ||
| 56 | "MBOX ", | ||
| 57 | "AXGMAC0", | ||
| 58 | "AXGMAC1", | ||
| 59 | "JTAG", | ||
| 60 | "MPU_INTPEND" | ||
| 61 | }; | ||
| 62 | |||
| 63 | /* UE Status High CSR */ | ||
| 64 | static const char * const desc_ue_status_hi[] = { | ||
| 65 | "LPCMEMHOST", | ||
| 66 | "MGMT_MAC", | ||
| 67 | "PCS0ONLINE", | ||
| 68 | "MPU_IRAM", | ||
| 69 | "PCS1ONLINE", | ||
| 70 | "PCTL0", | ||
| 71 | "PCTL1", | ||
| 72 | "PMEM", | ||
| 73 | "RR", | ||
| 74 | "TXPB", | ||
| 75 | "RXPP", | ||
| 76 | "XAUI", | ||
| 77 | "TXP", | ||
| 78 | "ARM", | ||
| 79 | "IPC", | ||
| 80 | "HOST2", | ||
| 81 | "HOST3", | ||
| 82 | "HOST4", | ||
| 83 | "HOST5", | ||
| 84 | "HOST6", | ||
| 85 | "HOST7", | ||
| 86 | "HOST8", | ||
| 87 | "HOST9", | ||
| 88 | "NETC", | ||
| 89 | "Unknown", | ||
| 90 | "Unknown", | ||
| 91 | "Unknown", | ||
| 92 | "Unknown", | ||
| 93 | "Unknown", | ||
| 94 | "Unknown", | ||
| 95 | "Unknown", | ||
| 96 | "Unknown" | ||
| 97 | }; | ||
| 98 | |||
| 99 | /* | ||
| 100 | * beiscsi_ue_detec()- Detect Unrecoverable Error on adapter | ||
| 101 | * @phba: Driver priv structure | ||
| 102 | * | ||
| 103 | * Read registers linked to UE and check for the UE status | ||
| 104 | **/ | ||
| 105 | void beiscsi_ue_detect(struct beiscsi_hba *phba) | ||
| 106 | { | ||
| 107 | uint32_t ue_hi = 0, ue_lo = 0; | ||
| 108 | uint32_t ue_mask_hi = 0, ue_mask_lo = 0; | ||
| 109 | uint8_t i = 0; | ||
| 110 | |||
| 111 | if (phba->ue_detected) | ||
| 112 | return; | ||
| 113 | |||
| 114 | pci_read_config_dword(phba->pcidev, | ||
| 115 | PCICFG_UE_STATUS_LOW, &ue_lo); | ||
| 116 | pci_read_config_dword(phba->pcidev, | ||
| 117 | PCICFG_UE_STATUS_MASK_LOW, | ||
| 118 | &ue_mask_lo); | ||
| 119 | pci_read_config_dword(phba->pcidev, | ||
| 120 | PCICFG_UE_STATUS_HIGH, | ||
| 121 | &ue_hi); | ||
| 122 | pci_read_config_dword(phba->pcidev, | ||
| 123 | PCICFG_UE_STATUS_MASK_HI, | ||
| 124 | &ue_mask_hi); | ||
| 125 | |||
| 126 | ue_lo = (ue_lo & ~ue_mask_lo); | ||
| 127 | ue_hi = (ue_hi & ~ue_mask_hi); | ||
| 128 | |||
| 129 | |||
| 130 | if (ue_lo || ue_hi) { | ||
| 131 | phba->ue_detected = true; | ||
| 132 | beiscsi_log(phba, KERN_ERR, | ||
| 133 | BEISCSI_LOG_CONFIG | BEISCSI_LOG_MBOX, | ||
| 134 | "BG_%d : Error detected on the adapter\n"); | ||
| 135 | } | ||
| 136 | |||
| 137 | if (ue_lo) { | ||
| 138 | for (i = 0; ue_lo; ue_lo >>= 1, i++) { | ||
| 139 | if (ue_lo & 1) | ||
| 140 | beiscsi_log(phba, KERN_ERR, | ||
| 141 | BEISCSI_LOG_CONFIG, | ||
| 142 | "BG_%d : UE_LOW %s bit set\n", | ||
| 143 | desc_ue_status_low[i]); | ||
| 144 | } | ||
| 145 | } | ||
| 146 | |||
| 147 | if (ue_hi) { | ||
| 148 | for (i = 0; ue_hi; ue_hi >>= 1, i++) { | ||
| 149 | if (ue_hi & 1) | ||
| 150 | beiscsi_log(phba, KERN_ERR, | ||
| 151 | BEISCSI_LOG_CONFIG, | ||
| 152 | "BG_%d : UE_HIGH %s bit set\n", | ||
| 153 | desc_ue_status_hi[i]); | ||
| 154 | } | ||
| 155 | } | ||
| 156 | } | ||
| 157 | |||
| 158 | int be_cmd_modify_eq_delay(struct beiscsi_hba *phba, | ||
| 159 | struct be_set_eqd *set_eqd, int num) | ||
| 160 | { | 30 | { |
| 161 | struct be_ctrl_info *ctrl = &phba->ctrl; | 31 | struct be_ctrl_info *ctrl = &phba->ctrl; |
| 162 | struct be_mcc_wrb *wrb; | 32 | struct be_mcc_wrb *wrb; |
| @@ -174,7 +44,7 @@ int be_cmd_modify_eq_delay(struct beiscsi_hba *phba, · 11 unmodified lines | |||
| 174 | req = embedded_payload(wrb); | 44 | req = embedded_payload(wrb); |
| 175 | be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); | 45 | be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); |
| 176 | be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, | 46 | be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, |
| 177 | OPCODE_COMMON_MODIFY_EQ_DELAY, sizeof(*req)); | 47 | OPCODE_COMMON_MODIFY_EQ_DELAY, sizeof(*req)); |
| 178 | 48 | ||
| 179 | req->num_eq = cpu_to_le32(num); | 49 | req->num_eq = cpu_to_le32(num); |
| 180 | for (i = 0; i < num; i++) { | 50 | for (i = 0; i < num; i++) { |
| @@ -184,386 +54,13 @@ int be_cmd_modify_eq_delay(struct beiscsi_hba *phba, · 3 unmodified lines | |||
| 184 | cpu_to_le32(set_eqd[i].delay_multiplier); | 54 | cpu_to_le32(set_eqd[i].delay_multiplier); |
| 185 | } | 55 | } |
| 186 | 56 | ||
| 57 | /* ignore the completion of this mbox command */ | ||
| 58 | set_bit(MCC_TAG_STATE_IGNORE, &ctrl->ptag_state[tag].tag_state); | ||
| 187 | be_mcc_notify(phba, tag); | 59 | be_mcc_notify(phba, tag); |
| 188 | mutex_unlock(&ctrl->mbox_lock); | 60 | mutex_unlock(&ctrl->mbox_lock); |
| 189 | return tag; | 61 | return tag; |
| 190 | } | 62 | } |
| 191 | 63 | ||
| 192 | /** | ||
| 193 | * mgmt_reopen_session()- Reopen a session based on reopen_type | ||
| 194 | * @phba: Device priv structure instance | ||
| 195 | * @reopen_type: Type of reopen_session FW should do. | ||
| 196 | * @sess_handle: Session Handle of the session to be re-opened | ||
| 197 | * | ||
| 198 | * return | ||
| 199 | * the TAG used for MBOX Command | ||
| 200 | * | ||
| 201 | **/ | ||
| 202 | unsigned int mgmt_reopen_session(struct beiscsi_hba *phba, | ||
| 203 | unsigned int reopen_type, | ||
| 204 | unsigned int sess_handle) | ||
| 205 | { | ||
| 206 | struct be_ctrl_info *ctrl = &phba->ctrl; | ||
| 207 | struct be_mcc_wrb *wrb; | ||
| 208 | struct be_cmd_reopen_session_req *req; | ||
| 209 | unsigned int tag; | ||
| 210 | |||
| 211 | beiscsi_log(phba, KERN_INFO, | ||
| 212 | BEISCSI_LOG_CONFIG | BEISCSI_LOG_MBOX, | ||
| 213 | "BG_%d : In bescsi_get_boot_target\n"); | ||
| 214 | |||
| 215 | mutex_lock(&ctrl->mbox_lock); | ||
| 216 | wrb = alloc_mcc_wrb(phba, &tag); | ||
| 217 | if (!wrb) { | ||
| 218 | mutex_unlock(&ctrl->mbox_lock); | ||
| 219 | return 0; | ||
| 220 | } | ||
| 221 | |||
| 222 | req = embedded_payload(wrb); | ||
| 223 | be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); | ||
| 224 | be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ISCSI_INI, | ||
| 225 | OPCODE_ISCSI_INI_DRIVER_REOPEN_ALL_SESSIONS, | ||
| 226 | sizeof(struct be_cmd_reopen_session_resp)); | ||
| 227 | |||
| 228 | /* set the reopen_type,sess_handle */ | ||
| 229 | req->reopen_type = reopen_type; | ||
| 230 | req->session_handle = sess_handle; | ||
| 231 | |||
| 232 | be_mcc_notify(phba, tag); | ||
| 233 | mutex_unlock(&ctrl->mbox_lock); | ||
| 234 | return tag; | ||
| 235 | } | ||
| 236 | |||
| 237 | unsigned int mgmt_get_boot_target(struct beiscsi_hba *phba) | ||
| 238 | { | ||
| 239 | struct be_ctrl_info *ctrl = &phba->ctrl; | ||
| 240 | struct be_mcc_wrb *wrb; | ||
| 241 | struct be_cmd_get_boot_target_req *req; | ||
| 242 | unsigned int tag; | ||
| 243 | |||
| 244 | beiscsi_log(phba, KERN_INFO, | ||
| 245 | BEISCSI_LOG_CONFIG | BEISCSI_LOG_MBOX, | ||
| 246 | "BG_%d : In bescsi_get_boot_target\n"); | ||
| 247 | |||
| 248 | mutex_lock(&ctrl->mbox_lock); | ||
| 249 | wrb = alloc_mcc_wrb(phba, &tag); | ||
| 250 | if (!wrb) { | ||
| 251 | mutex_unlock(&ctrl->mbox_lock); | ||
| 252 | return 0; | ||
| 253 | } | ||
| 254 | |||
| 255 | req = embedded_payload(wrb); | ||
| 256 | be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); | ||
| 257 | be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ISCSI_INI, | ||
| 258 | OPCODE_ISCSI_INI_BOOT_GET_BOOT_TARGET, | ||
| 259 | sizeof(struct be_cmd_get_boot_target_resp)); | ||
| 260 | |||
| 261 | be_mcc_notify(phba, tag); | ||
| 262 | mutex_unlock(&ctrl->mbox_lock); | ||
| 263 | return tag; | ||
| 264 | } | ||
| 265 | |||
| 266 | unsigned int mgmt_get_session_info(struct beiscsi_hba *phba, | ||
| 267 | u32 boot_session_handle, | ||
| 268 | struct be_dma_mem *nonemb_cmd) | ||
| 269 | { | ||
| 270 | struct be_ctrl_info *ctrl = &phba->ctrl; | ||
| 271 | struct be_mcc_wrb *wrb; | ||
| 272 | unsigned int tag; | ||
| 273 | struct be_cmd_get_session_req *req; | ||
| 274 | struct be_cmd_get_session_resp *resp; | ||
| 275 | struct be_sge *sge; | ||
| 276 | |||
| 277 | beiscsi_log(phba, KERN_INFO, | ||
| 278 | BEISCSI_LOG_CONFIG | BEISCSI_LOG_MBOX, | ||
| 279 | "BG_%d : In beiscsi_get_session_info\n"); | ||
| 280 | |||
| 281 | mutex_lock(&ctrl->mbox_lock); | ||
| 282 | wrb = alloc_mcc_wrb(phba, &tag); | ||
| 283 | if (!wrb) { | ||
| 284 | mutex_unlock(&ctrl->mbox_lock); | ||
| 285 | return 0; | ||
| 286 | } | ||
| 287 | |||
| 288 | nonemb_cmd->size = sizeof(*resp); | ||
| 289 | req = nonemb_cmd->va; | ||
| 290 | memset(req, 0, sizeof(*req)); | ||
| 291 | sge = nonembedded_sgl(wrb); | ||
| 292 | be_wrb_hdr_prepare(wrb, sizeof(*req), false, 1); | ||
| 293 | be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ISCSI_INI, | ||
| 294 | OPCODE_ISCSI_INI_SESSION_GET_A_SESSION, | ||
| 295 | sizeof(*resp)); | ||
| 296 | req->session_handle = boot_session_handle; | ||
| 297 | sge->pa_hi = cpu_to_le32(upper_32_bits(nonemb_cmd->dma)); | ||
| 298 | sge->pa_lo = cpu_to_le32(nonemb_cmd->dma & 0xFFFFFFFF); | ||
| 299 | sge->len = cpu_to_le32(nonemb_cmd->size); | ||
| 300 | |||
| 301 | be_mcc_notify(phba, tag); | ||
| 302 | mutex_unlock(&ctrl->mbox_lock); | ||
| 303 | return tag; | ||
| 304 | } | ||
| 305 | |||
| 306 | /** | ||
| 307 | * mgmt_get_port_name()- Get port name for the function | ||
| 308 | * @ctrl: ptr to Ctrl Info | ||
| 309 | * @phba: ptr to the dev priv structure | ||
| 310 | * | ||
| 311 | * Get the alphanumeric character for port | ||
| 312 | * | ||
| 313 | **/ | ||
| 314 | int mgmt_get_port_name(struct be_ctrl_info *ctrl, | ||
| 315 | struct beiscsi_hba *phba) | ||
| 316 | { | ||
| 317 | int ret = 0; | ||
| 318 | struct be_mcc_wrb *wrb; | ||
| 319 | struct be_cmd_get_port_name *ioctl; | ||
| 320 | |||
| 321 | mutex_lock(&ctrl->mbox_lock); | ||
| 322 | wrb = wrb_from_mbox(&ctrl->mbox_mem); | ||
| 323 | memset(wrb, 0, sizeof(*wrb)); | ||
| 324 | ioctl = embedded_payload(wrb); | ||
| 325 | |||
| 326 | be_wrb_hdr_prepare(wrb, sizeof(*ioctl), true, 0); | ||
| 327 | be_cmd_hdr_prepare(&ioctl->h.req_hdr, CMD_SUBSYSTEM_COMMON, | ||
| 328 | OPCODE_COMMON_GET_PORT_NAME, | ||
| 329 | EMBED_MBX_MAX_PAYLOAD_SIZE); | ||
| 330 | ret = be_mbox_notify(ctrl); | ||
| 331 | phba->port_name = 0; | ||
| 332 | if (!ret) { | ||
| 333 | phba->port_name = ioctl->p.resp.port_names >> | ||
| 334 | (phba->fw_config.phys_port * 8) & 0xff; | ||
| 335 | } else { | ||
| 336 | beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_INIT, | ||
| 337 | "BG_%d : GET_PORT_NAME ret 0x%x status 0x%x\n", | ||
| 338 | ret, ioctl->h.resp_hdr.status); | ||
| 339 | } | ||
| 340 | |||
| 341 | if (phba->port_name == 0) | ||
| 342 | phba->port_name = '?'; | ||
| 343 | |||
| 344 | mutex_unlock(&ctrl->mbox_lock); | ||
| 345 | return ret; | ||
| 346 | } | ||
| 347 | |||
| 348 | /** | ||
| 349 | * mgmt_get_fw_config()- Get the FW config for the function | ||
| 350 | * @ctrl: ptr to Ctrl Info | ||
| 351 | * @phba: ptr to the dev priv structure | ||
| 352 | * | ||
| 353 | * Get the FW config and resources available for the function. | ||
| 354 | * The resources are created based on the count received here. | ||
| 355 | * | ||
| 356 | * return | ||
| 357 | * Success: 0 | ||
| 358 | * Failure: Non-Zero Value | ||
| 359 | **/ | ||
| 360 | int mgmt_get_fw_config(struct be_ctrl_info *ctrl, | ||
| 361 | struct beiscsi_hba *phba) | ||
| 362 | { | ||
| 363 | struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem); | ||
| 364 | struct be_fw_cfg *pfw_cfg = embedded_payload(wrb); | ||
| 365 | uint32_t cid_count, icd_count; | ||
| 366 | int status = -EINVAL; | ||
| 367 | uint8_t ulp_num = 0; | ||
| 368 | |||
| 369 | mutex_lock(&ctrl->mbox_lock); | ||
| 370 | memset(wrb, 0, sizeof(*wrb)); | ||
| 371 | be_wrb_hdr_prepare(wrb, sizeof(*pfw_cfg), true, 0); | ||
| 372 | |||
| 373 | be_cmd_hdr_prepare(&pfw_cfg->hdr, CMD_SUBSYSTEM_COMMON, | ||
| 374 | OPCODE_COMMON_QUERY_FIRMWARE_CONFIG, | ||
| 375 | EMBED_MBX_MAX_PAYLOAD_SIZE); | ||
| 376 | |||
| 377 | if (be_mbox_notify(ctrl)) { | ||
| 378 | beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, | ||
| 379 | "BG_%d : Failed in mgmt_get_fw_config\n"); | ||
| 380 | goto fail_init; | ||
| 381 | } | ||
| 382 | |||
| 383 | /* FW response formats depend on port id */ | ||
| 384 | phba->fw_config.phys_port = pfw_cfg->phys_port; | ||
| 385 | if (phba->fw_config.phys_port >= BEISCSI_PHYS_PORT_MAX) { | ||
| 386 | beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, | ||
| 387 | "BG_%d : invalid physical port id %d\n", | ||
| 388 | phba->fw_config.phys_port); | ||
| 389 | goto fail_init; | ||
| 390 | } | ||
| 391 | |||
| 392 | /* populate and check FW config against min and max values */ | ||
| 393 | if (!is_chip_be2_be3r(phba)) { | ||
| 394 | phba->fw_config.eqid_count = pfw_cfg->eqid_count; | ||
| 395 | phba->fw_config.cqid_count = pfw_cfg->cqid_count; | ||
| 396 | if (phba->fw_config.eqid_count == 0 || | ||
| 397 | phba->fw_config.eqid_count > 2048) { | ||
| 398 | beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, | ||
| 399 | "BG_%d : invalid EQ count %d\n", | ||
| 400 | phba->fw_config.eqid_count); | ||
| 401 | goto fail_init; | ||
| 402 | } | ||
| 403 | if (phba->fw_config.cqid_count == 0 || | ||
| 404 | phba->fw_config.cqid_count > 4096) { | ||
| 405 | beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, | ||
| 406 | "BG_%d : invalid CQ count %d\n", | ||
| 407 | phba->fw_config.cqid_count); | ||
| 408 | goto fail_init; | ||
| 409 | } | ||
| 410 | beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_INIT, | ||
| 411 | "BG_%d : EQ_Count : %d CQ_Count : %d\n", | ||
| 412 | phba->fw_config.eqid_count, | ||
| 413 | phba->fw_config.cqid_count); | ||
| 414 | } | ||
| 415 | |||
| 416 | /** | ||
| 417 | * Check on which all ULP iSCSI Protocol is loaded. | ||
| 418 | * Set the Bit for those ULP. This set flag is used | ||
| 419 | * at all places in the code to check on which ULP | ||
| 420 | * iSCSi Protocol is loaded | ||
| 421 | **/ | ||
| 422 | for (ulp_num = 0; ulp_num < BEISCSI_ULP_COUNT; ulp_num++) { | ||
| 423 | if (pfw_cfg->ulp[ulp_num].ulp_mode & | ||
| 424 | BEISCSI_ULP_ISCSI_INI_MODE) { | ||
| 425 | set_bit(ulp_num, &phba->fw_config.ulp_supported); | ||
| 426 | |||
| 427 | /* Get the CID, ICD and Chain count for each ULP */ | ||
| 428 | phba->fw_config.iscsi_cid_start[ulp_num] = | ||
| 429 | pfw_cfg->ulp[ulp_num].sq_base; | ||
| 430 | phba->fw_config.iscsi_cid_count[ulp_num] = | ||
| 431 | pfw_cfg->ulp[ulp_num].sq_count; | ||
| 432 | |||
| 433 | phba->fw_config.iscsi_icd_start[ulp_num] = | ||
| 434 | pfw_cfg->ulp[ulp_num].icd_base; | ||
| 435 | phba->fw_config.iscsi_icd_count[ulp_num] = | ||
| 436 | pfw_cfg->ulp[ulp_num].icd_count; | ||
| 437 | |||
| 438 | phba->fw_config.iscsi_chain_start[ulp_num] = | ||
| 439 | pfw_cfg->chain_icd[ulp_num].chain_base; | ||
| 440 | phba->fw_config.iscsi_chain_count[ulp_num] = | ||
| 441 | pfw_cfg->chain_icd[ulp_num].chain_count; | ||
| 442 | |||
| 443 | beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_INIT, | ||
| 444 | "BG_%d : Function loaded on ULP : %d\n" | ||
| 445 | "\tiscsi_cid_count : %d\n" | ||
| 446 | "\tiscsi_cid_start : %d\n" | ||
| 447 | "\t iscsi_icd_count : %d\n" | ||
| 448 | "\t iscsi_icd_start : %d\n", | ||
| 449 | ulp_num, | ||
| 450 | phba->fw_config. | ||
| 451 | iscsi_cid_count[ulp_num], | ||
| 452 | phba->fw_config. | ||
| 453 | iscsi_cid_start[ulp_num], | ||
| 454 | phba->fw_config. | ||
| 455 | iscsi_icd_count[ulp_num], | ||
| 456 | phba->fw_config. | ||
| 457 | iscsi_icd_start[ulp_num]); | ||
| 458 | } | ||
| 459 | } | ||
| 460 | |||
| 461 | if (phba->fw_config.ulp_supported == 0) { | ||
| 462 | beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, | ||
| 463 | "BG_%d : iSCSI initiator mode not set: ULP0 %x ULP1 %x\n", | ||
| 464 | pfw_cfg->ulp[BEISCSI_ULP0].ulp_mode, | ||
| 465 | pfw_cfg->ulp[BEISCSI_ULP1].ulp_mode); | ||
| 466 | goto fail_init; | ||
| 467 | } | ||
| 468 | |||
| 469 | /** | ||
| 470 | * ICD is shared among ULPs. Use icd_count of any one loaded ULP | ||
| 471 | **/ | ||
| 472 | for (ulp_num = 0; ulp_num < BEISCSI_ULP_COUNT; ulp_num++) | ||
| 473 | if (test_bit(ulp_num, &phba->fw_config.ulp_supported)) | ||
| 474 | break; | ||
| 475 | icd_count = phba->fw_config.iscsi_icd_count[ulp_num]; | ||
| 476 | if (icd_count == 0 || icd_count > 65536) { | ||
| 477 | beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, | ||
| 478 | "BG_%d: invalid ICD count %d\n", icd_count); | ||
| 479 | goto fail_init; | ||
| 480 | } | ||
| 481 | |||
| 482 | cid_count = BEISCSI_GET_CID_COUNT(phba, BEISCSI_ULP0) + | ||
| 483 | BEISCSI_GET_CID_COUNT(phba, BEISCSI_ULP1); | ||
| 484 | if (cid_count == 0 || cid_count > 4096) { | ||
| 485 | beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, | ||
| 486 | "BG_%d: invalid CID count %d\n", cid_count); | ||
| 487 | goto fail_init; | ||
| 488 | } | ||
| 489 | |||
| 490 | /** | ||
| 491 | * Check FW is dual ULP aware i.e. can handle either | ||
| 492 | * of the protocols. | ||
| 493 | */ | ||
| 494 | phba->fw_config.dual_ulp_aware = (pfw_cfg->function_mode & | ||
| 495 | BEISCSI_FUNC_DUA_MODE); | ||
| 496 | |||
| 497 | beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_INIT, | ||
| 498 | "BG_%d : DUA Mode : 0x%x\n", | ||
| 499 | phba->fw_config.dual_ulp_aware); | ||
| 500 | |||
| 501 | /* all set, continue using this FW config */ | ||
| 502 | status = 0; | ||
| 503 | fail_init: | ||
| 504 | mutex_unlock(&ctrl->mbox_lock); | ||
| 505 | return status; | ||
| 506 | } | ||
| 507 | |||
| 508 | int mgmt_check_supported_fw(struct be_ctrl_info *ctrl, | ||
| 509 | struct beiscsi_hba *phba) | ||
| 510 | { | ||
| 511 | struct be_dma_mem nonemb_cmd; | ||
| 512 | struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem); | ||
| 513 | struct be_mgmt_controller_attributes *req; | ||
| 514 | struct be_sge *sge = nonembedded_sgl(wrb); | ||
| 515 | int status = 0; | ||
| 516 | |||
| 517 | nonemb_cmd.va = pci_alloc_consistent(ctrl->pdev, | ||
| 518 | sizeof(struct be_mgmt_controller_attributes), | ||
| 519 | &nonemb_cmd.dma); | ||
| 520 | if (nonemb_cmd.va == NULL) { | ||
| 521 | beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, | ||
| 522 | "BG_%d : Failed to allocate memory for " | ||
| 523 | "mgmt_check_supported_fw\n"); | ||
| 524 | return -ENOMEM; | ||
| 525 | } | ||
| 526 | nonemb_cmd.size = sizeof(struct be_mgmt_controller_attributes); | ||
| 527 | req = nonemb_cmd.va; | ||
| 528 | memset(req, 0, sizeof(*req)); | ||
| 529 | mutex_lock(&ctrl->mbox_lock); | ||
| 530 | memset(wrb, 0, sizeof(*wrb)); | ||
| 531 | be_wrb_hdr_prepare(wrb, sizeof(*req), false, 1); | ||
| 532 | be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, | ||
| 533 | OPCODE_COMMON_GET_CNTL_ATTRIBUTES, sizeof(*req)); | ||
| 534 | sge->pa_hi = cpu_to_le32(upper_32_bits(nonemb_cmd.dma)); | ||
| 535 | sge->pa_lo = cpu_to_le32(nonemb_cmd.dma & 0xFFFFFFFF); | ||
| 536 | sge->len = cpu_to_le32(nonemb_cmd.size); | ||
| 537 | status = be_mbox_notify(ctrl); | ||
| 538 | if (!status) { | ||
| 539 | struct be_mgmt_controller_attributes_resp *resp = nonemb_cmd.va; | ||
| 540 | beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_INIT, | ||
| 541 | "BG_%d : Firmware Version of CMD : %s\n" | ||
| 542 | "Firmware Version is : %s\n" | ||
| 543 | "Developer Build, not performing version check...\n", | ||
| 544 | resp->params.hba_attribs | ||
| 545 | .flashrom_version_string, | ||
| 546 | resp->params.hba_attribs. | ||
| 547 | firmware_version_string); | ||
| 548 | |||
| 549 | phba->fw_config.iscsi_features = | ||
| 550 | resp->params.hba_attribs.iscsi_features; | ||
| 551 | beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_INIT, | ||
| 552 | "BM_%d : phba->fw_config.iscsi_features = %d\n", | ||
| 553 | phba->fw_config.iscsi_features); | ||
| 554 | memcpy(phba->fw_ver_str, resp->params.hba_attribs. | ||
| 555 | firmware_version_string, BEISCSI_VER_STRLEN); | ||
| 556 | } else | ||
| 557 | beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, | ||
| 558 | "BG_%d : Failed in mgmt_check_supported_fw\n"); | ||
| 559 | mutex_unlock(&ctrl->mbox_lock); | ||
| 560 | if (nonemb_cmd.va) | ||
| 561 | pci_free_consistent(ctrl->pdev, nonemb_cmd.size, | ||
| 562 | nonemb_cmd.va, nonemb_cmd.dma); | ||
| 563 | |||
| 564 | return status; | ||
| 565 | } | ||
| 566 | |||
| 567 | unsigned int mgmt_vendor_specific_fw_cmd(struct be_ctrl_info *ctrl, | 64 | unsigned int mgmt_vendor_specific_fw_cmd(struct be_ctrl_info *ctrl, |
| 568 | struct beiscsi_hba *phba, | 65 | struct beiscsi_hba *phba, |
| 569 | struct bsg_job *job, | 66 | struct bsg_job *job, |
| @@ -609,7 +106,7 @@ unsigned int mgmt_vendor_specific_fw_cmd(struct be_ctrl_info *ctrl, · 39 unmodified lines | |||
| 609 | bsg_req->rqst_data.h_vendor.vendor_cmd[0]); | 106 | bsg_req->rqst_data.h_vendor.vendor_cmd[0]); |
| 610 | 107 | ||
| 611 | mutex_unlock(&ctrl->mbox_lock); | 108 | mutex_unlock(&ctrl->mbox_lock); |
| 612 | return -ENOSYS; | 109 | return -EPERM; |
| 613 | } | 110 | } |
| 614 | 111 | ||
| 615 | wrb = alloc_mcc_wrb(phba, &tag); | 112 | wrb = alloc_mcc_wrb(phba, &tag); |
| @@ -631,48 +128,6 @@ unsigned int mgmt_vendor_specific_fw_cmd(struct be_ctrl_info *ctrl, · 15 unmodified lines | |||
| 631 | return tag; | 128 | return tag; |
| 632 | } | 129 | } |
| 633 | 130 | ||
| 634 | /** | ||
| 635 | * mgmt_epfw_cleanup()- Inform FW to cleanup data structures. | ||
| 636 | * @phba: pointer to dev priv structure | ||
| 637 | * @ulp_num: ULP number. | ||
| 638 | * | ||
| 639 | * return | ||
| 640 | * Success: 0 | ||
| 641 | * Failure: Non-Zero Value | ||
| 642 | **/ | ||
| 643 | int mgmt_epfw_cleanup(struct beiscsi_hba *phba, unsigned short ulp_num) | ||
| 644 | { | ||
| 645 | struct be_ctrl_info *ctrl = &phba->ctrl; | ||
| 646 | struct be_mcc_wrb *wrb; | ||
| 647 | struct iscsi_cleanup_req *req; | ||
| 648 | unsigned int tag; | ||
| 649 | int status; | ||
| 650 | |||
| 651 | mutex_lock(&ctrl->mbox_lock); | ||
| 652 | wrb = alloc_mcc_wrb(phba, &tag); | ||
| 653 | if (!wrb) { | ||
| 654 | mutex_unlock(&ctrl->mbox_lock); | ||
| 655 | return -EBUSY; | ||
| 656 | } | ||
| 657 | |||
| 658 | req = embedded_payload(wrb); | ||
| 659 | be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); | ||
| 660 | be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ISCSI, | ||
| 661 | OPCODE_COMMON_ISCSI_CLEANUP, sizeof(*req)); | ||
| 662 | |||
| 663 | req->chute = (1 << ulp_num); | ||
| 664 | req->hdr_ring_id = cpu_to_le16(HWI_GET_DEF_HDRQ_ID(phba, ulp_num)); | ||
| 665 | req->data_ring_id = cpu_to_le16(HWI_GET_DEF_BUFQ_ID(phba, ulp_num)); | ||
| 666 | |||
| 667 | be_mcc_notify(phba, tag); | ||
| 668 | status = be_mcc_compl_poll(phba, tag); | ||
| 669 | if (status) | ||
| 670 | beiscsi_log(phba, KERN_WARNING, BEISCSI_LOG_INIT, | ||
| 671 | "BG_%d : mgmt_epfw_cleanup , FAILED\n"); | ||
| 672 | mutex_unlock(&ctrl->mbox_lock); | ||
| 673 | return status; | ||
| 674 | } | ||
| 675 | |||
| 676 | unsigned int mgmt_invalidate_icds(struct beiscsi_hba *phba, | 131 | unsigned int mgmt_invalidate_icds(struct beiscsi_hba *phba, |
| 677 | struct invalidate_command_table *inv_tbl, | 132 | struct invalidate_command_table *inv_tbl, |
| 678 | unsigned int num_invalidate, unsigned int cid, | 133 | unsigned int num_invalidate, unsigned int cid, |
| @@ -844,7 +299,7 @@ int mgmt_open_connection(struct beiscsi_hba *phba, · 165 unmodified lines | |||
| 844 | nonemb_cmd->size); | 299 | nonemb_cmd->size); |
| 845 | if (dst_addr->sa_family == PF_INET) { | 300 | if (dst_addr->sa_family == PF_INET) { |
| 846 | __be32 s_addr = daddr_in->sin_addr.s_addr; | 301 | __be32 s_addr = daddr_in->sin_addr.s_addr; |
| 847 | req->ip_address.ip_type = BE2_IPV4; | 302 | req->ip_address.ip_type = BEISCSI_IP_TYPE_V4; |
| 848 | req->ip_address.addr[0] = s_addr & 0x000000ff; | 303 | req->ip_address.addr[0] = s_addr & 0x000000ff; |
| 849 | req->ip_address.addr[1] = (s_addr & 0x0000ff00) >> 8; | 304 | req->ip_address.addr[1] = (s_addr & 0x0000ff00) >> 8; |
| 850 | req->ip_address.addr[2] = (s_addr & 0x00ff0000) >> 16; | 305 | req->ip_address.addr[2] = (s_addr & 0x00ff0000) >> 16; |
| @@ -852,17 +307,17 @@ int mgmt_open_connection(struct beiscsi_hba *phba, · 1 unmodified line | |||
| 852 | req->tcp_port = ntohs(daddr_in->sin_port); | 307 | req->tcp_port = ntohs(daddr_in->sin_port); |
| 853 | beiscsi_ep->dst_addr = daddr_in->sin_addr.s_addr; | 308 | beiscsi_ep->dst_addr = daddr_in->sin_addr.s_addr; |
| 854 | beiscsi_ep->dst_tcpport = ntohs(daddr_in->sin_port); | 309 | beiscsi_ep->dst_tcpport = ntohs(daddr_in->sin_port); |
| 855 | beiscsi_ep->ip_type = BE2_IPV4; | 310 | beiscsi_ep->ip_type = BEISCSI_IP_TYPE_V4; |
| 856 | } else { | 311 | } else { |
| 857 | /* else its PF_INET6 family */ | 312 | /* else its PF_INET6 family */ |
| 858 | req->ip_address.ip_type = BE2_IPV6; | 313 | req->ip_address.ip_type = BEISCSI_IP_TYPE_V6; |
| 859 | memcpy(&req->ip_address.addr, | 314 | memcpy(&req->ip_address.addr, |
| 860 | &daddr_in6->sin6_addr.in6_u.u6_addr8, 16); | 315 | &daddr_in6->sin6_addr.in6_u.u6_addr8, 16); |
| 861 | req->tcp_port = ntohs(daddr_in6->sin6_port); | 316 | req->tcp_port = ntohs(daddr_in6->sin6_port); |
| 862 | beiscsi_ep->dst_tcpport = ntohs(daddr_in6->sin6_port); | 317 | beiscsi_ep->dst_tcpport = ntohs(daddr_in6->sin6_port); |
| 863 | memcpy(&beiscsi_ep->dst6_addr, | 318 | memcpy(&beiscsi_ep->dst6_addr, |
| 864 | &daddr_in6->sin6_addr.in6_u.u6_addr8, 16); | 319 | &daddr_in6->sin6_addr.in6_u.u6_addr8, 16); |
| 865 | beiscsi_ep->ip_type = BE2_IPV6; | 320 | beiscsi_ep->ip_type = BEISCSI_IP_TYPE_V6; |
| 866 | } | 321 | } |
| 867 | req->cid = cid; | 322 | req->cid = cid; |
| 868 | i = phba->nxt_cqid++; | 323 | i = phba->nxt_cqid++; |
| @@ -883,7 +338,7 @@ int mgmt_open_connection(struct beiscsi_hba *phba, · 14 unmodified lines | |||
| 883 | 338 | ||
| 884 | if (!is_chip_be2_be3r(phba)) { | 339 | if (!is_chip_be2_be3r(phba)) { |
| 885 | req->hdr.version = MBX_CMD_VER1; | 340 | req->hdr.version = MBX_CMD_VER1; |
| 886 | req->tcp_window_size = 0; | 341 | req->tcp_window_size = 0x8000; |
| 887 | req->tcp_window_scale_count = 2; | 342 | req->tcp_window_scale_count = 2; |
| 888 | } | 343 | } |
| 889 | 344 | ||
| @@ -892,44 +347,6 @@ int mgmt_open_connection(struct beiscsi_hba *phba, · 2 unmodified lines | |||
| 892 | return tag; | 347 | return tag; |
| 893 | } | 348 | } |
| 894 | 349 | ||
| 895 | unsigned int mgmt_get_all_if_id(struct beiscsi_hba *phba) | ||
| 896 | { | ||
| 897 | struct be_ctrl_info *ctrl = &phba->ctrl; | ||
| 898 | struct be_mcc_wrb *wrb; | ||
| 899 | struct be_cmd_get_all_if_id_req *req; | ||
| 900 | struct be_cmd_get_all_if_id_req *pbe_allid; | ||
| 901 | unsigned int tag; | ||
| 902 | int status = 0; | ||
| 903 | |||
| 904 | if (mutex_lock_interruptible(&ctrl->mbox_lock)) | ||
| 905 | return -EINTR; | ||
| 906 | wrb = alloc_mcc_wrb(phba, &tag); | ||
| 907 | if (!wrb) { | ||
| 908 | mutex_unlock(&ctrl->mbox_lock); | ||
| 909 | return -ENOMEM; | ||
| 910 | } | ||
| 911 | |||
| 912 | req = embedded_payload(wrb); | ||
| 913 | be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); | ||
| 914 | be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ISCSI, | ||
| 915 | OPCODE_COMMON_ISCSI_NTWK_GET_ALL_IF_ID, | ||
| 916 | sizeof(*req)); | ||
| 917 | be_mcc_notify(phba, tag); | ||
| 918 | mutex_unlock(&ctrl->mbox_lock); | ||
| 919 | |||
| 920 | status = beiscsi_mccq_compl_wait(phba, tag, &wrb, NULL); | ||
| 921 | if (status) { | ||
| 922 | beiscsi_log(phba, KERN_WARNING, BEISCSI_LOG_CONFIG, | ||
| 923 | "BG_%d : Failed in mgmt_get_all_if_id\n"); | ||
| 924 | return -EBUSY; | ||
| 925 | } | ||
| 926 | |||
| 927 | pbe_allid = embedded_payload(wrb); | ||
| 928 | phba->interface_handle = pbe_allid->if_hndl_list[0]; | ||
| 929 | |||
| 930 | return status; | ||
| 931 | } | ||
| 932 | |||
| 933 | /* | 350 | /* |
| 934 | * mgmt_exec_nonemb_cmd()- Execute Non Embedded MBX Cmd | 351 | * mgmt_exec_nonemb_cmd()- Execute Non Embedded MBX Cmd |
| 935 | * @phba: Driver priv structure | 352 | * @phba: Driver priv structure |
| @@ -1001,72 +418,68 @@ static int mgmt_alloc_cmd_data(struct beiscsi_hba *phba, struct be_dma_mem *cmd, · 65 unmodified lines | |||
| 1001 | } | 418 | } |
| 1002 | cmd->size = size; | 419 | cmd->size = size; |
| 1003 | be_cmd_hdr_prepare(cmd->va, CMD_SUBSYSTEM_ISCSI, iscsi_cmd, size); | 420 | be_cmd_hdr_prepare(cmd->va, CMD_SUBSYSTEM_ISCSI, iscsi_cmd, size); |
| 421 | beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG, | ||
| 422 | "BG_%d : subsystem iSCSI cmd %d size %d\n", | ||
| 423 | iscsi_cmd, size); | ||
| 1004 | return 0; | 424 | return 0; |
| 1005 | } | 425 | } |
| 1006 | 426 | ||
| 1007 | static int | 427 | unsigned int beiscsi_if_get_handle(struct beiscsi_hba *phba) |
| 1008 | mgmt_static_ip_modify(struct beiscsi_hba *phba, | ||
| 1009 | struct be_cmd_get_if_info_resp *if_info, | ||
| 1010 | struct iscsi_iface_param_info *ip_param, | ||
| 1011 | struct iscsi_iface_param_info *subnet_param, | ||
| 1012 | uint32_t ip_action) | ||
| 1013 | { | 428 | { |
| 1014 | struct be_cmd_set_ip_addr_req *req; | 429 | struct be_ctrl_info *ctrl = &phba->ctrl; |
| 1015 | struct be_dma_mem nonemb_cmd; | 430 | struct be_mcc_wrb *wrb; |
| 1016 | uint32_t ip_type; | 431 | struct be_cmd_get_all_if_id_req *req; |
| 1017 | int rc; | 432 | struct be_cmd_get_all_if_id_req *pbe_allid; |
| 433 | unsigned int tag; | ||
| 434 | int status = 0; | ||
| 1018 | 435 | ||
| 1019 | rc = mgmt_alloc_cmd_data(phba, &nonemb_cmd, | 436 | if (mutex_lock_interruptible(&ctrl->mbox_lock)) |
| 1020 | OPCODE_COMMON_ISCSI_NTWK_MODIFY_IP_ADDR, | 437 | return -EINTR; |
| 1021 | sizeof(*req)); | 438 | wrb = alloc_mcc_wrb(phba, &tag); |
| 1022 | if (rc) | 439 | if (!wrb) { |
| 1023 | return rc; | 440 | mutex_unlock(&ctrl->mbox_lock); |
| 441 | return -ENOMEM; | ||
| 442 | } | ||
| 1024 | 443 | ||
| 1025 | ip_type = (ip_param->param == ISCSI_NET_PARAM_IPV6_ADDR) ? | 444 | req = embedded_payload(wrb); |
| 1026 | BE2_IPV6 : BE2_IPV4 ; | 445 | be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); |
| 446 | be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ISCSI, | ||
| 447 | OPCODE_COMMON_ISCSI_NTWK_GET_ALL_IF_ID, | ||
| 448 | sizeof(*req)); | ||
| 449 | be_mcc_notify(phba, tag); | ||
| 450 | mutex_unlock(&ctrl->mbox_lock); | ||
| 1027 | 451 | ||
| 1028 | req = nonemb_cmd.va; | 452 | status = beiscsi_mccq_compl_wait(phba, tag, &wrb, NULL); |
| 1029 | req->ip_params.record_entry_count = 1; | 453 | if (status) { |
| 1030 | req->ip_params.ip_record.action = ip_action; | 454 | beiscsi_log(phba, KERN_WARNING, BEISCSI_LOG_CONFIG, |
| 1031 | req->ip_params.ip_record.interface_hndl = | 455 | "BG_%d : %s failed: %d\n", __func__, status); |
| 1032 | phba->interface_handle; | 456 | return -EBUSY; |
| 1033 | req->ip_params.ip_record.ip_addr.size_of_structure = | 457 | } |
| 1034 | sizeof(struct be_ip_addr_subnet_format); | ||
| 1035 | req->ip_params.ip_record.ip_addr.ip_type = ip_type; | ||
| 1036 | 458 | ||
| 1037 | if (ip_action == IP_ACTION_ADD) { | 459 | pbe_allid = embedded_payload(wrb); |
| 1038 | memcpy(req->ip_params.ip_record.ip_addr.addr, ip_param->value, | 460 | /* we now support only one interface per function */ |
| 1039 | sizeof(req->ip_params.ip_record.ip_addr.addr)); | 461 | phba->interface_handle = pbe_allid->if_hndl_list[0]; |
| 1040 | 462 | ||
| 1041 | if (subnet_param) | 463 | return status; |
| 1042 | memcpy(req->ip_params.ip_record.ip_addr.subnet_mask, | 464 | } |
| 1043 | subnet_param->value, | ||
| 1044 | sizeof(req->ip_params.ip_record.ip_addr.subnet_mask)); | ||
| 1045 | } else { | ||
| 1046 | memcpy(req->ip_params.ip_record.ip_addr.addr, | ||
| 1047 | if_info->ip_addr.addr, | ||
| 1048 | sizeof(req->ip_params.ip_record.ip_addr.addr)); | ||
| 1049 | 465 | ||
| 1050 | memcpy(req->ip_params.ip_record.ip_addr.subnet_mask, | 466 | static inline bool beiscsi_if_zero_ip(u8 *ip, u32 ip_type) |
| 1051 | if_info->ip_addr.subnet_mask, | 467 | { |
| 1052 | sizeof(req->ip_params.ip_record.ip_addr.subnet_mask)); | 468 | u32 len; |
| 1053 | } | ||
| 1054 | 469 | ||
| 1055 | rc = mgmt_exec_nonemb_cmd(phba, &nonemb_cmd, NULL, 0); | 470 | len = (ip_type < BEISCSI_IP_TYPE_V6) ? IP_V4_LEN : IP_V6_LEN; |
| 1056 | if (rc < 0) | 471 | while (len && !ip[len - 1]) |
| 1057 | beiscsi_log(phba, KERN_WARNING, BEISCSI_LOG_CONFIG, | 472 | len--; |
| 1058 | "BG_%d : Failed to Modify existing IP Address\n"); | 473 | return (len == 0); |
| 1059 | return rc; | ||
| 1060 | } | 474 | } |
| 1061 | 475 | ||
| 1062 | static int mgmt_modify_gateway(struct beiscsi_hba *phba, uint8_t *gt_addr, | 476 | static int beiscsi_if_mod_gw(struct beiscsi_hba *phba, |
| 1063 | uint32_t gtway_action, uint32_t param_len) | 477 | u32 action, u32 ip_type, u8 *gw) |
| 1064 | { | 478 | { |
| 1065 | struct be_cmd_set_def_gateway_req *req; | 479 | struct be_cmd_set_def_gateway_req *req; |
| 1066 | struct be_dma_mem nonemb_cmd; | 480 | struct be_dma_mem nonemb_cmd; |
| 1067 | int rt_val; | 481 | int rt_val; |
| 1068 | 482 | ||
| 1069 | |||
| 1070 | rt_val = mgmt_alloc_cmd_data(phba, &nonemb_cmd, | 483 | rt_val = mgmt_alloc_cmd_data(phba, &nonemb_cmd, |
| 1071 | OPCODE_COMMON_ISCSI_NTWK_MODIFY_DEFAULT_GATEWAY, | 484 | OPCODE_COMMON_ISCSI_NTWK_MODIFY_DEFAULT_GATEWAY, |
| 1072 | sizeof(*req)); | 485 | sizeof(*req)); |
| @@ -1074,200 +487,300 @@ static int mgmt_modify_gateway(struct beiscsi_hba *phba, uint8_t *gt_addr, · 1 unmodified line | |||
| 1074 | return rt_val; | 487 | return rt_val; |
| 1075 | 488 | ||
| 1076 | req = nonemb_cmd.va; | 489 | req = nonemb_cmd.va; |
| 1077 | req->action = gtway_action; | 490 | req->action = action; |
| 1078 | req->ip_addr.ip_type = BE2_IPV4; | 491 | req->ip_addr.ip_type = ip_type; |
| 492 | memcpy(req->ip_addr.addr, gw, | ||
| 493 | (ip_type < BEISCSI_IP_TYPE_V6) ? IP_V4_LEN : IP_V6_LEN); | ||
| 494 | return mgmt_exec_nonemb_cmd(phba, &nonemb_cmd, NULL, 0); | ||
| 495 | } | ||
| 1079 | 496 | ||
| 1080 | memcpy(req->ip_addr.addr, gt_addr, sizeof(req->ip_addr.addr)); | 497 | int beiscsi_if_set_gw(struct beiscsi_hba *phba, u32 ip_type, u8 *gw) |
| 498 | { | ||
| 499 | struct be_cmd_get_def_gateway_resp gw_resp; | ||
| 500 | int rt_val; | ||
| 1081 | 501 | ||
| 1082 | return mgmt_exec_nonemb_cmd(phba, &nonemb_cmd, NULL, 0); | 502 | memset(&gw_resp, 0, sizeof(gw_resp)); |
| 503 | rt_val = beiscsi_if_get_gw(phba, ip_type, &gw_resp); | ||
| 504 | if (rt_val) { | ||
| 505 | beiscsi_log(phba, KERN_WARNING, BEISCSI_LOG_CONFIG, | ||
| 506 | "BG_%d : Failed to Get Gateway Addr\n"); | ||
| 507 | return rt_val; | ||
| 508 | } | ||
| 509 | |||
| 510 | if (!beiscsi_if_zero_ip(gw_resp.ip_addr.addr, ip_type)) { | ||
| 511 | rt_val = beiscsi_if_mod_gw(phba, IP_ACTION_DEL, ip_type, | ||
| 512 | gw_resp.ip_addr.addr); | ||
| 513 | if (rt_val) { | ||
| 514 | beiscsi_log(phba, KERN_WARNING, BEISCSI_LOG_CONFIG, | ||
| 515 | "BG_%d : Failed to clear Gateway Addr Set\n"); | ||
| 516 | return rt_val; | ||
| 517 | } | ||
| 518 | } | ||
| 519 | |||
| 520 | rt_val = beiscsi_if_mod_gw(phba, IP_ACTION_ADD, ip_type, gw); | ||
| 521 | if (rt_val) | ||
| 522 | beiscsi_log(phba, KERN_WARNING, BEISCSI_LOG_CONFIG, | ||
| 523 | "BG_%d : Failed to Set Gateway Addr\n"); | ||
| 524 | |||
| 525 | return rt_val; | ||
| 1083 | } | 526 | } |
| 1084 | 527 | ||
| 1085 | int mgmt_set_ip(struct beiscsi_hba *phba, | 528 | int beiscsi_if_get_gw(struct beiscsi_hba *phba, u32 ip_type, |
| 1086 | struct iscsi_iface_param_info *ip_param, | 529 | struct be_cmd_get_def_gateway_resp *resp) |
| 1087 | struct iscsi_iface_param_info *subnet_param, | ||
| 1088 | uint32_t boot_proto) | ||
| 1089 | { | 530 | { |
| 1090 | struct be_cmd_get_def_gateway_resp gtway_addr_set; | 531 | struct be_cmd_get_def_gateway_req *req; |
| 1091 | struct be_cmd_get_if_info_resp *if_info; | ||
| 1092 | struct be_cmd_set_dhcp_req *dhcpreq; | ||
| 1093 | struct be_cmd_rel_dhcp_req *reldhcp; | ||
| 1094 | struct be_dma_mem nonemb_cmd; | 532 | struct be_dma_mem nonemb_cmd; |
| 1095 | uint8_t *gtway_addr; | ||
| 1096 | uint32_t ip_type; | ||
| 1097 | int rc; | 533 | int rc; |
| 1098 | 534 | ||
| 1099 | rc = mgmt_get_all_if_id(phba); | 535 | rc = mgmt_alloc_cmd_data(phba, &nonemb_cmd, |
| 536 | OPCODE_COMMON_ISCSI_NTWK_GET_DEFAULT_GATEWAY, | ||
| 537 | sizeof(*resp)); | ||
| 1100 | if (rc) | 538 | if (rc) |
| 1101 | return rc; | 539 | return rc; |
| 1102 | 540 | ||
| 1103 | ip_type = (ip_param->param == ISCSI_NET_PARAM_IPV6_ADDR) ? | 541 | req = nonemb_cmd.va; |
| 1104 | BE2_IPV6 : BE2_IPV4 ; | 542 | req->ip_type = ip_type; |
| 543 | |||
| 544 | return mgmt_exec_nonemb_cmd(phba, &nonemb_cmd, resp, | ||
| 545 | sizeof(*resp)); | ||
| 546 | } | ||
| 1105 | 547 | ||
| 1106 | rc = mgmt_get_if_info(phba, ip_type, &if_info); | 548 | static int |
| 549 | beiscsi_if_clr_ip(struct beiscsi_hba *phba, | ||
| 550 | struct be_cmd_get_if_info_resp *if_info) | ||
| 551 | { | ||
| 552 | struct be_cmd_set_ip_addr_req *req; | ||
| 553 | struct be_dma_mem nonemb_cmd; | ||
| 554 | int rc; | ||
| 555 | |||
| 556 | rc = mgmt_alloc_cmd_data(phba, &nonemb_cmd, | ||
| 557 | OPCODE_COMMON_ISCSI_NTWK_MODIFY_IP_ADDR, | ||
| 558 | sizeof(*req)); | ||
| 1107 | if (rc) | 559 | if (rc) |
| 1108 | return rc; | 560 | return rc; |
| 1109 | 561 | ||
| 1110 | if (boot_proto == ISCSI_BOOTPROTO_DHCP) { | 562 | req = nonemb_cmd.va; |
| 1111 | if (if_info->dhcp_state) { | 563 | req->ip_params.record_entry_count = 1; |
| 1112 | beiscsi_log(phba, KERN_WARNING, BEISCSI_LOG_CONFIG, | 564 | req->ip_params.ip_record.action = IP_ACTION_DEL; |
| 1113 | "BG_%d : DHCP Already Enabled\n"); | 565 | req->ip_params.ip_record.interface_hndl = |
| 1114 | goto exit; | 566 | phba->interface_handle; |
| 1115 | } | 567 | req->ip_params.ip_record.ip_addr.size_of_structure = |
| 1116 | /* The ip_param->len is 1 in DHCP case. Setting | 568 | sizeof(struct be_ip_addr_subnet_format); |
| 1117 | proper IP len as this it is used while | 569 | req->ip_params.ip_record.ip_addr.ip_type = if_info->ip_addr.ip_type; |
| 1118 | freeing the Static IP. | 570 | memcpy(req->ip_params.ip_record.ip_addr.addr, |
| 1119 | */ | 571 | if_info->ip_addr.addr, |
| 1120 | ip_param->len = (ip_param->param == ISCSI_NET_PARAM_IPV6_ADDR) ? | 572 | sizeof(if_info->ip_addr.addr)); |
| 1121 | IP_V6_LEN : IP_V4_LEN; | 573 | memcpy(req->ip_params.ip_record.ip_addr.subnet_mask, |
| 1122 | 574 | if_info->ip_addr.subnet_mask, | |
| 1123 | } else { | 575 | sizeof(if_info->ip_addr.subnet_mask)); |
| 1124 | if (if_info->dhcp_state) { | 576 | rc = mgmt_exec_nonemb_cmd(phba, &nonemb_cmd, NULL, 0); |
| 577 | if (rc < 0 || req->ip_params.ip_record.status) { | ||
| 578 | beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG, | ||
| 579 | "BG_%d : failed to clear IP: rc %d status %d\n", | ||
| 580 | rc, req->ip_params.ip_record.status); | ||
| 581 | } | ||
| 582 | return rc; | ||
| 583 | } | ||
| 1125 | 584 | ||
| 1126 | memset(if_info, 0, sizeof(*if_info)); | 585 | static int |
| 1127 | rc = mgmt_alloc_cmd_data(phba, &nonemb_cmd, | 586 | beiscsi_if_set_ip(struct beiscsi_hba *phba, u8 *ip, |
| 1128 | OPCODE_COMMON_ISCSI_NTWK_REL_STATELESS_IP_ADDR, | 587 | u8 *subnet, u32 ip_type) |
| 1129 | sizeof(*reldhcp)); | 588 | { |
| 589 | struct be_cmd_set_ip_addr_req *req; | ||
| 590 | struct be_dma_mem nonemb_cmd; | ||
| 591 | uint32_t ip_len; | ||
| 592 | int rc; | ||
| 1130 | 593 | ||
| 1131 | if (rc) | 594 | rc = mgmt_alloc_cmd_data(phba, &nonemb_cmd, |
| 1132 | goto exit; | 595 | OPCODE_COMMON_ISCSI_NTWK_MODIFY_IP_ADDR, |
| 596 | sizeof(*req)); | ||
| 597 | if (rc) | ||
| 598 | return rc; | ||
| 1133 | 599 | ||
| 1134 | reldhcp = nonemb_cmd.va; | 600 | req = nonemb_cmd.va; |
| 1135 | reldhcp->interface_hndl = phba->interface_handle; | 601 | req->ip_params.record_entry_count = 1; |
| 1136 | reldhcp->ip_type = ip_type; | 602 | req->ip_params.ip_record.action = IP_ACTION_ADD; |
| 603 | req->ip_params.ip_record.interface_hndl = | ||
| 604 | phba->interface_handle; | ||
| 605 | req->ip_params.ip_record.ip_addr.size_of_structure = | ||
| 606 | sizeof(struct be_ip_addr_subnet_format); | ||
| 607 | req->ip_params.ip_record.ip_addr.ip_type = ip_type; | ||
| 608 | ip_len = (ip_type < BEISCSI_IP_TYPE_V6) ? IP_V4_LEN : IP_V6_LEN; | ||
| 609 | memcpy(req->ip_params.ip_record.ip_addr.addr, ip, ip_len); | ||
| 610 | if (subnet) | ||
| 611 | memcpy(req->ip_params.ip_record.ip_addr.subnet_mask, | ||
| 612 | subnet, ip_len); | ||
| 1137 | 613 | ||
| 1138 | rc = mgmt_exec_nonemb_cmd(phba, &nonemb_cmd, NULL, 0); | 614 | rc = mgmt_exec_nonemb_cmd(phba, &nonemb_cmd, NULL, 0); |
| 1139 | if (rc < 0) { | 615 | /** |
| 1140 | beiscsi_log(phba, KERN_WARNING, | 616 | * In some cases, host needs to look into individual record status |
| 1141 | BEISCSI_LOG_CONFIG, | 617 | * even though FW reported success for that IOCTL. |
| 1142 | "BG_%d : Failed to Delete existing dhcp\n"); | 618 | */ |
| 1143 | goto exit; | 619 | if (rc < 0 || req->ip_params.ip_record.status) { |
| 1144 | } | 620 | __beiscsi_log(phba, KERN_ERR, |
| 1145 | } | 621 | "BG_%d : failed to set IP: rc %d status %d\n", |
| 622 | rc, req->ip_params.ip_record.status); | ||
| 623 | if (req->ip_params.ip_record.status) | ||
| 624 | rc = -EINVAL; | ||
| 1146 | } | 625 | } |
| 626 | return rc; | ||
| 627 | } | ||
| 1147 | 628 | ||
| 1148 | /* Delete the Static IP Set */ | 629 | int beiscsi_if_en_static(struct beiscsi_hba *phba, u32 ip_type, |
| 1149 | if (if_info->ip_addr.addr[0]) { | 630 | u8 *ip, u8 *subnet) |
| 1150 | rc = mgmt_static_ip_modify(phba, if_info, ip_param, NULL, | 631 | { |
| 1151 | IP_ACTION_DEL); | 632 | struct be_cmd_get_if_info_resp *if_info; |
| 633 | struct be_cmd_rel_dhcp_req *reldhcp; | ||
| 634 | struct be_dma_mem nonemb_cmd; | ||
| 635 | int rc; | ||
| 636 | |||
| 637 | rc = beiscsi_if_get_info(phba, ip_type, &if_info); | ||
| 638 | if (rc) | ||
| 639 | return rc; | ||
| 640 | |||
| 641 | if (if_info->dhcp_state) { | ||
| 642 | rc = mgmt_alloc_cmd_data(phba, &nonemb_cmd, | ||
| 643 | OPCODE_COMMON_ISCSI_NTWK_REL_STATELESS_IP_ADDR, | ||
| 644 | sizeof(*reldhcp)); | ||
| 1152 | if (rc) | 645 | if (rc) |
| 1153 | goto exit; | 646 | goto exit; |
| 1154 | } | ||
| 1155 | 647 | ||
| 1156 | /* Delete the Gateway settings if mode change is to DHCP */ | 648 | reldhcp = nonemb_cmd.va; |
| 1157 | if (boot_proto == ISCSI_BOOTPROTO_DHCP) { | 649 | reldhcp->interface_hndl = phba->interface_handle; |
| 1158 | memset(>way_addr_set, 0, sizeof(gtway_addr_set)); | 650 | reldhcp->ip_type = ip_type; |
| 1159 | rc = mgmt_get_gateway(phba, BE2_IPV4, >way_addr_set); | 651 | rc = mgmt_exec_nonemb_cmd(phba, &nonemb_cmd, NULL, 0); |
| 1160 | if (rc) { | 652 | if (rc < 0) { |
| 1161 | beiscsi_log(phba, KERN_WARNING, BEISCSI_LOG_CONFIG, | 653 | beiscsi_log(phba, KERN_WARNING, BEISCSI_LOG_CONFIG, |
| 1162 | "BG_%d : Failed to Get Gateway Addr\n"); | 654 | "BG_%d : failed to release existing DHCP: %d\n", |
| 655 | rc); | ||
| 1163 | goto exit; | 656 | goto exit; |
| 1164 | } | 657 | } |
| 1165 | |||
| 1166 | if (gtway_addr_set.ip_addr.addr[0]) { | ||
| 1167 | gtway_addr = (uint8_t *)>way_addr_set.ip_addr.addr; | ||
| 1168 | rc = mgmt_modify_gateway(phba, gtway_addr, | ||
| 1169 | IP_ACTION_DEL, IP_V4_LEN); | ||
| 1170 | |||
| 1171 | if (rc) { | ||
| 1172 | beiscsi_log(phba, KERN_WARNING, | ||
| 1173 | BEISCSI_LOG_CONFIG, | ||
| 1174 | "BG_%d : Failed to clear Gateway Addr Set\n"); | ||
| 1175 | goto exit; | ||
| 1176 | } | ||
| 1177 | } | ||
| 1178 | } | 658 | } |
| 1179 | 659 | ||
| 1180 | /* Set Adapter to DHCP/Static Mode */ | 660 | /* first delete any IP set */ |
| 1181 | if (boot_proto == ISCSI_BOOTPROTO_DHCP) { | 661 | if (!beiscsi_if_zero_ip(if_info->ip_addr.addr, ip_type)) { |
| 1182 | rc = mgmt_alloc_cmd_data(phba, &nonemb_cmd, | 662 | rc = beiscsi_if_clr_ip(phba, if_info); |
| 1183 | OPCODE_COMMON_ISCSI_NTWK_CONFIG_STATELESS_IP_ADDR, | ||
| 1184 | sizeof(*dhcpreq)); | ||
| 1185 | if (rc) | 663 | if (rc) |
| 1186 | goto exit; | 664 | goto exit; |
| 1187 | |||
| 1188 | dhcpreq = nonemb_cmd.va; | ||
| 1189 | dhcpreq->flags = BLOCKING; | ||
| 1190 | dhcpreq->retry_count = 1; | ||
| 1191 | dhcpreq->interface_hndl = phba->interface_handle; | ||
| 1192 | dhcpreq->ip_type = BE2_DHCP_V4; | ||
| 1193 | |||
| 1194 | rc = mgmt_exec_nonemb_cmd(phba, &nonemb_cmd, NULL, 0); | ||
| 1195 | } else { | ||
| 1196 | rc = mgmt_static_ip_modify(phba, if_info, ip_param, | ||
| 1197 | subnet_param, IP_ACTION_ADD); | ||
| 1198 | } | 665 | } |
| 1199 | 666 | ||
| 667 | /* if ip == NULL then this is called just to release DHCP IP */ | ||
| 668 | if (ip) | ||
| 669 | rc = beiscsi_if_set_ip(phba, ip, subnet, ip_type); | ||
| 1200 | exit: | 670 | exit: |
| 1201 | kfree(if_info); | 671 | kfree(if_info); |
| 1202 | return rc; | 672 | return rc; |
| 1203 | } | 673 | } |
| 1204 | 674 | ||
| 1205 | int mgmt_set_gateway(struct beiscsi_hba *phba, | 675 | int beiscsi_if_en_dhcp(struct beiscsi_hba *phba, u32 ip_type) |
| 1206 | struct iscsi_iface_param_info *gateway_param) | ||
| 1207 | { | 676 | { |
| 1208 | struct be_cmd_get_def_gateway_resp gtway_addr_set; | 677 | struct be_cmd_get_def_gateway_resp gw_resp; |
| 1209 | uint8_t *gtway_addr; | 678 | struct be_cmd_get_if_info_resp *if_info; |
| 1210 | int rt_val; | 679 | struct be_cmd_set_dhcp_req *dhcpreq; |
| 680 | struct be_dma_mem nonemb_cmd; | ||
| 681 | u8 *gw; | ||
| 682 | int rc; | ||
| 1211 | 683 | ||
| 1212 | memset(>way_addr_set, 0, sizeof(gtway_addr_set)); | 684 | rc = beiscsi_if_get_info(phba, ip_type, &if_info); |
| 1213 | rt_val = mgmt_get_gateway(phba, BE2_IPV4, >way_addr_set); | 685 | if (rc) |
| 1214 | if (rt_val) { | 686 | return rc; |
| 687 | |||
| 688 | if (if_info->dhcp_state) { | ||
| 1215 | beiscsi_log(phba, KERN_WARNING, BEISCSI_LOG_CONFIG, | 689 | beiscsi_log(phba, KERN_WARNING, BEISCSI_LOG_CONFIG, |
| 1216 | "BG_%d : Failed to Get Gateway Addr\n"); | 690 | "BG_%d : DHCP Already Enabled\n"); |
| 1217 | return rt_val; | 691 | goto exit; |
| 1218 | } | 692 | } |
| 1219 | 693 | ||
| 1220 | if (gtway_addr_set.ip_addr.addr[0]) { | 694 | /* first delete any IP set */ |
| 1221 | gtway_addr = (uint8_t *)>way_addr_set.ip_addr.addr; | 695 | if (!beiscsi_if_zero_ip(if_info->ip_addr.addr, ip_type)) { |
| 1222 | rt_val = mgmt_modify_gateway(phba, gtway_addr, IP_ACTION_DEL, | 696 | rc = beiscsi_if_clr_ip(phba, if_info); |
| 1223 | gateway_param->len); | 697 | if (rc) |
| 1224 | if (rt_val) { | 698 | goto exit; |
| 699 | } | ||
| 700 | |||
| 701 | /* delete gateway settings if mode change is to DHCP */ | ||
| 702 | memset(&gw_resp, 0, sizeof(gw_resp)); | ||
| 703 | /* use ip_type provided in if_info */ | ||
| 704 | rc = beiscsi_if_get_gw(phba, if_info->ip_addr.ip_type, &gw_resp); | ||
| 705 | if (rc) { | ||
| 706 | beiscsi_log(phba, KERN_WARNING, BEISCSI_LOG_CONFIG, | ||
| 707 | "BG_%d : Failed to Get Gateway Addr\n"); | ||
| 708 | goto exit; | ||
| 709 | } | ||
| 710 | gw = (u8 *)&gw_resp.ip_addr.addr; | ||
| 711 | if (!beiscsi_if_zero_ip(gw, if_info->ip_addr.ip_type)) { | ||
| 712 | rc = beiscsi_if_mod_gw(phba, IP_ACTION_DEL, | ||
| 713 | if_info->ip_addr.ip_type, gw); | ||
| 714 | if (rc) { | ||
| 1225 | beiscsi_log(phba, KERN_WARNING, BEISCSI_LOG_CONFIG, | 715 | beiscsi_log(phba, KERN_WARNING, BEISCSI_LOG_CONFIG, |
| 1226 | "BG_%d : Failed to clear Gateway Addr Set\n"); | 716 | "BG_%d : Failed to clear Gateway Addr Set\n"); |
| 1227 | return rt_val; | 717 | goto exit; |
| 1228 | } | 718 | } |
| 1229 | } | 719 | } |
| 1230 | 720 | ||
| 1231 | gtway_addr = (uint8_t *)&gateway_param->value; | 721 | rc = mgmt_alloc_cmd_data(phba, &nonemb_cmd, |
| 1232 | rt_val = mgmt_modify_gateway(phba, gtway_addr, IP_ACTION_ADD, | 722 | OPCODE_COMMON_ISCSI_NTWK_CONFIG_STATELESS_IP_ADDR, |
| 1233 | gateway_param->len); | 723 | sizeof(*dhcpreq)); |
| 724 | if (rc) | ||
| 725 | goto exit; | ||
| 1234 | 726 | ||
| 1235 | if (rt_val) | 727 | dhcpreq = nonemb_cmd.va; |
| 1236 | beiscsi_log(phba, KERN_WARNING, BEISCSI_LOG_CONFIG, | 728 | dhcpreq->flags = 1; /* 1 - blocking; 0 - non-blocking */ |
| 1237 | "BG_%d : Failed to Set Gateway Addr\n"); | 729 | dhcpreq->retry_count = 1; |
| 730 | dhcpreq->interface_hndl = phba->interface_handle; | ||
| 731 | dhcpreq->ip_type = ip_type; | ||
| 732 | rc = mgmt_exec_nonemb_cmd(phba, &nonemb_cmd, NULL, 0); | ||
| 1238 | 733 | ||
| 1239 | return rt_val; | 734 | exit: |
| 735 | kfree(if_info); | ||
| 736 | return rc; | ||
| 1240 | } | 737 | } |
| 1241 | 738 | ||
| 1242 | int mgmt_get_gateway(struct beiscsi_hba *phba, int ip_type, | 739 | /** |
| 1243 | struct be_cmd_get_def_gateway_resp *gateway) | 740 | * beiscsi_if_set_vlan()- Issue and wait for CMD completion |
| 741 | * @phba: device private structure instance | ||
| 742 | * @vlan_tag: VLAN tag | ||
| 743 | * | ||
| 744 | * Issue the MBX Cmd and wait for the completion of the | ||
| 745 | * command. | ||
| 746 | * | ||
| 747 | * returns | ||
| 748 | * Success: 0 | ||
| 749 | * Failure: Non-Xero Value | ||
| 750 | **/ | ||
| 751 | int beiscsi_if_set_vlan(struct beiscsi_hba *phba, uint16_t vlan_tag) | ||
| 1244 | { | 752 | { |
| 1245 | struct be_cmd_get_def_gateway_req *req; | ||
| 1246 | struct be_dma_mem nonemb_cmd; | ||
| 1247 | int rc; | 753 | int rc; |
| 754 | unsigned int tag; | ||
| 1248 | 755 | ||
| 1249 | rc = mgmt_alloc_cmd_data(phba, &nonemb_cmd, | 756 | tag = be_cmd_set_vlan(phba, vlan_tag); |
| 1250 | OPCODE_COMMON_ISCSI_NTWK_GET_DEFAULT_GATEWAY, | 757 | if (!tag) { |
| 1251 | sizeof(*gateway)); | 758 | beiscsi_log(phba, KERN_ERR, |
| 1252 | if (rc) | 759 | (BEISCSI_LOG_CONFIG | BEISCSI_LOG_MBOX), |
| 1253 | return rc; | 760 | "BG_%d : VLAN Setting Failed\n"); |
| 1254 | 761 | return -EBUSY; | |
| 1255 | req = nonemb_cmd.va; | 762 | } |
| 1256 | req->ip_type = ip_type; | ||
| 1257 | 763 | ||
| 1258 | return mgmt_exec_nonemb_cmd(phba, &nonemb_cmd, gateway, | 764 | rc = beiscsi_mccq_compl_wait(phba, tag, NULL, NULL); |
| 1259 | sizeof(*gateway)); | 765 | if (rc) { |
| 766 | beiscsi_log(phba, KERN_ERR, | ||
| 767 | (BEISCSI_LOG_CONFIG | BEISCSI_LOG_MBOX), | ||
| 768 | "BS_%d : VLAN MBX Cmd Failed\n"); | ||
| 769 | return rc; | ||
| 770 | } | ||
| 771 | return rc; | ||
| 1260 | } | 772 | } |
| 1261 | 773 | ||
| 1262 | int mgmt_get_if_info(struct beiscsi_hba *phba, int ip_type, | 774 | |
| 1263 | struct be_cmd_get_if_info_resp **if_info) | 775 | int beiscsi_if_get_info(struct beiscsi_hba *phba, int ip_type, |
| 776 | struct be_cmd_get_if_info_resp **if_info) | ||
| 1264 | { | 777 | { |
| 1265 | struct be_cmd_get_if_info_req *req; | 778 | struct be_cmd_get_if_info_req *req; |
| 1266 | struct be_dma_mem nonemb_cmd; | 779 | struct be_dma_mem nonemb_cmd; |
| 1267 | uint32_t ioctl_size = sizeof(struct be_cmd_get_if_info_resp); | 780 | uint32_t ioctl_size = sizeof(struct be_cmd_get_if_info_resp); |
| 1268 | int rc; | 781 | int rc; |
| 1269 | 782 | ||
| 1270 | rc = mgmt_get_all_if_id(phba); | 783 | rc = beiscsi_if_get_handle(phba); |
| 1271 | if (rc) | 784 | if (rc) |
| 1272 | return rc; | 785 | return rc; |
| 1273 | 786 | ||
| @@ -1364,123 +877,317 @@ unsigned int be_cmd_get_initname(struct beiscsi_hba *phba) · 90 unmodified lines | |||
| 1364 | return tag; | 877 | return tag; |
| 1365 | } | 878 | } |
| 1366 | 879 | ||
| 880 | static void beiscsi_boot_process_compl(struct beiscsi_hba *phba, | ||
| 881 | unsigned int tag) | ||
| 882 | { | ||
| 883 | struct be_cmd_get_boot_target_resp *boot_resp; | ||
| 884 | struct be_cmd_resp_logout_fw_sess *logo_resp; | ||
| 885 | struct be_cmd_get_session_resp *sess_resp; | ||
| 886 | struct be_mcc_wrb *wrb; | ||
| 887 | struct boot_struct *bs; | ||
| 888 | int boot_work, status; | ||
| 889 | |||
| 890 | if (!test_bit(BEISCSI_HBA_BOOT_WORK, &phba->state)) { | ||
| 891 | __beiscsi_log(phba, KERN_ERR, | ||
| 892 | "BG_%d : %s no boot work %lx\n", | ||
| 893 | __func__, phba->state); | ||
| 894 | return; | ||
| 895 | } | ||
| 896 | |||
| 897 | if (phba->boot_struct.tag != tag) { | ||
| 898 | __beiscsi_log(phba, KERN_ERR, | ||
| 899 | "BG_%d : %s tag mismatch %d:%d\n", | ||
| 900 | __func__, tag, phba->boot_struct.tag); | ||
| 901 | return; | ||
| 902 | } | ||
| 903 | bs = &phba->boot_struct; | ||
| 904 | boot_work = 1; | ||
| 905 | status = 0; | ||
| 906 | switch (bs->action) { | ||
| 907 | case BEISCSI_BOOT_REOPEN_SESS: | ||
| 908 | status = __beiscsi_mcc_compl_status(phba, tag, NULL, NULL); | ||
| 909 | if (!status) | ||
| 910 | bs->action = BEISCSI_BOOT_GET_SHANDLE; | ||
| 911 | else | ||
| 912 | bs->retry--; | ||
| 913 | break; | ||
| 914 | case BEISCSI_BOOT_GET_SHANDLE: | ||
| 915 | status = __beiscsi_mcc_compl_status(phba, tag, &wrb, NULL); | ||
| 916 | if (!status) { | ||
| 917 | boot_resp = embedded_payload(wrb); | ||
| 918 | bs->s_handle = boot_resp->boot_session_handle; | ||
| 919 | } | ||
| 920 | if (bs->s_handle == BE_BOOT_INVALID_SHANDLE) { | ||
| 921 | bs->action = BEISCSI_BOOT_REOPEN_SESS; | ||
| 922 | bs->retry--; | ||
| 923 | } else { | ||
| 924 | bs->action = BEISCSI_BOOT_GET_SINFO; | ||
| 925 | } | ||
| 926 | break; | ||
| 927 | case BEISCSI_BOOT_GET_SINFO: | ||
| 928 | status = __beiscsi_mcc_compl_status(phba, tag, NULL, | ||
| 929 | &bs->nonemb_cmd); | ||
| 930 | if (!status) { | ||
| 931 | sess_resp = bs->nonemb_cmd.va; | ||
| 932 | memcpy(&bs->boot_sess, &sess_resp->session_info, | ||
| 933 | sizeof(struct mgmt_session_info)); | ||
| 934 | bs->action = BEISCSI_BOOT_LOGOUT_SESS; | ||
| 935 | } else { | ||
| 936 | __beiscsi_log(phba, KERN_ERR, | ||
| 937 | "BG_%d : get boot session info error : 0x%x\n", | ||
| 938 | status); | ||
| 939 | boot_work = 0; | ||
| 940 | } | ||
| 941 | pci_free_consistent(phba->ctrl.pdev, bs->nonemb_cmd.size, | ||
| 942 | bs->nonemb_cmd.va, bs->nonemb_cmd.dma); | ||
| 943 | bs->nonemb_cmd.va = NULL; | ||
| 944 | break; | ||
| 945 | case BEISCSI_BOOT_LOGOUT_SESS: | ||
| 946 | status = __beiscsi_mcc_compl_status(phba, tag, &wrb, NULL); | ||
| 947 | if (!status) { | ||
| 948 | logo_resp = embedded_payload(wrb); | ||
| 949 | if (logo_resp->session_status != BE_SESS_STATUS_CLOSE) { | ||
| 950 | __beiscsi_log(phba, KERN_ERR, | ||
| 951 | "BG_%d : FW boot session logout error : 0x%x\n", | ||
| 952 | logo_resp->session_status); | ||
| 953 | } | ||
| 954 | } | ||
| 955 | /* continue to create boot_kset even if logout failed? */ | ||
| 956 | bs->action = BEISCSI_BOOT_CREATE_KSET; | ||
| 957 | break; | ||
| 958 | default: | ||
| 959 | break; | ||
| 960 | } | ||
| 961 | |||
| 962 | /* clear the tag so no other completion matches this tag */ | ||
| 963 | bs->tag = 0; | ||
| 964 | if (!bs->retry) { | ||
| 965 | boot_work = 0; | ||
| 966 | __beiscsi_log(phba, KERN_ERR, | ||
| 967 | "BG_%d : failed to setup boot target: status %d action %d\n", | ||
| 968 | status, bs->action); | ||
| 969 | } | ||
| 970 | if (!boot_work) { | ||
| 971 | /* wait for next event to start boot_work */ | ||
| 972 | clear_bit(BEISCSI_HBA_BOOT_WORK, &phba->state); | ||
| 973 | return; | ||
| 974 | } | ||
| 975 | schedule_work(&phba->boot_work); | ||
| 976 | } | ||
| 977 | |||
| 1367 | /** | 978 | /** |
| 1368 | * be_mgmt_get_boot_shandle()- Get the session handle | 979 | * beiscsi_boot_logout_sess()- Logout from boot FW session |
| 1369 | * @phba: device priv structure instance | 980 | * @phba: Device priv structure instance |
| 1370 | * @s_handle: session handle returned for boot session. | 981 | * |
| 982 | * return | ||
| 983 | * the TAG used for MBOX Command | ||
| 1371 | * | 984 | * |
| 1372 | * Get the boot target session handle. In case of | 985 | */ |
| 1373 | * crashdump mode driver has to issue and MBX Cmd | 986 | unsigned int beiscsi_boot_logout_sess(struct beiscsi_hba *phba) |
| 1374 | * for FW to login to boot target | 987 | { |
| 988 | struct be_ctrl_info *ctrl = &phba->ctrl; | ||
| 989 | struct be_mcc_wrb *wrb; | ||
| 990 | struct be_cmd_req_logout_fw_sess *req; | ||
| 991 | unsigned int tag; | ||
| 992 | |||
| 993 | mutex_lock(&ctrl->mbox_lock); | ||
| 994 | wrb = alloc_mcc_wrb(phba, &tag); | ||
| 995 | if (!wrb) { | ||
| 996 | mutex_unlock(&ctrl->mbox_lock); | ||
| 997 | return 0; | ||
| 998 | } | ||
| 999 | |||
| 1000 | req = embedded_payload(wrb); | ||
| 1001 | be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); | ||
| 1002 | be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ISCSI_INI, | ||
| 1003 | OPCODE_ISCSI_INI_SESSION_LOGOUT_TARGET, | ||
| 1004 | sizeof(struct be_cmd_req_logout_fw_sess)); | ||
| 1005 | /* Use the session handle copied into boot_sess */ | ||
| 1006 | req->session_handle = phba->boot_struct.boot_sess.session_handle; | ||
| 1007 | |||
| 1008 | phba->boot_struct.tag = tag; | ||
| 1009 | set_bit(MCC_TAG_STATE_ASYNC, &ctrl->ptag_state[tag].tag_state); | ||
| 1010 | ctrl->ptag_state[tag].cbfn = beiscsi_boot_process_compl; | ||
| 1011 | |||
| 1012 | be_mcc_notify(phba, tag); | ||
| 1013 | mutex_unlock(&ctrl->mbox_lock); | ||
| 1014 | |||
| 1015 | return tag; | ||
| 1016 | } | ||
| 1017 | /** | ||
| 1018 | * beiscsi_boot_reopen_sess()- Reopen boot session | ||
| 1019 | * @phba: Device priv structure instance | ||
| 1375 | * | 1020 | * |
| 1376 | * return | 1021 | * return |
| 1377 | * Success: 0 | 1022 | * the TAG used for MBOX Command |
| 1378 | * Failure: Non-Zero value | ||
| 1379 | * | 1023 | * |
| 1380 | **/ | 1024 | **/ |
| 1381 | int be_mgmt_get_boot_shandle(struct beiscsi_hba *phba, | 1025 | unsigned int beiscsi_boot_reopen_sess(struct beiscsi_hba *phba) |
| 1382 | unsigned int *s_handle) | ||
| 1383 | { | 1026 | { |
| 1384 | struct be_cmd_get_boot_target_resp *boot_resp; | 1027 | struct be_ctrl_info *ctrl = &phba->ctrl; |
| 1385 | struct be_mcc_wrb *wrb; | 1028 | struct be_mcc_wrb *wrb; |
| 1029 | struct be_cmd_reopen_session_req *req; | ||
| 1386 | unsigned int tag; | 1030 | unsigned int tag; |
| 1387 | uint8_t boot_retry = 3; | ||
| 1388 | int rc; | ||
| 1389 | 1031 | ||
| 1390 | do { | 1032 | mutex_lock(&ctrl->mbox_lock); |
| 1391 | /* Get the Boot Target Session Handle and Count*/ | 1033 | wrb = alloc_mcc_wrb(phba, &tag); |
| 1392 | tag = mgmt_get_boot_target(phba); | 1034 | if (!wrb) { |
| 1393 | if (!tag) { | 1035 | mutex_unlock(&ctrl->mbox_lock); |
| 1394 | beiscsi_log(phba, KERN_ERR, | 1036 | return 0; |
| 1395 | BEISCSI_LOG_CONFIG | BEISCSI_LOG_INIT, | 1037 | } |
| 1396 | "BG_%d : Getting Boot Target Info Failed\n"); | ||
| 1397 | return -EAGAIN; | ||
| 1398 | } | ||
| 1399 | 1038 | ||
| 1400 | rc = beiscsi_mccq_compl_wait(phba, tag, &wrb, NULL); | 1039 | req = embedded_payload(wrb); |
| 1401 | if (rc) { | 1040 | be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); |
| 1402 | beiscsi_log(phba, KERN_ERR, | 1041 | be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ISCSI_INI, |
| 1403 | BEISCSI_LOG_INIT | BEISCSI_LOG_CONFIG, | 1042 | OPCODE_ISCSI_INI_DRIVER_REOPEN_ALL_SESSIONS, |
| 1404 | "BG_%d : MBX CMD get_boot_target Failed\n"); | 1043 | sizeof(struct be_cmd_reopen_session_resp)); |
| 1405 | return -EBUSY; | 1044 | req->reopen_type = BE_REOPEN_BOOT_SESSIONS; |
| 1406 | } | 1045 | req->session_handle = BE_BOOT_INVALID_SHANDLE; |
| 1407 | 1046 | ||
| 1408 | boot_resp = embedded_payload(wrb); | 1047 | phba->boot_struct.tag = tag; |
| 1048 | set_bit(MCC_TAG_STATE_ASYNC, &ctrl->ptag_state[tag].tag_state); | ||
| 1049 | ctrl->ptag_state[tag].cbfn = beiscsi_boot_process_compl; | ||
| 1409 | 1050 | ||
| 1410 | /* Check if the there are any Boot targets configured */ | 1051 | be_mcc_notify(phba, tag); |
| 1411 | if (!boot_resp->boot_session_count) { | 1052 | mutex_unlock(&ctrl->mbox_lock); |
| 1412 | beiscsi_log(phba, KERN_INFO, | 1053 | return tag; |
| 1413 | BEISCSI_LOG_INIT | BEISCSI_LOG_CONFIG, | 1054 | } |
| 1414 | "BG_%d ;No boot targets configured\n"); | ||
| 1415 | return -ENXIO; | ||
| 1416 | } | ||
| 1417 | 1055 | ||
| 1418 | /* FW returns the session handle of the boot session */ | ||
| 1419 | if (boot_resp->boot_session_handle != INVALID_SESS_HANDLE) { | ||
| 1420 | *s_handle = boot_resp->boot_session_handle; | ||
| 1421 | return 0; | ||
| 1422 | } | ||
| 1423 | 1056 | ||
| 1424 | /* Issue MBX Cmd to FW to login to the boot target */ | 1057 | /** |
| 1425 | tag = mgmt_reopen_session(phba, BE_REOPEN_BOOT_SESSIONS, | 1058 | * beiscsi_boot_get_sinfo()- Get boot session info |
| 1426 | INVALID_SESS_HANDLE); | 1059 | * @phba: device priv structure instance |
| 1427 | if (!tag) { | 1060 | * |
| 1428 | beiscsi_log(phba, KERN_ERR, | 1061 | * Fetches the boot_struct.s_handle info from FW. |
| 1429 | BEISCSI_LOG_INIT | BEISCSI_LOG_CONFIG, | 1062 | * return |
| 1430 | "BG_%d : mgmt_reopen_session Failed\n"); | 1063 | * the TAG used for MBOX Command |
| 1431 | return -EAGAIN; | 1064 | * |
| 1432 | } | 1065 | **/ |
| 1066 | unsigned int beiscsi_boot_get_sinfo(struct beiscsi_hba *phba) | ||
| 1067 | { | ||
| 1068 | struct be_ctrl_info *ctrl = &phba->ctrl; | ||
| 1069 | struct be_cmd_get_session_resp *resp; | ||
| 1070 | struct be_cmd_get_session_req *req; | ||
| 1071 | struct be_dma_mem *nonemb_cmd; | ||
| 1072 | struct be_mcc_wrb *wrb; | ||
| 1073 | struct be_sge *sge; | ||
| 1074 | unsigned int tag; | ||
| 1433 | 1075 | ||
| 1434 | rc = beiscsi_mccq_compl_wait(phba, tag, NULL, NULL); | 1076 | mutex_lock(&ctrl->mbox_lock); |
| 1435 | if (rc) { | 1077 | wrb = alloc_mcc_wrb(phba, &tag); |
| 1436 | beiscsi_log(phba, KERN_ERR, | 1078 | if (!wrb) { |
| 1437 | BEISCSI_LOG_INIT | BEISCSI_LOG_CONFIG, | 1079 | mutex_unlock(&ctrl->mbox_lock); |
| 1438 | "BG_%d : mgmt_reopen_session Failed"); | 1080 | return 0; |
| 1439 | return rc; | 1081 | } |
| 1440 | } | 1082 | |
| 1441 | } while (--boot_retry); | 1083 | nonemb_cmd = &phba->boot_struct.nonemb_cmd; |
| 1084 | nonemb_cmd->size = sizeof(*resp); | ||
| 1085 | nonemb_cmd->va = pci_alloc_consistent(phba->ctrl.pdev, | ||
| 1086 | sizeof(nonemb_cmd->size), | ||
| 1087 | &nonemb_cmd->dma); | ||
| 1088 | if (!nonemb_cmd->va) { | ||
| 1089 | mutex_unlock(&ctrl->mbox_lock); | ||
| 1090 | return 0; | ||
| 1091 | } | ||
| 1092 | |||
| 1093 | req = nonemb_cmd->va; | ||
| 1094 | memset(req, 0, sizeof(*req)); | ||
| 1095 | sge = nonembedded_sgl(wrb); | ||
| 1096 | be_wrb_hdr_prepare(wrb, sizeof(*req), false, 1); | ||
| 1097 | be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ISCSI_INI, | ||
| 1098 | OPCODE_ISCSI_INI_SESSION_GET_A_SESSION, | ||
| 1099 | sizeof(*resp)); | ||
| 1100 | req->session_handle = phba->boot_struct.s_handle; | ||
| 1101 | sge->pa_hi = cpu_to_le32(upper_32_bits(nonemb_cmd->dma)); | ||
| 1102 | sge->pa_lo = cpu_to_le32(nonemb_cmd->dma & 0xFFFFFFFF); | ||
| 1103 | sge->len = cpu_to_le32(nonemb_cmd->size); | ||
| 1104 | |||
| 1105 | phba->boot_struct.tag = tag; | ||
| 1106 | set_bit(MCC_TAG_STATE_ASYNC, &ctrl->ptag_state[tag].tag_state); | ||
| 1107 | ctrl->ptag_state[tag].cbfn = beiscsi_boot_process_compl; | ||
| 1108 | |||
| 1109 | be_mcc_notify(phba, tag); | ||
| 1110 | mutex_unlock(&ctrl->mbox_lock); | ||
| 1111 | return tag; | ||
| 1112 | } | ||
| 1113 | |||
| 1114 | unsigned int __beiscsi_boot_get_shandle(struct beiscsi_hba *phba, int async) | ||
| 1115 | { | ||
| 1116 | struct be_ctrl_info *ctrl = &phba->ctrl; | ||
| 1117 | struct be_mcc_wrb *wrb; | ||
| 1118 | struct be_cmd_get_boot_target_req *req; | ||
| 1119 | unsigned int tag; | ||
| 1120 | |||
| 1121 | mutex_lock(&ctrl->mbox_lock); | ||
| 1122 | wrb = alloc_mcc_wrb(phba, &tag); | ||
| 1123 | if (!wrb) { | ||
| 1124 | mutex_unlock(&ctrl->mbox_lock); | ||
| 1125 | return 0; | ||
| 1126 | } | ||
| 1127 | |||
| 1128 | req = embedded_payload(wrb); | ||
| 1129 | be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); | ||
| 1130 | be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ISCSI_INI, | ||
| 1131 | OPCODE_ISCSI_INI_BOOT_GET_BOOT_TARGET, | ||
| 1132 | sizeof(struct be_cmd_get_boot_target_resp)); | ||
| 1442 | 1133 | ||
| 1443 | /* Couldn't log into the boot target */ | 1134 | if (async) { |
| 1444 | beiscsi_log(phba, KERN_ERR, | 1135 | phba->boot_struct.tag = tag; |
| 1445 | BEISCSI_LOG_INIT | BEISCSI_LOG_CONFIG, | 1136 | set_bit(MCC_TAG_STATE_ASYNC, &ctrl->ptag_state[tag].tag_state); |
| 1446 | "BG_%d : Login to Boot Target Failed\n"); | 1137 | ctrl->ptag_state[tag].cbfn = beiscsi_boot_process_compl; |
| 1447 | return -ENXIO; | 1138 | } |
| 1139 | |||
| 1140 | be_mcc_notify(phba, tag); | ||
| 1141 | mutex_unlock(&ctrl->mbox_lock); | ||
| 1142 | return tag; | ||
| 1448 | } | 1143 | } |
| 1449 | 1144 | ||
| 1450 | /** | 1145 | /** |
| 1451 | * mgmt_set_vlan()- Issue and wait for CMD completion | 1146 | * beiscsi_boot_get_shandle()- Get boot session handle |
| 1452 | * @phba: device private structure instance | 1147 | * @phba: device priv structure instance |
| 1453 | * @vlan_tag: VLAN tag | 1148 | * @s_handle: session handle returned for boot session. |
| 1454 | * | 1149 | * |
| 1455 | * Issue the MBX Cmd and wait for the completion of the | 1150 | * return |
| 1456 | * command. | 1151 | * Success: 1 |
| 1152 | * Failure: negative | ||
| 1457 | * | 1153 | * |
| 1458 | * returns | ||
| 1459 | * Success: 0 | ||
| 1460 | * Failure: Non-Xero Value | ||
| 1461 | **/ | 1154 | **/ |
| 1462 | int mgmt_set_vlan(struct beiscsi_hba *phba, | 1155 | int beiscsi_boot_get_shandle(struct beiscsi_hba *phba, unsigned int *s_handle) |
| 1463 | uint16_t vlan_tag) | ||
| 1464 | { | 1156 | { |
| 1465 | int rc; | 1157 | struct be_cmd_get_boot_target_resp *boot_resp; |
| 1158 | struct be_mcc_wrb *wrb; | ||
| 1466 | unsigned int tag; | 1159 | unsigned int tag; |
| 1160 | int rc; | ||
| 1467 | 1161 | ||
| 1468 | tag = be_cmd_set_vlan(phba, vlan_tag); | 1162 | *s_handle = BE_BOOT_INVALID_SHANDLE; |
| 1163 | /* get configured boot session count and handle */ | ||
| 1164 | tag = __beiscsi_boot_get_shandle(phba, 0); | ||
| 1469 | if (!tag) { | 1165 | if (!tag) { |
| 1470 | beiscsi_log(phba, KERN_ERR, | 1166 | beiscsi_log(phba, KERN_ERR, |
| 1471 | (BEISCSI_LOG_CONFIG | BEISCSI_LOG_MBOX), | 1167 | BEISCSI_LOG_CONFIG | BEISCSI_LOG_INIT, |
| 1472 | "BG_%d : VLAN Setting Failed\n"); | 1168 | "BG_%d : Getting Boot Target Info Failed\n"); |
| 1473 | return -EBUSY; | 1169 | return -EAGAIN; |
| 1474 | } | 1170 | } |
| 1475 | 1171 | ||
| 1476 | rc = beiscsi_mccq_compl_wait(phba, tag, NULL, NULL); | 1172 | rc = beiscsi_mccq_compl_wait(phba, tag, &wrb, NULL); |
| 1477 | if (rc) { | 1173 | if (rc) { |
| 1478 | beiscsi_log(phba, KERN_ERR, | 1174 | beiscsi_log(phba, KERN_ERR, |
| 1479 | (BEISCSI_LOG_CONFIG | BEISCSI_LOG_MBOX), | 1175 | BEISCSI_LOG_INIT | BEISCSI_LOG_CONFIG, |
| 1480 | "BS_%d : VLAN MBX Cmd Failed\n"); | 1176 | "BG_%d : MBX CMD get_boot_target Failed\n"); |
| 1481 | return rc; | 1177 | return -EBUSY; |
| 1482 | } | 1178 | } |
| 1483 | return rc; | 1179 | |
| 1180 | boot_resp = embedded_payload(wrb); | ||
| 1181 | /* check if there are any boot targets configured */ | ||
| 1182 | if (!boot_resp->boot_session_count) { | ||
| 1183 | __beiscsi_log(phba, KERN_INFO, | ||
| 1184 | "BG_%d : No boot targets configured\n"); | ||
| 1185 | return -ENXIO; | ||
| 1186 | } | ||
| 1187 | |||
| 1188 | /* only if FW has logged in to the boot target, s_handle is valid */ | ||
| 1189 | *s_handle = boot_resp->boot_session_handle; | ||
| 1190 | return 1; | ||
| 1484 | } | 1191 | } |
| 1485 | 1192 | ||
| 1486 | /** | 1193 | /** |
| @@ -1645,7 +1352,6 @@ void beiscsi_offload_cxn_v0(struct beiscsi_offload_params *params, · 158 unmodified lines | |||
| 1645 | { | 1352 | { |
| 1646 | struct iscsi_wrb *pwrb = pwrb_handle->pwrb; | 1353 | struct iscsi_wrb *pwrb = pwrb_handle->pwrb; |
| 1647 | 1354 | ||
| 1648 | memset(pwrb, 0, sizeof(*pwrb)); | ||
| 1649 | AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, | 1355 | AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, |
| 1650 | max_send_data_segment_length, pwrb, | 1356 | max_send_data_segment_length, pwrb, |
| 1651 | params->dw[offsetof(struct amap_beiscsi_offload_params, | 1357 | params->dw[offsetof(struct amap_beiscsi_offload_params, |
| @@ -1717,8 +1423,6 @@ void beiscsi_offload_cxn_v2(struct beiscsi_offload_params *params, · 65 unmodified lines | |||
| 1717 | { | 1423 | { |
| 1718 | struct iscsi_wrb *pwrb = pwrb_handle->pwrb; | 1424 | struct iscsi_wrb *pwrb = pwrb_handle->pwrb; |
| 1719 | 1425 | ||
| 1720 | memset(pwrb, 0, sizeof(*pwrb)); | ||
| 1721 | |||
| 1722 | AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb_v2, | 1426 | AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb_v2, |
| 1723 | max_burst_length, pwrb, params->dw[offsetof | 1427 | max_burst_length, pwrb, params->dw[offsetof |
| 1724 | (struct amap_beiscsi_offload_params, | 1428 | (struct amap_beiscsi_offload_params, |
| @@ -1790,70 +1494,3 @@ void beiscsi_offload_cxn_v2(struct beiscsi_offload_params *params, · 65 unmodified lines | |||
| 1790 | (params->dw[offsetof(struct amap_beiscsi_offload_params, | 1494 | (params->dw[offsetof(struct amap_beiscsi_offload_params, |
| 1791 | exp_statsn) / 32] + 1)); | 1495 | exp_statsn) / 32] + 1)); |
| 1792 | } | 1496 | } |
| 1793 | |||
| 1794 | /** | ||
| 1795 | * beiscsi_logout_fw_sess()- Firmware Session Logout | ||
| 1796 | * @phba: Device priv structure instance | ||
| 1797 | * @fw_sess_handle: FW session handle | ||
| 1798 | * | ||
| 1799 | * Logout from the FW established sessions. | ||
| 1800 | * returns | ||
| 1801 | * Success: 0 | ||
| 1802 | * Failure: Non-Zero Value | ||
| 1803 | * | ||
| 1804 | */ | ||
| 1805 | int beiscsi_logout_fw_sess(struct beiscsi_hba *phba, | ||
| 1806 | uint32_t fw_sess_handle) | ||
| 1807 | { | ||
| 1808 | struct be_ctrl_info *ctrl = &phba->ctrl; | ||
| 1809 | struct be_mcc_wrb *wrb; | ||
| 1810 | struct be_cmd_req_logout_fw_sess *req; | ||
| 1811 | struct be_cmd_resp_logout_fw_sess *resp; | ||
| 1812 | unsigned int tag; | ||
| 1813 | int rc; | ||
| 1814 | |||
| 1815 | beiscsi_log(phba, KERN_INFO, | ||
| 1816 | BEISCSI_LOG_CONFIG | BEISCSI_LOG_MBOX, | ||
| 1817 | "BG_%d : In bescsi_logout_fwboot_sess\n"); | ||
| 1818 | |||
| 1819 | mutex_lock(&ctrl->mbox_lock); | ||
| 1820 | wrb = alloc_mcc_wrb(phba, &tag); | ||
| 1821 | if (!wrb) { | ||
| 1822 | mutex_unlock(&ctrl->mbox_lock); | ||
| 1823 | beiscsi_log(phba, KERN_INFO, | ||
| 1824 | BEISCSI_LOG_CONFIG | BEISCSI_LOG_MBOX, | ||
| 1825 | "BG_%d : MBX Tag Failure\n"); | ||
| 1826 | return -EINVAL; | ||
| 1827 | } | ||
| 1828 | |||
| 1829 | req = embedded_payload(wrb); | ||
| 1830 | be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); | ||
| 1831 | be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ISCSI_INI, | ||
| 1832 | OPCODE_ISCSI_INI_SESSION_LOGOUT_TARGET, | ||
| 1833 | sizeof(struct be_cmd_req_logout_fw_sess)); | ||
| 1834 | |||
| 1835 | /* Set the session handle */ | ||
| 1836 | req->session_handle = fw_sess_handle; | ||
| 1837 | be_mcc_notify(phba, tag); | ||
| 1838 | mutex_unlock(&ctrl->mbox_lock); | ||
| 1839 | |||
| 1840 | rc = beiscsi_mccq_compl_wait(phba, tag, &wrb, NULL); | ||
| 1841 | if (rc) { | ||
| 1842 | beiscsi_log(phba, KERN_ERR, | ||
| 1843 | BEISCSI_LOG_INIT | BEISCSI_LOG_CONFIG, | ||
| 1844 | "BG_%d : MBX CMD FW_SESSION_LOGOUT_TARGET Failed\n"); | ||
| 1845 | return -EBUSY; | ||
| 1846 | } | ||
| 1847 | |||
| 1848 | resp = embedded_payload(wrb); | ||
| 1849 | if (resp->session_status != | ||
| 1850 | BEISCSI_MGMT_SESSION_CLOSE) { | ||
| 1851 | beiscsi_log(phba, KERN_ERR, | ||
| 1852 | BEISCSI_LOG_INIT | BEISCSI_LOG_CONFIG, | ||
| 1853 | "BG_%d : FW_SESSION_LOGOUT_TARGET resp : 0x%x\n", | ||
| 1854 | resp->session_status); | ||
| 1855 | rc = -EINVAL; | ||
| 1856 | } | ||
| 1857 | |||
| 1858 | return rc; | ||
| 1859 | } | ||
| @@ -1,5 +1,5 @@ | |||
| 1 | /** | 1 | /** |
| 2 | * Copyright (C) 2005 - 2015 Emulex | 2 | * Copyright (C) 2005 - 2016 Broadcom |
| 3 | * All rights reserved. | 3 | * All rights reserved. |
| 4 | * | 4 | * |
| 5 | * This program is free software; you can redistribute it and/or | 5 | * This program is free software; you can redistribute it and/or |
| @@ -7,10 +7,10 @@ · 1 unmodified line | |||
| 7 | * as published by the Free Software Foundation. The full GNU General | 7 | * as published by the Free Software Foundation. The full GNU General |
| 8 | * Public License is included in this distribution in the file called COPYING. | 8 | * Public License is included in this distribution in the file called COPYING. |
| 9 | * | 9 | * |
| 10 | * Written by: Jayamohan Kallickal (jayamohan.kallickal@avagotech.com) | 10 | * Written by: Jayamohan Kallickal (jayamohan.kallickal@broadcom.com) |
| 11 | * | 11 | * |
| 12 | * Contact Information: | 12 | * Contact Information: |
| 13 | * linux-drivers@avagotech.com | 13 | * linux-drivers@broadcom.com |
| 14 | * | 14 | * |
| 15 | * Emulex | 15 | * Emulex |
| 16 | * 3333 Susan Street | 16 | * 3333 Susan Street |
| @@ -96,7 +96,6 @@ struct mcc_wrb { · 79 unmodified lines | |||
| 96 | struct mcc_wrb_payload payload; | 96 | struct mcc_wrb_payload payload; |
| 97 | }; | 97 | }; |
| 98 | 98 | ||
| 99 | int mgmt_epfw_cleanup(struct beiscsi_hba *phba, unsigned short chute); | ||
| 100 | int mgmt_open_connection(struct beiscsi_hba *phba, | 99 | int mgmt_open_connection(struct beiscsi_hba *phba, |
| 101 | struct sockaddr *dst_addr, | 100 | struct sockaddr *dst_addr, |
| 102 | struct beiscsi_endpoint *beiscsi_ep, | 101 | struct beiscsi_endpoint *beiscsi_ep, |
| @@ -266,50 +265,41 @@ struct beiscsi_endpoint { · 163 unmodified lines | |||
| 266 | u16 cid_vld; | 265 | u16 cid_vld; |
| 267 | }; | 266 | }; |
| 268 | 267 | ||
| 269 | int mgmt_get_fw_config(struct be_ctrl_info *ctrl, | ||
| 270 | struct beiscsi_hba *phba); | ||
| 271 | int mgmt_get_port_name(struct be_ctrl_info *ctrl, | ||
| 272 | struct beiscsi_hba *phba); | ||
| 273 | |||
| 274 | unsigned int mgmt_invalidate_connection(struct beiscsi_hba *phba, | 268 | unsigned int mgmt_invalidate_connection(struct beiscsi_hba *phba, |
| 275 | struct beiscsi_endpoint *beiscsi_ep, | 269 | struct beiscsi_endpoint *beiscsi_ep, |
| 276 | unsigned short cid, | 270 | unsigned short cid, |
| 277 | unsigned short issue_reset, | 271 | unsigned short issue_reset, |
| 278 | unsigned short savecfg_flag); | 272 | unsigned short savecfg_flag); |
| 279 | 273 | ||
| 280 | int mgmt_set_ip(struct beiscsi_hba *phba, | 274 | int beiscsi_if_en_dhcp(struct beiscsi_hba *phba, u32 ip_type); |
| 281 | struct iscsi_iface_param_info *ip_param, | ||
| 282 | struct iscsi_iface_param_info *subnet_param, | ||
| 283 | uint32_t boot_proto); | ||
| 284 | 275 | ||
| 285 | unsigned int mgmt_get_boot_target(struct beiscsi_hba *phba); | 276 | int beiscsi_if_en_static(struct beiscsi_hba *phba, u32 ip_type, |
| 277 | u8 *ip, u8 *subnet); | ||
| 286 | 278 | ||
| 287 | unsigned int mgmt_reopen_session(struct beiscsi_hba *phba, | 279 | int beiscsi_if_set_gw(struct beiscsi_hba *phba, u32 ip_type, u8 *gw); |
| 288 | unsigned int reopen_type, | ||
| 289 | unsigned sess_handle); | ||
| 290 | 280 | ||
| 291 | unsigned int mgmt_get_session_info(struct beiscsi_hba *phba, | 281 | int beiscsi_if_get_gw(struct beiscsi_hba *phba, u32 ip_type, |
| 292 | u32 boot_session_handle, | 282 | struct be_cmd_get_def_gateway_resp *resp); |
| 293 | struct be_dma_mem *nonemb_cmd); | ||
| 294 | 283 | ||
| 295 | int mgmt_get_nic_conf(struct beiscsi_hba *phba, | 284 | int mgmt_get_nic_conf(struct beiscsi_hba *phba, |
| 296 | struct be_cmd_get_nic_conf_resp *mac); | 285 | struct be_cmd_get_nic_conf_resp *mac); |
| 297 | 286 | ||
| 298 | int mgmt_get_if_info(struct beiscsi_hba *phba, int ip_type, | 287 | int beiscsi_if_get_info(struct beiscsi_hba *phba, int ip_type, |
| 299 | struct be_cmd_get_if_info_resp **if_info); | 288 | struct be_cmd_get_if_info_resp **if_info); |
| 289 | |||
| 290 | unsigned int beiscsi_if_get_handle(struct beiscsi_hba *phba); | ||
| 291 | |||
| 292 | int beiscsi_if_set_vlan(struct beiscsi_hba *phba, uint16_t vlan_tag); | ||
| 300 | 293 | ||
| 301 | int mgmt_get_gateway(struct beiscsi_hba *phba, int ip_type, | 294 | unsigned int beiscsi_boot_logout_sess(struct beiscsi_hba *phba); |
| 302 | struct be_cmd_get_def_gateway_resp *gateway); | ||
| 303 | 295 | ||
| 304 | int mgmt_set_gateway(struct beiscsi_hba *phba, | 296 | unsigned int beiscsi_boot_reopen_sess(struct beiscsi_hba *phba); |
| 305 | struct iscsi_iface_param_info *gateway_param); | ||
| 306 | 297 | ||
| 307 | int be_mgmt_get_boot_shandle(struct beiscsi_hba *phba, | 298 | unsigned int beiscsi_boot_get_sinfo(struct beiscsi_hba *phba); |
| 308 | unsigned int *s_handle); | ||
| 309 | 299 | ||
| 310 | unsigned int mgmt_get_all_if_id(struct beiscsi_hba *phba); | 300 | unsigned int __beiscsi_boot_get_shandle(struct beiscsi_hba *phba, int async); |
| 311 | 301 | ||
| 312 | int mgmt_set_vlan(struct beiscsi_hba *phba, uint16_t vlan_tag); | 302 | int beiscsi_boot_get_shandle(struct beiscsi_hba *phba, unsigned int *s_handle); |
| 313 | 303 | ||
| 314 | ssize_t beiscsi_drvr_ver_disp(struct device *dev, | 304 | ssize_t beiscsi_drvr_ver_disp(struct device *dev, |
| 315 | struct device_attribute *attr, char *buf); | 305 | struct device_attribute *attr, char *buf); |
| @@ -339,7 +329,6 @@ void beiscsi_offload_cxn_v2(struct beiscsi_offload_params *params, · 23 unmodified lines | |||
| 339 | struct wrb_handle *pwrb_handle, | 329 | struct wrb_handle *pwrb_handle, |
| 340 | struct hwi_wrb_context *pwrb_context); | 330 | struct hwi_wrb_context *pwrb_context); |
| 341 | 331 | ||
| 342 | void beiscsi_ue_detect(struct beiscsi_hba *phba); | ||
| 343 | int be_cmd_modify_eq_delay(struct beiscsi_hba *phba, | 332 | int be_cmd_modify_eq_delay(struct beiscsi_hba *phba, |
| 344 | struct be_set_eqd *, int num); | 333 | struct be_set_eqd *, int num); |
| 345 | 334 | ||
| @@ -5827,13 +5827,13 @@ bfa_fcs_lport_get_rport_max_speed(bfa_fcs_lport_t *port) · 5826 unmodified lines | |||
| 5827 | bfa_port_speed_t max_speed = 0; | 5827 | bfa_port_speed_t max_speed = 0; |
| 5828 | struct bfa_port_attr_s port_attr; | 5828 | struct bfa_port_attr_s port_attr; |
| 5829 | bfa_port_speed_t port_speed, rport_speed; | 5829 | bfa_port_speed_t port_speed, rport_speed; |
| 5830 | bfa_boolean_t trl_enabled = bfa_fcport_is_ratelim(port->fcs->bfa); | 5830 | bfa_boolean_t trl_enabled; |
| 5831 | |||
| 5832 | 5831 | ||
| 5833 | if (port == NULL) | 5832 | if (port == NULL) |
| 5834 | return 0; | 5833 | return 0; |
| 5835 | 5834 | ||
| 5836 | fcs = port->fcs; | 5835 | fcs = port->fcs; |
| 5836 | trl_enabled = bfa_fcport_is_ratelim(port->fcs->bfa); | ||
| 5837 | 5837 | ||
| 5838 | /* Get Physical port's current speed */ | 5838 | /* Get Physical port's current speed */ |
| 5839 | bfa_fcport_get_attr(port->fcs->bfa, &port_attr); | 5839 | bfa_fcport_get_attr(port->fcs->bfa, &port_attr); |
| @@ -254,7 +254,7 @@ int bnx2fc_send_rls(struct bnx2fc_rport *tgt, struct fc_frame *fp) · 253 unmodified lines | |||
| 254 | return rc; | 254 | return rc; |
| 255 | } | 255 | } |
| 256 | 256 | ||
| 257 | void bnx2fc_srr_compl(struct bnx2fc_els_cb_arg *cb_arg) | 257 | static void bnx2fc_srr_compl(struct bnx2fc_els_cb_arg *cb_arg) |
| 258 | { | 258 | { |
| 259 | struct bnx2fc_mp_req *mp_req; | 259 | struct bnx2fc_mp_req *mp_req; |
| 260 | struct fc_frame_header *fc_hdr, *fh; | 260 | struct fc_frame_header *fc_hdr, *fh; |
| @@ -364,7 +364,7 @@ srr_compl_done: · 103 unmodified lines | |||
| 364 | kref_put(&orig_io_req->refcount, bnx2fc_cmd_release); | 364 | kref_put(&orig_io_req->refcount, bnx2fc_cmd_release); |
| 365 | } | 365 | } |
| 366 | 366 | ||
| 367 | void bnx2fc_rec_compl(struct bnx2fc_els_cb_arg *cb_arg) | 367 | static void bnx2fc_rec_compl(struct bnx2fc_els_cb_arg *cb_arg) |
| 368 | { | 368 | { |
| 369 | struct bnx2fc_cmd *orig_io_req, *new_io_req; | 369 | struct bnx2fc_cmd *orig_io_req, *new_io_req; |
| 370 | struct bnx2fc_cmd *rec_req; | 370 | struct bnx2fc_cmd *rec_req; |
| @@ -625,7 +625,7 @@ static void bnx2fc_recv_frame(struct sk_buff *skb) · 624 unmodified lines | |||
| 625 | * | 625 | * |
| 626 | * @arg: ptr to bnx2fc_percpu_info structure | 626 | * @arg: ptr to bnx2fc_percpu_info structure |
| 627 | */ | 627 | */ |
| 628 | int bnx2fc_percpu_io_thread(void *arg) | 628 | static int bnx2fc_percpu_io_thread(void *arg) |
| 629 | { | 629 | { |
| 630 | struct bnx2fc_percpu_s *p = arg; | 630 | struct bnx2fc_percpu_s *p = arg; |
| 631 | struct bnx2fc_work *work, *tmp; | 631 | struct bnx2fc_work *work, *tmp; |
| @@ -1410,9 +1410,10 @@ bind_err: · 778 unmodified lines | |||
| 1410 | return NULL; | 1410 | return NULL; |
| 1411 | } | 1411 | } |
| 1412 | 1412 | ||
| 1413 | struct bnx2fc_interface *bnx2fc_interface_create(struct bnx2fc_hba *hba, | 1413 | static struct bnx2fc_interface * |
| 1414 | struct net_device *netdev, | 1414 | bnx2fc_interface_create(struct bnx2fc_hba *hba, |
| 1415 | enum fip_state fip_mode) | 1415 | struct net_device *netdev, |
| 1416 | enum fip_state fip_mode) | ||
| 1416 | { | 1417 | { |
| 1417 | struct fcoe_ctlr_device *ctlr_dev; | 1418 | struct fcoe_ctlr_device *ctlr_dev; |
| 1418 | struct bnx2fc_interface *interface; | 1419 | struct bnx2fc_interface *interface; |
| @@ -2765,8 +2766,7 @@ static void __exit bnx2fc_mod_exit(void) · 1346 unmodified lines | |||
| 2765 | * held. | 2766 | * held. |
| 2766 | */ | 2767 | */ |
| 2767 | mutex_lock(&bnx2fc_dev_lock); | 2768 | mutex_lock(&bnx2fc_dev_lock); |
| 2768 | list_splice(&adapter_list, &to_be_deleted); | 2769 | list_splice_init(&adapter_list, &to_be_deleted); |
| 2769 | INIT_LIST_HEAD(&adapter_list); | ||
| 2770 | adapter_count = 0; | 2770 | adapter_count = 0; |
| 2771 | mutex_unlock(&bnx2fc_dev_lock); | 2771 | mutex_unlock(&bnx2fc_dev_lock); |
| 2772 | 2772 | ||
| @@ -994,7 +994,7 @@ void bnx2fc_arm_cq(struct bnx2fc_rport *tgt) · 993 unmodified lines | |||
| 994 | 994 | ||
| 995 | } | 995 | } |
| 996 | 996 | ||
| 997 | struct bnx2fc_work *bnx2fc_alloc_work(struct bnx2fc_rport *tgt, u16 wqe) | 997 | static struct bnx2fc_work *bnx2fc_alloc_work(struct bnx2fc_rport *tgt, u16 wqe) |
| 998 | { | 998 | { |
| 999 | struct bnx2fc_work *work; | 999 | struct bnx2fc_work *work; |
| 1000 | work = kzalloc(sizeof(struct bnx2fc_work), GFP_ATOMIC); | 1000 | work = kzalloc(sizeof(struct bnx2fc_work), GFP_ATOMIC); |
| @@ -1079,7 +1079,7 @@ int bnx2fc_eh_device_reset(struct scsi_cmnd *sc_cmd) · 1078 unmodified lines | |||
| 1079 | return bnx2fc_initiate_tmf(sc_cmd, FCP_TMF_LUN_RESET); | 1079 | return bnx2fc_initiate_tmf(sc_cmd, FCP_TMF_LUN_RESET); |
| 1080 | } | 1080 | } |
| 1081 | 1081 | ||
| 1082 | int bnx2fc_abts_cleanup(struct bnx2fc_cmd *io_req) | 1082 | static int bnx2fc_abts_cleanup(struct bnx2fc_cmd *io_req) |
| 1083 | { | 1083 | { |
| 1084 | struct bnx2fc_rport *tgt = io_req->tgt; | 1084 | struct bnx2fc_rport *tgt = io_req->tgt; |
| 1085 | int rc = SUCCESS; | 1085 | int rc = SUCCESS; |
| @@ -1721,7 +1721,7 @@ out: · 1720 unmodified lines | |||
| 1721 | 1721 | ||
| 1722 | /* Wake up waiting threads */ | 1722 | /* Wake up waiting threads */ |
| 1723 | csio_scsi_cmnd(req) = NULL; | 1723 | csio_scsi_cmnd(req) = NULL; |
| 1724 | complete_all(&req->cmplobj); | 1724 | complete(&req->cmplobj); |
| 1725 | } | 1725 | } |
| 1726 | 1726 | ||
| 1727 | /* | 1727 | /* |
| @@ -1945,6 +1945,7 @@ csio_eh_abort_handler(struct scsi_cmnd *cmnd) · 217 unmodified lines | |||
| 1945 | ready = csio_is_lnode_ready(ln); | 1945 | ready = csio_is_lnode_ready(ln); |
| 1946 | tmo = CSIO_SCSI_ABRT_TMO_MS; | 1946 | tmo = CSIO_SCSI_ABRT_TMO_MS; |
| 1947 | 1947 | ||
| 1948 | reinit_completion(&ioreq->cmplobj); | ||
| 1948 | spin_lock_irq(&hw->lock); | 1949 | spin_lock_irq(&hw->lock); |
| 1949 | rv = csio_do_abrt_cls(hw, ioreq, (ready ? SCSI_ABORT : SCSI_CLOSE)); | 1950 | rv = csio_do_abrt_cls(hw, ioreq, (ready ? SCSI_ABORT : SCSI_CLOSE)); |
| 1950 | spin_unlock_irq(&hw->lock); | 1951 | spin_unlock_irq(&hw->lock); |
| @@ -1964,8 +1965,6 @@ csio_eh_abort_handler(struct scsi_cmnd *cmnd) · 13 unmodified lines | |||
| 1964 | goto inval_scmnd; | 1965 | goto inval_scmnd; |
| 1965 | } | 1966 | } |
| 1966 | 1967 | ||
| 1967 | /* Wait for completion */ | ||
| 1968 | init_completion(&ioreq->cmplobj); | ||
| 1969 | wait_for_completion_timeout(&ioreq->cmplobj, msecs_to_jiffies(tmo)); | 1968 | wait_for_completion_timeout(&ioreq->cmplobj, msecs_to_jiffies(tmo)); |
| 1970 | 1969 | ||
| 1971 | /* FW didnt respond to abort within our timeout */ | 1970 | /* FW didnt respond to abort within our timeout */ |
| @@ -822,17 +822,6 @@ static void notify_shutdown(struct cxlflash_cfg *cfg, bool wait) · 821 unmodified lines | |||
| 822 | } | 822 | } |
| 823 | } | 823 | } |
| 824 | 824 | ||
| 825 | /** | ||
| 826 | * cxlflash_shutdown() - shutdown handler | ||
| 827 | * @pdev: PCI device associated with the host. | ||
| 828 | */ | ||
| 829 | static void cxlflash_shutdown(struct pci_dev *pdev) | ||
| 830 | { | ||
| 831 | struct cxlflash_cfg *cfg = pci_get_drvdata(pdev); | ||
| 832 | |||
| 833 | notify_shutdown(cfg, false); | ||
| 834 | } | ||
| 835 | |||
| 836 | /** | 825 | /** |
| 837 | * cxlflash_remove() - PCI entry point to tear down host | 826 | * cxlflash_remove() - PCI entry point to tear down host |
| 838 | * @pdev: PCI device associated with the host. | 827 | * @pdev: PCI device associated with the host. |
| @@ -844,6 +833,11 @@ static void cxlflash_remove(struct pci_dev *pdev) · 5 unmodified lines | |||
| 844 | struct cxlflash_cfg *cfg = pci_get_drvdata(pdev); | 833 | struct cxlflash_cfg *cfg = pci_get_drvdata(pdev); |
| 845 | ulong lock_flags; | 834 | ulong lock_flags; |
| 846 | 835 | ||
| 836 | if (!pci_is_enabled(pdev)) { | ||
| 837 | pr_debug("%s: Device is disabled\n", __func__); | ||
| 838 | return; | ||
| 839 | } | ||
| 840 | |||
| 847 | /* If a Task Management Function is active, wait for it to complete | 841 | /* If a Task Management Function is active, wait for it to complete |
| 848 | * before continuing with remove. | 842 | * before continuing with remove. |
| 849 | */ | 843 | */ |
| @@ -1046,6 +1040,8 @@ static int wait_port_online(__be64 __iomem *fc_regs, u32 delay_us, u32 nretry) · 196 unmodified lines | |||
| 1046 | do { | 1040 | do { |
| 1047 | msleep(delay_us / 1000); | 1041 | msleep(delay_us / 1000); |
| 1048 | status = readq_be(&fc_regs[FC_MTIP_STATUS / 8]); | 1042 | status = readq_be(&fc_regs[FC_MTIP_STATUS / 8]); |
| 1043 | if (status == U64_MAX) | ||
| 1044 | nretry /= 2; | ||
| 1049 | } while ((status & FC_MTIP_STATUS_MASK) != FC_MTIP_STATUS_ONLINE && | 1045 | } while ((status & FC_MTIP_STATUS_MASK) != FC_MTIP_STATUS_ONLINE && |
| 1050 | nretry--); | 1046 | nretry--); |
| 1051 | 1047 | ||
| @@ -1077,6 +1073,8 @@ static int wait_port_offline(__be64 __iomem *fc_regs, u32 delay_us, u32 nretry) · 25 unmodified lines | |||
| 1077 | do { | 1073 | do { |
| 1078 | msleep(delay_us / 1000); | 1074 | msleep(delay_us / 1000); |
| 1079 | status = readq_be(&fc_regs[FC_MTIP_STATUS / 8]); | 1075 | status = readq_be(&fc_regs[FC_MTIP_STATUS / 8]); |
| 1076 | if (status == U64_MAX) | ||
| 1077 | nretry /= 2; | ||
| 1080 | } while ((status & FC_MTIP_STATUS_MASK) != FC_MTIP_STATUS_OFFLINE && | 1078 | } while ((status & FC_MTIP_STATUS_MASK) != FC_MTIP_STATUS_OFFLINE && |
| 1081 | nretry--); | 1079 | nretry--); |
| 1082 | 1080 | ||
| @@ -1095,42 +1093,25 @@ static int wait_port_offline(__be64 __iomem *fc_regs, u32 delay_us, u32 nretry) · 12 unmodified lines | |||
| 1095 | * online. This toggling action can cause this routine to delay up to a few | 1093 | * online. This toggling action can cause this routine to delay up to a few |
| 1096 | * seconds. When configured to use the internal LUN feature of the AFU, a | 1094 | * seconds. When configured to use the internal LUN feature of the AFU, a |
| 1097 | * failure to come online is overridden. | 1095 | * failure to come online is overridden. |
| 1098 | * | ||
| 1099 | * Return: | ||
| 1100 | * 0 when the WWPN is successfully written and the port comes back online | ||
| 1101 | * -1 when the port fails to go offline or come back up online | ||
| 1102 | */ | 1096 | */ |
| 1103 | static int afu_set_wwpn(struct afu *afu, int port, __be64 __iomem *fc_regs, | 1097 | static void afu_set_wwpn(struct afu *afu, int port, __be64 __iomem *fc_regs, |
| 1104 | u64 wwpn) | 1098 | u64 wwpn) |
| 1105 | { | 1099 | { |
| 1106 | int rc = 0; | ||
| 1107 | |||
| 1108 | set_port_offline(fc_regs); | 1100 | set_port_offline(fc_regs); |
| 1109 | |||
| 1110 | if (!wait_port_offline(fc_regs, FC_PORT_STATUS_RETRY_INTERVAL_US, | 1101 | if (!wait_port_offline(fc_regs, FC_PORT_STATUS_RETRY_INTERVAL_US, |
| 1111 | FC_PORT_STATUS_RETRY_CNT)) { | 1102 | FC_PORT_STATUS_RETRY_CNT)) { |
| 1112 | pr_debug("%s: wait on port %d to go offline timed out\n", | 1103 | pr_debug("%s: wait on port %d to go offline timed out\n", |
| 1113 | __func__, port); | 1104 | __func__, port); |
| 1114 | rc = -1; /* but continue on to leave the port back online */ | ||
| 1115 | } | 1105 | } |
| 1116 | 1106 | ||
| 1117 | if (rc == 0) | 1107 | writeq_be(wwpn, &fc_regs[FC_PNAME / 8]); |
| 1118 | writeq_be(wwpn, &fc_regs[FC_PNAME / 8]); | ||
| 1119 | |||
| 1120 | /* Always return success after programming WWPN */ | ||
| 1121 | rc = 0; | ||
| 1122 | 1108 | ||
| 1123 | set_port_online(fc_regs); | 1109 | set_port_online(fc_regs); |
| 1124 | |||
| 1125 | if (!wait_port_online(fc_regs, FC_PORT_STATUS_RETRY_INTERVAL_US, | 1110 | if (!wait_port_online(fc_regs, FC_PORT_STATUS_RETRY_INTERVAL_US, |
| 1126 | FC_PORT_STATUS_RETRY_CNT)) { | 1111 | FC_PORT_STATUS_RETRY_CNT)) { |
| 1127 | pr_err("%s: wait on port %d to go online timed out\n", | 1112 | pr_debug("%s: wait on port %d to go online timed out\n", |
| 1128 | __func__, port); | 1113 | __func__, port); |
| 1129 | } | 1114 | } |
| 1130 | |||
| 1131 | pr_debug("%s: returning rc=%d\n", __func__, rc); | ||
| 1132 | |||
| 1133 | return rc; | ||
| 1134 | } | 1115 | } |
| 1135 | 1116 | ||
| 1136 | /** | 1117 | /** |
| @@ -1187,7 +1168,7 @@ static const struct asyc_intr_info ainfo[] = { · 50 unmodified lines | |||
| 1187 | {SISL_ASTATUS_FC0_LOGI_F, "login failed", 0, CLR_FC_ERROR}, | 1168 | {SISL_ASTATUS_FC0_LOGI_F, "login failed", 0, CLR_FC_ERROR}, |
| 1188 | {SISL_ASTATUS_FC0_LOGI_S, "login succeeded", 0, SCAN_HOST}, | 1169 | {SISL_ASTATUS_FC0_LOGI_S, "login succeeded", 0, SCAN_HOST}, |
| 1189 | {SISL_ASTATUS_FC0_LINK_DN, "link down", 0, 0}, | 1170 | {SISL_ASTATUS_FC0_LINK_DN, "link down", 0, 0}, |
| 1190 | {SISL_ASTATUS_FC0_LINK_UP, "link up", 0, SCAN_HOST}, | 1171 | {SISL_ASTATUS_FC0_LINK_UP, "link up", 0, 0}, |
| 1191 | {SISL_ASTATUS_FC1_OTHER, "other error", 1, CLR_FC_ERROR | LINK_RESET}, | 1172 | {SISL_ASTATUS_FC1_OTHER, "other error", 1, CLR_FC_ERROR | LINK_RESET}, |
| 1192 | {SISL_ASTATUS_FC1_LOGO, "target initiated LOGO", 1, 0}, | 1173 | {SISL_ASTATUS_FC1_LOGO, "target initiated LOGO", 1, 0}, |
| 1193 | {SISL_ASTATUS_FC1_CRC_T, "CRC threshold exceeded", 1, LINK_RESET}, | 1174 | {SISL_ASTATUS_FC1_CRC_T, "CRC threshold exceeded", 1, LINK_RESET}, |
| @@ -1195,7 +1176,7 @@ static const struct asyc_intr_info ainfo[] = { · 1 unmodified line | |||
| 1195 | {SISL_ASTATUS_FC1_LOGI_F, "login failed", 1, CLR_FC_ERROR}, | 1176 | {SISL_ASTATUS_FC1_LOGI_F, "login failed", 1, CLR_FC_ERROR}, |
| 1196 | {SISL_ASTATUS_FC1_LOGI_S, "login succeeded", 1, SCAN_HOST}, | 1177 | {SISL_ASTATUS_FC1_LOGI_S, "login succeeded", 1, SCAN_HOST}, |
| 1197 | {SISL_ASTATUS_FC1_LINK_DN, "link down", 1, 0}, | 1178 | {SISL_ASTATUS_FC1_LINK_DN, "link down", 1, 0}, |
| 1198 | {SISL_ASTATUS_FC1_LINK_UP, "link up", 1, SCAN_HOST}, | 1179 | {SISL_ASTATUS_FC1_LINK_UP, "link up", 1, 0}, |
| 1199 | {0x0, "", 0, 0} /* terminator */ | 1180 | {0x0, "", 0, 0} /* terminator */ |
| 1200 | }; | 1181 | }; |
| 1201 | 1182 | ||
| @@ -1631,15 +1612,10 @@ static int init_global(struct cxlflash_cfg *cfg) · 429 unmodified lines | |||
| 1631 | [FC_CRC_THRESH / 8]); | 1612 | [FC_CRC_THRESH / 8]); |
| 1632 | 1613 | ||
| 1633 | /* Set WWPNs. If already programmed, wwpn[i] is 0 */ | 1614 | /* Set WWPNs. If already programmed, wwpn[i] is 0 */ |
| 1634 | if (wwpn[i] != 0 && | 1615 | if (wwpn[i] != 0) |
| 1635 | afu_set_wwpn(afu, i, | 1616 | afu_set_wwpn(afu, i, |
| 1636 | &afu->afu_map->global.fc_regs[i][0], | 1617 | &afu->afu_map->global.fc_regs[i][0], |
| 1637 | wwpn[i])) { | 1618 | wwpn[i]); |
| 1638 | dev_err(dev, "%s: failed to set WWPN on port %d\n", | ||
| 1639 | __func__, i); | ||
| 1640 | rc = -EIO; | ||
| 1641 | goto out; | ||
| 1642 | } | ||
| 1643 | /* Programming WWPN back to back causes additional | 1619 | /* Programming WWPN back to back causes additional |
| 1644 | * offline/online transitions and a PLOGI | 1620 | * offline/online transitions and a PLOGI |
| 1645 | */ | 1621 | */ |
| @@ -2048,6 +2024,11 @@ retry: · 402 unmodified lines | |||
| 2048 | * cxlflash_eh_host_reset_handler() - reset the host adapter | 2024 | * cxlflash_eh_host_reset_handler() - reset the host adapter |
| 2049 | * @scp: SCSI command from stack identifying host. | 2025 | * @scp: SCSI command from stack identifying host. |
| 2050 | * | 2026 | * |
| 2027 | * Following a reset, the state is evaluated again in case an EEH occurred | ||
| 2028 | * during the reset. In such a scenario, the host reset will either yield | ||
| 2029 | * until the EEH recovery is complete or return success or failure based | ||
| 2030 | * upon the current device state. | ||
| 2031 | * | ||
| 2051 | * Return: | 2032 | * Return: |
| 2052 | * SUCCESS as defined in scsi/scsi.h | 2033 | * SUCCESS as defined in scsi/scsi.h |
| 2053 | * FAILED as defined in scsi/scsi.h | 2034 | * FAILED as defined in scsi/scsi.h |
| @@ -2080,7 +2061,8 @@ static int cxlflash_eh_host_reset_handler(struct scsi_cmnd *scp) · 26 unmodified lines | |||
| 2080 | } else | 2061 | } else |
| 2081 | cfg->state = STATE_NORMAL; | 2062 | cfg->state = STATE_NORMAL; |
| 2082 | wake_up_all(&cfg->reset_waitq); | 2063 | wake_up_all(&cfg->reset_waitq); |
| 2083 | break; | 2064 | ssleep(1); |
| 2065 | /* fall through */ | ||
| 2084 | case STATE_RESET: | 2066 | case STATE_RESET: |
| 2085 | wait_event(cfg->reset_waitq, cfg->state != STATE_RESET); | 2067 | wait_event(cfg->reset_waitq, cfg->state != STATE_RESET); |
| 2086 | if (cfg->state == STATE_NORMAL) | 2068 | if (cfg->state == STATE_NORMAL) |
| @@ -2596,6 +2578,9 @@ out_remove: · 509 unmodified lines | |||
| 2596 | * @pdev: PCI device struct. | 2578 | * @pdev: PCI device struct. |
| 2597 | * @state: PCI channel state. | 2579 | * @state: PCI channel state. |
| 2598 | * | 2580 | * |
| 2581 | * When an EEH occurs during an active reset, wait until the reset is | ||
| 2582 | * complete and then take action based upon the device state. | ||
| 2583 | * | ||
| 2599 | * Return: PCI_ERS_RESULT_NEED_RESET or PCI_ERS_RESULT_DISCONNECT | 2584 | * Return: PCI_ERS_RESULT_NEED_RESET or PCI_ERS_RESULT_DISCONNECT |
| 2600 | */ | 2585 | */ |
| 2601 | static pci_ers_result_t cxlflash_pci_error_detected(struct pci_dev *pdev, | 2586 | static pci_ers_result_t cxlflash_pci_error_detected(struct pci_dev *pdev, |
| @@ -2609,6 +2594,10 @@ static pci_ers_result_t cxlflash_pci_error_detected(struct pci_dev *pdev, · 7 unmodified lines | |||
| 2609 | 2594 | ||
| 2610 | switch (state) { | 2595 | switch (state) { |
| 2611 | case pci_channel_io_frozen: | 2596 | case pci_channel_io_frozen: |
| 2597 | wait_event(cfg->reset_waitq, cfg->state != STATE_RESET); | ||
| 2598 | if (cfg->state == STATE_FAILTERM) | ||
| 2599 | return PCI_ERS_RESULT_DISCONNECT; | ||
| 2600 | |||
| 2612 | cfg->state = STATE_RESET; | 2601 | cfg->state = STATE_RESET; |
| 2613 | scsi_block_requests(cfg->host); | 2602 | scsi_block_requests(cfg->host); |
| 2614 | drain_ioctls(cfg); | 2603 | drain_ioctls(cfg); |
| @@ -2685,7 +2674,7 @@ static struct pci_driver cxlflash_driver = { · 70 unmodified lines | |||
| 2685 | .id_table = cxlflash_pci_table, | 2674 | .id_table = cxlflash_pci_table, |
| 2686 | .probe = cxlflash_probe, | 2675 | .probe = cxlflash_probe, |
| 2687 | .remove = cxlflash_remove, | 2676 | .remove = cxlflash_remove, |
| 2688 | .shutdown = cxlflash_shutdown, | 2677 | .shutdown = cxlflash_remove, |
| 2689 | .err_handler = &cxlflash_err_handler, | 2678 | .err_handler = &cxlflash_err_handler, |
| 2690 | }; | 2679 | }; |
| 2691 | 2680 | ||
| @@ -709,14 +709,13 @@ int cxlflash_disk_release(struct scsi_device *sdev, · 708 unmodified lines | |||
| 709 | * @cfg: Internal structure associated with the host. | 709 | * @cfg: Internal structure associated with the host. |
| 710 | * @ctxi: Context to release. | 710 | * @ctxi: Context to release. |
| 711 | * | 711 | * |
| 712 | * This routine is safe to be called with a a non-initialized context | 712 | * This routine is safe to be called with a a non-initialized context. |
| 713 | * and is tolerant of being called with the context's mutex held (it | 713 | * Also note that the routine conditionally checks for the existence |
| 714 | * will be unlocked if necessary before freeing). Also note that the | 714 | * of the context control map before clearing the RHT registers and |
| 715 | * routine conditionally checks for the existence of the context control | 715 | * context capabilities because it is possible to destroy a context |
| 716 | * map before clearing the RHT registers and context capabilities because | 716 | * while the context is in the error state (previous mapping was |
| 717 | * it is possible to destroy a context while the context is in the error | 717 | * removed [so there is no need to worry about clearing] and context |
| 718 | * state (previous mapping was removed [so there is no need to worry about | 718 | * is waiting for a new mapping). |
| 719 | * clearing] and context is waiting for a new mapping). | ||
| 720 | */ | 719 | */ |
| 721 | static void destroy_context(struct cxlflash_cfg *cfg, | 720 | static void destroy_context(struct cxlflash_cfg *cfg, |
| 722 | struct ctx_info *ctxi) | 721 | struct ctx_info *ctxi) |
| @@ -732,9 +731,6 @@ static void destroy_context(struct cxlflash_cfg *cfg, · 9 unmodified lines | |||
| 732 | writeq_be(0, &ctxi->ctrl_map->rht_cnt_id); | 731 | writeq_be(0, &ctxi->ctrl_map->rht_cnt_id); |
| 733 | writeq_be(0, &ctxi->ctrl_map->ctx_cap); | 732 | writeq_be(0, &ctxi->ctrl_map->ctx_cap); |
| 734 | } | 733 | } |
| 735 | |||
| 736 | if (mutex_is_locked(&ctxi->mutex)) | ||
| 737 | mutex_unlock(&ctxi->mutex); | ||
| 738 | } | 734 | } |
| 739 | 735 | ||
| 740 | /* Free memory associated with context */ | 736 | /* Free memory associated with context */ |
| @@ -792,32 +788,58 @@ err: · 51 unmodified lines | |||
| 792 | * @cfg: Internal structure associated with the host. | 788 | * @cfg: Internal structure associated with the host. |
| 793 | * @ctx: Previously obtained CXL context reference. | 789 | * @ctx: Previously obtained CXL context reference. |
| 794 | * @ctxid: Previously obtained process element associated with CXL context. | 790 | * @ctxid: Previously obtained process element associated with CXL context. |
| 795 | * @adap_fd: Previously obtained adapter fd associated with CXL context. | ||
| 796 | * @file: Previously obtained file associated with CXL context. | 791 | * @file: Previously obtained file associated with CXL context. |
| 797 | * @perms: User-specified permissions. | 792 | * @perms: User-specified permissions. |
| 798 | * | ||
| 799 | * Upon return, the context is marked as initialized and the context's mutex | ||
| 800 | * is locked. | ||
| 801 | */ | 793 | */ |
| 802 | static void init_context(struct ctx_info *ctxi, struct cxlflash_cfg *cfg, | 794 | static void init_context(struct ctx_info *ctxi, struct cxlflash_cfg *cfg, |
| 803 | struct cxl_context *ctx, int ctxid, int adap_fd, | 795 | struct cxl_context *ctx, int ctxid, struct file *file, |
| 804 | struct file *file, u32 perms) | 796 | u32 perms) |
| 805 | { | 797 | { |
| 806 | struct afu *afu = cfg->afu; | 798 | struct afu *afu = cfg->afu; |
| 807 | 799 | ||
| 808 | ctxi->rht_perms = perms; | 800 | ctxi->rht_perms = perms; |
| 809 | ctxi->ctrl_map = &afu->afu_map->ctrls[ctxid].ctrl; | 801 | ctxi->ctrl_map = &afu->afu_map->ctrls[ctxid].ctrl; |
| 810 | ctxi->ctxid = ENCODE_CTXID(ctxi, ctxid); | 802 | ctxi->ctxid = ENCODE_CTXID(ctxi, ctxid); |
| 811 | ctxi->lfd = adap_fd; | ||
| 812 | ctxi->pid = current->tgid; /* tgid = pid */ | 803 | ctxi->pid = current->tgid; /* tgid = pid */ |
| 813 | ctxi->ctx = ctx; | 804 | ctxi->ctx = ctx; |
| 805 | ctxi->cfg = cfg; | ||
| 814 | ctxi->file = file; | 806 | ctxi->file = file; |
| 815 | ctxi->initialized = true; | 807 | ctxi->initialized = true; |
| 816 | mutex_init(&ctxi->mutex); | 808 | mutex_init(&ctxi->mutex); |
| 809 | kref_init(&ctxi->kref); | ||
| 817 | INIT_LIST_HEAD(&ctxi->luns); | 810 | INIT_LIST_HEAD(&ctxi->luns); |
| 818 | INIT_LIST_HEAD(&ctxi->list); /* initialize for list_empty() */ | 811 | INIT_LIST_HEAD(&ctxi->list); /* initialize for list_empty() */ |
| 812 | } | ||
| 819 | 813 | ||
| 814 | /** | ||
| 815 | * remove_context() - context kref release handler | ||
| 816 | * @kref: Kernel reference associated with context to be removed. | ||
| 817 | * | ||
| 818 | * When a context no longer has any references it can safely be removed | ||
| 819 | * from global access and destroyed. Note that it is assumed the thread | ||
| 820 | * relinquishing access to the context holds its mutex. | ||
| 821 | */ | ||
| 822 | static void remove_context(struct kref *kref) | ||
| 823 | { | ||
| 824 | struct ctx_info *ctxi = container_of(kref, struct ctx_info, kref); | ||
| 825 | struct cxlflash_cfg *cfg = ctxi->cfg; | ||
| 826 | u64 ctxid = DECODE_CTXID(ctxi->ctxid); | ||
| 827 | |||
| 828 | /* Remove context from table/error list */ | ||
| 829 | WARN_ON(!mutex_is_locked(&ctxi->mutex)); | ||
| 830 | ctxi->unavail = true; | ||
| 831 | mutex_unlock(&ctxi->mutex); | ||
| 832 | mutex_lock(&cfg->ctx_tbl_list_mutex); | ||
| 820 | mutex_lock(&ctxi->mutex); | 833 | mutex_lock(&ctxi->mutex); |
| 834 | |||
| 835 | if (!list_empty(&ctxi->list)) | ||
| 836 | list_del(&ctxi->list); | ||
| 837 | cfg->ctx_tbl[ctxid] = NULL; | ||
| 838 | mutex_unlock(&cfg->ctx_tbl_list_mutex); | ||
| 839 | mutex_unlock(&ctxi->mutex); | ||
| 840 | |||
| 841 | /* Context now completely uncoupled/unreachable */ | ||
| 842 | destroy_context(cfg, ctxi); | ||
| 821 | } | 843 | } |
| 822 | 844 | ||
| 823 | /** | 845 | /** |
| @@ -845,7 +867,6 @@ static int _cxlflash_disk_detach(struct scsi_device *sdev, · 21 unmodified lines | |||
| 845 | 867 | ||
| 846 | int i; | 868 | int i; |
| 847 | int rc = 0; | 869 | int rc = 0; |
| 848 | int lfd; | ||
| 849 | u64 ctxid = DECODE_CTXID(detach->context_id), | 870 | u64 ctxid = DECODE_CTXID(detach->context_id), |
| 850 | rctxid = detach->context_id; | 871 | rctxid = detach->context_id; |
| 851 | 872 | ||
| @@ -887,40 +908,13 @@ static int _cxlflash_disk_detach(struct scsi_device *sdev, · 35 unmodified lines | |||
| 887 | break; | 908 | break; |
| 888 | } | 909 | } |
| 889 | 910 | ||
| 890 | /* Tear down context following last LUN cleanup */ | 911 | /* |
| 891 | if (list_empty(&ctxi->luns)) { | 912 | * Release the context reference and the sdev reference that |
| 892 | ctxi->unavail = true; | 913 | * bound this LUN to the context. |
| 893 | mutex_unlock(&ctxi->mutex); | 914 | */ |
| 894 | mutex_lock(&cfg->ctx_tbl_list_mutex); | 915 | if (kref_put(&ctxi->kref, remove_context)) |
| 895 | mutex_lock(&ctxi->mutex); | ||
| 896 | |||
| 897 | /* Might not have been in error list so conditionally remove */ | ||
| 898 | if (!list_empty(&ctxi->list)) | ||
| 899 | list_del(&ctxi->list); | ||
| 900 | cfg->ctx_tbl[ctxid] = NULL; | ||
| 901 | mutex_unlock(&cfg->ctx_tbl_list_mutex); | ||
| 902 | mutex_unlock(&ctxi->mutex); | ||
| 903 | |||
| 904 | lfd = ctxi->lfd; | ||
| 905 | destroy_context(cfg, ctxi); | ||
| 906 | ctxi = NULL; | ||
| 907 | put_ctx = false; | 916 | put_ctx = false; |
| 908 | |||
| 909 | /* | ||
| 910 | * As a last step, clean up external resources when not | ||
| 911 | * already on an external cleanup thread, i.e.: close(adap_fd). | ||
| 912 | * | ||
| 913 | * NOTE: this will free up the context from the CXL services, | ||
| 914 | * allowing it to dole out the same context_id on a future | ||
| 915 | * (or even currently in-flight) disk_attach operation. | ||
| 916 | */ | ||
| 917 | if (lfd != -1) | ||
| 918 | sys_close(lfd); | ||
| 919 | } | ||
| 920 | |||
| 921 | /* Release the sdev reference that bound this LUN to the context */ | ||
| 922 | scsi_device_put(sdev); | 917 | scsi_device_put(sdev); |
| 923 | |||
| 924 | out: | 918 | out: |
| 925 | if (put_ctx) | 919 | if (put_ctx) |
| 926 | put_context(ctxi); | 920 | put_context(ctxi); |
| @@ -941,34 +935,18 @@ static int cxlflash_disk_detach(struct scsi_device *sdev, · 14 unmodified lines | |||
| 941 | * | 935 | * |
| 942 | * This routine is the release handler for the fops registered with | 936 | * This routine is the release handler for the fops registered with |
| 943 | * the CXL services on an initial attach for a context. It is called | 937 | * the CXL services on an initial attach for a context. It is called |
| 944 | * when a close is performed on the adapter file descriptor returned | 938 | * when a close (explicity by the user or as part of a process tear |
| 945 | * to the user. Programmatically, the user is not required to perform | 939 | * down) is performed on the adapter file descriptor returned to the |
| 946 | * the close, as it is handled internally via the detach ioctl when | 940 | * user. The user should be aware that explicitly performing a close |
| 947 | * a context is being removed. Note that nothing prevents the user | 941 | * considered catastrophic and subsequent usage of the superpipe API |
| 948 | * from performing a close, but the user should be aware that doing | 942 | * with previously saved off tokens will fail. |
| 949 | * so is considered catastrophic and subsequent usage of the superpipe | ||
| 950 | * API with previously saved off tokens will fail. | ||
| 951 | * | ||
| 952 | * When initiated from an external close (either by the user or via | ||
| 953 | * a process tear down), the routine derives the context reference | ||
| 954 | * and calls detach for each LUN associated with the context. The | ||
| 955 | * final detach operation will cause the context itself to be freed. | ||
| 956 | * Note that the saved off lfd is reset prior to calling detach to | ||
| 957 | * signify that the final detach should not perform a close. | ||
| 958 | * | ||
| 959 | * When initiated from a detach operation as part of the tear down | ||
| 960 | * of a context, the context is first completely freed and then the | ||
| 961 | * close is performed. This routine will fail to derive the context | ||
| 962 | * reference (due to the context having already been freed) and then | ||
| 963 | * call into the CXL release entry point. | ||
| 964 | * | 943 | * |
| 965 | * Thus, with exception to when the CXL process element (context id) | 944 | * This routine derives the context reference and calls detach for |
| 966 | * lookup fails (a case that should theoretically never occur), every | 945 | * each LUN associated with the context.The final detach operation |
| 967 | * call into this routine results in a complete freeing of a context. | 946 | * causes the context itself to be freed. With exception to when the |
| 968 | * | 947 | * CXL process element (context id) lookup fails (a case that should |
| 969 | * As part of the detach, all per-context resources associated with the LUN | 948 | * theoretically never occur), every call into this routine results |
| 970 | * are cleaned up. When detaching the last LUN for a context, the context | 949 | * in a complete freeing of a context. |
| 971 | * itself is cleaned up and released. | ||
| 972 | * | 950 | * |
| 973 | * Return: 0 on success | 951 | * Return: 0 on success |
| 974 | */ | 952 | */ |
| @@ -1006,11 +984,8 @@ static int cxlflash_cxl_release(struct inode *inode, struct file *file) · 31 unmodified lines | |||
| 1006 | goto out; | 984 | goto out; |
| 1007 | } | 985 | } |
| 1008 | 986 | ||
| 1009 | dev_dbg(dev, "%s: close(%d) for context %d\n", | 987 | dev_dbg(dev, "%s: close for context %d\n", __func__, ctxid); |
| 1010 | __func__, ctxi->lfd, ctxid); | ||
| 1011 | 988 | ||
| 1012 | /* Reset the file descriptor to indicate we're on a close() thread */ | ||
| 1013 | ctxi->lfd = -1; | ||
| 1014 | detach.context_id = ctxi->ctxid; | 989 | detach.context_id = ctxi->ctxid; |
| 1015 | list_for_each_entry_safe(lun_access, t, &ctxi->luns, list) | 990 | list_for_each_entry_safe(lun_access, t, &ctxi->luns, list) |
| 1016 | _cxlflash_disk_detach(lun_access->sdev, ctxi, &detach); | 991 | _cxlflash_disk_detach(lun_access->sdev, ctxi, &detach); |
| @@ -1110,8 +1085,7 @@ static int cxlflash_mmap_fault(struct vm_area_struct *vma, struct vm_fault *vmf) · 93 unmodified lines | |||
| 1110 | goto err; | 1085 | goto err; |
| 1111 | } | 1086 | } |
| 1112 | 1087 | ||
| 1113 | dev_dbg(dev, "%s: fault(%d) for context %d\n", | 1088 | dev_dbg(dev, "%s: fault for context %d\n", __func__, ctxid); |
| 1114 | __func__, ctxi->lfd, ctxid); | ||
| 1115 | 1089 | ||
| 1116 | if (likely(!ctxi->err_recovery_active)) { | 1090 | if (likely(!ctxi->err_recovery_active)) { |
| 1117 | vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); | 1091 | vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); |
| @@ -1186,8 +1160,7 @@ static int cxlflash_cxl_mmap(struct file *file, struct vm_area_struct *vma) · 68 unmodified lines | |||
| 1186 | goto out; | 1160 | goto out; |
| 1187 | } | 1161 | } |
| 1188 | 1162 | ||
| 1189 | dev_dbg(dev, "%s: mmap(%d) for context %d\n", | 1163 | dev_dbg(dev, "%s: mmap for context %d\n", __func__, ctxid); |
| 1190 | __func__, ctxi->lfd, ctxid); | ||
| 1191 | 1164 | ||
| 1192 | rc = cxl_fd_mmap(file, vma); | 1165 | rc = cxl_fd_mmap(file, vma); |
| 1193 | if (likely(!rc)) { | 1166 | if (likely(!rc)) { |
| @@ -1377,12 +1350,12 @@ static int cxlflash_disk_attach(struct scsi_device *sdev, · 183 unmodified lines | |||
| 1377 | lun_access->lli = lli; | 1350 | lun_access->lli = lli; |
| 1378 | lun_access->sdev = sdev; | 1351 | lun_access->sdev = sdev; |
| 1379 | 1352 | ||
| 1380 | /* Non-NULL context indicates reuse */ | 1353 | /* Non-NULL context indicates reuse (another context reference) */ |
| 1381 | if (ctxi) { | 1354 | if (ctxi) { |
| 1382 | dev_dbg(dev, "%s: Reusing context for LUN! (%016llX)\n", | 1355 | dev_dbg(dev, "%s: Reusing context for LUN! (%016llX)\n", |
| 1383 | __func__, rctxid); | 1356 | __func__, rctxid); |
| 1357 | kref_get(&ctxi->kref); | ||
| 1384 | list_add(&lun_access->list, &ctxi->luns); | 1358 | list_add(&lun_access->list, &ctxi->luns); |
| 1385 | fd = ctxi->lfd; | ||
| 1386 | goto out_attach; | 1359 | goto out_attach; |
| 1387 | } | 1360 | } |
| 1388 | 1361 | ||
| @@ -1430,7 +1403,7 @@ static int cxlflash_disk_attach(struct scsi_device *sdev, · 41 unmodified lines | |||
| 1430 | perms = SISL_RHT_PERM(attach->hdr.flags + 1); | 1403 | perms = SISL_RHT_PERM(attach->hdr.flags + 1); |
| 1431 | 1404 | ||
| 1432 | /* Context mutex is locked upon return */ | 1405 | /* Context mutex is locked upon return */ |
| 1433 | init_context(ctxi, cfg, ctx, ctxid, fd, file, perms); | 1406 | init_context(ctxi, cfg, ctx, ctxid, file, perms); |
| 1434 | 1407 | ||
| 1435 | rc = afu_attach(cfg, ctxi); | 1408 | rc = afu_attach(cfg, ctxi); |
| 1436 | if (unlikely(rc)) { | 1409 | if (unlikely(rc)) { |
| @@ -1445,7 +1418,6 @@ static int cxlflash_disk_attach(struct scsi_device *sdev, · 8 unmodified lines | |||
| 1445 | * knows about us yet; we can be the only one holding our mutex. | 1418 | * knows about us yet; we can be the only one holding our mutex. |
| 1446 | */ | 1419 | */ |
| 1447 | list_add(&lun_access->list, &ctxi->luns); | 1420 | list_add(&lun_access->list, &ctxi->luns); |
| 1448 | mutex_unlock(&ctxi->mutex); | ||
| 1449 | mutex_lock(&cfg->ctx_tbl_list_mutex); | 1421 | mutex_lock(&cfg->ctx_tbl_list_mutex); |
| 1450 | mutex_lock(&ctxi->mutex); | 1422 | mutex_lock(&ctxi->mutex); |
| 1451 | cfg->ctx_tbl[ctxid] = ctxi; | 1423 | cfg->ctx_tbl[ctxid] = ctxi; |
| @@ -1453,7 +1425,11 @@ static int cxlflash_disk_attach(struct scsi_device *sdev, · 1 unmodified line | |||
| 1453 | fd_install(fd, file); | 1425 | fd_install(fd, file); |
| 1454 | 1426 | ||
| 1455 | out_attach: | 1427 | out_attach: |
| 1456 | attach->hdr.return_flags = 0; | 1428 | if (fd != -1) |
| 1429 | attach->hdr.return_flags = DK_CXLFLASH_APP_CLOSE_ADAP_FD; | ||
| 1430 | else | ||
| 1431 | attach->hdr.return_flags = 0; | ||
| 1432 | |||
| 1457 | attach->context_id = ctxi->ctxid; | 1433 | attach->context_id = ctxi->ctxid; |
| 1458 | attach->block_size = gli->blk_len; | 1434 | attach->block_size = gli->blk_len; |
| 1459 | attach->mmio_size = sizeof(afu->afu_map->hosts[0].harea); | 1435 | attach->mmio_size = sizeof(afu->afu_map->hosts[0].harea); |
| @@ -1494,7 +1470,7 @@ err: · 34 unmodified lines | |||
| 1494 | file = NULL; | 1470 | file = NULL; |
| 1495 | } | 1471 | } |
| 1496 | 1472 | ||
| 1497 | /* Cleanup our context; safe to call even with mutex locked */ | 1473 | /* Cleanup our context */ |
| 1498 | if (ctxi) { | 1474 | if (ctxi) { |
| 1499 | destroy_context(cfg, ctxi); | 1475 | destroy_context(cfg, ctxi); |
| 1500 | ctxi = NULL; | 1476 | ctxi = NULL; |
| @@ -1509,16 +1485,19 @@ err: · 8 unmodified lines | |||
| 1509 | * recover_context() - recovers a context in error | 1485 | * recover_context() - recovers a context in error |
| 1510 | * @cfg: Internal structure associated with the host. | 1486 | * @cfg: Internal structure associated with the host. |
| 1511 | * @ctxi: Context to release. | 1487 | * @ctxi: Context to release. |
| 1488 | * @adap_fd: Adapter file descriptor associated with new/recovered context. | ||
| 1512 | * | 1489 | * |
| 1513 | * Restablishes the state for a context-in-error. | 1490 | * Restablishes the state for a context-in-error. |
| 1514 | * | 1491 | * |
| 1515 | * Return: 0 on success, -errno on failure | 1492 | * Return: 0 on success, -errno on failure |
| 1516 | */ | 1493 | */ |
| 1517 | static int recover_context(struct cxlflash_cfg *cfg, struct ctx_info *ctxi) | 1494 | static int recover_context(struct cxlflash_cfg *cfg, |
| 1495 | struct ctx_info *ctxi, | ||
| 1496 | int *adap_fd) | ||
| 1518 | { | 1497 | { |
| 1519 | struct device *dev = &cfg->dev->dev; | 1498 | struct device *dev = &cfg->dev->dev; |
| 1520 | int rc = 0; | 1499 | int rc = 0; |
| 1521 | int old_fd, fd = -1; | 1500 | int fd = -1; |
| 1522 | int ctxid = -1; | 1501 | int ctxid = -1; |
| 1523 | struct file *file; | 1502 | struct file *file; |
| 1524 | struct cxl_context *ctx; | 1503 | struct cxl_context *ctx; |
| @@ -1566,9 +1545,7 @@ static int recover_context(struct cxlflash_cfg *cfg, struct ctx_info *ctxi) · 41 unmodified lines | |||
| 1566 | * No error paths after this point. Once the fd is installed it's | 1545 | * No error paths after this point. Once the fd is installed it's |
| 1567 | * visible to user space and can't be undone safely on this thread. | 1546 | * visible to user space and can't be undone safely on this thread. |
| 1568 | */ | 1547 | */ |
| 1569 | old_fd = ctxi->lfd; | ||
| 1570 | ctxi->ctxid = ENCODE_CTXID(ctxi, ctxid); | 1548 | ctxi->ctxid = ENCODE_CTXID(ctxi, ctxid); |
| 1571 | ctxi->lfd = fd; | ||
| 1572 | ctxi->ctx = ctx; | 1549 | ctxi->ctx = ctx; |
| 1573 | ctxi->file = file; | 1550 | ctxi->file = file; |
| 1574 | 1551 | ||
| @@ -1585,9 +1562,7 @@ static int recover_context(struct cxlflash_cfg *cfg, struct ctx_info *ctxi) · 10 unmodified lines | |||
| 1585 | cfg->ctx_tbl[ctxid] = ctxi; | 1562 | cfg->ctx_tbl[ctxid] = ctxi; |
| 1586 | mutex_unlock(&cfg->ctx_tbl_list_mutex); | 1563 | mutex_unlock(&cfg->ctx_tbl_list_mutex); |
| 1587 | fd_install(fd, file); | 1564 | fd_install(fd, file); |
| 1588 | 1565 | *adap_fd = fd; | |
| 1589 | /* Release the original adapter fd and associated CXL resources */ | ||
| 1590 | sys_close(old_fd); | ||
| 1591 | out: | 1566 | out: |
| 1592 | dev_dbg(dev, "%s: returning ctxid=%d fd=%d rc=%d\n", | 1567 | dev_dbg(dev, "%s: returning ctxid=%d fd=%d rc=%d\n", |
| 1593 | __func__, ctxid, fd, rc); | 1568 | __func__, ctxid, fd, rc); |
| @@ -1646,6 +1621,7 @@ static int cxlflash_afu_recover(struct scsi_device *sdev, · 52 unmodified lines | |||
| 1646 | rctxid = recover->context_id; | 1621 | rctxid = recover->context_id; |
| 1647 | long reg; | 1622 | long reg; |
| 1648 | int lretry = 20; /* up to 2 seconds */ | 1623 | int lretry = 20; /* up to 2 seconds */ |
| 1624 | int new_adap_fd = -1; | ||
| 1649 | int rc = 0; | 1625 | int rc = 0; |
| 1650 | 1626 | ||
| 1651 | atomic_inc(&cfg->recovery_threads); | 1627 | atomic_inc(&cfg->recovery_threads); |
| @@ -1675,7 +1651,7 @@ retry: · 23 unmodified lines | |||
| 1675 | 1651 | ||
| 1676 | if (ctxi->err_recovery_active) { | 1652 | if (ctxi->err_recovery_active) { |
| 1677 | retry_recover: | 1653 | retry_recover: |
| 1678 | rc = recover_context(cfg, ctxi); | 1654 | rc = recover_context(cfg, ctxi, &new_adap_fd); |
| 1679 | if (unlikely(rc)) { | 1655 | if (unlikely(rc)) { |
| 1680 | dev_err(dev, "%s: Recovery failed for context %llu (rc=%d)\n", | 1656 | dev_err(dev, "%s: Recovery failed for context %llu (rc=%d)\n", |
| 1681 | __func__, ctxid, rc); | 1657 | __func__, ctxid, rc); |
| @@ -1697,9 +1673,9 @@ retry_recover: · 15 unmodified lines | |||
| 1697 | 1673 | ||
| 1698 | ctxi->err_recovery_active = false; | 1674 | ctxi->err_recovery_active = false; |
| 1699 | recover->context_id = ctxi->ctxid; | 1675 | recover->context_id = ctxi->ctxid; |
| 1700 | recover->adap_fd = ctxi->lfd; | 1676 | recover->adap_fd = new_adap_fd; |
| 1701 | recover->mmio_size = sizeof(afu->afu_map->hosts[0].harea); | 1677 | recover->mmio_size = sizeof(afu->afu_map->hosts[0].harea); |
| 1702 | recover->hdr.return_flags |= | 1678 | recover->hdr.return_flags = DK_CXLFLASH_APP_CLOSE_ADAP_FD | |
| 1703 | DK_CXLFLASH_RECOVER_AFU_CONTEXT_RESET; | 1679 | DK_CXLFLASH_RECOVER_AFU_CONTEXT_RESET; |
| 1704 | goto out; | 1680 | goto out; |
| 1705 | } | 1681 | } |
| @@ -100,13 +100,14 @@ struct ctx_info { · 99 unmodified lines | |||
| 100 | 100 | ||
| 101 | struct cxl_ioctl_start_work work; | 101 | struct cxl_ioctl_start_work work; |
| 102 | u64 ctxid; | 102 | u64 ctxid; |
| 103 | int lfd; | ||
| 104 | pid_t pid; | 103 | pid_t pid; |
| 105 | bool initialized; | 104 | bool initialized; |
| 106 | bool unavail; | 105 | bool unavail; |
| 107 | bool err_recovery_active; | 106 | bool err_recovery_active; |
| 108 | struct mutex mutex; /* Context protection */ | 107 | struct mutex mutex; /* Context protection */ |
| 108 | struct kref kref; | ||
| 109 | struct cxl_context *ctx; | 109 | struct cxl_context *ctx; |
| 110 | struct cxlflash_cfg *cfg; | ||
| 110 | struct list_head luns; /* LUNs attached to this context */ | 111 | struct list_head luns; /* LUNs attached to this context */ |
| 111 | const struct vm_operations_struct *cxl_mmap_vmops; | 112 | const struct vm_operations_struct *cxl_mmap_vmops; |
| 112 | struct file *file; | 113 | struct file *file; |
| @@ -1135,14 +1135,13 @@ int cxlflash_disk_clone(struct scsi_device *sdev, · 1134 unmodified lines | |||
| 1135 | ctxid_dst = DECODE_CTXID(clone->context_id_dst), | 1135 | ctxid_dst = DECODE_CTXID(clone->context_id_dst), |
| 1136 | rctxid_src = clone->context_id_src, | 1136 | rctxid_src = clone->context_id_src, |
| 1137 | rctxid_dst = clone->context_id_dst; | 1137 | rctxid_dst = clone->context_id_dst; |
| 1138 | int adap_fd_src = clone->adap_fd_src; | ||
| 1139 | int i, j; | 1138 | int i, j; |
| 1140 | int rc = 0; | 1139 | int rc = 0; |
| 1141 | bool found; | 1140 | bool found; |
| 1142 | LIST_HEAD(sidecar); | 1141 | LIST_HEAD(sidecar); |
| 1143 | 1142 | ||
| 1144 | pr_debug("%s: ctxid_src=%llu ctxid_dst=%llu adap_fd_src=%d\n", | 1143 | pr_debug("%s: ctxid_src=%llu ctxid_dst=%llu\n", |
| 1145 | __func__, ctxid_src, ctxid_dst, adap_fd_src); | 1144 | __func__, ctxid_src, ctxid_dst); |
| 1146 | 1145 | ||
| 1147 | /* Do not clone yourself */ | 1146 | /* Do not clone yourself */ |
| 1148 | if (unlikely(rctxid_src == rctxid_dst)) { | 1147 | if (unlikely(rctxid_src == rctxid_dst)) { |
| @@ -1166,13 +1165,6 @@ int cxlflash_disk_clone(struct scsi_device *sdev, · 17 unmodified lines | |||
| 1166 | goto out; | 1165 | goto out; |
| 1167 | } | 1166 | } |
| 1168 | 1167 | ||
| 1169 | if (unlikely(adap_fd_src != ctxi_src->lfd)) { | ||
| 1170 | pr_debug("%s: Invalid source adapter fd! (%d)\n", | ||
| 1171 | __func__, adap_fd_src); | ||
| 1172 | rc = -EINVAL; | ||
| 1173 | goto out; | ||
| 1174 | } | ||
| 1175 | |||
| 1176 | /* Verify there is no open resource handle in the destination context */ | 1168 | /* Verify there is no open resource handle in the destination context */ |
| 1177 | for (i = 0; i < MAX_RHT_PER_CONTEXT; i++) | 1169 | for (i = 0; i < MAX_RHT_PER_CONTEXT; i++) |
| 1178 | if (ctxi_dst->rht_start[i].nmask != 0) { | 1170 | if (ctxi_dst->rht_start[i].nmask != 0) { |
| @@ -1257,7 +1249,6 @@ int cxlflash_disk_clone(struct scsi_device *sdev, · 78 unmodified lines | |||
| 1257 | 1249 | ||
| 1258 | out_success: | 1250 | out_success: |
| 1259 | list_splice(&sidecar, &ctxi_dst->luns); | 1251 | list_splice(&sidecar, &ctxi_dst->luns); |
| 1260 | sys_close(adap_fd_src); | ||
| 1261 | 1252 | ||
| 1262 | /* fall through */ | 1253 | /* fall through */ |
| 1263 | out: | 1254 | out: |
| @@ -583,6 +583,7 @@ static int alua_rtpg(struct scsi_device *sdev, struct alua_port_group *pg) · 582 unmodified lines | |||
| 583 | sdev_printk(KERN_ERR, sdev, "%s: rtpg retry\n", | 583 | sdev_printk(KERN_ERR, sdev, "%s: rtpg retry\n", |
| 584 | ALUA_DH_NAME); | 584 | ALUA_DH_NAME); |
| 585 | scsi_print_sense_hdr(sdev, ALUA_DH_NAME, &sense_hdr); | 585 | scsi_print_sense_hdr(sdev, ALUA_DH_NAME, &sense_hdr); |
| 586 | kfree(buff); | ||
| 586 | return err; | 587 | return err; |
| 587 | } | 588 | } |
| 588 | sdev_printk(KERN_ERR, sdev, "%s: rtpg failed\n", | 589 | sdev_printk(KERN_ERR, sdev, "%s: rtpg failed\n", |
| @@ -1,447 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * DTC 3180/3280 driver, by | ||
| 3 | * Ray Van Tassle rayvt@comm.mot.com | ||
| 4 | * | ||
| 5 | * taken from ... | ||
| 6 | * Trantor T128/T128F/T228 driver by... | ||
| 7 | * | ||
| 8 | * Drew Eckhardt | ||
| 9 | * Visionary Computing | ||
| 10 | * (Unix and Linux consulting and custom programming) | ||
| 11 | * drew@colorado.edu | ||
| 12 | * +1 (303) 440-4894 | ||
| 13 | */ | ||
| 14 | |||
| 15 | /* | ||
| 16 | * The card is detected and initialized in one of several ways : | ||
| 17 | * 1. Autoprobe (default) - since the board is memory mapped, | ||
| 18 | * a BIOS signature is scanned for to locate the registers. | ||
| 19 | * An interrupt is triggered to autoprobe for the interrupt | ||
| 20 | * line. | ||
| 21 | * | ||
| 22 | * 2. With command line overrides - dtc=address,irq may be | ||
| 23 | * used on the LILO command line to override the defaults. | ||
| 24 | * | ||
| 25 | */ | ||
| 26 | |||
| 27 | /*----------------------------------------------------------------*/ | ||
| 28 | /* the following will set the monitor border color (useful to find | ||
| 29 | where something crashed or gets stuck at */ | ||
| 30 | /* 1 = blue | ||
| 31 | 2 = green | ||
| 32 | 3 = cyan | ||
| 33 | 4 = red | ||
| 34 | 5 = magenta | ||
| 35 | 6 = yellow | ||
| 36 | 7 = white | ||
| 37 | */ | ||
| 38 | #if 0 | ||
| 39 | #define rtrc(i) {inb(0x3da); outb(0x31, 0x3c0); outb((i), 0x3c0);} | ||
| 40 | #else | ||
| 41 | #define rtrc(i) {} | ||
| 42 | #endif | ||
| 43 | |||
| 44 | |||
| 45 | #include <linux/module.h> | ||
| 46 | #include <linux/blkdev.h> | ||
| 47 | #include <linux/string.h> | ||
| 48 | #include <linux/init.h> | ||
| 49 | #include <linux/interrupt.h> | ||
| 50 | #include <linux/io.h> | ||
| 51 | #include <scsi/scsi_host.h> | ||
| 52 | |||
| 53 | #include "dtc.h" | ||
| 54 | #include "NCR5380.h" | ||
| 55 | |||
| 56 | /* | ||
| 57 | * The DTC3180 & 3280 boards are memory mapped. | ||
| 58 | * | ||
| 59 | */ | ||
| 60 | |||
| 61 | /* | ||
| 62 | */ | ||
| 63 | /* Offset from DTC_5380_OFFSET */ | ||
| 64 | #define DTC_CONTROL_REG 0x100 /* rw */ | ||
| 65 | #define D_CR_ACCESS 0x80 /* ro set=can access 3280 registers */ | ||
| 66 | #define CSR_DIR_READ 0x40 /* rw direction, 1 = read 0 = write */ | ||
| 67 | |||
| 68 | #define CSR_RESET 0x80 /* wo Resets 53c400 */ | ||
| 69 | #define CSR_5380_REG 0x80 /* ro 5380 registers can be accessed */ | ||
| 70 | #define CSR_TRANS_DIR 0x40 /* rw Data transfer direction */ | ||
| 71 | #define CSR_SCSI_BUFF_INTR 0x20 /* rw Enable int on transfer ready */ | ||
| 72 | #define CSR_5380_INTR 0x10 /* rw Enable 5380 interrupts */ | ||
| 73 | #define CSR_SHARED_INTR 0x08 /* rw Interrupt sharing */ | ||
| 74 | #define CSR_HOST_BUF_NOT_RDY 0x04 /* ro Host buffer not ready */ | ||
| 75 | #define CSR_SCSI_BUF_RDY 0x02 /* ro SCSI buffer ready */ | ||
| 76 | #define CSR_GATED_5380_IRQ 0x01 /* ro Last block xferred */ | ||
| 77 | #define CSR_INT_BASE (CSR_SCSI_BUFF_INTR | CSR_5380_INTR) | ||
| 78 | |||
| 79 | |||
| 80 | #define DTC_BLK_CNT 0x101 /* rw | ||
| 81 | * # of 128-byte blocks to transfer */ | ||
| 82 | |||
| 83 | |||
| 84 | #define D_CR_ACCESS 0x80 /* ro set=can access 3280 registers */ | ||
| 85 | |||
| 86 | #define DTC_SWITCH_REG 0x3982 /* ro - DIP switches */ | ||
| 87 | #define DTC_RESUME_XFER 0x3982 /* wo - resume data xfer | ||
| 88 | * after disconnect/reconnect*/ | ||
| 89 | |||
| 90 | #define DTC_5380_OFFSET 0x3880 /* 8 registers here, see NCR5380.h */ | ||
| 91 | |||
| 92 | /*!!!! for dtc, it's a 128 byte buffer at 3900 !!! */ | ||
| 93 | #define DTC_DATA_BUF 0x3900 /* rw 128 bytes long */ | ||
| 94 | |||
| 95 | static struct override { | ||
| 96 | unsigned int address; | ||
| 97 | int irq; | ||
| 98 | } overrides | ||
| 99 | #ifdef OVERRIDE | ||
| 100 | [] __initdata = OVERRIDE; | ||
| 101 | #else | ||
| 102 | [4] __initdata = { | ||
| 103 | { 0, IRQ_AUTO }, { 0, IRQ_AUTO }, { 0, IRQ_AUTO }, { 0, IRQ_AUTO } | ||
| 104 | }; | ||
| 105 | #endif | ||
| 106 | |||
| 107 | #define NO_OVERRIDES ARRAY_SIZE(overrides) | ||
| 108 | |||
| 109 | static struct base { | ||
| 110 | unsigned long address; | ||
| 111 | int noauto; | ||
| 112 | } bases[] __initdata = { | ||
| 113 | { 0xcc000, 0 }, | ||
| 114 | { 0xc8000, 0 }, | ||
| 115 | { 0xdc000, 0 }, | ||
| 116 | { 0xd8000, 0 } | ||
| 117 | }; | ||
| 118 | |||
| 119 | #define NO_BASES ARRAY_SIZE(bases) | ||
| 120 | |||
| 121 | static const struct signature { | ||
| 122 | const char *string; | ||
| 123 | int offset; | ||
| 124 | } signatures[] = { | ||
| 125 | {"DATA TECHNOLOGY CORPORATION BIOS", 0x25}, | ||
| 126 | }; | ||
| 127 | |||
| 128 | #define NO_SIGNATURES ARRAY_SIZE(signatures) | ||
| 129 | |||
| 130 | #ifndef MODULE | ||
| 131 | /* | ||
| 132 | * Function : dtc_setup(char *str, int *ints) | ||
| 133 | * | ||
| 134 | * Purpose : LILO command line initialization of the overrides array, | ||
| 135 | * | ||
| 136 | * Inputs : str - unused, ints - array of integer parameters with ints[0] | ||
| 137 | * equal to the number of ints. | ||
| 138 | * | ||
| 139 | */ | ||
| 140 | |||
| 141 | static int __init dtc_setup(char *str) | ||
| 142 | { | ||
| 143 | static int commandline_current; | ||
| 144 | int i; | ||
| 145 | int ints[10]; | ||
| 146 | |||
| 147 | get_options(str, ARRAY_SIZE(ints), ints); | ||
| 148 | if (ints[0] != 2) | ||
| 149 | printk("dtc_setup: usage dtc=address,irq\n"); | ||
| 150 | else if (commandline_current < NO_OVERRIDES) { | ||
| 151 | overrides[commandline_current].address = ints[1]; | ||
| 152 | overrides[commandline_current].irq = ints[2]; | ||
| 153 | for (i = 0; i < NO_BASES; ++i) | ||
| 154 | if (bases[i].address == ints[1]) { | ||
| 155 | bases[i].noauto = 1; | ||
| 156 | break; | ||
| 157 | } | ||
| 158 | ++commandline_current; | ||
| 159 | } | ||
| 160 | return 1; | ||
| 161 | } | ||
| 162 | |||
| 163 | __setup("dtc=", dtc_setup); | ||
| 164 | #endif | ||
| 165 | |||
| 166 | /* | ||
| 167 | * Function : int dtc_detect(struct scsi_host_template * tpnt) | ||
| 168 | * | ||
| 169 | * Purpose : detects and initializes DTC 3180/3280 controllers | ||
| 170 | * that were autoprobed, overridden on the LILO command line, | ||
| 171 | * or specified at compile time. | ||
| 172 | * | ||
| 173 | * Inputs : tpnt - template for this SCSI adapter. | ||
| 174 | * | ||
| 175 | * Returns : 1 if a host adapter was found, 0 if not. | ||
| 176 | * | ||
| 177 | */ | ||
| 178 | |||
| 179 | static int __init dtc_detect(struct scsi_host_template * tpnt) | ||
| 180 | { | ||
| 181 | static int current_override, current_base; | ||
| 182 | struct Scsi_Host *instance; | ||
| 183 | unsigned int addr; | ||
| 184 | void __iomem *base; | ||
| 185 | int sig, count; | ||
| 186 | |||
| 187 | for (count = 0; current_override < NO_OVERRIDES; ++current_override) { | ||
| 188 | addr = 0; | ||
| 189 | base = NULL; | ||
| 190 | |||
| 191 | if (overrides[current_override].address) { | ||
| 192 | addr = overrides[current_override].address; | ||
| 193 | base = ioremap(addr, 0x2000); | ||
| 194 | if (!base) | ||
| 195 | addr = 0; | ||
| 196 | } else | ||
| 197 | for (; !addr && (current_base < NO_BASES); ++current_base) { | ||
| 198 | dprintk(NDEBUG_INIT, "dtc: probing address 0x%08x\n", | ||
| 199 | (unsigned int)bases[current_base].address); | ||
| 200 | if (bases[current_base].noauto) | ||
| 201 | continue; | ||
| 202 | base = ioremap(bases[current_base].address, 0x2000); | ||
| 203 | if (!base) | ||
| 204 | continue; | ||
| 205 | for (sig = 0; sig < NO_SIGNATURES; ++sig) { | ||
| 206 | if (check_signature(base + signatures[sig].offset, signatures[sig].string, strlen(signatures[sig].string))) { | ||
| 207 | addr = bases[current_base].address; | ||
| 208 | dprintk(NDEBUG_INIT, "dtc: detected board\n"); | ||
| 209 | goto found; | ||
| 210 | } | ||
| 211 | } | ||
| 212 | iounmap(base); | ||
| 213 | } | ||
| 214 | |||
| 215 | dprintk(NDEBUG_INIT, "dtc: addr = 0x%08x\n", addr); | ||
| 216 | |||
| 217 | if (!addr) | ||
| 218 | break; | ||
| 219 | |||
| 220 | found: | ||
| 221 | instance = scsi_register(tpnt, sizeof(struct NCR5380_hostdata)); | ||
| 222 | if (instance == NULL) | ||
| 223 | goto out_unmap; | ||
| 224 | |||
| 225 | instance->base = addr; | ||
| 226 | ((struct NCR5380_hostdata *)(instance)->hostdata)->base = base; | ||
| 227 | |||
| 228 | if (NCR5380_init(instance, FLAG_LATE_DMA_SETUP)) | ||
| 229 | goto out_unregister; | ||
| 230 | |||
| 231 | NCR5380_maybe_reset_bus(instance); | ||
| 232 | |||
| 233 | NCR5380_write(DTC_CONTROL_REG, CSR_5380_INTR); /* Enable int's */ | ||
| 234 | if (overrides[current_override].irq != IRQ_AUTO) | ||
| 235 | instance->irq = overrides[current_override].irq; | ||
| 236 | else | ||
| 237 | instance->irq = NCR5380_probe_irq(instance, DTC_IRQS); | ||
| 238 | |||
| 239 | /* Compatibility with documented NCR5380 kernel parameters */ | ||
| 240 | if (instance->irq == 255) | ||
| 241 | instance->irq = NO_IRQ; | ||
| 242 | |||
| 243 | /* With interrupts enabled, it will sometimes hang when doing heavy | ||
| 244 | * reads. So better not enable them until I finger it out. */ | ||
| 245 | instance->irq = NO_IRQ; | ||
| 246 | |||
| 247 | if (instance->irq != NO_IRQ) | ||
| 248 | if (request_irq(instance->irq, dtc_intr, 0, | ||
| 249 | "dtc", instance)) { | ||
| 250 | printk(KERN_ERR "scsi%d : IRQ%d not free, interrupts disabled\n", instance->host_no, instance->irq); | ||
| 251 | instance->irq = NO_IRQ; | ||
| 252 | } | ||
| 253 | |||
| 254 | if (instance->irq == NO_IRQ) { | ||
| 255 | printk(KERN_WARNING "scsi%d : interrupts not enabled. for better interactive performance,\n", instance->host_no); | ||
| 256 | printk(KERN_WARNING "scsi%d : please jumper the board for a free IRQ.\n", instance->host_no); | ||
| 257 | } | ||
| 258 | |||
| 259 | dprintk(NDEBUG_INIT, "scsi%d : irq = %d\n", | ||
| 260 | instance->host_no, instance->irq); | ||
| 261 | |||
| 262 | ++current_override; | ||
| 263 | ++count; | ||
| 264 | } | ||
| 265 | return count; | ||
| 266 | |||
| 267 | out_unregister: | ||
| 268 | scsi_unregister(instance); | ||
| 269 | out_unmap: | ||
| 270 | iounmap(base); | ||
| 271 | return count; | ||
| 272 | } | ||
| 273 | |||
| 274 | /* | ||
| 275 | * Function : int dtc_biosparam(Disk * disk, struct block_device *dev, int *ip) | ||
| 276 | * | ||
| 277 | * Purpose : Generates a BIOS / DOS compatible H-C-S mapping for | ||
| 278 | * the specified device / size. | ||
| 279 | * | ||
| 280 | * Inputs : size = size of device in sectors (512 bytes), dev = block device | ||
| 281 | * major / minor, ip[] = {heads, sectors, cylinders} | ||
| 282 | * | ||
| 283 | * Returns : always 0 (success), initializes ip | ||
| 284 | * | ||
| 285 | */ | ||
| 286 | |||
| 287 | /* | ||
| 288 | * XXX Most SCSI boards use this mapping, I could be incorrect. Some one | ||
| 289 | * using hard disks on a trantor should verify that this mapping corresponds | ||
| 290 | * to that used by the BIOS / ASPI driver by running the linux fdisk program | ||
| 291 | * and matching the H_C_S coordinates to what DOS uses. | ||
| 292 | */ | ||
| 293 | |||
| 294 | static int dtc_biosparam(struct scsi_device *sdev, struct block_device *dev, | ||
| 295 | sector_t capacity, int *ip) | ||
| 296 | { | ||
| 297 | int size = capacity; | ||
| 298 | |||
| 299 | ip[0] = 64; | ||
| 300 | ip[1] = 32; | ||
| 301 | ip[2] = size >> 11; | ||
| 302 | return 0; | ||
| 303 | } | ||
| 304 | |||
| 305 | |||
| 306 | /**************************************************************** | ||
| 307 | * Function : int NCR5380_pread (struct Scsi_Host *instance, | ||
| 308 | * unsigned char *dst, int len) | ||
| 309 | * | ||
| 310 | * Purpose : Fast 5380 pseudo-dma read function, reads len bytes to | ||
| 311 | * dst | ||
| 312 | * | ||
| 313 | * Inputs : dst = destination, len = length in bytes | ||
| 314 | * | ||
| 315 | * Returns : 0 on success, non zero on a failure such as a watchdog | ||
| 316 | * timeout. | ||
| 317 | */ | ||
| 318 | |||
| 319 | static inline int dtc_pread(struct Scsi_Host *instance, | ||
| 320 | unsigned char *dst, int len) | ||
| 321 | { | ||
| 322 | unsigned char *d = dst; | ||
| 323 | int i; /* For counting time spent in the poll-loop */ | ||
| 324 | struct NCR5380_hostdata *hostdata = shost_priv(instance); | ||
| 325 | |||
| 326 | i = 0; | ||
| 327 | if (instance->irq == NO_IRQ) | ||
| 328 | NCR5380_write(DTC_CONTROL_REG, CSR_DIR_READ); | ||
| 329 | else | ||
| 330 | NCR5380_write(DTC_CONTROL_REG, CSR_DIR_READ | CSR_INT_BASE); | ||
| 331 | NCR5380_write(DTC_BLK_CNT, len >> 7); /* Block count */ | ||
| 332 | rtrc(1); | ||
| 333 | while (len > 0) { | ||
| 334 | rtrc(2); | ||
| 335 | while (NCR5380_read(DTC_CONTROL_REG) & CSR_HOST_BUF_NOT_RDY) | ||
| 336 | ++i; | ||
| 337 | rtrc(3); | ||
| 338 | memcpy_fromio(d, hostdata->base + DTC_DATA_BUF, 128); | ||
| 339 | d += 128; | ||
| 340 | len -= 128; | ||
| 341 | rtrc(7); | ||
| 342 | /*** with int's on, it sometimes hangs after here. | ||
| 343 | * Looks like something makes HBNR go away. */ | ||
| 344 | } | ||
| 345 | rtrc(4); | ||
| 346 | while (!(NCR5380_read(DTC_CONTROL_REG) & D_CR_ACCESS)) | ||
| 347 | ++i; | ||
| 348 | rtrc(0); | ||
| 349 | return (0); | ||
| 350 | } | ||
| 351 | |||
| 352 | /**************************************************************** | ||
| 353 | * Function : int NCR5380_pwrite (struct Scsi_Host *instance, | ||
| 354 | * unsigned char *src, int len) | ||
| 355 | * | ||
| 356 | * Purpose : Fast 5380 pseudo-dma write function, transfers len bytes from | ||
| 357 | * src | ||
| 358 | * | ||
| 359 | * Inputs : src = source, len = length in bytes | ||
| 360 | * | ||
| 361 | * Returns : 0 on success, non zero on a failure such as a watchdog | ||
| 362 | * timeout. | ||
| 363 | */ | ||
| 364 | |||
| 365 | static inline int dtc_pwrite(struct Scsi_Host *instance, | ||
| 366 | unsigned char *src, int len) | ||
| 367 | { | ||
| 368 | int i; | ||
| 369 | struct NCR5380_hostdata *hostdata = shost_priv(instance); | ||
| 370 | |||
| 371 | if (instance->irq == NO_IRQ) | ||
| 372 | NCR5380_write(DTC_CONTROL_REG, 0); | ||
| 373 | else | ||
| 374 | NCR5380_write(DTC_CONTROL_REG, CSR_5380_INTR); | ||
| 375 | NCR5380_write(DTC_BLK_CNT, len >> 7); /* Block count */ | ||
| 376 | for (i = 0; len > 0; ++i) { | ||
| 377 | rtrc(5); | ||
| 378 | /* Poll until the host buffer can accept data. */ | ||
| 379 | while (NCR5380_read(DTC_CONTROL_REG) & CSR_HOST_BUF_NOT_RDY) | ||
| 380 | ++i; | ||
| 381 | rtrc(3); | ||
| 382 | memcpy_toio(hostdata->base + DTC_DATA_BUF, src, 128); | ||
| 383 | src += 128; | ||
| 384 | len -= 128; | ||
| 385 | } | ||
| 386 | rtrc(4); | ||
| 387 | while (!(NCR5380_read(DTC_CONTROL_REG) & D_CR_ACCESS)) | ||
| 388 | ++i; | ||
| 389 | rtrc(6); | ||
| 390 | /* Wait until the last byte has been sent to the disk */ | ||
| 391 | while (!(NCR5380_read(TARGET_COMMAND_REG) & TCR_LAST_BYTE_SENT)) | ||
| 392 | ++i; | ||
| 393 | rtrc(7); | ||
| 394 | /* Check for parity error here. fixme. */ | ||
| 395 | rtrc(0); | ||
| 396 | return (0); | ||
| 397 | } | ||
| 398 | |||
| 399 | static int dtc_dma_xfer_len(struct scsi_cmnd *cmd) | ||
| 400 | { | ||
| 401 | int transfersize = cmd->transfersize; | ||
| 402 | |||
| 403 | /* Limit transfers to 32K, for xx400 & xx406 | ||
| 404 | * pseudoDMA that transfers in 128 bytes blocks. | ||
| 405 | */ | ||
| 406 | if (transfersize > 32 * 1024 && cmd->SCp.this_residual && | ||
| 407 | !(cmd->SCp.this_residual % transfersize)) | ||
| 408 | transfersize = 32 * 1024; | ||
| 409 | |||
| 410 | return transfersize; | ||
| 411 | } | ||
| 412 | |||
| 413 | MODULE_LICENSE("GPL"); | ||
| 414 | |||
| 415 | #include "NCR5380.c" | ||
| 416 | |||
| 417 | static int dtc_release(struct Scsi_Host *shost) | ||
| 418 | { | ||
| 419 | struct NCR5380_hostdata *hostdata = shost_priv(shost); | ||
| 420 | |||
| 421 | if (shost->irq != NO_IRQ) | ||
| 422 | free_irq(shost->irq, shost); | ||
| 423 | NCR5380_exit(shost); | ||
| 424 | scsi_unregister(shost); | ||
| 425 | iounmap(hostdata->base); | ||
| 426 | return 0; | ||
| 427 | } | ||
| 428 | |||
| 429 | static struct scsi_host_template driver_template = { | ||
| 430 | .name = "DTC 3180/3280", | ||
| 431 | .detect = dtc_detect, | ||
| 432 | .release = dtc_release, | ||
| 433 | .proc_name = "dtc3x80", | ||
| 434 | .info = dtc_info, | ||
| 435 | .queuecommand = dtc_queue_command, | ||
| 436 | .eh_abort_handler = dtc_abort, | ||
| 437 | .eh_bus_reset_handler = dtc_bus_reset, | ||
| 438 | .bios_param = dtc_biosparam, | ||
| 439 | .can_queue = 32, | ||
| 440 | .this_id = 7, | ||
| 441 | .sg_tablesize = SG_ALL, | ||
| 442 | .cmd_per_lun = 2, | ||
| 443 | .use_clustering = DISABLE_CLUSTERING, | ||
| 444 | .cmd_size = NCR5380_CMD_SIZE, | ||
| 445 | .max_sectors = 128, | ||
| 446 | }; | ||
| 447 | #include "scsi_module.c" | ||
| @@ -1,42 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * DTC controller, taken from T128 driver by... | ||
| 3 | * Copyright 1993, Drew Eckhardt | ||
| 4 | * Visionary Computing | ||
| 5 | * (Unix and Linux consulting and custom programming) | ||
| 6 | * drew@colorado.edu | ||
| 7 | * +1 (303) 440-4894 | ||
| 8 | */ | ||
| 9 | |||
| 10 | #ifndef DTC3280_H | ||
| 11 | #define DTC3280_H | ||
| 12 | |||
| 13 | #define NCR5380_implementation_fields \ | ||
| 14 | void __iomem *base | ||
| 15 | |||
| 16 | #define DTC_address(reg) \ | ||
| 17 | (((struct NCR5380_hostdata *)shost_priv(instance))->base + DTC_5380_OFFSET + reg) | ||
| 18 | |||
| 19 | #define NCR5380_read(reg) (readb(DTC_address(reg))) | ||
| 20 | #define NCR5380_write(reg, value) (writeb(value, DTC_address(reg))) | ||
| 21 | |||
| 22 | #define NCR5380_dma_xfer_len(instance, cmd, phase) \ | ||
| 23 | dtc_dma_xfer_len(cmd) | ||
| 24 | #define NCR5380_dma_recv_setup dtc_pread | ||
| 25 | #define NCR5380_dma_send_setup dtc_pwrite | ||
| 26 | #define NCR5380_dma_residual(instance) (0) | ||
| 27 | |||
| 28 | #define NCR5380_intr dtc_intr | ||
| 29 | #define NCR5380_queue_command dtc_queue_command | ||
| 30 | #define NCR5380_abort dtc_abort | ||
| 31 | #define NCR5380_bus_reset dtc_bus_reset | ||
| 32 | #define NCR5380_info dtc_info | ||
| 33 | |||
| 34 | #define NCR5380_io_delay(x) udelay(x) | ||
| 35 | |||
| 36 | /* 15 12 11 10 | ||
| 37 | 1001 1100 0000 0000 */ | ||
| 38 | |||
| 39 | #define DTC_IRQS 0x9c00 | ||
| 40 | |||
| 41 | |||
| 42 | #endif /* DTC3280_H */ | ||
| @@ -963,10 +963,6 @@ bool esas2r_init_adapter_struct(struct esas2r_adapter *a, · 962 unmodified lines | |||
| 963 | 963 | ||
| 964 | /* initialize the allocated memory */ | 964 | /* initialize the allocated memory */ |
| 965 | if (test_bit(AF_FIRST_INIT, &a->flags)) { | 965 | if (test_bit(AF_FIRST_INIT, &a->flags)) { |
| 966 | memset(a->req_table, 0, | ||
| 967 | (num_requests + num_ae_requests + | ||
| 968 | 1) * sizeof(struct esas2r_request *)); | ||
| 969 | |||
| 970 | esas2r_targ_db_initialize(a); | 966 | esas2r_targ_db_initialize(a); |
| 971 | 967 | ||
| 972 | /* prime parts of the inbound list */ | 968 | /* prime parts of the inbound list */ |
| @@ -194,7 +194,7 @@ static ssize_t write_hw(struct file *file, struct kobject *kobj, · 193 unmodified lines | |||
| 194 | int length = min(sizeof(struct atto_ioctl), count); | 194 | int length = min(sizeof(struct atto_ioctl), count); |
| 195 | 195 | ||
| 196 | if (!a->local_atto_ioctl) { | 196 | if (!a->local_atto_ioctl) { |
| 197 | a->local_atto_ioctl = kzalloc(sizeof(struct atto_ioctl), | 197 | a->local_atto_ioctl = kmalloc(sizeof(struct atto_ioctl), |
| 198 | GFP_KERNEL); | 198 | GFP_KERNEL); |
| 199 | if (a->local_atto_ioctl == NULL) { | 199 | if (a->local_atto_ioctl == NULL) { |
| 200 | esas2r_log(ESAS2R_LOG_WARN, | 200 | esas2r_log(ESAS2R_LOG_WARN, |
| @@ -83,6 +83,41 @@ static struct notifier_block libfcoe_notifier = { · 82 unmodified lines | |||
| 83 | .notifier_call = libfcoe_device_notification, | 83 | .notifier_call = libfcoe_device_notification, |
| 84 | }; | 84 | }; |
| 85 | 85 | ||
| 86 | static const struct { | ||
| 87 | u32 fc_port_speed; | ||
| 88 | #define SPEED_2000 2000 | ||
| 89 | #define SPEED_4000 4000 | ||
| 90 | #define SPEED_8000 8000 | ||
| 91 | #define SPEED_16000 16000 | ||
| 92 | #define SPEED_32000 32000 | ||
| 93 | u32 eth_port_speed; | ||
| 94 | } fcoe_port_speed_mapping[] = { | ||
| 95 | { FC_PORTSPEED_1GBIT, SPEED_1000 }, | ||
| 96 | { FC_PORTSPEED_2GBIT, SPEED_2000 }, | ||
| 97 | { FC_PORTSPEED_4GBIT, SPEED_4000 }, | ||
| 98 | { FC_PORTSPEED_8GBIT, SPEED_8000 }, | ||
| 99 | { FC_PORTSPEED_10GBIT, SPEED_10000 }, | ||
| 100 | { FC_PORTSPEED_16GBIT, SPEED_16000 }, | ||
| 101 | { FC_PORTSPEED_20GBIT, SPEED_20000 }, | ||
| 102 | { FC_PORTSPEED_25GBIT, SPEED_25000 }, | ||
| 103 | { FC_PORTSPEED_32GBIT, SPEED_32000 }, | ||
| 104 | { FC_PORTSPEED_40GBIT, SPEED_40000 }, | ||
| 105 | { FC_PORTSPEED_50GBIT, SPEED_50000 }, | ||
| 106 | { FC_PORTSPEED_100GBIT, SPEED_100000 }, | ||
| 107 | }; | ||
| 108 | |||
| 109 | static inline u32 eth2fc_speed(u32 eth_port_speed) | ||
| 110 | { | ||
| 111 | int i; | ||
| 112 | |||
| 113 | for (i = 0; i < ARRAY_SIZE(fcoe_port_speed_mapping); i++) { | ||
| 114 | if (fcoe_port_speed_mapping[i].eth_port_speed == eth_port_speed) | ||
| 115 | return fcoe_port_speed_mapping[i].fc_port_speed; | ||
| 116 | } | ||
| 117 | |||
| 118 | return FC_PORTSPEED_UNKNOWN; | ||
| 119 | } | ||
| 120 | |||
| 86 | /** | 121 | /** |
| 87 | * fcoe_link_speed_update() - Update the supported and actual link speeds | 122 | * fcoe_link_speed_update() - Update the supported and actual link speeds |
| 88 | * @lport: The local port to update speeds for | 123 | * @lport: The local port to update speeds for |
| @@ -126,23 +161,7 @@ int fcoe_link_speed_update(struct fc_lport *lport) · 37 unmodified lines | |||
| 126 | SUPPORTED_40000baseLR4_Full)) | 161 | SUPPORTED_40000baseLR4_Full)) |
| 127 | lport->link_supported_speeds |= FC_PORTSPEED_40GBIT; | 162 | lport->link_supported_speeds |= FC_PORTSPEED_40GBIT; |
| 128 | 163 | ||
| 129 | switch (ecmd.base.speed) { | 164 | lport->link_speed = eth2fc_speed(ecmd.base.speed); |
| 130 | case SPEED_1000: | ||
| 131 | lport->link_speed = FC_PORTSPEED_1GBIT; | ||
| 132 | break; | ||
| 133 | case SPEED_10000: | ||
| 134 | lport->link_speed = FC_PORTSPEED_10GBIT; | ||
| 135 | break; | ||
| 136 | case SPEED_20000: | ||
| 137 | lport->link_speed = FC_PORTSPEED_20GBIT; | ||
| 138 | break; | ||
| 139 | case SPEED_40000: | ||
| 140 | lport->link_speed = FC_PORTSPEED_40GBIT; | ||
| 141 | break; | ||
| 142 | default: | ||
| 143 | lport->link_speed = FC_PORTSPEED_UNKNOWN; | ||
| 144 | break; | ||
| 145 | } | ||
| 146 | return 0; | 165 | return 0; |
| 147 | } | 166 | } |
| 148 | return -1; | 167 | return -1; |
| @@ -23,7 +23,7 @@ · 22 unmodified lines | |||
| 23 | #include <scsi/sas_ata.h> | 23 | #include <scsi/sas_ata.h> |
| 24 | #include <scsi/libsas.h> | 24 | #include <scsi/libsas.h> |
| 25 | 25 | ||
| 26 | #define DRV_VERSION "v1.5" | 26 | #define DRV_VERSION "v1.6" |
| 27 | 27 | ||
| 28 | #define HISI_SAS_MAX_PHYS 9 | 28 | #define HISI_SAS_MAX_PHYS 9 |
| 29 | #define HISI_SAS_MAX_QUEUES 32 | 29 | #define HISI_SAS_MAX_QUEUES 32 |
| @@ -56,6 +56,11 @@ enum dev_status { · 26 unmodified lines | |||
| 56 | HISI_SAS_DEV_EH, | 56 | HISI_SAS_DEV_EH, |
| 57 | }; | 57 | }; |
| 58 | 58 | ||
| 59 | enum { | ||
| 60 | HISI_SAS_INT_ABT_CMD = 0, | ||
| 61 | HISI_SAS_INT_ABT_DEV = 1, | ||
| 62 | }; | ||
| 63 | |||
| 59 | enum hisi_sas_dev_type { | 64 | enum hisi_sas_dev_type { |
| 60 | HISI_SAS_DEV_TYPE_STP = 0, | 65 | HISI_SAS_DEV_TYPE_STP = 0, |
| 61 | HISI_SAS_DEV_TYPE_SSP, | 66 | HISI_SAS_DEV_TYPE_SSP, |
| @@ -89,6 +94,13 @@ struct hisi_sas_port { · 27 unmodified lines | |||
| 89 | 94 | ||
| 90 | struct hisi_sas_cq { | 95 | struct hisi_sas_cq { |
| 91 | struct hisi_hba *hisi_hba; | 96 | struct hisi_hba *hisi_hba; |
| 97 | int rd_point; | ||
| 98 | int id; | ||
| 99 | }; | ||
| 100 | |||
| 101 | struct hisi_sas_dq { | ||
| 102 | struct hisi_hba *hisi_hba; | ||
| 103 | int wr_point; | ||
| 92 | int id; | 104 | int id; |
| 93 | }; | 105 | }; |
| 94 | 106 | ||
| @@ -146,6 +158,9 @@ struct hisi_sas_hw { · 51 unmodified lines | |||
| 146 | struct hisi_sas_slot *slot); | 158 | struct hisi_sas_slot *slot); |
| 147 | int (*prep_stp)(struct hisi_hba *hisi_hba, | 159 | int (*prep_stp)(struct hisi_hba *hisi_hba, |
| 148 | struct hisi_sas_slot *slot); | 160 | struct hisi_sas_slot *slot); |
| 161 | int (*prep_abort)(struct hisi_hba *hisi_hba, | ||
| 162 | struct hisi_sas_slot *slot, | ||
| 163 | int device_id, int abort_flag, int tag_to_abort); | ||
| 149 | int (*slot_complete)(struct hisi_hba *hisi_hba, | 164 | int (*slot_complete)(struct hisi_hba *hisi_hba, |
| 150 | struct hisi_sas_slot *slot, int abort); | 165 | struct hisi_sas_slot *slot, int abort); |
| 151 | void (*phy_enable)(struct hisi_hba *hisi_hba, int phy_no); | 166 | void (*phy_enable)(struct hisi_hba *hisi_hba, int phy_no); |
| @@ -185,6 +200,7 @@ struct hisi_hba { · 33 unmodified lines | |||
| 185 | struct Scsi_Host *shost; | 200 | struct Scsi_Host *shost; |
| 186 | 201 | ||
| 187 | struct hisi_sas_cq cq[HISI_SAS_MAX_QUEUES]; | 202 | struct hisi_sas_cq cq[HISI_SAS_MAX_QUEUES]; |
| 203 | struct hisi_sas_dq dq[HISI_SAS_MAX_QUEUES]; | ||
| 188 | struct hisi_sas_phy phy[HISI_SAS_MAX_PHYS]; | 204 | struct hisi_sas_phy phy[HISI_SAS_MAX_PHYS]; |
| 189 | struct hisi_sas_port port[HISI_SAS_MAX_PHYS]; | 205 | struct hisi_sas_port port[HISI_SAS_MAX_PHYS]; |
| 190 | 206 | ||
| @@ -17,6 +17,10 @@ · 16 unmodified lines | |||
| 17 | 17 | ||
| 18 | static int hisi_sas_debug_issue_ssp_tmf(struct domain_device *device, | 18 | static int hisi_sas_debug_issue_ssp_tmf(struct domain_device *device, |
| 19 | u8 *lun, struct hisi_sas_tmf_task *tmf); | 19 | u8 *lun, struct hisi_sas_tmf_task *tmf); |
| 20 | static int | ||
| 21 | hisi_sas_internal_task_abort(struct hisi_hba *hisi_hba, | ||
| 22 | struct domain_device *device, | ||
| 23 | int abort_flag, int tag); | ||
| 20 | 24 | ||
| 21 | static struct hisi_hba *dev_to_hisi_hba(struct domain_device *device) | 25 | static struct hisi_hba *dev_to_hisi_hba(struct domain_device *device) |
| 22 | { | 26 | { |
| @@ -93,7 +97,7 @@ void hisi_sas_slot_task_free(struct hisi_hba *hisi_hba, struct sas_task *task, · 70 unmodified lines | |||
| 93 | slot->task = NULL; | 97 | slot->task = NULL; |
| 94 | slot->port = NULL; | 98 | slot->port = NULL; |
| 95 | hisi_sas_slot_index_free(hisi_hba, slot->idx); | 99 | hisi_sas_slot_index_free(hisi_hba, slot->idx); |
| 96 | memset(slot, 0, sizeof(*slot)); | 100 | /* slot memory is fully zeroed when it is reused */ |
| 97 | } | 101 | } |
| 98 | EXPORT_SYMBOL_GPL(hisi_sas_slot_task_free); | 102 | EXPORT_SYMBOL_GPL(hisi_sas_slot_task_free); |
| 99 | 103 | ||
| @@ -116,6 +120,14 @@ static int hisi_sas_task_prep_ata(struct hisi_hba *hisi_hba, · 16 unmodified lines | |||
| 116 | return hisi_hba->hw->prep_stp(hisi_hba, slot); | 120 | return hisi_hba->hw->prep_stp(hisi_hba, slot); |
| 117 | } | 121 | } |
| 118 | 122 | ||
| 123 | static int hisi_sas_task_prep_abort(struct hisi_hba *hisi_hba, | ||
| 124 | struct hisi_sas_slot *slot, | ||
| 125 | int device_id, int abort_flag, int tag_to_abort) | ||
| 126 | { | ||
| 127 | return hisi_hba->hw->prep_abort(hisi_hba, slot, | ||
| 128 | device_id, abort_flag, tag_to_abort); | ||
| 129 | } | ||
| 130 | |||
| 119 | /* | 131 | /* |
| 120 | * This function will issue an abort TMF regardless of whether the | 132 | * This function will issue an abort TMF regardless of whether the |
| 121 | * task is in the sdev or not. Then it will do the task complete | 133 | * task is in the sdev or not. Then it will do the task complete |
| @@ -192,27 +204,13 @@ static int hisi_sas_task_prep(struct sas_task *task, struct hisi_hba *hisi_hba, · 70 unmodified lines | |||
| 192 | return rc; | 204 | return rc; |
| 193 | } | 205 | } |
| 194 | port = device->port->lldd_port; | 206 | port = device->port->lldd_port; |
| 195 | if (port && !port->port_attached && !tmf) { | 207 | if (port && !port->port_attached) { |
| 196 | if (sas_protocol_ata(task->task_proto)) { | 208 | dev_info(dev, "task prep: %s port%d not attach device\n", |
| 197 | struct task_status_struct *ts = &task->task_status; | 209 | (sas_protocol_ata(task->task_proto)) ? |
| 198 | 210 | "SATA/STP" : "SAS", | |
| 199 | dev_info(dev, | 211 | device->port->id); |
| 200 | "task prep: SATA/STP port%d not attach device\n", | 212 | |
| 201 | device->port->id); | 213 | return SAS_PHY_DOWN; |
| 202 | ts->resp = SAS_TASK_COMPLETE; | ||
| 203 | ts->stat = SAS_PHY_DOWN; | ||
| 204 | task->task_done(task); | ||
| 205 | } else { | ||
| 206 | struct task_status_struct *ts = &task->task_status; | ||
| 207 | |||
| 208 | dev_info(dev, | ||
| 209 | "task prep: SAS port%d does not attach device\n", | ||
| 210 | device->port->id); | ||
| 211 | ts->resp = SAS_TASK_UNDELIVERED; | ||
| 212 | ts->stat = SAS_PHY_DOWN; | ||
| 213 | task->task_done(task); | ||
| 214 | } | ||
| 215 | return 0; | ||
| 216 | } | 214 | } |
| 217 | 215 | ||
| 218 | if (!sas_protocol_ata(task->task_proto)) { | 216 | if (!sas_protocol_ata(task->task_proto)) { |
| @@ -609,6 +607,9 @@ static void hisi_sas_dev_gone(struct domain_device *device) · 390 unmodified lines | |||
| 609 | dev_info(dev, "found dev[%lld:%x] is gone\n", | 607 | dev_info(dev, "found dev[%lld:%x] is gone\n", |
| 610 | sas_dev->device_id, sas_dev->dev_type); | 608 | sas_dev->device_id, sas_dev->dev_type); |
| 611 | 609 | ||
| 610 | hisi_sas_internal_task_abort(hisi_hba, device, | ||
| 611 | HISI_SAS_INT_ABT_DEV, 0); | ||
| 612 | |||
| 612 | hisi_hba->hw->free_device(hisi_hba, sas_dev); | 613 | hisi_hba->hw->free_device(hisi_hba, sas_dev); |
| 613 | device->lldd_dev = NULL; | 614 | device->lldd_dev = NULL; |
| 614 | memset(sas_dev, 0, sizeof(*sas_dev)); | 615 | memset(sas_dev, 0, sizeof(*sas_dev)); |
| @@ -728,6 +729,12 @@ static int hisi_sas_exec_internal_tmf_task(struct domain_device *device, · 113 unmodified lines | |||
| 728 | break; | 729 | break; |
| 729 | } | 730 | } |
| 730 | 731 | ||
| 732 | if (task->task_status.resp == SAS_TASK_COMPLETE && | ||
| 733 | task->task_status.stat == TMF_RESP_FUNC_SUCC) { | ||
| 734 | res = TMF_RESP_FUNC_SUCC; | ||
| 735 | break; | ||
| 736 | } | ||
| 737 | |||
| 731 | if (task->task_status.resp == SAS_TASK_COMPLETE && | 738 | if (task->task_status.resp == SAS_TASK_COMPLETE && |
| 732 | task->task_status.stat == SAS_DATA_UNDERRUN) { | 739 | task->task_status.stat == SAS_DATA_UNDERRUN) { |
| 733 | /* no error, but return the number of bytes of | 740 | /* no error, but return the number of bytes of |
| @@ -826,18 +833,22 @@ static int hisi_sas_abort_task(struct sas_task *task) · 92 unmodified lines | |||
| 826 | } | 833 | } |
| 827 | } | 834 | } |
| 828 | 835 | ||
| 836 | hisi_sas_internal_task_abort(hisi_hba, device, | ||
| 837 | HISI_SAS_INT_ABT_CMD, tag); | ||
| 829 | } else if (task->task_proto & SAS_PROTOCOL_SATA || | 838 | } else if (task->task_proto & SAS_PROTOCOL_SATA || |
| 830 | task->task_proto & SAS_PROTOCOL_STP) { | 839 | task->task_proto & SAS_PROTOCOL_STP) { |
| 831 | if (task->dev->dev_type == SAS_SATA_DEV) { | 840 | if (task->dev->dev_type == SAS_SATA_DEV) { |
| 832 | struct hisi_slot_info *slot = task->lldd_task; | 841 | hisi_sas_internal_task_abort(hisi_hba, device, |
| 833 | 842 | HISI_SAS_INT_ABT_DEV, 0); | |
| 834 | dev_notice(dev, "abort task: hba=%p task=%p slot=%p\n", | ||
| 835 | hisi_hba, task, slot); | ||
| 836 | task->task_state_flags |= SAS_TASK_STATE_ABORTED; | ||
| 837 | rc = TMF_RESP_FUNC_COMPLETE; | 843 | rc = TMF_RESP_FUNC_COMPLETE; |
| 838 | goto out; | ||
| 839 | } | 844 | } |
| 845 | } else if (task->task_proto & SAS_PROTOCOL_SMP) { | ||
| 846 | /* SMP */ | ||
| 847 | struct hisi_sas_slot *slot = task->lldd_task; | ||
| 848 | u32 tag = slot->idx; | ||
| 840 | 849 | ||
| 850 | hisi_sas_internal_task_abort(hisi_hba, device, | ||
| 851 | HISI_SAS_INT_ABT_CMD, tag); | ||
| 841 | } | 852 | } |
| 842 | 853 | ||
| 843 | out: | 854 | out: |
| @@ -954,6 +965,157 @@ static int hisi_sas_query_task(struct sas_task *task) · 110 unmodified lines | |||
| 954 | return rc; | 965 | return rc; |
| 955 | } | 966 | } |
| 956 | 967 | ||
| 968 | static int | ||
| 969 | hisi_sas_internal_abort_task_exec(struct hisi_hba *hisi_hba, u64 device_id, | ||
| 970 | struct sas_task *task, int abort_flag, | ||
| 971 | int task_tag) | ||
| 972 | { | ||
| 973 | struct domain_device *device = task->dev; | ||
| 974 | struct hisi_sas_device *sas_dev = device->lldd_dev; | ||
| 975 | struct device *dev = &hisi_hba->pdev->dev; | ||
| 976 | struct hisi_sas_port *port; | ||
| 977 | struct hisi_sas_slot *slot; | ||
| 978 | struct hisi_sas_cmd_hdr *cmd_hdr_base; | ||
| 979 | int dlvry_queue_slot, dlvry_queue, n_elem = 0, rc, slot_idx; | ||
| 980 | |||
| 981 | if (!device->port) | ||
| 982 | return -1; | ||
| 983 | |||
| 984 | port = device->port->lldd_port; | ||
| 985 | |||
| 986 | /* simply get a slot and send abort command */ | ||
| 987 | rc = hisi_sas_slot_index_alloc(hisi_hba, &slot_idx); | ||
| 988 | if (rc) | ||
| 989 | goto err_out; | ||
| 990 | rc = hisi_hba->hw->get_free_slot(hisi_hba, &dlvry_queue, | ||
| 991 | &dlvry_queue_slot); | ||
| 992 | if (rc) | ||
| 993 | goto err_out_tag; | ||
| 994 | |||
| 995 | slot = &hisi_hba->slot_info[slot_idx]; | ||
| 996 | memset(slot, 0, sizeof(struct hisi_sas_slot)); | ||
| 997 | |||
| 998 | slot->idx = slot_idx; | ||
| 999 | slot->n_elem = n_elem; | ||
| 1000 | slot->dlvry_queue = dlvry_queue; | ||
| 1001 | slot->dlvry_queue_slot = dlvry_queue_slot; | ||
| 1002 | cmd_hdr_base = hisi_hba->cmd_hdr[dlvry_queue]; | ||
| 1003 | slot->cmd_hdr = &cmd_hdr_base[dlvry_queue_slot]; | ||
| 1004 | slot->task = task; | ||
| 1005 | slot->port = port; | ||
| 1006 | task->lldd_task = slot; | ||
| 1007 | |||
| 1008 | memset(slot->cmd_hdr, 0, sizeof(struct hisi_sas_cmd_hdr)); | ||
| 1009 | |||
| 1010 | rc = hisi_sas_task_prep_abort(hisi_hba, slot, device_id, | ||
| 1011 | abort_flag, task_tag); | ||
| 1012 | if (rc) | ||
| 1013 | goto err_out_tag; | ||
| 1014 | |||
| 1015 | /* Port structure is static for the HBA, so | ||
| 1016 | * even if the port is deformed it is ok | ||
| 1017 | * to reference. | ||
| 1018 | */ | ||
| 1019 | list_add_tail(&slot->entry, &port->list); | ||
| 1020 | spin_lock(&task->task_state_lock); | ||
| 1021 | task->task_state_flags |= SAS_TASK_AT_INITIATOR; | ||
| 1022 | spin_unlock(&task->task_state_lock); | ||
| 1023 | |||
| 1024 | hisi_hba->slot_prep = slot; | ||
| 1025 | |||
| 1026 | sas_dev->running_req++; | ||
| 1027 | /* send abort command to our chip */ | ||
| 1028 | hisi_hba->hw->start_delivery(hisi_hba); | ||
| 1029 | |||
| 1030 | return 0; | ||
| 1031 | |||
| 1032 | err_out_tag: | ||
| 1033 | hisi_sas_slot_index_free(hisi_hba, slot_idx); | ||
| 1034 | err_out: | ||
| 1035 | dev_err(dev, "internal abort task prep: failed[%d]!\n", rc); | ||
| 1036 | |||
| 1037 | return rc; | ||
| 1038 | } | ||
| 1039 | |||
| 1040 | /** | ||
| 1041 | * hisi_sas_internal_task_abort -- execute an internal | ||
| 1042 | * abort command for single IO command or a device | ||
| 1043 | * @hisi_hba: host controller struct | ||
| 1044 | * @device: domain device | ||
| 1045 | * @abort_flag: mode of operation, device or single IO | ||
| 1046 | * @tag: tag of IO to be aborted (only relevant to single | ||
| 1047 | * IO mode) | ||
| 1048 | */ | ||
| 1049 | static int | ||
| 1050 | hisi_sas_internal_task_abort(struct hisi_hba *hisi_hba, | ||
| 1051 | struct domain_device *device, | ||
| 1052 | int abort_flag, int tag) | ||
| 1053 | { | ||
| 1054 | struct sas_task *task; | ||
| 1055 | struct hisi_sas_device *sas_dev = device->lldd_dev; | ||
| 1056 | struct device *dev = &hisi_hba->pdev->dev; | ||
| 1057 | int res; | ||
| 1058 | unsigned long flags; | ||
| 1059 | |||
| 1060 | if (!hisi_hba->hw->prep_abort) | ||
| 1061 | return -EOPNOTSUPP; | ||
| 1062 | |||
| 1063 | task = sas_alloc_slow_task(GFP_KERNEL); | ||
| 1064 | if (!task) | ||
| 1065 | return -ENOMEM; | ||
| 1066 | |||
| 1067 | task->dev = device; | ||
| 1068 | task->task_proto = device->tproto; | ||
| 1069 | task->task_done = hisi_sas_task_done; | ||
| 1070 | task->slow_task->timer.data = (unsigned long)task; | ||
| 1071 | task->slow_task->timer.function = hisi_sas_tmf_timedout; | ||
| 1072 | task->slow_task->timer.expires = jiffies + 20*HZ; | ||
| 1073 | add_timer(&task->slow_task->timer); | ||
| 1074 | |||
| 1075 | /* Lock as we are alloc'ing a slot, which cannot be interrupted */ | ||
| 1076 | spin_lock_irqsave(&hisi_hba->lock, flags); | ||
| 1077 | res = hisi_sas_internal_abort_task_exec(hisi_hba, sas_dev->device_id, | ||
| 1078 | task, abort_flag, tag); | ||
| 1079 | spin_unlock_irqrestore(&hisi_hba->lock, flags); | ||
| 1080 | if (res) { | ||
| 1081 | del_timer(&task->slow_task->timer); | ||
| 1082 | dev_err(dev, "internal task abort: executing internal task failed: %d\n", | ||
| 1083 | res); | ||
| 1084 | goto exit; | ||
| 1085 | } | ||
| 1086 | wait_for_completion(&task->slow_task->completion); | ||
| 1087 | res = TMF_RESP_FUNC_FAILED; | ||
| 1088 | |||
| 1089 | if (task->task_status.resp == SAS_TASK_COMPLETE && | ||
| 1090 | task->task_status.stat == TMF_RESP_FUNC_COMPLETE) { | ||
| 1091 | res = TMF_RESP_FUNC_COMPLETE; | ||
| 1092 | goto exit; | ||
| 1093 | } | ||
| 1094 | |||
| 1095 | /* TMF timed out, return direct. */ | ||
| 1096 | if ((task->task_state_flags & SAS_TASK_STATE_ABORTED)) { | ||
| 1097 | if (!(task->task_state_flags & SAS_TASK_STATE_DONE)) { | ||
| 1098 | dev_err(dev, "internal task abort: timeout.\n"); | ||
| 1099 | if (task->lldd_task) { | ||
| 1100 | struct hisi_sas_slot *slot = task->lldd_task; | ||
| 1101 | |||
| 1102 | hisi_sas_slot_task_free(hisi_hba, task, slot); | ||
| 1103 | } | ||
| 1104 | } | ||
| 1105 | } | ||
| 1106 | |||
| 1107 | exit: | ||
| 1108 | dev_info(dev, "internal task abort: task to dev %016llx task=%p " | ||
| 1109 | "resp: 0x%x sts 0x%x\n", | ||
| 1110 | SAS_ADDR(device->sas_addr), | ||
| 1111 | task, | ||
| 1112 | task->task_status.resp, /* 0 is complete, -1 is undelivered */ | ||
| 1113 | task->task_status.stat); | ||
| 1114 | sas_free_task(task); | ||
| 1115 | |||
| 1116 | return res; | ||
| 1117 | } | ||
| 1118 | |||
| 957 | static void hisi_sas_port_formed(struct asd_sas_phy *sas_phy) | 1119 | static void hisi_sas_port_formed(struct asd_sas_phy *sas_phy) |
| 958 | { | 1120 | { |
| 959 | hisi_sas_port_notify_formed(sas_phy); | 1121 | hisi_sas_port_notify_formed(sas_phy); |
| @@ -1063,11 +1225,16 @@ static int hisi_sas_alloc(struct hisi_hba *hisi_hba, struct Scsi_Host *shost) · 103 unmodified lines | |||
| 1063 | 1225 | ||
| 1064 | for (i = 0; i < hisi_hba->queue_count; i++) { | 1226 | for (i = 0; i < hisi_hba->queue_count; i++) { |
| 1065 | struct hisi_sas_cq *cq = &hisi_hba->cq[i]; | 1227 | struct hisi_sas_cq *cq = &hisi_hba->cq[i]; |
| 1228 | struct hisi_sas_dq *dq = &hisi_hba->dq[i]; | ||
| 1066 | 1229 | ||
| 1067 | /* Completion queue structure */ | 1230 | /* Completion queue structure */ |
| 1068 | cq->id = i; | 1231 | cq->id = i; |
| 1069 | cq->hisi_hba = hisi_hba; | 1232 | cq->hisi_hba = hisi_hba; |
| 1070 | 1233 | ||
| 1234 | /* Delivery queue structure */ | ||
| 1235 | dq->id = i; | ||
| 1236 | dq->hisi_hba = hisi_hba; | ||
| 1237 | |||
| 1071 | /* Delivery queue */ | 1238 | /* Delivery queue */ |
| 1072 | s = sizeof(struct hisi_sas_cmd_hdr) * HISI_SAS_QUEUE_SLOTS; | 1239 | s = sizeof(struct hisi_sas_cmd_hdr) * HISI_SAS_QUEUE_SLOTS; |
| 1073 | hisi_hba->cmd_hdr[i] = dma_alloc_coherent(dev, s, | 1240 | hisi_hba->cmd_hdr[i] = dma_alloc_coherent(dev, s, |
| @@ -1128,7 +1295,7 @@ static int hisi_sas_alloc(struct hisi_hba *hisi_hba, struct Scsi_Host *shost) · 54 unmodified lines | |||
| 1128 | memset(hisi_hba->breakpoint, 0, s); | 1295 | memset(hisi_hba->breakpoint, 0, s); |
| 1129 | 1296 | ||
| 1130 | hisi_hba->slot_index_count = max_command_entries; | 1297 | hisi_hba->slot_index_count = max_command_entries; |
| 1131 | s = hisi_hba->slot_index_count / sizeof(unsigned long); | 1298 | s = hisi_hba->slot_index_count / BITS_PER_BYTE; |
| 1132 | hisi_hba->slot_index_tags = devm_kzalloc(dev, s, GFP_KERNEL); | 1299 | hisi_hba->slot_index_tags = devm_kzalloc(dev, s, GFP_KERNEL); |
| 1133 | if (!hisi_hba->slot_index_tags) | 1300 | if (!hisi_hba->slot_index_tags) |
| 1134 | goto err_out; | 1301 | goto err_out; |
| @@ -1272,6 +1439,12 @@ static struct Scsi_Host *hisi_sas_shost_alloc(struct platform_device *pdev, · 137 unmodified lines | |||
| 1272 | &hisi_hba->queue_count)) | 1439 | &hisi_hba->queue_count)) |
| 1273 | goto err_out; | 1440 | goto err_out; |
| 1274 | 1441 | ||
| 1442 | if (dma_set_mask_and_coherent(dev, DMA_BIT_MASK(64)) && | ||
| 1443 | dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32))) { | ||
| 1444 | dev_err(dev, "No usable DMA addressing method\n"); | ||
| 1445 | goto err_out; | ||
| 1446 | } | ||
| 1447 | |||
| 1275 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 1448 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
| 1276 | hisi_hba->regs = devm_ioremap_resource(dev, res); | 1449 | hisi_hba->regs = devm_ioremap_resource(dev, res); |
| 1277 | if (IS_ERR(hisi_hba->regs)) | 1450 | if (IS_ERR(hisi_hba->regs)) |
| @@ -1319,13 +1492,6 @@ int hisi_sas_probe(struct platform_device *pdev, · 41 unmodified lines | |||
| 1319 | hisi_hba = shost_priv(shost); | 1492 | hisi_hba = shost_priv(shost); |
| 1320 | platform_set_drvdata(pdev, sha); | 1493 | platform_set_drvdata(pdev, sha); |
| 1321 | 1494 | ||
| 1322 | if (dma_set_mask_and_coherent(dev, DMA_BIT_MASK(64)) && | ||
| 1323 | dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32))) { | ||
| 1324 | dev_err(dev, "No usable DMA addressing method\n"); | ||
| 1325 | rc = -EIO; | ||
| 1326 | goto err_out_ha; | ||
| 1327 | } | ||
| 1328 | |||
| 1329 | phy_nr = port_nr = hisi_hba->n_phy; | 1495 | phy_nr = port_nr = hisi_hba->n_phy; |
| 1330 | 1496 | ||
| 1331 | arr_phy = devm_kcalloc(dev, phy_nr, sizeof(void *), GFP_KERNEL); | 1497 | arr_phy = devm_kcalloc(dev, phy_nr, sizeof(void *), GFP_KERNEL); |
| @@ -490,25 +490,17 @@ static void config_id_frame_v1_hw(struct hisi_hba *hisi_hba, int phy_no) · 489 unmodified lines | |||
| 490 | hisi_sas_phy_write32(hisi_hba, phy_no, TX_ID_DWORD0, | 490 | hisi_sas_phy_write32(hisi_hba, phy_no, TX_ID_DWORD0, |
| 491 | __swab32(identify_buffer[0])); | 491 | __swab32(identify_buffer[0])); |
| 492 | hisi_sas_phy_write32(hisi_hba, phy_no, TX_ID_DWORD1, | 492 | hisi_sas_phy_write32(hisi_hba, phy_no, TX_ID_DWORD1, |
| 493 | identify_buffer[2]); | 493 | __swab32(identify_buffer[1])); |
| 494 | hisi_sas_phy_write32(hisi_hba, phy_no, TX_ID_DWORD2, | 494 | hisi_sas_phy_write32(hisi_hba, phy_no, TX_ID_DWORD2, |
| 495 | identify_buffer[1]); | 495 | __swab32(identify_buffer[2])); |
| 496 | hisi_sas_phy_write32(hisi_hba, phy_no, TX_ID_DWORD3, | 496 | hisi_sas_phy_write32(hisi_hba, phy_no, TX_ID_DWORD3, |
| 497 | identify_buffer[4]); | 497 | __swab32(identify_buffer[3])); |
| 498 | hisi_sas_phy_write32(hisi_hba, phy_no, TX_ID_DWORD4, | 498 | hisi_sas_phy_write32(hisi_hba, phy_no, TX_ID_DWORD4, |
| 499 | identify_buffer[3]); | 499 | __swab32(identify_buffer[4])); |
| 500 | hisi_sas_phy_write32(hisi_hba, phy_no, TX_ID_DWORD5, | 500 | hisi_sas_phy_write32(hisi_hba, phy_no, TX_ID_DWORD5, |
| 501 | __swab32(identify_buffer[5])); | 501 | __swab32(identify_buffer[5])); |
| 502 | } | 502 | } |
| 503 | 503 | ||
| 504 | static void init_id_frame_v1_hw(struct hisi_hba *hisi_hba) | ||
| 505 | { | ||
| 506 | int i; | ||
| 507 | |||
| 508 | for (i = 0; i < hisi_hba->n_phy; i++) | ||
| 509 | config_id_frame_v1_hw(hisi_hba, i); | ||
| 510 | } | ||
| 511 | |||
| 512 | static void setup_itct_v1_hw(struct hisi_hba *hisi_hba, | 504 | static void setup_itct_v1_hw(struct hisi_hba *hisi_hba, |
| 513 | struct hisi_sas_device *sas_dev) | 505 | struct hisi_sas_device *sas_dev) |
| 514 | { | 506 | { |
| @@ -774,8 +766,6 @@ static int hw_init_v1_hw(struct hisi_hba *hisi_hba) · 259 unmodified lines | |||
| 774 | msleep(100); | 766 | msleep(100); |
| 775 | init_reg_v1_hw(hisi_hba); | 767 | init_reg_v1_hw(hisi_hba); |
| 776 | 768 | ||
| 777 | init_id_frame_v1_hw(hisi_hba); | ||
| 778 | |||
| 779 | return 0; | 769 | return 0; |
| 780 | } | 770 | } |
| 781 | 771 | ||
| @@ -875,12 +865,13 @@ static int get_wideport_bitmap_v1_hw(struct hisi_hba *hisi_hba, int port_id) · 93 unmodified lines | |||
| 875 | static int get_free_slot_v1_hw(struct hisi_hba *hisi_hba, int *q, int *s) | 865 | static int get_free_slot_v1_hw(struct hisi_hba *hisi_hba, int *q, int *s) |
| 876 | { | 866 | { |
| 877 | struct device *dev = &hisi_hba->pdev->dev; | 867 | struct device *dev = &hisi_hba->pdev->dev; |
| 868 | struct hisi_sas_dq *dq; | ||
| 878 | u32 r, w; | 869 | u32 r, w; |
| 879 | int queue = hisi_hba->queue; | 870 | int queue = hisi_hba->queue; |
| 880 | 871 | ||
| 881 | while (1) { | 872 | while (1) { |
| 882 | w = hisi_sas_read32_relaxed(hisi_hba, | 873 | dq = &hisi_hba->dq[queue]; |
| 883 | DLVRY_Q_0_WR_PTR + (queue * 0x14)); | 874 | w = dq->wr_point; |
| 884 | r = hisi_sas_read32_relaxed(hisi_hba, | 875 | r = hisi_sas_read32_relaxed(hisi_hba, |
| 885 | DLVRY_Q_0_RD_PTR + (queue * 0x14)); | 876 | DLVRY_Q_0_RD_PTR + (queue * 0x14)); |
| 886 | if (r == (w+1) % HISI_SAS_QUEUE_SLOTS) { | 877 | if (r == (w+1) % HISI_SAS_QUEUE_SLOTS) { |
| @@ -903,10 +894,11 @@ static void start_delivery_v1_hw(struct hisi_hba *hisi_hba) · 16 unmodified lines | |||
| 903 | { | 894 | { |
| 904 | int dlvry_queue = hisi_hba->slot_prep->dlvry_queue; | 895 | int dlvry_queue = hisi_hba->slot_prep->dlvry_queue; |
| 905 | int dlvry_queue_slot = hisi_hba->slot_prep->dlvry_queue_slot; | 896 | int dlvry_queue_slot = hisi_hba->slot_prep->dlvry_queue_slot; |
| 897 | struct hisi_sas_dq *dq = &hisi_hba->dq[dlvry_queue]; | ||
| 906 | 898 | ||
| 907 | hisi_sas_write32(hisi_hba, | 899 | dq->wr_point = ++dlvry_queue_slot % HISI_SAS_QUEUE_SLOTS; |
| 908 | DLVRY_Q_0_WR_PTR + (dlvry_queue * 0x14), | 900 | hisi_sas_write32(hisi_hba, DLVRY_Q_0_WR_PTR + (dlvry_queue * 0x14), |
| 909 | ++dlvry_queue_slot % HISI_SAS_QUEUE_SLOTS); | 901 | dq->wr_point); |
| 910 | } | 902 | } |
| 911 | 903 | ||
| 912 | static int prep_prd_sge_v1_hw(struct hisi_hba *hisi_hba, | 904 | static int prep_prd_sge_v1_hw(struct hisi_hba *hisi_hba, |
| @@ -1565,14 +1557,11 @@ static irqreturn_t cq_interrupt_v1_hw(int irq, void *p) · 652 unmodified lines | |||
| 1565 | struct hisi_sas_complete_v1_hdr *complete_queue = | 1557 | struct hisi_sas_complete_v1_hdr *complete_queue = |
| 1566 | (struct hisi_sas_complete_v1_hdr *) | 1558 | (struct hisi_sas_complete_v1_hdr *) |
| 1567 | hisi_hba->complete_hdr[queue]; | 1559 | hisi_hba->complete_hdr[queue]; |
| 1568 | u32 irq_value, rd_point, wr_point; | 1560 | u32 irq_value, rd_point = cq->rd_point, wr_point; |
| 1569 | 1561 | ||
| 1570 | irq_value = hisi_sas_read32(hisi_hba, OQ_INT_SRC); | 1562 | irq_value = hisi_sas_read32(hisi_hba, OQ_INT_SRC); |
| 1571 | 1563 | ||
| 1572 | hisi_sas_write32(hisi_hba, OQ_INT_SRC, 1 << queue); | 1564 | hisi_sas_write32(hisi_hba, OQ_INT_SRC, 1 << queue); |
| 1573 | |||
| 1574 | rd_point = hisi_sas_read32(hisi_hba, | ||
| 1575 | COMPL_Q_0_RD_PTR + (0x14 * queue)); | ||
| 1576 | wr_point = hisi_sas_read32(hisi_hba, | 1565 | wr_point = hisi_sas_read32(hisi_hba, |
| 1577 | COMPL_Q_0_WR_PTR + (0x14 * queue)); | 1566 | COMPL_Q_0_WR_PTR + (0x14 * queue)); |
| 1578 | 1567 | ||
| @@ -1600,6 +1589,7 @@ static irqreturn_t cq_interrupt_v1_hw(int irq, void *p) · 21 unmodified lines | |||
| 1600 | } | 1589 | } |
| 1601 | 1590 | ||
| 1602 | /* update rd_point */ | 1591 | /* update rd_point */ |
| 1592 | cq->rd_point = rd_point; | ||
| 1603 | hisi_sas_write32(hisi_hba, COMPL_Q_0_RD_PTR + (0x14 * queue), rd_point); | 1593 | hisi_sas_write32(hisi_hba, COMPL_Q_0_RD_PTR + (0x14 * queue), rd_point); |
| 1604 | 1594 | ||
| 1605 | return IRQ_HANDLED; | 1595 | return IRQ_HANDLED; |
| @@ -117,6 +117,8 @@ · 116 unmodified lines | |||
| 117 | #define SL_CONTROL (PORT_BASE + 0x94) | 117 | #define SL_CONTROL (PORT_BASE + 0x94) |
| 118 | #define SL_CONTROL_NOTIFY_EN_OFF 0 | 118 | #define SL_CONTROL_NOTIFY_EN_OFF 0 |
| 119 | #define SL_CONTROL_NOTIFY_EN_MSK (0x1 << SL_CONTROL_NOTIFY_EN_OFF) | 119 | #define SL_CONTROL_NOTIFY_EN_MSK (0x1 << SL_CONTROL_NOTIFY_EN_OFF) |
| 120 | #define SL_CONTROL_CTA_OFF 17 | ||
| 121 | #define SL_CONTROL_CTA_MSK (0x1 << SL_CONTROL_CTA_OFF) | ||
| 120 | #define TX_ID_DWORD0 (PORT_BASE + 0x9c) | 122 | #define TX_ID_DWORD0 (PORT_BASE + 0x9c) |
| 121 | #define TX_ID_DWORD1 (PORT_BASE + 0xa0) | 123 | #define TX_ID_DWORD1 (PORT_BASE + 0xa0) |
| 122 | #define TX_ID_DWORD2 (PORT_BASE + 0xa4) | 124 | #define TX_ID_DWORD2 (PORT_BASE + 0xa4) |
| @@ -124,6 +126,9 @@ · 1 unmodified line | |||
| 124 | #define TX_ID_DWORD4 (PORT_BASE + 0xaC) | 126 | #define TX_ID_DWORD4 (PORT_BASE + 0xaC) |
| 125 | #define TX_ID_DWORD5 (PORT_BASE + 0xb0) | 127 | #define TX_ID_DWORD5 (PORT_BASE + 0xb0) |
| 126 | #define TX_ID_DWORD6 (PORT_BASE + 0xb4) | 128 | #define TX_ID_DWORD6 (PORT_BASE + 0xb4) |
| 129 | #define TXID_AUTO (PORT_BASE + 0xb8) | ||
| 130 | #define TXID_AUTO_CT3_OFF 1 | ||
| 131 | #define TXID_AUTO_CT3_MSK (0x1 << TXID_AUTO_CT3_OFF) | ||
| 127 | #define RX_IDAF_DWORD0 (PORT_BASE + 0xc4) | 132 | #define RX_IDAF_DWORD0 (PORT_BASE + 0xc4) |
| 128 | #define RX_IDAF_DWORD1 (PORT_BASE + 0xc8) | 133 | #define RX_IDAF_DWORD1 (PORT_BASE + 0xc8) |
| 129 | #define RX_IDAF_DWORD2 (PORT_BASE + 0xcc) | 134 | #define RX_IDAF_DWORD2 (PORT_BASE + 0xcc) |
| @@ -174,6 +179,10 @@ · 44 unmodified lines | |||
| 174 | /* HW dma structures */ | 179 | /* HW dma structures */ |
| 175 | /* Delivery queue header */ | 180 | /* Delivery queue header */ |
| 176 | /* dw0 */ | 181 | /* dw0 */ |
| 182 | #define CMD_HDR_ABORT_FLAG_OFF 0 | ||
| 183 | #define CMD_HDR_ABORT_FLAG_MSK (0x3 << CMD_HDR_ABORT_FLAG_OFF) | ||
| 184 | #define CMD_HDR_ABORT_DEVICE_TYPE_OFF 2 | ||
| 185 | #define CMD_HDR_ABORT_DEVICE_TYPE_MSK (0x1 << CMD_HDR_ABORT_DEVICE_TYPE_OFF) | ||
| 177 | #define CMD_HDR_RESP_REPORT_OFF 5 | 186 | #define CMD_HDR_RESP_REPORT_OFF 5 |
| 178 | #define CMD_HDR_RESP_REPORT_MSK (0x1 << CMD_HDR_RESP_REPORT_OFF) | 187 | #define CMD_HDR_RESP_REPORT_MSK (0x1 << CMD_HDR_RESP_REPORT_OFF) |
| 179 | #define CMD_HDR_TLR_CTRL_OFF 6 | 188 | #define CMD_HDR_TLR_CTRL_OFF 6 |
| @@ -214,6 +223,8 @@ · 34 unmodified lines | |||
| 214 | #define CMD_HDR_DIF_SGL_LEN_MSK (0xffff << CMD_HDR_DIF_SGL_LEN_OFF) | 223 | #define CMD_HDR_DIF_SGL_LEN_MSK (0xffff << CMD_HDR_DIF_SGL_LEN_OFF) |
| 215 | #define CMD_HDR_DATA_SGL_LEN_OFF 16 | 224 | #define CMD_HDR_DATA_SGL_LEN_OFF 16 |
| 216 | #define CMD_HDR_DATA_SGL_LEN_MSK (0xffff << CMD_HDR_DATA_SGL_LEN_OFF) | 225 | #define CMD_HDR_DATA_SGL_LEN_MSK (0xffff << CMD_HDR_DATA_SGL_LEN_OFF) |
| 226 | #define CMD_HDR_ABORT_IPTT_OFF 16 | ||
| 227 | #define CMD_HDR_ABORT_IPTT_MSK (0xffff << CMD_HDR_ABORT_IPTT_OFF) | ||
| 217 | 228 | ||
| 218 | /* Completion header */ | 229 | /* Completion header */ |
| 219 | /* dw0 */ | 230 | /* dw0 */ |
| @@ -221,6 +232,13 @@ · 1 unmodified line | |||
| 221 | #define CMPLT_HDR_RSPNS_XFRD_MSK (0x1 << CMPLT_HDR_RSPNS_XFRD_OFF) | 232 | #define CMPLT_HDR_RSPNS_XFRD_MSK (0x1 << CMPLT_HDR_RSPNS_XFRD_OFF) |
| 222 | #define CMPLT_HDR_ERX_OFF 12 | 233 | #define CMPLT_HDR_ERX_OFF 12 |
| 223 | #define CMPLT_HDR_ERX_MSK (0x1 << CMPLT_HDR_ERX_OFF) | 234 | #define CMPLT_HDR_ERX_MSK (0x1 << CMPLT_HDR_ERX_OFF) |
| 235 | #define CMPLT_HDR_ABORT_STAT_OFF 13 | ||
| 236 | #define CMPLT_HDR_ABORT_STAT_MSK (0x7 << CMPLT_HDR_ABORT_STAT_OFF) | ||
| 237 | /* abort_stat */ | ||
| 238 | #define STAT_IO_NOT_VALID 0x1 | ||
| 239 | #define STAT_IO_NO_DEVICE 0x2 | ||
| 240 | #define STAT_IO_COMPLETE 0x3 | ||
| 241 | #define STAT_IO_ABORTED 0x4 | ||
| 224 | /* dw1 */ | 242 | /* dw1 */ |
| 225 | #define CMPLT_HDR_IPTT_OFF 0 | 243 | #define CMPLT_HDR_IPTT_OFF 0 |
| 226 | #define CMPLT_HDR_IPTT_MSK (0xffff << CMPLT_HDR_IPTT_OFF) | 244 | #define CMPLT_HDR_IPTT_MSK (0xffff << CMPLT_HDR_IPTT_OFF) |
| @@ -549,25 +567,17 @@ static void config_id_frame_v2_hw(struct hisi_hba *hisi_hba, int phy_no) · 322 unmodified lines | |||
| 549 | hisi_sas_phy_write32(hisi_hba, phy_no, TX_ID_DWORD0, | 567 | hisi_sas_phy_write32(hisi_hba, phy_no, TX_ID_DWORD0, |
| 550 | __swab32(identify_buffer[0])); | 568 | __swab32(identify_buffer[0])); |
| 551 | hisi_sas_phy_write32(hisi_hba, phy_no, TX_ID_DWORD1, | 569 | hisi_sas_phy_write32(hisi_hba, phy_no, TX_ID_DWORD1, |
| 552 | identify_buffer[2]); | 570 | __swab32(identify_buffer[1])); |
| 553 | hisi_sas_phy_write32(hisi_hba, phy_no, TX_ID_DWORD2, | 571 | hisi_sas_phy_write32(hisi_hba, phy_no, TX_ID_DWORD2, |
| 554 | identify_buffer[1]); | 572 | __swab32(identify_buffer[2])); |
| 555 | hisi_sas_phy_write32(hisi_hba, phy_no, TX_ID_DWORD3, | 573 | hisi_sas_phy_write32(hisi_hba, phy_no, TX_ID_DWORD3, |
| 556 | identify_buffer[4]); | 574 | __swab32(identify_buffer[3])); |
| 557 | hisi_sas_phy_write32(hisi_hba, phy_no, TX_ID_DWORD4, | 575 | hisi_sas_phy_write32(hisi_hba, phy_no, TX_ID_DWORD4, |
| 558 | identify_buffer[3]); | 576 | __swab32(identify_buffer[4])); |
| 559 | hisi_sas_phy_write32(hisi_hba, phy_no, TX_ID_DWORD5, | 577 | hisi_sas_phy_write32(hisi_hba, phy_no, TX_ID_DWORD5, |
| 560 | __swab32(identify_buffer[5])); | 578 | __swab32(identify_buffer[5])); |
| 561 | } | 579 | } |
| 562 | 580 | ||
| 563 | static void init_id_frame_v2_hw(struct hisi_hba *hisi_hba) | ||
| 564 | { | ||
| 565 | int i; | ||
| 566 | |||
| 567 | for (i = 0; i < hisi_hba->n_phy; i++) | ||
| 568 | config_id_frame_v2_hw(hisi_hba, i); | ||
| 569 | } | ||
| 570 | |||
| 571 | static void setup_itct_v2_hw(struct hisi_hba *hisi_hba, | 581 | static void setup_itct_v2_hw(struct hisi_hba *hisi_hba, |
| 572 | struct hisi_sas_device *sas_dev) | 582 | struct hisi_sas_device *sas_dev) |
| 573 | { | 583 | { |
| @@ -589,6 +599,7 @@ static void setup_itct_v2_hw(struct hisi_hba *hisi_hba, · 15 unmodified lines | |||
| 589 | qw0 = HISI_SAS_DEV_TYPE_SSP << ITCT_HDR_DEV_TYPE_OFF; | 599 | qw0 = HISI_SAS_DEV_TYPE_SSP << ITCT_HDR_DEV_TYPE_OFF; |
| 590 | break; | 600 | break; |
| 591 | case SAS_SATA_DEV: | 601 | case SAS_SATA_DEV: |
| 602 | case SAS_SATA_PENDING: | ||
| 592 | if (parent_dev && DEV_IS_EXPANDER(parent_dev->dev_type)) | 603 | if (parent_dev && DEV_IS_EXPANDER(parent_dev->dev_type)) |
| 593 | qw0 = HISI_SAS_DEV_TYPE_STP << ITCT_HDR_DEV_TYPE_OFF; | 604 | qw0 = HISI_SAS_DEV_TYPE_STP << ITCT_HDR_DEV_TYPE_OFF; |
| 594 | else | 605 | else |
| @@ -672,9 +683,7 @@ static int reset_hw_v2_hw(struct hisi_hba *hisi_hba) · 77 unmodified lines | |||
| 672 | else | 683 | else |
| 673 | reset_val = 0x7ffff; | 684 | reset_val = 0x7ffff; |
| 674 | 685 | ||
| 675 | /* Disable all of the DQ */ | 686 | hisi_sas_write32(hisi_hba, DLVRY_QUEUE_ENABLE, 0); |
| 676 | for (i = 0; i < HISI_SAS_MAX_QUEUES; i++) | ||
| 677 | hisi_sas_write32(hisi_hba, DLVRY_QUEUE_ENABLE, 0); | ||
| 678 | 687 | ||
| 679 | /* Disable all of the PHYs */ | 688 | /* Disable all of the PHYs */ |
| 680 | for (i = 0; i < hisi_hba->n_phy; i++) { | 689 | for (i = 0; i < hisi_hba->n_phy; i++) { |
| @@ -810,6 +819,8 @@ static void init_reg_v2_hw(struct hisi_hba *hisi_hba) · 129 unmodified lines | |||
| 810 | hisi_sas_phy_write32(hisi_hba, i, PROG_PHY_LINK_RATE, 0x855); | 819 | hisi_sas_phy_write32(hisi_hba, i, PROG_PHY_LINK_RATE, 0x855); |
| 811 | hisi_sas_phy_write32(hisi_hba, i, SAS_PHY_CTRL, 0x30b9908); | 820 | hisi_sas_phy_write32(hisi_hba, i, SAS_PHY_CTRL, 0x30b9908); |
| 812 | hisi_sas_phy_write32(hisi_hba, i, SL_TOUT_CFG, 0x7d7d7d7d); | 821 | hisi_sas_phy_write32(hisi_hba, i, SL_TOUT_CFG, 0x7d7d7d7d); |
| 822 | hisi_sas_phy_write32(hisi_hba, i, SL_CONTROL, 0x0); | ||
| 823 | hisi_sas_phy_write32(hisi_hba, i, TXID_AUTO, 0x2); | ||
| 813 | hisi_sas_phy_write32(hisi_hba, i, DONE_RECEIVED_TIME, 0x10); | 824 | hisi_sas_phy_write32(hisi_hba, i, DONE_RECEIVED_TIME, 0x10); |
| 814 | hisi_sas_phy_write32(hisi_hba, i, CHL_INT0, 0xffffffff); | 825 | hisi_sas_phy_write32(hisi_hba, i, CHL_INT0, 0xffffffff); |
| 815 | hisi_sas_phy_write32(hisi_hba, i, CHL_INT1, 0xffffffff); | 826 | hisi_sas_phy_write32(hisi_hba, i, CHL_INT1, 0xffffffff); |
| @@ -901,8 +912,6 @@ static int hw_init_v2_hw(struct hisi_hba *hisi_hba) · 85 unmodified lines | |||
| 901 | msleep(100); | 912 | msleep(100); |
| 902 | init_reg_v2_hw(hisi_hba); | 913 | init_reg_v2_hw(hisi_hba); |
| 903 | 914 | ||
| 904 | init_id_frame_v2_hw(hisi_hba); | ||
| 905 | |||
| 906 | return 0; | 915 | return 0; |
| 907 | } | 916 | } |
| 908 | 917 | ||
| @@ -952,14 +961,8 @@ static void start_phys_v2_hw(unsigned long data) · 43 unmodified lines | |||
| 952 | 961 | ||
| 953 | static void phys_init_v2_hw(struct hisi_hba *hisi_hba) | 962 | static void phys_init_v2_hw(struct hisi_hba *hisi_hba) |
| 954 | { | 963 | { |
| 955 | int i; | ||
| 956 | struct timer_list *timer = &hisi_hba->timer; | 964 | struct timer_list *timer = &hisi_hba->timer; |
| 957 | 965 | ||
| 958 | for (i = 0; i < hisi_hba->n_phy; i++) { | ||
| 959 | hisi_sas_phy_write32(hisi_hba, i, CHL_INT2_MSK, 0x6a); | ||
| 960 | hisi_sas_phy_read32(hisi_hba, i, CHL_INT2_MSK); | ||
| 961 | } | ||
| 962 | |||
| 963 | setup_timer(timer, start_phys_v2_hw, (unsigned long)hisi_hba); | 966 | setup_timer(timer, start_phys_v2_hw, (unsigned long)hisi_hba); |
| 964 | mod_timer(timer, jiffies + HZ); | 967 | mod_timer(timer, jiffies + HZ); |
| 965 | } | 968 | } |
| @@ -1010,12 +1013,13 @@ static int get_wideport_bitmap_v2_hw(struct hisi_hba *hisi_hba, int port_id) · 44 unmodified lines | |||
| 1010 | static int get_free_slot_v2_hw(struct hisi_hba *hisi_hba, int *q, int *s) | 1013 | static int get_free_slot_v2_hw(struct hisi_hba *hisi_hba, int *q, int *s) |
| 1011 | { | 1014 | { |
| 1012 | struct device *dev = &hisi_hba->pdev->dev; | 1015 | struct device *dev = &hisi_hba->pdev->dev; |
| 1016 | struct hisi_sas_dq *dq; | ||
| 1013 | u32 r, w; | 1017 | u32 r, w; |
| 1014 | int queue = hisi_hba->queue; | 1018 | int queue = hisi_hba->queue; |
| 1015 | 1019 | ||
| 1016 | while (1) { | 1020 | while (1) { |
| 1017 | w = hisi_sas_read32_relaxed(hisi_hba, | 1021 | dq = &hisi_hba->dq[queue]; |
| 1018 | DLVRY_Q_0_WR_PTR + (queue * 0x14)); | 1022 | w = dq->wr_point; |
| 1019 | r = hisi_sas_read32_relaxed(hisi_hba, | 1023 | r = hisi_sas_read32_relaxed(hisi_hba, |
| 1020 | DLVRY_Q_0_RD_PTR + (queue * 0x14)); | 1024 | DLVRY_Q_0_RD_PTR + (queue * 0x14)); |
| 1021 | if (r == (w+1) % HISI_SAS_QUEUE_SLOTS) { | 1025 | if (r == (w+1) % HISI_SAS_QUEUE_SLOTS) { |
| @@ -1038,9 +1042,11 @@ static void start_delivery_v2_hw(struct hisi_hba *hisi_hba) · 16 unmodified lines | |||
| 1038 | { | 1042 | { |
| 1039 | int dlvry_queue = hisi_hba->slot_prep->dlvry_queue; | 1043 | int dlvry_queue = hisi_hba->slot_prep->dlvry_queue; |
| 1040 | int dlvry_queue_slot = hisi_hba->slot_prep->dlvry_queue_slot; | 1044 | int dlvry_queue_slot = hisi_hba->slot_prep->dlvry_queue_slot; |
| 1045 | struct hisi_sas_dq *dq = &hisi_hba->dq[dlvry_queue]; | ||
| 1041 | 1046 | ||
| 1047 | dq->wr_point = ++dlvry_queue_slot % HISI_SAS_QUEUE_SLOTS; | ||
| 1042 | hisi_sas_write32(hisi_hba, DLVRY_Q_0_WR_PTR + (dlvry_queue * 0x14), | 1048 | hisi_sas_write32(hisi_hba, DLVRY_Q_0_WR_PTR + (dlvry_queue * 0x14), |
| 1043 | ++dlvry_queue_slot % HISI_SAS_QUEUE_SLOTS); | 1049 | dq->wr_point); |
| 1044 | } | 1050 | } |
| 1045 | 1051 | ||
| 1046 | static int prep_prd_sge_v2_hw(struct hisi_hba *hisi_hba, | 1052 | static int prep_prd_sge_v2_hw(struct hisi_hba *hisi_hba, |
| @@ -1563,6 +1569,30 @@ slot_complete_v2_hw(struct hisi_hba *hisi_hba, struct hisi_sas_slot *slot, · 516 unmodified lines | |||
| 1563 | goto out; | 1569 | goto out; |
| 1564 | } | 1570 | } |
| 1565 | 1571 | ||
| 1572 | /* Use SAS+TMF status codes */ | ||
| 1573 | switch ((complete_hdr->dw0 & CMPLT_HDR_ABORT_STAT_MSK) | ||
| 1574 | >> CMPLT_HDR_ABORT_STAT_OFF) { | ||
| 1575 | case STAT_IO_ABORTED: | ||
| 1576 | /* this io has been aborted by abort command */ | ||
| 1577 | ts->stat = SAS_ABORTED_TASK; | ||
| 1578 | goto out; | ||
| 1579 | case STAT_IO_COMPLETE: | ||
| 1580 | /* internal abort command complete */ | ||
| 1581 | ts->stat = TMF_RESP_FUNC_COMPLETE; | ||
| 1582 | goto out; | ||
| 1583 | case STAT_IO_NO_DEVICE: | ||
| 1584 | ts->stat = TMF_RESP_FUNC_COMPLETE; | ||
| 1585 | goto out; | ||
| 1586 | case STAT_IO_NOT_VALID: | ||
| 1587 | /* abort single io, controller don't find | ||
| 1588 | * the io need to abort | ||
| 1589 | */ | ||
| 1590 | ts->stat = TMF_RESP_FUNC_FAILED; | ||
| 1591 | goto out; | ||
| 1592 | default: | ||
| 1593 | break; | ||
| 1594 | } | ||
| 1595 | |||
| 1566 | if ((complete_hdr->dw0 & CMPLT_HDR_ERX_MSK) && | 1596 | if ((complete_hdr->dw0 & CMPLT_HDR_ERX_MSK) && |
| 1567 | (!(complete_hdr->dw0 & CMPLT_HDR_RSPNS_XFRD_MSK))) { | 1597 | (!(complete_hdr->dw0 & CMPLT_HDR_RSPNS_XFRD_MSK))) { |
| 1568 | 1598 | ||
| @@ -1775,6 +1805,32 @@ static int prep_ata_v2_hw(struct hisi_hba *hisi_hba, · 206 unmodified lines | |||
| 1775 | return 0; | 1805 | return 0; |
| 1776 | } | 1806 | } |
| 1777 | 1807 | ||
| 1808 | static int prep_abort_v2_hw(struct hisi_hba *hisi_hba, | ||
| 1809 | struct hisi_sas_slot *slot, | ||
| 1810 | int device_id, int abort_flag, int tag_to_abort) | ||
| 1811 | { | ||
| 1812 | struct sas_task *task = slot->task; | ||
| 1813 | struct domain_device *dev = task->dev; | ||
| 1814 | struct hisi_sas_cmd_hdr *hdr = slot->cmd_hdr; | ||
| 1815 | struct hisi_sas_port *port = slot->port; | ||
| 1816 | |||
| 1817 | /* dw0 */ | ||
| 1818 | hdr->dw0 = cpu_to_le32((5 << CMD_HDR_CMD_OFF) | /*abort*/ | ||
| 1819 | (port->id << CMD_HDR_PORT_OFF) | | ||
| 1820 | ((dev_is_sata(dev) ? 1:0) << | ||
| 1821 | CMD_HDR_ABORT_DEVICE_TYPE_OFF) | | ||
| 1822 | (abort_flag << CMD_HDR_ABORT_FLAG_OFF)); | ||
| 1823 | |||
| 1824 | /* dw1 */ | ||
| 1825 | hdr->dw1 = cpu_to_le32(device_id << CMD_HDR_DEV_ID_OFF); | ||
| 1826 | |||
| 1827 | /* dw7 */ | ||
| 1828 | hdr->dw7 = cpu_to_le32(tag_to_abort << CMD_HDR_ABORT_IPTT_OFF); | ||
| 1829 | hdr->transfer_tags = cpu_to_le32(slot->idx); | ||
| 1830 | |||
| 1831 | return 0; | ||
| 1832 | } | ||
| 1833 | |||
| 1778 | static int phy_up_v2_hw(int phy_no, struct hisi_hba *hisi_hba) | 1834 | static int phy_up_v2_hw(int phy_no, struct hisi_hba *hisi_hba) |
| 1779 | { | 1835 | { |
| 1780 | int i, res = 0; | 1836 | int i, res = 0; |
| @@ -1818,9 +1874,6 @@ static int phy_up_v2_hw(int phy_no, struct hisi_hba *hisi_hba) · 37 unmodified lines | |||
| 1818 | frame_rcvd[i] = __swab32(idaf); | 1874 | frame_rcvd[i] = __swab32(idaf); |
| 1819 | } | 1875 | } |
| 1820 | 1876 | ||
| 1821 | /* Get the linkrates */ | ||
| 1822 | link_rate = hisi_sas_read32(hisi_hba, PHY_CONN_RATE); | ||
| 1823 | link_rate = (link_rate >> (phy_no * 4)) & 0xf; | ||
| 1824 | sas_phy->linkrate = link_rate; | 1877 | sas_phy->linkrate = link_rate; |
| 1825 | hard_phy_linkrate = hisi_sas_phy_read32(hisi_hba, phy_no, | 1878 | hard_phy_linkrate = hisi_sas_phy_read32(hisi_hba, phy_no, |
| 1826 | HARD_PHY_LINKRATE); | 1879 | HARD_PHY_LINKRATE); |
| @@ -1855,16 +1908,21 @@ end: · 28 unmodified lines | |||
| 1855 | static int phy_down_v2_hw(int phy_no, struct hisi_hba *hisi_hba) | 1908 | static int phy_down_v2_hw(int phy_no, struct hisi_hba *hisi_hba) |
| 1856 | { | 1909 | { |
| 1857 | int res = 0; | 1910 | int res = 0; |
| 1858 | u32 phy_cfg, phy_state; | 1911 | u32 phy_state, sl_ctrl, txid_auto; |
| 1859 | 1912 | ||
| 1860 | hisi_sas_phy_write32(hisi_hba, phy_no, PHYCTRL_NOT_RDY_MSK, 1); | 1913 | hisi_sas_phy_write32(hisi_hba, phy_no, PHYCTRL_NOT_RDY_MSK, 1); |
| 1861 | 1914 | ||
| 1862 | phy_cfg = hisi_sas_phy_read32(hisi_hba, phy_no, PHY_CFG); | ||
| 1863 | |||
| 1864 | phy_state = hisi_sas_read32(hisi_hba, PHY_STATE); | 1915 | phy_state = hisi_sas_read32(hisi_hba, PHY_STATE); |
| 1865 | |||
| 1866 | hisi_sas_phy_down(hisi_hba, phy_no, (phy_state & 1 << phy_no) ? 1 : 0); | 1916 | hisi_sas_phy_down(hisi_hba, phy_no, (phy_state & 1 << phy_no) ? 1 : 0); |
| 1867 | 1917 | ||
| 1918 | sl_ctrl = hisi_sas_phy_read32(hisi_hba, phy_no, SL_CONTROL); | ||
| 1919 | hisi_sas_phy_write32(hisi_hba, phy_no, SL_CONTROL, | ||
| 1920 | sl_ctrl & ~SL_CONTROL_CTA_MSK); | ||
| 1921 | |||
| 1922 | txid_auto = hisi_sas_phy_read32(hisi_hba, phy_no, TXID_AUTO); | ||
| 1923 | hisi_sas_phy_write32(hisi_hba, phy_no, TXID_AUTO, | ||
| 1924 | txid_auto | TXID_AUTO_CT3_MSK); | ||
| 1925 | |||
| 1868 | hisi_sas_phy_write32(hisi_hba, phy_no, CHL_INT0, CHL_INT0_NOT_RDY_MSK); | 1926 | hisi_sas_phy_write32(hisi_hba, phy_no, CHL_INT0, CHL_INT0_NOT_RDY_MSK); |
| 1869 | hisi_sas_phy_write32(hisi_hba, phy_no, PHYCTRL_NOT_RDY_MSK, 0); | 1927 | hisi_sas_phy_write32(hisi_hba, phy_no, PHYCTRL_NOT_RDY_MSK, 0); |
| 1870 | 1928 | ||
| @@ -1986,7 +2044,7 @@ static irqreturn_t cq_interrupt_v2_hw(int irq_no, void *p) · 115 unmodified lines | |||
| 1986 | struct hisi_sas_slot *slot; | 2044 | struct hisi_sas_slot *slot; |
| 1987 | struct hisi_sas_itct *itct; | 2045 | struct hisi_sas_itct *itct; |
| 1988 | struct hisi_sas_complete_v2_hdr *complete_queue; | 2046 | struct hisi_sas_complete_v2_hdr *complete_queue; |
| 1989 | u32 irq_value, rd_point, wr_point, dev_id; | 2047 | u32 irq_value, rd_point = cq->rd_point, wr_point, dev_id; |
| 1990 | int queue = cq->id; | 2048 | int queue = cq->id; |
| 1991 | 2049 | ||
| 1992 | complete_queue = hisi_hba->complete_hdr[queue]; | 2050 | complete_queue = hisi_hba->complete_hdr[queue]; |
| @@ -1994,8 +2052,6 @@ static irqreturn_t cq_interrupt_v2_hw(int irq_no, void *p) · 1 unmodified line | |||
| 1994 | 2052 | ||
| 1995 | hisi_sas_write32(hisi_hba, OQ_INT_SRC, 1 << queue); | 2053 | hisi_sas_write32(hisi_hba, OQ_INT_SRC, 1 << queue); |
| 1996 | 2054 | ||
| 1997 | rd_point = hisi_sas_read32(hisi_hba, COMPL_Q_0_RD_PTR + | ||
| 1998 | (0x14 * queue)); | ||
| 1999 | wr_point = hisi_sas_read32(hisi_hba, COMPL_Q_0_WR_PTR + | 2055 | wr_point = hisi_sas_read32(hisi_hba, COMPL_Q_0_WR_PTR + |
| 2000 | (0x14 * queue)); | 2056 | (0x14 * queue)); |
| 2001 | 2057 | ||
| @@ -2043,6 +2099,7 @@ static irqreturn_t cq_interrupt_v2_hw(int irq_no, void *p) · 41 unmodified lines | |||
| 2043 | } | 2099 | } |
| 2044 | 2100 | ||
| 2045 | /* update rd_point */ | 2101 | /* update rd_point */ |
| 2102 | cq->rd_point = rd_point; | ||
| 2046 | hisi_sas_write32(hisi_hba, COMPL_Q_0_RD_PTR + (0x14 * queue), rd_point); | 2103 | hisi_sas_write32(hisi_hba, COMPL_Q_0_RD_PTR + (0x14 * queue), rd_point); |
| 2047 | return IRQ_HANDLED; | 2104 | return IRQ_HANDLED; |
| 2048 | } | 2105 | } |
| @@ -2239,6 +2296,7 @@ static const struct hisi_sas_hw hisi_sas_v2_hw = { · 190 unmodified lines | |||
| 2239 | .prep_smp = prep_smp_v2_hw, | 2296 | .prep_smp = prep_smp_v2_hw, |
| 2240 | .prep_ssp = prep_ssp_v2_hw, | 2297 | .prep_ssp = prep_ssp_v2_hw, |
| 2241 | .prep_stp = prep_ata_v2_hw, | 2298 | .prep_stp = prep_ata_v2_hw, |
| 2299 | .prep_abort = prep_abort_v2_hw, | ||
| 2242 | .get_free_slot = get_free_slot_v2_hw, | 2300 | .get_free_slot = get_free_slot_v2_hw, |
| 2243 | .start_delivery = start_delivery_v2_hw, | 2301 | .start_delivery = start_delivery_v2_hw, |
| 2244 | .slot_complete = slot_complete_v2_hw, | 2302 | .slot_complete = slot_complete_v2_hw, |
| @@ -246,10 +246,6 @@ int scsi_add_host_with_dma(struct Scsi_Host *shost, struct device *dev, · 245 unmodified lines | |||
| 246 | 246 | ||
| 247 | shost->dma_dev = dma_dev; | 247 | shost->dma_dev = dma_dev; |
| 248 | 248 | ||
| 249 | error = device_add(&shost->shost_gendev); | ||
| 250 | if (error) | ||
| 251 | goto out_destroy_freelist; | ||
| 252 | |||
| 253 | /* | 249 | /* |
| 254 | * Increase usage count temporarily here so that calling | 250 | * Increase usage count temporarily here so that calling |
| 255 | * scsi_autopm_put_host() will trigger runtime idle if there is | 251 | * scsi_autopm_put_host() will trigger runtime idle if there is |
| @@ -260,6 +256,10 @@ int scsi_add_host_with_dma(struct Scsi_Host *shost, struct device *dev, · 4 unmodified lines | |||
| 260 | pm_runtime_enable(&shost->shost_gendev); | 256 | pm_runtime_enable(&shost->shost_gendev); |
| 261 | device_enable_async_suspend(&shost->shost_gendev); | 257 | device_enable_async_suspend(&shost->shost_gendev); |
| 262 | 258 | ||
| 259 | error = device_add(&shost->shost_gendev); | ||
| 260 | if (error) | ||
| 261 | goto out_destroy_freelist; | ||
| 262 | |||
| 263 | scsi_host_set_state(shost, SHOST_RUNNING); | 263 | scsi_host_set_state(shost, SHOST_RUNNING); |
| 264 | get_device(shost->shost_gendev.parent); | 264 | get_device(shost->shost_gendev.parent); |
| 265 | 265 | ||
| @@ -309,6 +309,10 @@ int scsi_add_host_with_dma(struct Scsi_Host *shost, struct device *dev, · 43 unmodified lines | |||
| 309 | out_del_gendev: | 309 | out_del_gendev: |
| 310 | device_del(&shost->shost_gendev); | 310 | device_del(&shost->shost_gendev); |
| 311 | out_destroy_freelist: | 311 | out_destroy_freelist: |
| 312 | device_disable_async_suspend(&shost->shost_gendev); | ||
| 313 | pm_runtime_disable(&shost->shost_gendev); | ||
| 314 | pm_runtime_set_suspended(&shost->shost_gendev); | ||
| 315 | pm_runtime_put_noidle(&shost->shost_gendev); | ||
| 312 | scsi_destroy_command_freelist(shost); | 316 | scsi_destroy_command_freelist(shost); |
| 313 | out_destroy_tags: | 317 | out_destroy_tags: |
| 314 | if (shost_use_blk_mq(shost)) | 318 | if (shost_use_blk_mq(shost)) |
| @@ -293,6 +293,8 @@ static int detect_controller_lockup(struct ctlr_info *h); · 292 unmodified lines | |||
| 293 | static void hpsa_disable_rld_caching(struct ctlr_info *h); | 293 | static void hpsa_disable_rld_caching(struct ctlr_info *h); |
| 294 | static inline int hpsa_scsi_do_report_phys_luns(struct ctlr_info *h, | 294 | static inline int hpsa_scsi_do_report_phys_luns(struct ctlr_info *h, |
| 295 | struct ReportExtendedLUNdata *buf, int bufsize); | 295 | struct ReportExtendedLUNdata *buf, int bufsize); |
| 296 | static bool hpsa_vpd_page_supported(struct ctlr_info *h, | ||
| 297 | unsigned char scsi3addr[], u8 page); | ||
| 296 | static int hpsa_luns_changed(struct ctlr_info *h); | 298 | static int hpsa_luns_changed(struct ctlr_info *h); |
| 297 | static bool hpsa_cmd_dev_match(struct ctlr_info *h, struct CommandList *c, | 299 | static bool hpsa_cmd_dev_match(struct ctlr_info *h, struct CommandList *c, |
| 298 | struct hpsa_scsi_dev_t *dev, | 300 | struct hpsa_scsi_dev_t *dev, |
| @@ -2388,7 +2390,8 @@ static void hpsa_cmd_free_and_done(struct ctlr_info *h, · 2089 unmodified lines | |||
| 2388 | struct CommandList *c, struct scsi_cmnd *cmd) | 2390 | struct CommandList *c, struct scsi_cmnd *cmd) |
| 2389 | { | 2391 | { |
| 2390 | hpsa_cmd_resolve_and_free(h, c); | 2392 | hpsa_cmd_resolve_and_free(h, c); |
| 2391 | cmd->scsi_done(cmd); | 2393 | if (cmd && cmd->scsi_done) |
| 2394 | cmd->scsi_done(cmd); | ||
| 2392 | } | 2395 | } |
| 2393 | 2396 | ||
| 2394 | static void hpsa_retry_cmd(struct ctlr_info *h, struct CommandList *c) | 2397 | static void hpsa_retry_cmd(struct ctlr_info *h, struct CommandList *c) |
| @@ -2489,7 +2492,17 @@ static void complete_scsi_command(struct CommandList *cp) · 94 unmodified lines | |||
| 2489 | ei = cp->err_info; | 2492 | ei = cp->err_info; |
| 2490 | cmd = cp->scsi_cmd; | 2493 | cmd = cp->scsi_cmd; |
| 2491 | h = cp->h; | 2494 | h = cp->h; |
| 2495 | |||
| 2496 | if (!cmd->device) { | ||
| 2497 | cmd->result = DID_NO_CONNECT << 16; | ||
| 2498 | return hpsa_cmd_free_and_done(h, cp, cmd); | ||
| 2499 | } | ||
| 2500 | |||
| 2492 | dev = cmd->device->hostdata; | 2501 | dev = cmd->device->hostdata; |
| 2502 | if (!dev) { | ||
| 2503 | cmd->result = DID_NO_CONNECT << 16; | ||
| 2504 | return hpsa_cmd_free_and_done(h, cp, cmd); | ||
| 2505 | } | ||
| 2493 | c2 = &h->ioaccel2_cmd_pool[cp->cmdindex]; | 2506 | c2 = &h->ioaccel2_cmd_pool[cp->cmdindex]; |
| 2494 | 2507 | ||
| 2495 | scsi_dma_unmap(cmd); /* undo the DMA mappings */ | 2508 | scsi_dma_unmap(cmd); /* undo the DMA mappings */ |
| @@ -2504,8 +2517,15 @@ static void complete_scsi_command(struct CommandList *cp) · 8 unmodified lines | |||
| 2504 | cmd->result = (DID_OK << 16); /* host byte */ | 2517 | cmd->result = (DID_OK << 16); /* host byte */ |
| 2505 | cmd->result |= (COMMAND_COMPLETE << 8); /* msg byte */ | 2518 | cmd->result |= (COMMAND_COMPLETE << 8); /* msg byte */ |
| 2506 | 2519 | ||
| 2507 | if (cp->cmd_type == CMD_IOACCEL2 || cp->cmd_type == CMD_IOACCEL1) | 2520 | if (cp->cmd_type == CMD_IOACCEL2 || cp->cmd_type == CMD_IOACCEL1) { |
| 2508 | atomic_dec(&cp->phys_disk->ioaccel_cmds_out); | 2521 | if (dev->physical_device && dev->expose_device && |
| 2522 | dev->removed) { | ||
| 2523 | cmd->result = DID_NO_CONNECT << 16; | ||
| 2524 | return hpsa_cmd_free_and_done(h, cp, cmd); | ||
| 2525 | } | ||
| 2526 | if (likely(cp->phys_disk != NULL)) | ||
| 2527 | atomic_dec(&cp->phys_disk->ioaccel_cmds_out); | ||
| 2528 | } | ||
| 2509 | 2529 | ||
| 2510 | /* | 2530 | /* |
| 2511 | * We check for lockup status here as it may be set for | 2531 | * We check for lockup status here as it may be set for |
| @@ -3074,11 +3094,19 @@ static void hpsa_get_raid_level(struct ctlr_info *h, · 562 unmodified lines | |||
| 3074 | buf = kzalloc(64, GFP_KERNEL); | 3094 | buf = kzalloc(64, GFP_KERNEL); |
| 3075 | if (!buf) | 3095 | if (!buf) |
| 3076 | return; | 3096 | return; |
| 3077 | rc = hpsa_scsi_do_inquiry(h, scsi3addr, VPD_PAGE | 0xC1, buf, 64); | 3097 | |
| 3098 | if (!hpsa_vpd_page_supported(h, scsi3addr, | ||
| 3099 | HPSA_VPD_LV_DEVICE_GEOMETRY)) | ||
| 3100 | goto exit; | ||
| 3101 | |||
| 3102 | rc = hpsa_scsi_do_inquiry(h, scsi3addr, VPD_PAGE | | ||
| 3103 | HPSA_VPD_LV_DEVICE_GEOMETRY, buf, 64); | ||
| 3104 | |||
| 3078 | if (rc == 0) | 3105 | if (rc == 0) |
| 3079 | *raid_level = buf[8]; | 3106 | *raid_level = buf[8]; |
| 3080 | if (*raid_level > RAID_UNKNOWN) | 3107 | if (*raid_level > RAID_UNKNOWN) |
| 3081 | *raid_level = RAID_UNKNOWN; | 3108 | *raid_level = RAID_UNKNOWN; |
| 3109 | exit: | ||
| 3082 | kfree(buf); | 3110 | kfree(buf); |
| 3083 | return; | 3111 | return; |
| 3084 | } | 3112 | } |
| @@ -3436,7 +3464,7 @@ static void hpsa_get_sas_address(struct ctlr_info *h, unsigned char *scsi3addr, · 351 unmodified lines | |||
| 3436 | } | 3464 | } |
| 3437 | 3465 | ||
| 3438 | /* Get a device id from inquiry page 0x83 */ | 3466 | /* Get a device id from inquiry page 0x83 */ |
| 3439 | static int hpsa_vpd_page_supported(struct ctlr_info *h, | 3467 | static bool hpsa_vpd_page_supported(struct ctlr_info *h, |
| 3440 | unsigned char scsi3addr[], u8 page) | 3468 | unsigned char scsi3addr[], u8 page) |
| 3441 | { | 3469 | { |
| 3442 | int rc; | 3470 | int rc; |
| @@ -3446,7 +3474,7 @@ static int hpsa_vpd_page_supported(struct ctlr_info *h, · 3 unmodified lines | |||
| 3446 | 3474 | ||
| 3447 | buf = kzalloc(256, GFP_KERNEL); | 3475 | buf = kzalloc(256, GFP_KERNEL); |
| 3448 | if (!buf) | 3476 | if (!buf) |
| 3449 | return 0; | 3477 | return false; |
| 3450 | 3478 | ||
| 3451 | /* Get the size of the page list first */ | 3479 | /* Get the size of the page list first */ |
| 3452 | rc = hpsa_scsi_do_inquiry(h, scsi3addr, | 3480 | rc = hpsa_scsi_do_inquiry(h, scsi3addr, |
| @@ -3473,10 +3501,10 @@ static int hpsa_vpd_page_supported(struct ctlr_info *h, · 20 unmodified lines | |||
| 3473 | goto exit_supported; | 3501 | goto exit_supported; |
| 3474 | exit_unsupported: | 3502 | exit_unsupported: |
| 3475 | kfree(buf); | 3503 | kfree(buf); |
| 3476 | return 0; | 3504 | return false; |
| 3477 | exit_supported: | 3505 | exit_supported: |
| 3478 | kfree(buf); | 3506 | kfree(buf); |
| 3479 | return 1; | 3507 | return true; |
| 3480 | } | 3508 | } |
| 3481 | 3509 | ||
| 3482 | static void hpsa_get_ioaccel_status(struct ctlr_info *h, | 3510 | static void hpsa_get_ioaccel_status(struct ctlr_info *h, |
| @@ -3525,18 +3553,25 @@ static int hpsa_get_device_id(struct ctlr_info *h, unsigned char *scsi3addr, · 42 unmodified lines | |||
| 3525 | int rc; | 3553 | int rc; |
| 3526 | unsigned char *buf; | 3554 | unsigned char *buf; |
| 3527 | 3555 | ||
| 3528 | if (buflen > 16) | 3556 | /* Does controller have VPD for device id? */ |
| 3529 | buflen = 16; | 3557 | if (!hpsa_vpd_page_supported(h, scsi3addr, HPSA_VPD_LV_DEVICE_ID)) |
| 3558 | return 1; /* not supported */ | ||
| 3559 | |||
| 3530 | buf = kzalloc(64, GFP_KERNEL); | 3560 | buf = kzalloc(64, GFP_KERNEL); |
| 3531 | if (!buf) | 3561 | if (!buf) |
| 3532 | return -ENOMEM; | 3562 | return -ENOMEM; |
| 3533 | rc = hpsa_scsi_do_inquiry(h, scsi3addr, VPD_PAGE | 0x83, buf, 64); | 3563 | |
| 3534 | if (rc == 0) | 3564 | rc = hpsa_scsi_do_inquiry(h, scsi3addr, VPD_PAGE | |
| 3535 | memcpy(device_id, &buf[index], buflen); | 3565 | HPSA_VPD_LV_DEVICE_ID, buf, 64); |
| 3566 | if (rc == 0) { | ||
| 3567 | if (buflen > 16) | ||
| 3568 | buflen = 16; | ||
| 3569 | memcpy(device_id, &buf[8], buflen); | ||
| 3570 | } | ||
| 3536 | 3571 | ||
| 3537 | kfree(buf); | 3572 | kfree(buf); |
| 3538 | 3573 | ||
| 3539 | return rc != 0; | 3574 | return rc; /*0 - got id, otherwise, didn't */ |
| 3540 | } | 3575 | } |
| 3541 | 3576 | ||
| 3542 | static int hpsa_scsi_do_report_luns(struct ctlr_info *h, int logical, | 3577 | static int hpsa_scsi_do_report_luns(struct ctlr_info *h, int logical, |
| @@ -3807,8 +3842,15 @@ static int hpsa_update_device_info(struct ctlr_info *h, · 264 unmodified lines | |||
| 3807 | sizeof(this_device->model)); | 3842 | sizeof(this_device->model)); |
| 3808 | memset(this_device->device_id, 0, | 3843 | memset(this_device->device_id, 0, |
| 3809 | sizeof(this_device->device_id)); | 3844 | sizeof(this_device->device_id)); |
| 3810 | hpsa_get_device_id(h, scsi3addr, this_device->device_id, 8, | 3845 | if (hpsa_get_device_id(h, scsi3addr, this_device->device_id, 8, |
| 3811 | sizeof(this_device->device_id)); | 3846 | sizeof(this_device->device_id))) |
| 3847 | dev_err(&h->pdev->dev, | ||
| 3848 | "hpsa%d: %s: can't get device id for host %d:C0:T%d:L%d\t%s\t%.16s\n", | ||
| 3849 | h->ctlr, __func__, | ||
| 3850 | h->scsi_host->host_no, | ||
| 3851 | this_device->target, this_device->lun, | ||
| 3852 | scsi_device_type(this_device->devtype), | ||
| 3853 | this_device->model); | ||
| 3812 | 3854 | ||
| 3813 | if ((this_device->devtype == TYPE_DISK || | 3855 | if ((this_device->devtype == TYPE_DISK || |
| 3814 | this_device->devtype == TYPE_ZBC) && | 3856 | this_device->devtype == TYPE_ZBC) && |
| @@ -4034,7 +4076,17 @@ static void hpsa_get_ioaccel_drive_info(struct ctlr_info *h, · 219 unmodified lines | |||
| 4034 | struct bmic_identify_physical_device *id_phys) | 4076 | struct bmic_identify_physical_device *id_phys) |
| 4035 | { | 4077 | { |
| 4036 | int rc; | 4078 | int rc; |
| 4037 | struct ext_report_lun_entry *rle = &rlep->LUN[rle_index]; | 4079 | struct ext_report_lun_entry *rle; |
| 4080 | |||
| 4081 | /* | ||
| 4082 | * external targets don't support BMIC | ||
| 4083 | */ | ||
| 4084 | if (dev->external) { | ||
| 4085 | dev->queue_depth = 7; | ||
| 4086 | return; | ||
| 4087 | } | ||
| 4088 | |||
| 4089 | rle = &rlep->LUN[rle_index]; | ||
| 4038 | 4090 | ||
| 4039 | dev->ioaccel_handle = rle->ioaccel_handle; | 4091 | dev->ioaccel_handle = rle->ioaccel_handle; |
| 4040 | if ((rle->device_flags & 0x08) && dev->ioaccel_handle) | 4092 | if ((rle->device_flags & 0x08) && dev->ioaccel_handle) |
| @@ -4270,6 +4322,11 @@ static void hpsa_update_scsi_devices(struct ctlr_info *h) · 229 unmodified lines | |||
| 4270 | lunaddrbytes = figure_lunaddrbytes(h, raid_ctlr_position, | 4322 | lunaddrbytes = figure_lunaddrbytes(h, raid_ctlr_position, |
| 4271 | i, nphysicals, nlogicals, physdev_list, logdev_list); | 4323 | i, nphysicals, nlogicals, physdev_list, logdev_list); |
| 4272 | 4324 | ||
| 4325 | /* Determine if this is a lun from an external target array */ | ||
| 4326 | tmpdevice->external = | ||
| 4327 | figure_external_status(h, raid_ctlr_position, i, | ||
| 4328 | nphysicals, nlocal_logicals); | ||
| 4329 | |||
| 4273 | /* | 4330 | /* |
| 4274 | * Skip over some devices such as a spare. | 4331 | * Skip over some devices such as a spare. |
| 4275 | */ | 4332 | */ |
| @@ -4295,11 +4352,6 @@ static void hpsa_update_scsi_devices(struct ctlr_info *h) · 19 unmodified lines | |||
| 4295 | continue; | 4352 | continue; |
| 4296 | } | 4353 | } |
| 4297 | 4354 | ||
| 4298 | /* Determine if this is a lun from an external target array */ | ||
| 4299 | tmpdevice->external = | ||
| 4300 | figure_external_status(h, raid_ctlr_position, i, | ||
| 4301 | nphysicals, nlocal_logicals); | ||
| 4302 | |||
| 4303 | figure_bus_target_lun(h, lunaddrbytes, tmpdevice); | 4355 | figure_bus_target_lun(h, lunaddrbytes, tmpdevice); |
| 4304 | hpsa_update_device_supports_aborts(h, tmpdevice, lunaddrbytes); | 4356 | hpsa_update_device_supports_aborts(h, tmpdevice, lunaddrbytes); |
| 4305 | this_device = currentsd[ncurrent]; | 4357 | this_device = currentsd[ncurrent]; |
| @@ -4513,7 +4565,9 @@ static int fixup_ioaccel_cdb(u8 *cdb, int *cdb_len) · 207 unmodified lines | |||
| 4513 | case READ_6: | 4565 | case READ_6: |
| 4514 | case READ_12: | 4566 | case READ_12: |
| 4515 | if (*cdb_len == 6) { | 4567 | if (*cdb_len == 6) { |
| 4516 | block = get_unaligned_be16(&cdb[2]); | 4568 | block = (((cdb[1] & 0x1F) << 16) | |
| 4569 | (cdb[2] << 8) | | ||
| 4570 | cdb[3]); | ||
| 4517 | block_cnt = cdb[4]; | 4571 | block_cnt = cdb[4]; |
| 4518 | if (block_cnt == 0) | 4572 | if (block_cnt == 0) |
| 4519 | block_cnt = 256; | 4573 | block_cnt = 256; |
| @@ -4638,6 +4692,9 @@ static int hpsa_scsi_ioaccel_direct_map(struct ctlr_info *h, · 118 unmodified lines | |||
| 4638 | struct scsi_cmnd *cmd = c->scsi_cmd; | 4692 | struct scsi_cmnd *cmd = c->scsi_cmd; |
| 4639 | struct hpsa_scsi_dev_t *dev = cmd->device->hostdata; | 4693 | struct hpsa_scsi_dev_t *dev = cmd->device->hostdata; |
| 4640 | 4694 | ||
| 4695 | if (!dev) | ||
| 4696 | return -1; | ||
| 4697 | |||
| 4641 | c->phys_disk = dev; | 4698 | c->phys_disk = dev; |
| 4642 | 4699 | ||
| 4643 | return hpsa_scsi_ioaccel_queue_command(h, c, dev->ioaccel_handle, | 4700 | return hpsa_scsi_ioaccel_queue_command(h, c, dev->ioaccel_handle, |
| @@ -4670,9 +4727,11 @@ static void set_encrypt_ioaccel2(struct ctlr_info *h, · 26 unmodified lines | |||
| 4670 | */ | 4727 | */ |
| 4671 | switch (cmd->cmnd[0]) { | 4728 | switch (cmd->cmnd[0]) { |
| 4672 | /* Required? 6-byte cdbs eliminated by fixup_ioaccel_cdb */ | 4729 | /* Required? 6-byte cdbs eliminated by fixup_ioaccel_cdb */ |
| 4673 | case WRITE_6: | ||
| 4674 | case READ_6: | 4730 | case READ_6: |
| 4675 | first_block = get_unaligned_be16(&cmd->cmnd[2]); | 4731 | case WRITE_6: |
| 4732 | first_block = (((cmd->cmnd[1] & 0x1F) << 16) | | ||
| 4733 | (cmd->cmnd[2] << 8) | | ||
| 4734 | cmd->cmnd[3]); | ||
| 4676 | break; | 4735 | break; |
| 4677 | case WRITE_10: | 4736 | case WRITE_10: |
| 4678 | case READ_10: | 4737 | case READ_10: |
| @@ -4714,6 +4773,12 @@ static int hpsa_scsi_ioaccel2_queue_command(struct ctlr_info *h, · 35 unmodified lines | |||
| 4714 | u32 len; | 4773 | u32 len; |
| 4715 | u32 total_len = 0; | 4774 | u32 total_len = 0; |
| 4716 | 4775 | ||
| 4776 | if (!cmd->device) | ||
| 4777 | return -1; | ||
| 4778 | |||
| 4779 | if (!cmd->device->hostdata) | ||
| 4780 | return -1; | ||
| 4781 | |||
| 4717 | BUG_ON(scsi_sg_count(cmd) > h->maxsgentries); | 4782 | BUG_ON(scsi_sg_count(cmd) > h->maxsgentries); |
| 4718 | 4783 | ||
| 4719 | if (fixup_ioaccel_cdb(cdb, &cdb_len)) { | 4784 | if (fixup_ioaccel_cdb(cdb, &cdb_len)) { |
| @@ -4822,6 +4887,12 @@ static int hpsa_scsi_ioaccel_queue_command(struct ctlr_info *h, · 102 unmodified lines | |||
| 4822 | struct CommandList *c, u32 ioaccel_handle, u8 *cdb, int cdb_len, | 4887 | struct CommandList *c, u32 ioaccel_handle, u8 *cdb, int cdb_len, |
| 4823 | u8 *scsi3addr, struct hpsa_scsi_dev_t *phys_disk) | 4888 | u8 *scsi3addr, struct hpsa_scsi_dev_t *phys_disk) |
| 4824 | { | 4889 | { |
| 4890 | if (!c->scsi_cmd->device) | ||
| 4891 | return -1; | ||
| 4892 | |||
| 4893 | if (!c->scsi_cmd->device->hostdata) | ||
| 4894 | return -1; | ||
| 4895 | |||
| 4825 | /* Try to honor the device's queue depth */ | 4896 | /* Try to honor the device's queue depth */ |
| 4826 | if (atomic_inc_return(&phys_disk->ioaccel_cmds_out) > | 4897 | if (atomic_inc_return(&phys_disk->ioaccel_cmds_out) > |
| 4827 | phys_disk->queue_depth) { | 4898 | phys_disk->queue_depth) { |
| @@ -4902,12 +4973,17 @@ static int hpsa_scsi_ioaccel_raid_map(struct ctlr_info *h, · 74 unmodified lines | |||
| 4902 | #endif | 4973 | #endif |
| 4903 | int offload_to_mirror; | 4974 | int offload_to_mirror; |
| 4904 | 4975 | ||
| 4976 | if (!dev) | ||
| 4977 | return -1; | ||
| 4978 | |||
| 4905 | /* check for valid opcode, get LBA and block count */ | 4979 | /* check for valid opcode, get LBA and block count */ |
| 4906 | switch (cmd->cmnd[0]) { | 4980 | switch (cmd->cmnd[0]) { |
| 4907 | case WRITE_6: | 4981 | case WRITE_6: |
| 4908 | is_write = 1; | 4982 | is_write = 1; |
| 4909 | case READ_6: | 4983 | case READ_6: |
| 4910 | first_block = get_unaligned_be16(&cmd->cmnd[2]); | 4984 | first_block = (((cmd->cmnd[1] & 0x1F) << 16) | |
| 4985 | (cmd->cmnd[2] << 8) | | ||
| 4986 | cmd->cmnd[3]); | ||
| 4911 | block_cnt = cmd->cmnd[4]; | 4987 | block_cnt = cmd->cmnd[4]; |
| 4912 | if (block_cnt == 0) | 4988 | if (block_cnt == 0) |
| 4913 | block_cnt = 256; | 4989 | block_cnt = 256; |
| @@ -5314,6 +5390,9 @@ static int hpsa_ioaccel_submit(struct ctlr_info *h, · 400 unmodified lines | |||
| 5314 | struct hpsa_scsi_dev_t *dev = cmd->device->hostdata; | 5390 | struct hpsa_scsi_dev_t *dev = cmd->device->hostdata; |
| 5315 | int rc = IO_ACCEL_INELIGIBLE; | 5391 | int rc = IO_ACCEL_INELIGIBLE; |
| 5316 | 5392 | ||
| 5393 | if (!dev) | ||
| 5394 | return SCSI_MLQUEUE_HOST_BUSY; | ||
| 5395 | |||
| 5317 | cmd->host_scribble = (unsigned char *) c; | 5396 | cmd->host_scribble = (unsigned char *) c; |
| 5318 | 5397 | ||
| 5319 | if (dev->offload_enabled) { | 5398 | if (dev->offload_enabled) { |
| @@ -5852,6 +5931,9 @@ static void setup_ioaccel2_abort_cmd(struct CommandList *c, struct ctlr_info *h, · 532 unmodified lines | |||
| 5852 | struct scsi_cmnd *scmd = command_to_abort->scsi_cmd; | 5931 | struct scsi_cmnd *scmd = command_to_abort->scsi_cmd; |
| 5853 | struct hpsa_scsi_dev_t *dev = scmd->device->hostdata; | 5932 | struct hpsa_scsi_dev_t *dev = scmd->device->hostdata; |
| 5854 | 5933 | ||
| 5934 | if (!dev) | ||
| 5935 | return; | ||
| 5936 | |||
| 5855 | /* | 5937 | /* |
| 5856 | * We're overlaying struct hpsa_tmf_struct on top of something which | 5938 | * We're overlaying struct hpsa_tmf_struct on top of something which |
| 5857 | * was allocated as a struct io_accel2_cmd, so we better be sure it | 5939 | * was allocated as a struct io_accel2_cmd, so we better be sure it |
| @@ -5935,7 +6017,7 @@ static int hpsa_send_reset_as_abort_ioaccel2(struct ctlr_info *h, · 77 unmodified lines | |||
| 5935 | "Reset as abort: Resetting physical device at scsi3addr 0x%02x%02x%02x%02x%02x%02x%02x%02x\n", | 6017 | "Reset as abort: Resetting physical device at scsi3addr 0x%02x%02x%02x%02x%02x%02x%02x%02x\n", |
| 5936 | psa[0], psa[1], psa[2], psa[3], | 6018 | psa[0], psa[1], psa[2], psa[3], |
| 5937 | psa[4], psa[5], psa[6], psa[7]); | 6019 | psa[4], psa[5], psa[6], psa[7]); |
| 5938 | rc = hpsa_do_reset(h, dev, psa, HPSA_RESET_TYPE_TARGET, reply_queue); | 6020 | rc = hpsa_do_reset(h, dev, psa, HPSA_PHYS_TARGET_RESET, reply_queue); |
| 5939 | if (rc != 0) { | 6021 | if (rc != 0) { |
| 5940 | dev_warn(&h->pdev->dev, | 6022 | dev_warn(&h->pdev->dev, |
| 5941 | "Reset as abort: Failed on physical device at scsi3addr 0x%02x%02x%02x%02x%02x%02x%02x%02x\n", | 6023 | "Reset as abort: Failed on physical device at scsi3addr 0x%02x%02x%02x%02x%02x%02x%02x%02x\n", |
| @@ -5972,6 +6054,9 @@ static int hpsa_send_abort_ioaccel2(struct ctlr_info *h, · 30 unmodified lines | |||
| 5972 | struct io_accel2_cmd *c2; | 6054 | struct io_accel2_cmd *c2; |
| 5973 | 6055 | ||
| 5974 | dev = abort->scsi_cmd->device->hostdata; | 6056 | dev = abort->scsi_cmd->device->hostdata; |
| 6057 | if (!dev) | ||
| 6058 | return -1; | ||
| 6059 | |||
| 5975 | if (!dev->offload_enabled && !dev->hba_ioaccel_enabled) | 6060 | if (!dev->offload_enabled && !dev->hba_ioaccel_enabled) |
| 5976 | return -1; | 6061 | return -1; |
| 5977 | 6062 | ||
| @@ -312,7 +312,6 @@ struct offline_device_entry { · 311 unmodified lines | |||
| 312 | #define HPSA_DEVICE_RESET_MSG 1 | 312 | #define HPSA_DEVICE_RESET_MSG 1 |
| 313 | #define HPSA_RESET_TYPE_CONTROLLER 0x00 | 313 | #define HPSA_RESET_TYPE_CONTROLLER 0x00 |
| 314 | #define HPSA_RESET_TYPE_BUS 0x01 | 314 | #define HPSA_RESET_TYPE_BUS 0x01 |
| 315 | #define HPSA_RESET_TYPE_TARGET 0x03 | ||
| 316 | #define HPSA_RESET_TYPE_LUN 0x04 | 315 | #define HPSA_RESET_TYPE_LUN 0x04 |
| 317 | #define HPSA_PHYS_TARGET_RESET 0x99 /* not defined by cciss spec */ | 316 | #define HPSA_PHYS_TARGET_RESET 0x99 /* not defined by cciss spec */ |
| 318 | #define HPSA_MSG_SEND_RETRY_LIMIT 10 | 317 | #define HPSA_MSG_SEND_RETRY_LIMIT 10 |
| @@ -157,6 +157,7 @@ · 156 unmodified lines | |||
| 157 | 157 | ||
| 158 | /* VPD Inquiry types */ | 158 | /* VPD Inquiry types */ |
| 159 | #define HPSA_VPD_SUPPORTED_PAGES 0x00 | 159 | #define HPSA_VPD_SUPPORTED_PAGES 0x00 |
| 160 | #define HPSA_VPD_LV_DEVICE_ID 0x83 | ||
| 160 | #define HPSA_VPD_LV_DEVICE_GEOMETRY 0xC1 | 161 | #define HPSA_VPD_LV_DEVICE_GEOMETRY 0xC1 |
| 161 | #define HPSA_VPD_LV_IOACCEL_STATUS 0xC2 | 162 | #define HPSA_VPD_LV_IOACCEL_STATUS 0xC2 |
| 162 | #define HPSA_VPD_LV_STATUS 0xC3 | 163 | #define HPSA_VPD_LV_STATUS 0xC3 |
| @@ -52,6 +52,7 @@ static unsigned int max_requests = IBMVFC_MAX_REQUESTS_DEFAULT; · 51 unmodified lines | |||
| 52 | static unsigned int disc_threads = IBMVFC_MAX_DISC_THREADS; | 52 | static unsigned int disc_threads = IBMVFC_MAX_DISC_THREADS; |
| 53 | static unsigned int ibmvfc_debug = IBMVFC_DEBUG; | 53 | static unsigned int ibmvfc_debug = IBMVFC_DEBUG; |
| 54 | static unsigned int log_level = IBMVFC_DEFAULT_LOG_LEVEL; | 54 | static unsigned int log_level = IBMVFC_DEFAULT_LOG_LEVEL; |
| 55 | static unsigned int cls3_error = IBMVFC_CLS3_ERROR; | ||
| 55 | static LIST_HEAD(ibmvfc_head); | 56 | static LIST_HEAD(ibmvfc_head); |
| 56 | static DEFINE_SPINLOCK(ibmvfc_driver_lock); | 57 | static DEFINE_SPINLOCK(ibmvfc_driver_lock); |
| 57 | static struct scsi_transport_template *ibmvfc_transport_template; | 58 | static struct scsi_transport_template *ibmvfc_transport_template; |
| @@ -86,6 +87,9 @@ MODULE_PARM_DESC(debug, "Enable driver debug information. " · 28 unmodified lines | |||
| 86 | module_param_named(log_level, log_level, uint, 0); | 87 | module_param_named(log_level, log_level, uint, 0); |
| 87 | MODULE_PARM_DESC(log_level, "Set to 0 - 4 for increasing verbosity of device driver. " | 88 | MODULE_PARM_DESC(log_level, "Set to 0 - 4 for increasing verbosity of device driver. " |
| 88 | "[Default=" __stringify(IBMVFC_DEFAULT_LOG_LEVEL) "]"); | 89 | "[Default=" __stringify(IBMVFC_DEFAULT_LOG_LEVEL) "]"); |
| 90 | module_param_named(cls3_error, cls3_error, uint, 0); | ||
| 91 | MODULE_PARM_DESC(cls3_error, "Enable FC Class 3 Error Recovery. " | ||
| 92 | "[Default=" __stringify(IBMVFC_CLS3_ERROR) "]"); | ||
| 89 | 93 | ||
| 90 | static const struct { | 94 | static const struct { |
| 91 | u16 status; | 95 | u16 status; |
| @@ -717,7 +721,6 @@ static int ibmvfc_reset_crq(struct ibmvfc_host *vhost) · 625 unmodified lines | |||
| 717 | spin_lock_irqsave(vhost->host->host_lock, flags); | 721 | spin_lock_irqsave(vhost->host->host_lock, flags); |
| 718 | vhost->state = IBMVFC_NO_CRQ; | 722 | vhost->state = IBMVFC_NO_CRQ; |
| 719 | vhost->logged_in = 0; | 723 | vhost->logged_in = 0; |
| 720 | ibmvfc_set_host_action(vhost, IBMVFC_HOST_ACTION_NONE); | ||
| 721 | 724 | ||
| 722 | /* Clean out the queue */ | 725 | /* Clean out the queue */ |
| 723 | memset(crq->msgs, 0, PAGE_SIZE); | 726 | memset(crq->msgs, 0, PAGE_SIZE); |
| @@ -1335,6 +1338,9 @@ static int ibmvfc_map_sg_data(struct scsi_cmnd *scmd, · 611 unmodified lines | |||
| 1335 | struct srp_direct_buf *data = &vfc_cmd->ioba; | 1338 | struct srp_direct_buf *data = &vfc_cmd->ioba; |
| 1336 | struct ibmvfc_host *vhost = dev_get_drvdata(dev); | 1339 | struct ibmvfc_host *vhost = dev_get_drvdata(dev); |
| 1337 | 1340 | ||
| 1341 | if (cls3_error) | ||
| 1342 | vfc_cmd->flags |= cpu_to_be16(IBMVFC_CLASS_3_ERR); | ||
| 1343 | |||
| 1338 | sg_mapped = scsi_dma_map(scmd); | 1344 | sg_mapped = scsi_dma_map(scmd); |
| 1339 | if (!sg_mapped) { | 1345 | if (!sg_mapped) { |
| 1340 | vfc_cmd->flags |= cpu_to_be16(IBMVFC_NO_MEM_DESC); | 1346 | vfc_cmd->flags |= cpu_to_be16(IBMVFC_NO_MEM_DESC); |
| @@ -3381,6 +3387,10 @@ static void ibmvfc_tgt_send_prli(struct ibmvfc_target *tgt) · 2040 unmodified lines | |||
| 3381 | prli->parms.type = IBMVFC_SCSI_FCP_TYPE; | 3387 | prli->parms.type = IBMVFC_SCSI_FCP_TYPE; |
| 3382 | prli->parms.flags = cpu_to_be16(IBMVFC_PRLI_EST_IMG_PAIR); | 3388 | prli->parms.flags = cpu_to_be16(IBMVFC_PRLI_EST_IMG_PAIR); |
| 3383 | prli->parms.service_parms = cpu_to_be32(IBMVFC_PRLI_INITIATOR_FUNC); | 3389 | prli->parms.service_parms = cpu_to_be32(IBMVFC_PRLI_INITIATOR_FUNC); |
| 3390 | prli->parms.service_parms |= cpu_to_be32(IBMVFC_PRLI_READ_FCP_XFER_RDY_DISABLED); | ||
| 3391 | |||
| 3392 | if (cls3_error) | ||
| 3393 | prli->parms.service_parms |= cpu_to_be32(IBMVFC_PRLI_RETRY); | ||
| 3384 | 3394 | ||
| 3385 | ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_INIT_WAIT); | 3395 | ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_INIT_WAIT); |
| 3386 | if (ibmvfc_send_event(evt, vhost, default_timeout)) { | 3396 | if (ibmvfc_send_event(evt, vhost, default_timeout)) { |
| @@ -54,6 +54,7 @@ · 53 unmodified lines | |||
| 54 | #define IBMVFC_DEV_LOSS_TMO (5 * 60) | 54 | #define IBMVFC_DEV_LOSS_TMO (5 * 60) |
| 55 | #define IBMVFC_DEFAULT_LOG_LEVEL 2 | 55 | #define IBMVFC_DEFAULT_LOG_LEVEL 2 |
| 56 | #define IBMVFC_MAX_CDB_LEN 16 | 56 | #define IBMVFC_MAX_CDB_LEN 16 |
| 57 | #define IBMVFC_CLS3_ERROR 0 | ||
| 57 | 58 | ||
| 58 | /* | 59 | /* |
| 59 | * Ensure we have resources for ERP and initialization: | 60 | * Ensure we have resources for ERP and initialization: |
| @@ -1606,8 +1606,6 @@ static void ibmvscsis_send_messages(struct scsi_info *vscsi) · 1605 unmodified lines | |||
| 1606 | 1606 | ||
| 1607 | if (!(vscsi->flags & RESPONSE_Q_DOWN)) { | 1607 | if (!(vscsi->flags & RESPONSE_Q_DOWN)) { |
| 1608 | list_for_each_entry_safe(cmd, nxt, &vscsi->waiting_rsp, list) { | 1608 | list_for_each_entry_safe(cmd, nxt, &vscsi->waiting_rsp, list) { |
| 1609 | pr_debug("send_messages cmd %p\n", cmd); | ||
| 1610 | |||
| 1611 | iue = cmd->iue; | 1609 | iue = cmd->iue; |
| 1612 | 1610 | ||
| 1613 | crq->valid = VALID_CMD_RESP_EL; | 1611 | crq->valid = VALID_CMD_RESP_EL; |
| @@ -1934,6 +1932,8 @@ static int ibmvscsis_drop_nexus(struct ibmvscsis_tport *tport) · 320 unmodified lines | |||
| 1934 | /* | 1932 | /* |
| 1935 | * Release the SCSI I_T Nexus to the emulated ibmvscsis Target Port | 1933 | * Release the SCSI I_T Nexus to the emulated ibmvscsis Target Port |
| 1936 | */ | 1934 | */ |
| 1935 | target_wait_for_sess_cmds(se_sess); | ||
| 1936 | transport_deregister_session_configfs(se_sess); | ||
| 1937 | transport_deregister_session(se_sess); | 1937 | transport_deregister_session(se_sess); |
| 1938 | tport->ibmv_nexus = NULL; | 1938 | tport->ibmv_nexus = NULL; |
| 1939 | kfree(nexus); | 1939 | kfree(nexus); |
| @@ -1978,7 +1978,7 @@ static long ibmvscsis_srp_login(struct scsi_info *vscsi, · 38 unmodified lines | |||
| 1978 | reason = SRP_LOGIN_REJ_MULTI_CHANNEL_UNSUPPORTED; | 1978 | reason = SRP_LOGIN_REJ_MULTI_CHANNEL_UNSUPPORTED; |
| 1979 | else if (fmt->buffers & (~SUPPORTED_FORMATS)) | 1979 | else if (fmt->buffers & (~SUPPORTED_FORMATS)) |
| 1980 | reason = SRP_LOGIN_REJ_UNSUPPORTED_DESCRIPTOR_FMT; | 1980 | reason = SRP_LOGIN_REJ_UNSUPPORTED_DESCRIPTOR_FMT; |
| 1981 | else if ((fmt->buffers | SUPPORTED_FORMATS) == 0) | 1981 | else if ((fmt->buffers & SUPPORTED_FORMATS) == 0) |
| 1982 | reason = SRP_LOGIN_REJ_UNSUPPORTED_DESCRIPTOR_FMT; | 1982 | reason = SRP_LOGIN_REJ_UNSUPPORTED_DESCRIPTOR_FMT; |
| 1983 | 1983 | ||
| 1984 | if (vscsi->state == SRP_PROCESSING) | 1984 | if (vscsi->state == SRP_PROCESSING) |
| @@ -2554,10 +2554,6 @@ static void ibmvscsis_parse_cmd(struct scsi_info *vscsi, · 569 unmodified lines | |||
| 2554 | 2554 | ||
| 2555 | srp->lun.scsi_lun[0] &= 0x3f; | 2555 | srp->lun.scsi_lun[0] &= 0x3f; |
| 2556 | 2556 | ||
| 2557 | pr_debug("calling submit_cmd, se_cmd %p, lun 0x%llx, cdb 0x%x, attr:%d\n", | ||
| 2558 | &cmd->se_cmd, scsilun_to_int(&srp->lun), (int)srp->cdb[0], | ||
| 2559 | attr); | ||
| 2560 | |||
| 2561 | rc = target_submit_cmd(&cmd->se_cmd, nexus->se_sess, srp->cdb, | 2557 | rc = target_submit_cmd(&cmd->se_cmd, nexus->se_sess, srp->cdb, |
| 2562 | cmd->sense_buf, scsilun_to_int(&srp->lun), | 2558 | cmd->sense_buf, scsilun_to_int(&srp->lun), |
| 2563 | data_len, attr, dir, 0); | 2559 | data_len, attr, dir, 0); |
| @@ -3142,8 +3138,6 @@ static int ibmvscsis_rdma(struct ibmvscsis_cmd *cmd, struct scatterlist *sg, · 578 unmodified lines | |||
| 3142 | long tx_len; | 3138 | long tx_len; |
| 3143 | long rc = 0; | 3139 | long rc = 0; |
| 3144 | 3140 | ||
| 3145 | pr_debug("rdma: dir %d, bytes 0x%x\n", dir, bytes); | ||
| 3146 | |||
| 3147 | if (bytes == 0) | 3141 | if (bytes == 0) |
| 3148 | return 0; | 3142 | return 0; |
| 3149 | 3143 | ||
| @@ -3192,12 +3186,6 @@ static int ibmvscsis_rdma(struct ibmvscsis_cmd *cmd, struct scatterlist *sg, · 42 unmodified lines | |||
| 3192 | vscsi->dds.window[LOCAL].liobn, | 3186 | vscsi->dds.window[LOCAL].liobn, |
| 3193 | server_ioba); | 3187 | server_ioba); |
| 3194 | } else { | 3188 | } else { |
| 3195 | /* write to client */ | ||
| 3196 | struct srp_cmd *srp = (struct srp_cmd *)iue->sbuf->buf; | ||
| 3197 | |||
| 3198 | if (!READ_CMD(srp->cdb)) | ||
| 3199 | print_hex_dump_bytes(" data:", DUMP_PREFIX_NONE, | ||
| 3200 | sg_virt(sgp), buf_len); | ||
| 3201 | /* The h_copy_rdma will cause phyp, running in another | 3189 | /* The h_copy_rdma will cause phyp, running in another |
| 3202 | * partition, to read memory, so we need to make sure | 3190 | * partition, to read memory, so we need to make sure |
| 3203 | * the data has been written out, hence these syncs. | 3191 | * the data has been written out, hence these syncs. |
| @@ -3322,12 +3310,9 @@ cmd_work: · 118 unmodified lines | |||
| 3322 | rc = ibmvscsis_trans_event(vscsi, crq); | 3310 | rc = ibmvscsis_trans_event(vscsi, crq); |
| 3323 | } else if (vscsi->flags & TRANS_EVENT) { | 3311 | } else if (vscsi->flags & TRANS_EVENT) { |
| 3324 | /* | 3312 | /* |
| 3325 | * if a tranport event has occurred leave | 3313 | * if a transport event has occurred leave |
| 3326 | * everything but transport events on the queue | 3314 | * everything but transport events on the queue |
| 3327 | */ | 3315 | * |
| 3328 | pr_debug("handle_crq, ignoring\n"); | ||
| 3329 | |||
| 3330 | /* | ||
| 3331 | * need to decrement the queue index so we can | 3316 | * need to decrement the queue index so we can |
| 3332 | * look at the elment again | 3317 | * look at the elment again |
| 3333 | */ | 3318 | */ |
| @@ -3461,6 +3446,7 @@ static int ibmvscsis_probe(struct vio_dev *vdev, · 127 unmodified lines | |||
| 3461 | vscsi->map_ioba = dma_map_single(&vdev->dev, vscsi->map_buf, PAGE_SIZE, | 3446 | vscsi->map_ioba = dma_map_single(&vdev->dev, vscsi->map_buf, PAGE_SIZE, |
| 3462 | DMA_BIDIRECTIONAL); | 3447 | DMA_BIDIRECTIONAL); |
| 3463 | if (dma_mapping_error(&vdev->dev, vscsi->map_ioba)) { | 3448 | if (dma_mapping_error(&vdev->dev, vscsi->map_ioba)) { |
| 3449 | rc = -ENOMEM; | ||
| 3464 | dev_err(&vscsi->dev, "probe: error mapping command buffer\n"); | 3450 | dev_err(&vscsi->dev, "probe: error mapping command buffer\n"); |
| 3465 | goto free_buf; | 3451 | goto free_buf; |
| 3466 | } | 3452 | } |
| @@ -3693,12 +3679,9 @@ static void ibmvscsis_release_cmd(struct se_cmd *se_cmd) · 226 unmodified lines | |||
| 3693 | se_cmd); | 3679 | se_cmd); |
| 3694 | struct scsi_info *vscsi = cmd->adapter; | 3680 | struct scsi_info *vscsi = cmd->adapter; |
| 3695 | 3681 | ||
| 3696 | pr_debug("release_cmd %p, flags %d\n", se_cmd, cmd->flags); | ||
| 3697 | |||
| 3698 | spin_lock_bh(&vscsi->intr_lock); | 3682 | spin_lock_bh(&vscsi->intr_lock); |
| 3699 | /* Remove from active_q */ | 3683 | /* Remove from active_q */ |
| 3700 | list_del(&cmd->list); | 3684 | list_move_tail(&cmd->list, &vscsi->waiting_rsp); |
| 3701 | list_add_tail(&cmd->list, &vscsi->waiting_rsp); | ||
| 3702 | ibmvscsis_send_messages(vscsi); | 3685 | ibmvscsis_send_messages(vscsi); |
| 3703 | spin_unlock_bh(&vscsi->intr_lock); | 3686 | spin_unlock_bh(&vscsi->intr_lock); |
| 3704 | } | 3687 | } |
| @@ -3715,9 +3698,6 @@ static int ibmvscsis_write_pending(struct se_cmd *se_cmd) · 10 unmodified lines | |||
| 3715 | struct iu_entry *iue = cmd->iue; | 3698 | struct iu_entry *iue = cmd->iue; |
| 3716 | int rc; | 3699 | int rc; |
| 3717 | 3700 | ||
| 3718 | pr_debug("write_pending, se_cmd %p, length 0x%x\n", | ||
| 3719 | se_cmd, se_cmd->data_length); | ||
| 3720 | |||
| 3721 | rc = srp_transfer_data(cmd, &vio_iu(iue)->srp.cmd, ibmvscsis_rdma, | 3701 | rc = srp_transfer_data(cmd, &vio_iu(iue)->srp.cmd, ibmvscsis_rdma, |
| 3722 | 1, 1); | 3702 | 1, 1); |
| 3723 | if (rc) { | 3703 | if (rc) { |
| @@ -3756,9 +3736,6 @@ static int ibmvscsis_queue_data_in(struct se_cmd *se_cmd) · 32 unmodified lines | |||
| 3756 | uint len = 0; | 3736 | uint len = 0; |
| 3757 | int rc; | 3737 | int rc; |
| 3758 | 3738 | ||
| 3759 | pr_debug("queue_data_in, se_cmd %p, length 0x%x\n", | ||
| 3760 | se_cmd, se_cmd->data_length); | ||
| 3761 | |||
| 3762 | rc = srp_transfer_data(cmd, &vio_iu(iue)->srp.cmd, ibmvscsis_rdma, 1, | 3739 | rc = srp_transfer_data(cmd, &vio_iu(iue)->srp.cmd, ibmvscsis_rdma, 1, |
| 3763 | 1); | 3740 | 1); |
| 3764 | if (rc) { | 3741 | if (rc) { |
| @@ -1,2302 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * in2000.c - Linux device driver for the | ||
| 3 | * Always IN2000 ISA SCSI card. | ||
| 4 | * | ||
| 5 | * Copyright (c) 1996 John Shifflett, GeoLog Consulting | ||
| 6 | * john@geolog.com | ||
| 7 | * jshiffle@netcom.com | ||
| 8 | * | ||
| 9 | * This program is free software; you can redistribute it and/or modify | ||
| 10 | * it under the terms of the GNU General Public License as published by | ||
| 11 | * the Free Software Foundation; either version 2, or (at your option) | ||
| 12 | * any later version. | ||
| 13 | * | ||
| 14 | * This program is distributed in the hope that it will be useful, | ||
| 15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 17 | * GNU General Public License for more details. | ||
| 18 | * | ||
| 19 | * For the avoidance of doubt the "preferred form" of this code is one which | ||
| 20 | * is in an open non patent encumbered format. Where cryptographic key signing | ||
| 21 | * forms part of the process of creating an executable the information | ||
| 22 | * including keys needed to generate an equivalently functional executable | ||
| 23 | * are deemed to be part of the source code. | ||
| 24 | * | ||
| 25 | * Drew Eckhardt's excellent 'Generic NCR5380' sources provided | ||
| 26 | * much of the inspiration and some of the code for this driver. | ||
| 27 | * The Linux IN2000 driver distributed in the Linux kernels through | ||
| 28 | * version 1.2.13 was an extremely valuable reference on the arcane | ||
| 29 | * (and still mysterious) workings of the IN2000's fifo. It also | ||
| 30 | * is where I lifted in2000_biosparam(), the gist of the card | ||
| 31 | * detection scheme, and other bits of code. Many thanks to the | ||
| 32 | * talented and courageous people who wrote, contributed to, and | ||
| 33 | * maintained that driver (including Brad McLean, Shaun Savage, | ||
| 34 | * Bill Earnest, Larry Doolittle, Roger Sunshine, John Luckey, | ||
| 35 | * Matt Postiff, Peter Lu, zerucha@shell.portal.com, and Eric | ||
| 36 | * Youngdale). I should also mention the driver written by | ||
| 37 | * Hamish Macdonald for the (GASP!) Amiga A2091 card, included | ||
| 38 | * in the Linux-m68k distribution; it gave me a good initial | ||
| 39 | * understanding of the proper way to run a WD33c93 chip, and I | ||
| 40 | * ended up stealing lots of code from it. | ||
| 41 | * | ||
| 42 | * _This_ driver is (I feel) an improvement over the old one in | ||
| 43 | * several respects: | ||
| 44 | * - All problems relating to the data size of a SCSI request are | ||
| 45 | * gone (as far as I know). The old driver couldn't handle | ||
| 46 | * swapping to partitions because that involved 4k blocks, nor | ||
| 47 | * could it deal with the st.c tape driver unmodified, because | ||
| 48 | * that usually involved 4k - 32k blocks. The old driver never | ||
| 49 | * quite got away from a morbid dependence on 2k block sizes - | ||
| 50 | * which of course is the size of the card's fifo. | ||
| 51 | * | ||
| 52 | * - Target Disconnection/Reconnection is now supported. Any | ||
| 53 | * system with more than one device active on the SCSI bus | ||
| 54 | * will benefit from this. The driver defaults to what I'm | ||
| 55 | * calling 'adaptive disconnect' - meaning that each command | ||
| 56 | * is evaluated individually as to whether or not it should | ||
| 57 | * be run with the option to disconnect/reselect (if the | ||
| 58 | * device chooses), or as a "SCSI-bus-hog". | ||
| 59 | * | ||
| 60 | * - Synchronous data transfers are now supported. Because there | ||
| 61 | * are a few devices (and many improperly terminated systems) | ||
| 62 | * that choke when doing sync, the default is sync DISABLED | ||
| 63 | * for all devices. This faster protocol can (and should!) | ||
| 64 | * be enabled on selected devices via the command-line. | ||
| 65 | * | ||
| 66 | * - Runtime operating parameters can now be specified through | ||
| 67 | * either the LILO or the 'insmod' command line. For LILO do: | ||
| 68 | * "in2000=blah,blah,blah" | ||
| 69 | * and with insmod go like: | ||
| 70 | * "insmod /usr/src/linux/modules/in2000.o setup_strings=blah,blah" | ||
| 71 | * The defaults should be good for most people. See the comment | ||
| 72 | * for 'setup_strings' below for more details. | ||
| 73 | * | ||
| 74 | * - The old driver relied exclusively on what the Western Digital | ||
| 75 | * docs call "Combination Level 2 Commands", which are a great | ||
| 76 | * idea in that the CPU is relieved of a lot of interrupt | ||
| 77 | * overhead. However, by accepting a certain (user-settable) | ||
| 78 | * amount of additional interrupts, this driver achieves | ||
| 79 | * better control over the SCSI bus, and data transfers are | ||
| 80 | * almost as fast while being much easier to define, track, | ||
| 81 | * and debug. | ||
| 82 | * | ||
| 83 | * - You can force detection of a card whose BIOS has been disabled. | ||
| 84 | * | ||
| 85 | * - Multiple IN2000 cards might almost be supported. I've tried to | ||
| 86 | * keep it in mind, but have no way to test... | ||
| 87 | * | ||
| 88 | * | ||
| 89 | * TODO: | ||
| 90 | * tagged queuing. multiple cards. | ||
| 91 | * | ||
| 92 | * | ||
| 93 | * NOTE: | ||
| 94 | * When using this or any other SCSI driver as a module, you'll | ||
| 95 | * find that with the stock kernel, at most _two_ SCSI hard | ||
| 96 | * drives will be linked into the device list (ie, usable). | ||
| 97 | * If your IN2000 card has more than 2 disks on its bus, you | ||
| 98 | * might want to change the define of 'SD_EXTRA_DEVS' in the | ||
| 99 | * 'hosts.h' file from 2 to whatever is appropriate. It took | ||
| 100 | * me a while to track down this surprisingly obscure and | ||
| 101 | * undocumented little "feature". | ||
| 102 | * | ||
| 103 | * | ||
| 104 | * People with bug reports, wish-lists, complaints, comments, | ||
| 105 | * or improvements are asked to pah-leeez email me (John Shifflett) | ||
| 106 | * at john@geolog.com or jshiffle@netcom.com! I'm anxious to get | ||
| 107 | * this thing into as good a shape as possible, and I'm positive | ||
| 108 | * there are lots of lurking bugs and "Stupid Places". | ||
| 109 | * | ||
| 110 | * Updated for Linux 2.5 by Alan Cox <alan@lxorguk.ukuu.org.uk> | ||
| 111 | * - Using new_eh handler | ||
| 112 | * - Hopefully got all the locking right again | ||
| 113 | * See "FIXME" notes for items that could do with more work | ||
| 114 | */ | ||
| 115 | |||
| 116 | #include <linux/module.h> | ||
| 117 | #include <linux/blkdev.h> | ||
| 118 | #include <linux/interrupt.h> | ||
| 119 | #include <linux/string.h> | ||
| 120 | #include <linux/delay.h> | ||
| 121 | #include <linux/proc_fs.h> | ||
| 122 | #include <linux/ioport.h> | ||
| 123 | #include <linux/stat.h> | ||
| 124 | |||
| 125 | #include <asm/io.h> | ||
| 126 | |||
| 127 | #include "scsi.h" | ||
| 128 | #include <scsi/scsi_host.h> | ||
| 129 | |||
| 130 | #define IN2000_VERSION "1.33-2.5" | ||
| 131 | #define IN2000_DATE "2002/11/03" | ||
| 132 | |||
| 133 | #include "in2000.h" | ||
| 134 | |||
| 135 | |||
| 136 | /* | ||
| 137 | * 'setup_strings' is a single string used to pass operating parameters and | ||
| 138 | * settings from the kernel/module command-line to the driver. 'setup_args[]' | ||
| 139 | * is an array of strings that define the compile-time default values for | ||
| 140 | * these settings. If Linux boots with a LILO or insmod command-line, those | ||
| 141 | * settings are combined with 'setup_args[]'. Note that LILO command-lines | ||
| 142 | * are prefixed with "in2000=" while insmod uses a "setup_strings=" prefix. | ||
| 143 | * The driver recognizes the following keywords (lower case required) and | ||
| 144 | * arguments: | ||
| 145 | * | ||
| 146 | * - ioport:addr -Where addr is IO address of a (usually ROM-less) card. | ||
| 147 | * - noreset -No optional args. Prevents SCSI bus reset at boot time. | ||
| 148 | * - nosync:x -x is a bitmask where the 1st 7 bits correspond with | ||
| 149 | * the 7 possible SCSI devices (bit 0 for device #0, etc). | ||
| 150 | * Set a bit to PREVENT sync negotiation on that device. | ||
| 151 | * The driver default is sync DISABLED on all devices. | ||
| 152 | * - period:ns -ns is the minimum # of nanoseconds in a SCSI data transfer | ||
| 153 | * period. Default is 500; acceptable values are 250 - 1000. | ||
| 154 | * - disconnect:x -x = 0 to never allow disconnects, 2 to always allow them. | ||
| 155 | * x = 1 does 'adaptive' disconnects, which is the default | ||
| 156 | * and generally the best choice. | ||
| 157 | * - debug:x -If 'DEBUGGING_ON' is defined, x is a bitmask that causes | ||
| 158 | * various types of debug output to printed - see the DB_xxx | ||
| 159 | * defines in in2000.h | ||
| 160 | * - proc:x -If 'PROC_INTERFACE' is defined, x is a bitmask that | ||
| 161 | * determines how the /proc interface works and what it | ||
| 162 | * does - see the PR_xxx defines in in2000.h | ||
| 163 | * | ||
| 164 | * Syntax Notes: | ||
| 165 | * - Numeric arguments can be decimal or the '0x' form of hex notation. There | ||
| 166 | * _must_ be a colon between a keyword and its numeric argument, with no | ||
| 167 | * spaces. | ||
| 168 | * - Keywords are separated by commas, no spaces, in the standard kernel | ||
| 169 | * command-line manner. | ||
| 170 | * - A keyword in the 'nth' comma-separated command-line member will overwrite | ||
| 171 | * the 'nth' element of setup_args[]. A blank command-line member (in | ||
| 172 | * other words, a comma with no preceding keyword) will _not_ overwrite | ||
| 173 | * the corresponding setup_args[] element. | ||
| 174 | * | ||
| 175 | * A few LILO examples (for insmod, use 'setup_strings' instead of 'in2000'): | ||
| 176 | * - in2000=ioport:0x220,noreset | ||
| 177 | * - in2000=period:250,disconnect:2,nosync:0x03 | ||
| 178 | * - in2000=debug:0x1e | ||
| 179 | * - in2000=proc:3 | ||
| 180 | */ | ||
| 181 | |||
| 182 | /* Normally, no defaults are specified... */ | ||
| 183 | static char *setup_args[] = { "", "", "", "", "", "", "", "", "" }; | ||
| 184 | |||
| 185 | /* filled in by 'insmod' */ | ||
| 186 | static char *setup_strings; | ||
| 187 | |||
| 188 | module_param(setup_strings, charp, 0); | ||
| 189 | |||
| 190 | static inline uchar read_3393(struct IN2000_hostdata *hostdata, uchar reg_num) | ||
| 191 | { | ||
| 192 | write1_io(reg_num, IO_WD_ADDR); | ||
| 193 | return read1_io(IO_WD_DATA); | ||
| 194 | } | ||
| 195 | |||
| 196 | |||
| 197 | #define READ_AUX_STAT() read1_io(IO_WD_ASR) | ||
| 198 | |||
| 199 | |||
| 200 | static inline void write_3393(struct IN2000_hostdata *hostdata, uchar reg_num, uchar value) | ||
| 201 | { | ||
| 202 | write1_io(reg_num, IO_WD_ADDR); | ||
| 203 | write1_io(value, IO_WD_DATA); | ||
| 204 | } | ||
| 205 | |||
| 206 | |||
| 207 | static inline void write_3393_cmd(struct IN2000_hostdata *hostdata, uchar cmd) | ||
| 208 | { | ||
| 209 | /* while (READ_AUX_STAT() & ASR_CIP) | ||
| 210 | printk("|");*/ | ||
| 211 | write1_io(WD_COMMAND, IO_WD_ADDR); | ||
| 212 | write1_io(cmd, IO_WD_DATA); | ||
| 213 | } | ||
| 214 | |||
| 215 | |||
| 216 | static uchar read_1_byte(struct IN2000_hostdata *hostdata) | ||
| 217 | { | ||
| 218 | uchar asr, x = 0; | ||
| 219 | |||
| 220 | write_3393(hostdata, WD_CONTROL, CTRL_IDI | CTRL_EDI | CTRL_POLLED); | ||
| 221 | write_3393_cmd(hostdata, WD_CMD_TRANS_INFO | 0x80); | ||
| 222 | do { | ||
| 223 | asr = READ_AUX_STAT(); | ||
| 224 | if (asr & ASR_DBR) | ||
| 225 | x = read_3393(hostdata, WD_DATA); | ||
| 226 | } while (!(asr & ASR_INT)); | ||
| 227 | return x; | ||
| 228 | } | ||
| 229 | |||
| 230 | |||
| 231 | static void write_3393_count(struct IN2000_hostdata *hostdata, unsigned long value) | ||
| 232 | { | ||
| 233 | write1_io(WD_TRANSFER_COUNT_MSB, IO_WD_ADDR); | ||
| 234 | write1_io((value >> 16), IO_WD_DATA); | ||
| 235 | write1_io((value >> 8), IO_WD_DATA); | ||
| 236 | write1_io(value, IO_WD_DATA); | ||
| 237 | } | ||
| 238 | |||
| 239 | |||
| 240 | static unsigned long read_3393_count(struct IN2000_hostdata *hostdata) | ||
| 241 | { | ||
| 242 | unsigned long value; | ||
| 243 | |||
| 244 | write1_io(WD_TRANSFER_COUNT_MSB, IO_WD_ADDR); | ||
| 245 | value = read1_io(IO_WD_DATA) << 16; | ||
| 246 | value |= read1_io(IO_WD_DATA) << 8; | ||
| 247 | value |= read1_io(IO_WD_DATA); | ||
| 248 | return value; | ||
| 249 | } | ||
| 250 | |||
| 251 | |||
| 252 | /* The 33c93 needs to be told which direction a command transfers its | ||
| 253 | * data; we use this function to figure it out. Returns true if there | ||
| 254 | * will be a DATA_OUT phase with this command, false otherwise. | ||
| 255 | * (Thanks to Joerg Dorchain for the research and suggestion.) | ||
| 256 | */ | ||
| 257 | static int is_dir_out(Scsi_Cmnd * cmd) | ||
| 258 | { | ||
| 259 | switch (cmd->cmnd[0]) { | ||
| 260 | case WRITE_6: | ||
| 261 | case WRITE_10: | ||
| 262 | case WRITE_12: | ||
| 263 | case WRITE_LONG: | ||
| 264 | case WRITE_SAME: | ||
| 265 | case WRITE_BUFFER: | ||
| 266 | case WRITE_VERIFY: | ||
| 267 | case WRITE_VERIFY_12: | ||
| 268 | case COMPARE: | ||
| 269 | case COPY: | ||
| 270 | case COPY_VERIFY: | ||
| 271 | case SEARCH_EQUAL: | ||
| 272 | case SEARCH_HIGH: | ||
| 273 | case SEARCH_LOW: | ||
| 274 | case SEARCH_EQUAL_12: | ||
| 275 | case SEARCH_HIGH_12: | ||
| 276 | case SEARCH_LOW_12: | ||
| 277 | case FORMAT_UNIT: | ||
| 278 | case REASSIGN_BLOCKS: | ||
| 279 | case RESERVE: | ||
| 280 | case MODE_SELECT: | ||
| 281 | case MODE_SELECT_10: | ||
| 282 | case LOG_SELECT: | ||
| 283 | case SEND_DIAGNOSTIC: | ||
| 284 | case CHANGE_DEFINITION: | ||
| 285 | case UPDATE_BLOCK: | ||
| 286 | case SET_WINDOW: | ||
| 287 | case MEDIUM_SCAN: | ||
| 288 | case SEND_VOLUME_TAG: | ||
| 289 | case 0xea: | ||
| 290 | return 1; | ||
| 291 | default: | ||
| 292 | return 0; | ||
| 293 | } | ||
| 294 | } | ||
| 295 | |||
| 296 | |||
| 297 | |||
| 298 | static struct sx_period sx_table[] = { | ||
| 299 | {1, 0x20}, | ||
| 300 | {252, 0x20}, | ||
| 301 | {376, 0x30}, | ||
| 302 | {500, 0x40}, | ||
| 303 | {624, 0x50}, | ||
| 304 | {752, 0x60}, | ||
| 305 | {876, 0x70}, | ||
| 306 | {1000, 0x00}, | ||
| 307 | {0, 0} | ||
| 308 | }; | ||
| 309 | |||
| 310 | static int round_period(unsigned int period) | ||
| 311 | { | ||
| 312 | int x; | ||
| 313 | |||
| 314 | for (x = 1; sx_table[x].period_ns; x++) { | ||
| 315 | if ((period <= sx_table[x - 0].period_ns) && (period > sx_table[x - 1].period_ns)) { | ||
| 316 | return x; | ||
| 317 | } | ||
| 318 | } | ||
| 319 | return 7; | ||
| 320 | } | ||
| 321 | |||
| 322 | static uchar calc_sync_xfer(unsigned int period, unsigned int offset) | ||
| 323 | { | ||
| 324 | uchar result; | ||
| 325 | |||
| 326 | period *= 4; /* convert SDTR code to ns */ | ||
| 327 | result = sx_table[round_period(period)].reg_value; | ||
| 328 | result |= (offset < OPTIMUM_SX_OFF) ? offset : OPTIMUM_SX_OFF; | ||
| 329 | return result; | ||
| 330 | } | ||
| 331 | |||
| 332 | |||
| 333 | |||
| 334 | static void in2000_execute(struct Scsi_Host *instance); | ||
| 335 | |||
| 336 | static int in2000_queuecommand_lck(Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *)) | ||
| 337 | { | ||
| 338 | struct Scsi_Host *instance; | ||
| 339 | struct IN2000_hostdata *hostdata; | ||
| 340 | Scsi_Cmnd *tmp; | ||
| 341 | |||
| 342 | instance = cmd->device->host; | ||
| 343 | hostdata = (struct IN2000_hostdata *) instance->hostdata; | ||
| 344 | |||
| 345 | DB(DB_QUEUE_COMMAND, scmd_printk(KERN_DEBUG, cmd, "Q-%02x(", cmd->cmnd[0])) | ||
| 346 | |||
| 347 | /* Set up a few fields in the Scsi_Cmnd structure for our own use: | ||
| 348 | * - host_scribble is the pointer to the next cmd in the input queue | ||
| 349 | * - scsi_done points to the routine we call when a cmd is finished | ||
| 350 | * - result is what you'd expect | ||
| 351 | */ | ||
| 352 | cmd->host_scribble = NULL; | ||
| 353 | cmd->scsi_done = done; | ||
| 354 | cmd->result = 0; | ||
| 355 | |||
| 356 | /* We use the Scsi_Pointer structure that's included with each command | ||
| 357 | * as a scratchpad (as it's intended to be used!). The handy thing about | ||
| 358 | * the SCp.xxx fields is that they're always associated with a given | ||
| 359 | * cmd, and are preserved across disconnect-reselect. This means we | ||
| 360 | * can pretty much ignore SAVE_POINTERS and RESTORE_POINTERS messages | ||
| 361 | * if we keep all the critical pointers and counters in SCp: | ||
| 362 | * - SCp.ptr is the pointer into the RAM buffer | ||
| 363 | * - SCp.this_residual is the size of that buffer | ||
| 364 | * - SCp.buffer points to the current scatter-gather buffer | ||
| 365 | * - SCp.buffers_residual tells us how many S.G. buffers there are | ||
| 366 | * - SCp.have_data_in helps keep track of >2048 byte transfers | ||
| 367 | * - SCp.sent_command is not used | ||
| 368 | * - SCp.phase records this command's SRCID_ER bit setting | ||
| 369 | */ | ||
| 370 | |||
| 371 | if (scsi_bufflen(cmd)) { | ||
| 372 | cmd->SCp.buffer = scsi_sglist(cmd); | ||
| 373 | cmd->SCp.buffers_residual = scsi_sg_count(cmd) - 1; | ||
| 374 | cmd->SCp.ptr = sg_virt(cmd->SCp.buffer); | ||
| 375 | cmd->SCp.this_residual = cmd->SCp.buffer->length; | ||
| 376 | } else { | ||
| 377 | cmd->SCp.buffer = NULL; | ||
| 378 | cmd->SCp.buffers_residual = 0; | ||
| 379 | cmd->SCp.ptr = NULL; | ||
| 380 | cmd->SCp.this_residual = 0; | ||
| 381 | } | ||
| 382 | cmd->SCp.have_data_in = 0; | ||
| 383 | |||
| 384 | /* We don't set SCp.phase here - that's done in in2000_execute() */ | ||
| 385 | |||
| 386 | /* WD docs state that at the conclusion of a "LEVEL2" command, the | ||
| 387 | * status byte can be retrieved from the LUN register. Apparently, | ||
| 388 | * this is the case only for *uninterrupted* LEVEL2 commands! If | ||
| 389 | * there are any unexpected phases entered, even if they are 100% | ||
| 390 | * legal (different devices may choose to do things differently), | ||
| 391 | * the LEVEL2 command sequence is exited. This often occurs prior | ||
| 392 | * to receiving the status byte, in which case the driver does a | ||
| 393 | * status phase interrupt and gets the status byte on its own. | ||
| 394 | * While such a command can then be "resumed" (ie restarted to | ||
| 395 | * finish up as a LEVEL2 command), the LUN register will NOT be | ||
| 396 | * a valid status byte at the command's conclusion, and we must | ||
| 397 | * use the byte obtained during the earlier interrupt. Here, we | ||
| 398 | * preset SCp.Status to an illegal value (0xff) so that when | ||
| 399 | * this command finally completes, we can tell where the actual | ||
| 400 | * status byte is stored. | ||
| 401 | */ | ||
| 402 | |||
| 403 | cmd->SCp.Status = ILLEGAL_STATUS_BYTE; | ||
| 404 | |||
| 405 | /* We need to disable interrupts before messing with the input | ||
| 406 | * queue and calling in2000_execute(). | ||
| 407 | */ | ||
| 408 | |||
| 409 | /* | ||
| 410 | * Add the cmd to the end of 'input_Q'. Note that REQUEST_SENSE | ||
| 411 | * commands are added to the head of the queue so that the desired | ||
| 412 | * sense data is not lost before REQUEST_SENSE executes. | ||
| 413 | */ | ||
| 414 | |||
| 415 | if (!(hostdata->input_Q) || (cmd->cmnd[0] == REQUEST_SENSE)) { | ||
| 416 | cmd->host_scribble = (uchar *) hostdata->input_Q; | ||
| 417 | hostdata->input_Q = cmd; | ||
| 418 | } else { /* find the end of the queue */ | ||
| 419 | for (tmp = (Scsi_Cmnd *) hostdata->input_Q; tmp->host_scribble; tmp = (Scsi_Cmnd *) tmp->host_scribble); | ||
| 420 | tmp->host_scribble = (uchar *) cmd; | ||
| 421 | } | ||
| 422 | |||
| 423 | /* We know that there's at least one command in 'input_Q' now. | ||
| 424 | * Go see if any of them are runnable! | ||
| 425 | */ | ||
| 426 | |||
| 427 | in2000_execute(cmd->device->host); | ||
| 428 | |||
| 429 | DB(DB_QUEUE_COMMAND, printk(")Q ")) | ||
| 430 | return 0; | ||
| 431 | } | ||
| 432 | |||
| 433 | static DEF_SCSI_QCMD(in2000_queuecommand) | ||
| 434 | |||
| 435 | |||
| 436 | |||
| 437 | /* | ||
| 438 | * This routine attempts to start a scsi command. If the host_card is | ||
| 439 | * already connected, we give up immediately. Otherwise, look through | ||
| 440 | * the input_Q, using the first command we find that's intended | ||
| 441 | * for a currently non-busy target/lun. | ||
| 442 | * Note that this function is always called with interrupts already | ||
| 443 | * disabled (either from in2000_queuecommand() or in2000_intr()). | ||
| 444 | */ | ||
| 445 | static void in2000_execute(struct Scsi_Host *instance) | ||
| 446 | { | ||
| 447 | struct IN2000_hostdata *hostdata; | ||
| 448 | Scsi_Cmnd *cmd, *prev; | ||
| 449 | int i; | ||
| 450 | unsigned short *sp; | ||
| 451 | unsigned short f; | ||
| 452 | unsigned short flushbuf[16]; | ||
| 453 | |||
| 454 | |||
| 455 | hostdata = (struct IN2000_hostdata *) instance->hostdata; | ||
| 456 | |||
| 457 | DB(DB_EXECUTE, printk("EX(")) | ||
| 458 | |||
| 459 | if (hostdata->selecting || hostdata->connected) { | ||
| 460 | |||
| 461 | DB(DB_EXECUTE, printk(")EX-0 ")) | ||
| 462 | |||
| 463 | return; | ||
| 464 | } | ||
| 465 | |||
| 466 | /* | ||
| 467 | * Search through the input_Q for a command destined | ||
| 468 | * for an idle target/lun. | ||
| 469 | */ | ||
| 470 | |||
| 471 | cmd = (Scsi_Cmnd *) hostdata->input_Q; | ||
| 472 | prev = NULL; | ||
| 473 | while (cmd) { | ||
| 474 | if (!(hostdata->busy[cmd->device->id] & (1 << cmd->device->lun))) | ||
| 475 | break; | ||
| 476 | prev = cmd; | ||
| 477 | cmd = (Scsi_Cmnd *) cmd->host_scribble; | ||
| 478 | } | ||
| 479 | |||
| 480 | /* quit if queue empty or all possible targets are busy */ | ||
| 481 | |||
| 482 | if (!cmd) { | ||
| 483 | |||
| 484 | DB(DB_EXECUTE, printk(")EX-1 ")) | ||
| 485 | |||
| 486 | return; | ||
| 487 | } | ||
| 488 | |||
| 489 | /* remove command from queue */ | ||
| 490 | |||
| 491 | if (prev) | ||
| 492 | prev->host_scribble = cmd->host_scribble; | ||
| 493 | else | ||
| 494 | hostdata->input_Q = (Scsi_Cmnd *) cmd->host_scribble; | ||
| 495 | |||
| 496 | #ifdef PROC_STATISTICS | ||
| 497 | hostdata->cmd_cnt[cmd->device->id]++; | ||
| 498 | #endif | ||
| 499 | |||
| 500 | /* | ||
| 501 | * Start the selection process | ||
| 502 | */ | ||
| 503 | |||
| 504 | if (is_dir_out(cmd)) | ||
| 505 | write_3393(hostdata, WD_DESTINATION_ID, cmd->device->id); | ||
| 506 | else | ||
| 507 | write_3393(hostdata, WD_DESTINATION_ID, cmd->device->id | DSTID_DPD); | ||
| 508 | |||
| 509 | /* Now we need to figure out whether or not this command is a good | ||
| 510 | * candidate for disconnect/reselect. We guess to the best of our | ||
| 511 | * ability, based on a set of hierarchical rules. When several | ||
| 512 | * devices are operating simultaneously, disconnects are usually | ||
| 513 | * an advantage. In a single device system, or if only 1 device | ||
| 514 | * is being accessed, transfers usually go faster if disconnects | ||
| 515 | * are not allowed: | ||
| 516 | * | ||
| 517 | * + Commands should NEVER disconnect if hostdata->disconnect = | ||
| 518 | * DIS_NEVER (this holds for tape drives also), and ALWAYS | ||
| 519 | * disconnect if hostdata->disconnect = DIS_ALWAYS. | ||
| 520 | * + Tape drive commands should always be allowed to disconnect. | ||
| 521 | * + Disconnect should be allowed if disconnected_Q isn't empty. | ||
| 522 | * + Commands should NOT disconnect if input_Q is empty. | ||
| 523 | * + Disconnect should be allowed if there are commands in input_Q | ||
| 524 | * for a different target/lun. In this case, the other commands | ||
| 525 | * should be made disconnect-able, if not already. | ||
| 526 | * | ||
| 527 | * I know, I know - this code would flunk me out of any | ||
| 528 | * "C Programming 101" class ever offered. But it's easy | ||
| 529 | * to change around and experiment with for now. | ||
| 530 | */ | ||
| 531 | |||
| 532 | cmd->SCp.phase = 0; /* assume no disconnect */ | ||
| 533 | if (hostdata->disconnect == DIS_NEVER) | ||
| 534 | goto no; | ||
| 535 | if (hostdata->disconnect == DIS_ALWAYS) | ||
| 536 | goto yes; | ||
| 537 | if (cmd->device->type == 1) /* tape drive? */ | ||
| 538 | goto yes; | ||
| 539 | if (hostdata->disconnected_Q) /* other commands disconnected? */ | ||
| 540 | goto yes; | ||
| 541 | if (!(hostdata->input_Q)) /* input_Q empty? */ | ||
| 542 | goto no; | ||
| 543 | for (prev = (Scsi_Cmnd *) hostdata->input_Q; prev; prev = (Scsi_Cmnd *) prev->host_scribble) { | ||
| 544 | if ((prev->device->id != cmd->device->id) || (prev->device->lun != cmd->device->lun)) { | ||
| 545 | for (prev = (Scsi_Cmnd *) hostdata->input_Q; prev; prev = (Scsi_Cmnd *) prev->host_scribble) | ||
| 546 | prev->SCp.phase = 1; | ||
| 547 | goto yes; | ||
| 548 | } | ||
| 549 | } | ||
| 550 | goto no; | ||
| 551 | |||
| 552 | yes: | ||
| 553 | cmd->SCp.phase = 1; | ||
| 554 | |||
| 555 | #ifdef PROC_STATISTICS | ||
| 556 | hostdata->disc_allowed_cnt[cmd->device->id]++; | ||
| 557 | #endif | ||
| 558 | |||
| 559 | no: | ||
| 560 | write_3393(hostdata, WD_SOURCE_ID, ((cmd->SCp.phase) ? SRCID_ER : 0)); | ||
| 561 | |||
| 562 | write_3393(hostdata, WD_TARGET_LUN, cmd->device->lun); | ||
| 563 | write_3393(hostdata, WD_SYNCHRONOUS_TRANSFER, hostdata->sync_xfer[cmd->device->id]); | ||
| 564 | hostdata->busy[cmd->device->id] |= (1 << cmd->device->lun); | ||
| 565 | |||
| 566 | if ((hostdata->level2 <= L2_NONE) || (hostdata->sync_stat[cmd->device->id] == SS_UNSET)) { | ||
| 567 | |||
| 568 | /* | ||
| 569 | * Do a 'Select-With-ATN' command. This will end with | ||
| 570 | * one of the following interrupts: | ||
| 571 | * CSR_RESEL_AM: failure - can try again later. | ||
| 572 | * CSR_TIMEOUT: failure - give up. | ||
| 573 | * CSR_SELECT: success - proceed. | ||
| 574 | */ | ||
| 575 | |||
| 576 | hostdata->selecting = cmd; | ||
| 577 | |||
| 578 | /* Every target has its own synchronous transfer setting, kept in | ||
| 579 | * the sync_xfer array, and a corresponding status byte in sync_stat[]. | ||
| 580 | * Each target's sync_stat[] entry is initialized to SS_UNSET, and its | ||
| 581 | * sync_xfer[] entry is initialized to the default/safe value. SS_UNSET | ||
| 582 | * means that the parameters are undetermined as yet, and that we | ||
| 583 | * need to send an SDTR message to this device after selection is | ||
| 584 | * complete. We set SS_FIRST to tell the interrupt routine to do so, | ||
| 585 | * unless we don't want to even _try_ synchronous transfers: In this | ||
| 586 | * case we set SS_SET to make the defaults final. | ||
| 587 | */ | ||
| 588 | if (hostdata->sync_stat[cmd->device->id] == SS_UNSET) { | ||
| 589 | if (hostdata->sync_off & (1 << cmd->device->id)) | ||
| 590 | hostdata->sync_stat[cmd->device->id] = SS_SET; | ||
| 591 | else | ||
| 592 | hostdata->sync_stat[cmd->device->id] = SS_FIRST; | ||
| 593 | } | ||
| 594 | hostdata->state = S_SELECTING; | ||
| 595 | write_3393_count(hostdata, 0); /* this guarantees a DATA_PHASE interrupt */ | ||
| 596 | write_3393_cmd(hostdata, WD_CMD_SEL_ATN); | ||
| 597 | } | ||
| 598 | |||
| 599 | else { | ||
| 600 | |||
| 601 | /* | ||
| 602 | * Do a 'Select-With-ATN-Xfer' command. This will end with | ||
| 603 | * one of the following interrupts: | ||
| 604 | * CSR_RESEL_AM: failure - can try again later. | ||
| 605 | * CSR_TIMEOUT: failure - give up. | ||
| 606 | * anything else: success - proceed. | ||
| 607 | */ | ||
| 608 | |||
| 609 | hostdata->connected = cmd; | ||
| 610 | write_3393(hostdata, WD_COMMAND_PHASE, 0); | ||
| 611 | |||
| 612 | /* copy command_descriptor_block into WD chip | ||
| 613 | * (take advantage of auto-incrementing) | ||
| 614 | */ | ||
| 615 | |||
| 616 | write1_io(WD_CDB_1, IO_WD_ADDR); | ||
| 617 | for (i = 0; i < cmd->cmd_len; i++) | ||
| 618 | write1_io(cmd->cmnd[i], IO_WD_DATA); | ||
| 619 | |||
| 620 | /* The wd33c93 only knows about Group 0, 1, and 5 commands when | ||
| 621 | * it's doing a 'select-and-transfer'. To be safe, we write the | ||
| 622 | * size of the CDB into the OWN_ID register for every case. This | ||
| 623 | * way there won't be problems with vendor-unique, audio, etc. | ||
| 624 | */ | ||
| 625 | |||
| 626 | write_3393(hostdata, WD_OWN_ID, cmd->cmd_len); | ||
| 627 | |||
| 628 | /* When doing a non-disconnect command, we can save ourselves a DATA | ||
| 629 | * phase interrupt later by setting everything up now. With writes we | ||
| 630 | * need to pre-fill the fifo; if there's room for the 32 flush bytes, | ||
| 631 | * put them in there too - that'll avoid a fifo interrupt. Reads are | ||
| 632 | * somewhat simpler. | ||
| 633 | * KLUDGE NOTE: It seems that you can't completely fill the fifo here: | ||
| 634 | * This results in the IO_FIFO_COUNT register rolling over to zero, | ||
| 635 | * and apparently the gate array logic sees this as empty, not full, | ||
| 636 | * so the 3393 chip is never signalled to start reading from the | ||
| 637 | * fifo. Or maybe it's seen as a permanent fifo interrupt condition. | ||
| 638 | * Regardless, we fix this by temporarily pretending that the fifo | ||
| 639 | * is 16 bytes smaller. (I see now that the old driver has a comment | ||
| 640 | * about "don't fill completely" in an analogous place - must be the | ||
| 641 | * same deal.) This results in CDROM, swap partitions, and tape drives | ||
| 642 | * needing an extra interrupt per write command - I think we can live | ||
| 643 | * with that! | ||
| 644 | */ | ||
| 645 | |||
| 646 | if (!(cmd->SCp.phase)) { | ||
| 647 | write_3393_count(hostdata, cmd->SCp.this_residual); | ||
| 648 | write_3393(hostdata, WD_CONTROL, CTRL_IDI | CTRL_EDI | CTRL_BUS); | ||
| 649 | write1_io(0, IO_FIFO_WRITE); /* clear fifo counter, write mode */ | ||
| 650 | |||
| 651 | if (is_dir_out(cmd)) { | ||
| 652 | hostdata->fifo = FI_FIFO_WRITING; | ||
| 653 | if ((i = cmd->SCp.this_residual) > (IN2000_FIFO_SIZE - 16)) | ||
| 654 | i = IN2000_FIFO_SIZE - 16; | ||
| 655 | cmd->SCp.have_data_in = i; /* this much data in fifo */ | ||
| 656 | i >>= 1; /* Gulp. Assuming modulo 2. */ | ||
| 657 | sp = (unsigned short *) cmd->SCp.ptr; | ||
| 658 | f = hostdata->io_base + IO_FIFO; | ||
| 659 | |||
| 660 | #ifdef FAST_WRITE_IO | ||
| 661 | |||
| 662 | FAST_WRITE2_IO(); | ||
| 663 | #else | ||
| 664 | while (i--) | ||
| 665 | write2_io(*sp++, IO_FIFO); | ||
| 666 | |||
| 667 | #endif | ||
| 668 | |||
| 669 | /* Is there room for the flush bytes? */ | ||
| 670 | |||
| 671 | if (cmd->SCp.have_data_in <= ((IN2000_FIFO_SIZE - 16) - 32)) { | ||
| 672 | sp = flushbuf; | ||
| 673 | i = 16; | ||
| 674 | |||
| 675 | #ifdef FAST_WRITE_IO | ||
| 676 | |||
| 677 | FAST_WRITE2_IO(); | ||
| 678 | #else | ||
| 679 | while (i--) | ||
| 680 | write2_io(0, IO_FIFO); | ||
| 681 | |||
| 682 | #endif | ||
| 683 | |||
| 684 | } | ||
| 685 | } | ||
| 686 | |||
| 687 | else { | ||
| 688 | write1_io(0, IO_FIFO_READ); /* put fifo in read mode */ | ||
| 689 | hostdata->fifo = FI_FIFO_READING; | ||
| 690 | cmd->SCp.have_data_in = 0; /* nothing transferred yet */ | ||
| 691 | } | ||
| 692 | |||
| 693 | } else { | ||
| 694 | write_3393_count(hostdata, 0); /* this guarantees a DATA_PHASE interrupt */ | ||
| 695 | } | ||
| 696 | hostdata->state = S_RUNNING_LEVEL2; | ||
| 697 | write_3393_cmd(hostdata, WD_CMD_SEL_ATN_XFER); | ||
| 698 | } | ||
| 699 | |||
| 700 | /* | ||
| 701 | * Since the SCSI bus can handle only 1 connection at a time, | ||
| 702 | * we get out of here now. If the selection fails, or when | ||
| 703 | * the command disconnects, we'll come back to this routine | ||
| 704 | * to search the input_Q again... | ||
| 705 | */ | ||
| 706 | |||
| 707 | DB(DB_EXECUTE, printk("%s)EX-2 ", (cmd->SCp.phase) ? "d:" : "")) | ||
| 708 | |||
| 709 | } | ||
| 710 | |||
| 711 | |||
| 712 | |||
| 713 | static void transfer_pio(uchar * buf, int cnt, int data_in_dir, struct IN2000_hostdata *hostdata) | ||
| 714 | { | ||
| 715 | uchar asr; | ||
| 716 | |||
| 717 | DB(DB_TRANSFER, printk("(%p,%d,%s)", buf, cnt, data_in_dir ? "in" : "out")) | ||
| 718 | |||
| 719 | write_3393(hostdata, WD_CONTROL, CTRL_IDI | CTRL_EDI | CTRL_POLLED); | ||
| 720 | write_3393_count(hostdata, cnt); | ||
| 721 | write_3393_cmd(hostdata, WD_CMD_TRANS_INFO); | ||
| 722 | if (data_in_dir) { | ||
| 723 | do { | ||
| 724 | asr = READ_AUX_STAT(); | ||
| 725 | if (asr & ASR_DBR) | ||
| 726 | *buf++ = read_3393(hostdata, WD_DATA); | ||
| 727 | } while (!(asr & ASR_INT)); | ||
| 728 | } else { | ||
| 729 | do { | ||
| 730 | asr = READ_AUX_STAT(); | ||
| 731 | if (asr & ASR_DBR) | ||
| 732 | write_3393(hostdata, WD_DATA, *buf++); | ||
| 733 | } while (!(asr & ASR_INT)); | ||
| 734 | } | ||
| 735 | |||
| 736 | /* Note: we are returning with the interrupt UN-cleared. | ||
| 737 | * Since (presumably) an entire I/O operation has | ||
| 738 | * completed, the bus phase is probably different, and | ||
| 739 | * the interrupt routine will discover this when it | ||
| 740 | * responds to the uncleared int. | ||
| 741 | */ | ||
| 742 | |||
| 743 | } | ||
| 744 | |||
| 745 | |||
| 746 | |||
| 747 | static void transfer_bytes(Scsi_Cmnd * cmd, int data_in_dir) | ||
| 748 | { | ||
| 749 | struct IN2000_hostdata *hostdata; | ||
| 750 | unsigned short *sp; | ||
| 751 | unsigned short f; | ||
| 752 | int i; | ||
| 753 | |||
| 754 | hostdata = (struct IN2000_hostdata *) cmd->device->host->hostdata; | ||
| 755 | |||
| 756 | /* Normally, you'd expect 'this_residual' to be non-zero here. | ||
| 757 | * In a series of scatter-gather transfers, however, this | ||
| 758 | * routine will usually be called with 'this_residual' equal | ||
| 759 | * to 0 and 'buffers_residual' non-zero. This means that a | ||
| 760 | * previous transfer completed, clearing 'this_residual', and | ||
| 761 | * now we need to setup the next scatter-gather buffer as the | ||
| 762 | * source or destination for THIS transfer. | ||
| 763 | */ | ||
| 764 | if (!cmd->SCp.this_residual && cmd->SCp.buffers_residual) { | ||
| 765 | ++cmd->SCp.buffer; | ||
| 766 | --cmd->SCp.buffers_residual; | ||
| 767 | cmd->SCp.this_residual = cmd->SCp.buffer->length; | ||
| 768 | cmd->SCp.ptr = sg_virt(cmd->SCp.buffer); | ||
| 769 | } | ||
| 770 | |||
| 771 | /* Set up hardware registers */ | ||
| 772 | |||
| 773 | write_3393(hostdata, WD_SYNCHRONOUS_TRANSFER, hostdata->sync_xfer[cmd->device->id]); | ||
| 774 | write_3393_count(hostdata, cmd->SCp.this_residual); | ||
| 775 | write_3393(hostdata, WD_CONTROL, CTRL_IDI | CTRL_EDI | CTRL_BUS); | ||
| 776 | write1_io(0, IO_FIFO_WRITE); /* zero counter, assume write */ | ||
| 777 | |||
| 778 | /* Reading is easy. Just issue the command and return - we'll | ||
| 779 | * get an interrupt later when we have actual data to worry about. | ||
| 780 | */ | ||
| 781 | |||
| 782 | if (data_in_dir) { | ||
| 783 | write1_io(0, IO_FIFO_READ); | ||
| 784 | if ((hostdata->level2 >= L2_DATA) || (hostdata->level2 == L2_BASIC && cmd->SCp.phase == 0)) { | ||
| 785 | write_3393(hostdata, WD_COMMAND_PHASE, 0x45); | ||
| 786 | write_3393_cmd(hostdata, WD_CMD_SEL_ATN_XFER); | ||
| 787 | hostdata->state = S_RUNNING_LEVEL2; | ||
| 788 | } else | ||
| 789 | write_3393_cmd(hostdata, WD_CMD_TRANS_INFO); | ||
| 790 | hostdata->fifo = FI_FIFO_READING; | ||
| 791 | cmd->SCp.have_data_in = 0; | ||
| 792 | return; | ||
| 793 | } | ||
| 794 | |||
| 795 | /* Writing is more involved - we'll start the WD chip and write as | ||
| 796 | * much data to the fifo as we can right now. Later interrupts will | ||
| 797 | * write any bytes that don't make it at this stage. | ||
| 798 | */ | ||
| 799 | |||
| 800 | if ((hostdata->level2 >= L2_DATA) || (hostdata->level2 == L2_BASIC && cmd->SCp.phase == 0)) { | ||
| 801 | write_3393(hostdata, WD_COMMAND_PHASE, 0x45); | ||
| 802 | write_3393_cmd(hostdata, WD_CMD_SEL_ATN_XFER); | ||
| 803 | hostdata->state = S_RUNNING_LEVEL2; | ||
| 804 | } else | ||
| 805 | write_3393_cmd(hostdata, WD_CMD_TRANS_INFO); | ||
| 806 | hostdata->fifo = FI_FIFO_WRITING; | ||
| 807 | sp = (unsigned short *) cmd->SCp.ptr; | ||
| 808 | |||
| 809 | if ((i = cmd->SCp.this_residual) > IN2000_FIFO_SIZE) | ||
| 810 | i = IN2000_FIFO_SIZE; | ||
| 811 | cmd->SCp.have_data_in = i; | ||
| 812 | i >>= 1; /* Gulp. We assume this_residual is modulo 2 */ | ||
| 813 | f = hostdata->io_base + IO_FIFO; | ||
| 814 | |||
| 815 | #ifdef FAST_WRITE_IO | ||
| 816 | |||
| 817 | FAST_WRITE2_IO(); | ||
| 818 | #else | ||
| 819 | while (i--) | ||
| 820 | write2_io(*sp++, IO_FIFO); | ||
| 821 | |||
| 822 | #endif | ||
| 823 | |||
| 824 | } | ||
| 825 | |||
| 826 | |||
| 827 | /* We need to use spin_lock_irqsave() & spin_unlock_irqrestore() in this | ||
| 828 | * function in order to work in an SMP environment. (I'd be surprised | ||
| 829 | * if the driver is ever used by anyone on a real multi-CPU motherboard, | ||
| 830 | * but it _does_ need to be able to compile and run in an SMP kernel.) | ||
| 831 | */ | ||
| 832 | |||
| 833 | static irqreturn_t in2000_intr(int irqnum, void *dev_id) | ||
| 834 | { | ||
| 835 | struct Scsi_Host *instance = dev_id; | ||
| 836 | struct IN2000_hostdata *hostdata; | ||
| 837 | Scsi_Cmnd *patch, *cmd; | ||
| 838 | uchar asr, sr, phs, id, lun, *ucp, msg; | ||
| 839 | int i, j; | ||
| 840 | unsigned long length; | ||
| 841 | unsigned short *sp; | ||
| 842 | unsigned short f; | ||
| 843 | unsigned long flags; | ||
| 844 | |||
| 845 | hostdata = (struct IN2000_hostdata *) instance->hostdata; | ||
| 846 | |||
| 847 | /* Get the spin_lock and disable further ints, for SMP */ | ||
| 848 | |||
| 849 | spin_lock_irqsave(instance->host_lock, flags); | ||
| 850 | |||
| 851 | #ifdef PROC_STATISTICS | ||
| 852 | hostdata->int_cnt++; | ||
| 853 | #endif | ||
| 854 | |||
| 855 | /* The IN2000 card has 2 interrupt sources OR'ed onto its IRQ line - the | ||
| 856 | * WD3393 chip and the 2k fifo (which is actually a dual-port RAM combined | ||
| 857 | * with a big logic array, so it's a little different than what you might | ||
| 858 | * expect). As far as I know, there's no reason that BOTH can't be active | ||
| 859 | * at the same time, but there's a problem: while we can read the 3393 | ||
| 860 | * to tell if _it_ wants an interrupt, I don't know of a way to ask the | ||
| 861 | * fifo the same question. The best we can do is check the 3393 and if | ||
| 862 | * it _isn't_ the source of the interrupt, then we can be pretty sure | ||
| 863 | * that the fifo is the culprit. | ||
| 864 | * UPDATE: I have it on good authority (Bill Earnest) that bit 0 of the | ||
| 865 | * IO_FIFO_COUNT register mirrors the fifo interrupt state. I | ||
| 866 | * assume that bit clear means interrupt active. As it turns | ||
| 867 | * out, the driver really doesn't need to check for this after | ||
| 868 | * all, so my remarks above about a 'problem' can safely be | ||
| 869 | * ignored. The way the logic is set up, there's no advantage | ||
| 870 | * (that I can see) to worrying about it. | ||
| 871 | * | ||
| 872 | * It seems that the fifo interrupt signal is negated when we extract | ||
| 873 | * bytes during read or write bytes during write. | ||
| 874 | * - fifo will interrupt when data is moving from it to the 3393, and | ||
| 875 | * there are 31 (or less?) bytes left to go. This is sort of short- | ||
| 876 | * sighted: what if you don't WANT to do more? In any case, our | ||
| 877 | * response is to push more into the fifo - either actual data or | ||
| 878 | * dummy bytes if need be. Note that we apparently have to write at | ||
| 879 | * least 32 additional bytes to the fifo after an interrupt in order | ||
| 880 | * to get it to release the ones it was holding on to - writing fewer | ||
| 881 | * than 32 will result in another fifo int. | ||
| 882 | * UPDATE: Again, info from Bill Earnest makes this more understandable: | ||
| 883 | * 32 bytes = two counts of the fifo counter register. He tells | ||
| 884 | * me that the fifo interrupt is a non-latching signal derived | ||
| 885 | * from a straightforward boolean interpretation of the 7 | ||
| 886 | * highest bits of the fifo counter and the fifo-read/fifo-write | ||
| 887 | * state. Who'd a thought? | ||
| 888 | */ | ||
| 889 | |||
| 890 | write1_io(0, IO_LED_ON); | ||
| 891 | asr = READ_AUX_STAT(); | ||
| 892 | if (!(asr & ASR_INT)) { /* no WD33c93 interrupt? */ | ||
| 893 | |||
| 894 | /* Ok. This is definitely a FIFO-only interrupt. | ||
| 895 | * | ||
| 896 | * If FI_FIFO_READING is set, there are up to 2048 bytes waiting to be read, | ||
| 897 | * maybe more to come from the SCSI bus. Read as many as we can out of the | ||
| 898 | * fifo and into memory at the location of SCp.ptr[SCp.have_data_in], and | ||
| 899 | * update have_data_in afterwards. | ||
| 900 | * | ||
| 901 | * If we have FI_FIFO_WRITING, the FIFO has almost run out of bytes to move | ||
| 902 | * into the WD3393 chip (I think the interrupt happens when there are 31 | ||
| 903 | * bytes left, but it may be fewer...). The 3393 is still waiting, so we | ||
| 904 | * shove some more into the fifo, which gets things moving again. If the | ||
| 905 | * original SCSI command specified more than 2048 bytes, there may still | ||
| 906 | * be some of that data left: fine - use it (from SCp.ptr[SCp.have_data_in]). | ||
| 907 | * Don't forget to update have_data_in. If we've already written out the | ||
| 908 | * entire buffer, feed 32 dummy bytes to the fifo - they're needed to | ||
| 909 | * push out the remaining real data. | ||
| 910 | * (Big thanks to Bill Earnest for getting me out of the mud in here.) | ||
| 911 | */ | ||
| 912 | |||
| 913 | cmd = (Scsi_Cmnd *) hostdata->connected; /* assume we're connected */ | ||
| 914 | CHECK_NULL(cmd, "fifo_int") | ||
| 915 | |||
| 916 | if (hostdata->fifo == FI_FIFO_READING) { | ||
| 917 | |||
| 918 | DB(DB_FIFO, printk("{R:%02x} ", read1_io(IO_FIFO_COUNT))) | ||
| 919 | |||
| 920 | sp = (unsigned short *) (cmd->SCp.ptr + cmd->SCp.have_data_in); | ||
| 921 | i = read1_io(IO_FIFO_COUNT) & 0xfe; | ||
| 922 | i <<= 2; /* # of words waiting in the fifo */ | ||
| 923 | f = hostdata->io_base + IO_FIFO; | ||
| 924 | |||
| 925 | #ifdef FAST_READ_IO | ||
| 926 | |||
| 927 | FAST_READ2_IO(); | ||
| 928 | #else | ||
| 929 | while (i--) | ||
| 930 | *sp++ = read2_io(IO_FIFO); | ||
| 931 | |||
| 932 | #endif | ||
| 933 | |||
| 934 | i = sp - (unsigned short *) (cmd->SCp.ptr + cmd->SCp.have_data_in); | ||
| 935 | i <<= 1; | ||
| 936 | cmd->SCp.have_data_in += i; | ||
| 937 | } | ||
| 938 | |||
| 939 | else if (hostdata->fifo == FI_FIFO_WRITING) { | ||
| 940 | |||
| 941 | DB(DB_FIFO, printk("{W:%02x} ", read1_io(IO_FIFO_COUNT))) | ||
| 942 | |||
| 943 | /* If all bytes have been written to the fifo, flush out the stragglers. | ||
| 944 | * Note that while writing 16 dummy words seems arbitrary, we don't | ||
| 945 | * have another choice that I can see. What we really want is to read | ||
| 946 | * the 3393 transfer count register (that would tell us how many bytes | ||
| 947 | * needed flushing), but the TRANSFER_INFO command hasn't completed | ||
| 948 | * yet (not enough bytes!) and that register won't be accessible. So, | ||
| 949 | * we use 16 words - a number obtained through trial and error. | ||
| 950 | * UPDATE: Bill says this is exactly what Always does, so there. | ||
| 951 | * More thanks due him for help in this section. | ||
| 952 | */ | ||
| 953 | if (cmd->SCp.this_residual == cmd->SCp.have_data_in) { | ||
| 954 | i = 16; | ||
| 955 | while (i--) /* write 32 dummy bytes */ | ||
| 956 | write2_io(0, IO_FIFO); | ||
| 957 | } | ||
| 958 | |||
| 959 | /* If there are still bytes left in the SCSI buffer, write as many as we | ||
| 960 | * can out to the fifo. | ||
| 961 | */ | ||
| 962 | |||
| 963 | else { | ||
| 964 | sp = (unsigned short *) (cmd->SCp.ptr + cmd->SCp.have_data_in); | ||
| 965 | i = cmd->SCp.this_residual - cmd->SCp.have_data_in; /* bytes yet to go */ | ||
| 966 | j = read1_io(IO_FIFO_COUNT) & 0xfe; | ||
| 967 | j <<= 2; /* how many words the fifo has room for */ | ||
| 968 | if ((j << 1) > i) | ||
| 969 | j = (i >> 1); | ||
| 970 | while (j--) | ||
| 971 | write2_io(*sp++, IO_FIFO); | ||
| 972 | |||
| 973 | i = sp - (unsigned short *) (cmd->SCp.ptr + cmd->SCp.have_data_in); | ||
| 974 | i <<= 1; | ||
| 975 | cmd->SCp.have_data_in += i; | ||
| 976 | } | ||
| 977 | } | ||
| 978 | |||
| 979 | else { | ||
| 980 | printk("*** Spurious FIFO interrupt ***"); | ||
| 981 | } | ||
| 982 | |||
| 983 | write1_io(0, IO_LED_OFF); | ||
| 984 | |||
| 985 | /* release the SMP spin_lock and restore irq state */ | ||
| 986 | spin_unlock_irqrestore(instance->host_lock, flags); | ||
| 987 | return IRQ_HANDLED; | ||
| 988 | } | ||
| 989 | |||
| 990 | /* This interrupt was triggered by the WD33c93 chip. The fifo interrupt | ||
| 991 | * may also be asserted, but we don't bother to check it: we get more | ||
| 992 | * detailed info from FIFO_READING and FIFO_WRITING (see below). | ||
| 993 | */ | ||
| 994 | |||
| 995 | cmd = (Scsi_Cmnd *) hostdata->connected; /* assume we're connected */ | ||
| 996 | sr = read_3393(hostdata, WD_SCSI_STATUS); /* clear the interrupt */ | ||
| 997 | phs = read_3393(hostdata, WD_COMMAND_PHASE); | ||
| 998 | |||
| 999 | if (!cmd && (sr != CSR_RESEL_AM && sr != CSR_TIMEOUT && sr != CSR_SELECT)) { | ||
| 1000 | printk("\nNR:wd-intr-1\n"); | ||
| 1001 | write1_io(0, IO_LED_OFF); | ||
| 1002 | |||
| 1003 | /* release the SMP spin_lock and restore irq state */ | ||
| 1004 | spin_unlock_irqrestore(instance->host_lock, flags); | ||
| 1005 | return IRQ_HANDLED; | ||
| 1006 | } | ||
| 1007 | |||
| 1008 | DB(DB_INTR, printk("{%02x:%02x-", asr, sr)) | ||
| 1009 | |||
| 1010 | /* After starting a FIFO-based transfer, the next _WD3393_ interrupt is | ||
| 1011 | * guaranteed to be in response to the completion of the transfer. | ||
| 1012 | * If we were reading, there's probably data in the fifo that needs | ||
| 1013 | * to be copied into RAM - do that here. Also, we have to update | ||
| 1014 | * 'this_residual' and 'ptr' based on the contents of the | ||
| 1015 | * TRANSFER_COUNT register, in case the device decided to do an | ||
| 1016 | * intermediate disconnect (a device may do this if it has to | ||
| 1017 | * do a seek, or just to be nice and let other devices have | ||
| 1018 | * some bus time during long transfers). | ||
| 1019 | * After doing whatever is necessary with the fifo, we go on and | ||
| 1020 | * service the WD3393 interrupt normally. | ||
| 1021 | */ | ||
| 1022 | if (hostdata->fifo == FI_FIFO_READING) { | ||
| 1023 | |||
| 1024 | /* buffer index = start-of-buffer + #-of-bytes-already-read */ | ||
| 1025 | |||
| 1026 | sp = (unsigned short *) (cmd->SCp.ptr + cmd->SCp.have_data_in); | ||
| 1027 | |||
| 1028 | /* bytes remaining in fifo = (total-wanted - #-not-got) - #-already-read */ | ||
| 1029 | |||
| 1030 | i = (cmd->SCp.this_residual - read_3393_count(hostdata)) - cmd->SCp.have_data_in; | ||
| 1031 | i >>= 1; /* Gulp. We assume this will always be modulo 2 */ | ||
| 1032 | f = hostdata->io_base + IO_FIFO; | ||
| 1033 | |||
| 1034 | #ifdef FAST_READ_IO | ||
| 1035 | |||
| 1036 | FAST_READ2_IO(); | ||
| 1037 | #else | ||
| 1038 | while (i--) | ||
| 1039 | *sp++ = read2_io(IO_FIFO); | ||
| 1040 | |||
| 1041 | #endif | ||
| 1042 | |||
| 1043 | hostdata->fifo = FI_FIFO_UNUSED; | ||
| 1044 | length = cmd->SCp.this_residual; | ||
| 1045 | cmd->SCp.this_residual = read_3393_count(hostdata); | ||
| 1046 | cmd->SCp.ptr += (length - cmd->SCp.this_residual); | ||
| 1047 | |||
| 1048 | DB(DB_TRANSFER, printk("(%p,%d)", cmd->SCp.ptr, cmd->SCp.this_residual)) | ||
| 1049 | |||
| 1050 | } | ||
| 1051 | |||
| 1052 | else if (hostdata->fifo == FI_FIFO_WRITING) { | ||
| 1053 | hostdata->fifo = FI_FIFO_UNUSED; | ||
| 1054 | length = cmd->SCp.this_residual; | ||
| 1055 | cmd->SCp.this_residual = read_3393_count(hostdata); | ||
| 1056 | cmd->SCp.ptr += (length - cmd->SCp.this_residual); | ||
| 1057 | |||
| 1058 | DB(DB_TRANSFER, printk("(%p,%d)", cmd->SCp.ptr, cmd->SCp.this_residual)) | ||
| 1059 | |||
| 1060 | } | ||
| 1061 | |||
| 1062 | /* Respond to the specific WD3393 interrupt - there are quite a few! */ | ||
| 1063 | |||
| 1064 | switch (sr) { | ||
| 1065 | |||
| 1066 | case CSR_TIMEOUT: | ||
| 1067 | DB(DB_INTR, printk("TIMEOUT")) | ||
| 1068 | |||
| 1069 | if (hostdata->state == S_RUNNING_LEVEL2) | ||
| 1070 | hostdata->connected = NULL; | ||
| 1071 | else { | ||
| 1072 | cmd = (Scsi_Cmnd *) hostdata->selecting; /* get a valid cmd */ | ||
| 1073 | CHECK_NULL(cmd, "csr_timeout") | ||
| 1074 | hostdata->selecting = NULL; | ||
| 1075 | } | ||
| 1076 | |||
| 1077 | cmd->result = DID_NO_CONNECT << 16; | ||
| 1078 | hostdata->busy[cmd->device->id] &= ~(1 << cmd->device->lun); | ||
| 1079 | hostdata->state = S_UNCONNECTED; | ||
| 1080 | cmd->scsi_done(cmd); | ||
| 1081 | |||
| 1082 | /* We are not connected to a target - check to see if there | ||
| 1083 | * are commands waiting to be executed. | ||
| 1084 | */ | ||
| 1085 | |||
| 1086 | in2000_execute(instance); | ||
| 1087 | break; | ||
| 1088 | |||
| 1089 | |||
| 1090 | /* Note: this interrupt should not occur in a LEVEL2 command */ | ||
| 1091 | |||
| 1092 | case CSR_SELECT: | ||
| 1093 | DB(DB_INTR, printk("SELECT")) | ||
| 1094 | hostdata->connected = cmd = (Scsi_Cmnd *) hostdata->selecting; | ||
| 1095 | CHECK_NULL(cmd, "csr_select") | ||
| 1096 | hostdata->selecting = NULL; | ||
| 1097 | |||
| 1098 | /* construct an IDENTIFY message with correct disconnect bit */ | ||
| 1099 | |||
| 1100 | hostdata->outgoing_msg[0] = (0x80 | 0x00 | cmd->device->lun); | ||
| 1101 | if (cmd->SCp.phase) | ||
| 1102 | hostdata->outgoing_msg[0] |= 0x40; | ||
| 1103 | |||
| 1104 | if (hostdata->sync_stat[cmd->device->id] == SS_FIRST) { | ||
| 1105 | #ifdef SYNC_DEBUG | ||
| 1106 | printk(" sending SDTR "); | ||
| 1107 | #endif | ||
| 1108 | |||
| 1109 | hostdata->sync_stat[cmd->device->id] = SS_WAITING; | ||
| 1110 | |||
| 1111 | /* tack on a 2nd message to ask about synchronous transfers */ | ||
| 1112 | |||
| 1113 | hostdata->outgoing_msg[1] = EXTENDED_MESSAGE; | ||
| 1114 | hostdata->outgoing_msg[2] = 3; | ||
| 1115 | hostdata->outgoing_msg[3] = EXTENDED_SDTR; | ||
| 1116 | hostdata->outgoing_msg[4] = OPTIMUM_SX_PER / 4; | ||
| 1117 | hostdata->outgoing_msg[5] = OPTIMUM_SX_OFF; | ||
| 1118 | hostdata->outgoing_len = 6; | ||
| 1119 | } else | ||
| 1120 | hostdata->outgoing_len = 1; | ||
| 1121 | |||
| 1122 | hostdata->state = S_CONNECTED; | ||
| 1123 | break; | ||
| 1124 | |||
| 1125 | |||
| 1126 | case CSR_XFER_DONE | PHS_DATA_IN: | ||
| 1127 | case CSR_UNEXP | PHS_DATA_IN: | ||
| 1128 | case CSR_SRV_REQ | PHS_DATA_IN: | ||
| 1129 | DB(DB_INTR, printk("IN-%d.%d", cmd->SCp.this_residual, cmd->SCp.buffers_residual)) | ||
| 1130 | transfer_bytes(cmd, DATA_IN_DIR); | ||
| 1131 | if (hostdata->state != S_RUNNING_LEVEL2) | ||
| 1132 | hostdata->state = S_CONNECTED; | ||
| 1133 | break; | ||
| 1134 | |||
| 1135 | |||
| 1136 | case CSR_XFER_DONE | PHS_DATA_OUT: | ||
| 1137 | case CSR_UNEXP | PHS_DATA_OUT: | ||
| 1138 | case CSR_SRV_REQ | PHS_DATA_OUT: | ||
| 1139 | DB(DB_INTR, printk("OUT-%d.%d", cmd->SCp.this_residual, cmd->SCp.buffers_residual)) | ||
| 1140 | transfer_bytes(cmd, DATA_OUT_DIR); | ||
| 1141 | if (hostdata->state != S_RUNNING_LEVEL2) | ||
| 1142 | hostdata->state = S_CONNECTED; | ||
| 1143 | break; | ||
| 1144 | |||
| 1145 | |||
| 1146 | /* Note: this interrupt should not occur in a LEVEL2 command */ | ||
| 1147 | |||
| 1148 | case CSR_XFER_DONE | PHS_COMMAND: | ||
| 1149 | case CSR_UNEXP | PHS_COMMAND: | ||
| 1150 | case CSR_SRV_REQ | PHS_COMMAND: | ||
| 1151 | DB(DB_INTR, printk("CMND-%02x", cmd->cmnd[0])) | ||
| 1152 | transfer_pio(cmd->cmnd, cmd->cmd_len, DATA_OUT_DIR, hostdata); | ||
| 1153 | hostdata->state = S_CONNECTED; | ||
| 1154 | break; | ||
| 1155 | |||
| 1156 | |||
| 1157 | case CSR_XFER_DONE | PHS_STATUS: | ||
| 1158 | case CSR_UNEXP | PHS_STATUS: | ||
| 1159 | case CSR_SRV_REQ | PHS_STATUS: | ||
| 1160 | DB(DB_INTR, printk("STATUS=")) | ||
| 1161 | |||
| 1162 | cmd->SCp.Status = read_1_byte(hostdata); | ||
| 1163 | DB(DB_INTR, printk("%02x", cmd->SCp.Status)) | ||
| 1164 | if (hostdata->level2 >= L2_BASIC) { | ||
| 1165 | sr = read_3393(hostdata, WD_SCSI_STATUS); /* clear interrupt */ | ||
| 1166 | hostdata->state = S_RUNNING_LEVEL2; | ||
| 1167 | write_3393(hostdata, WD_COMMAND_PHASE, 0x50); | ||
| 1168 | write_3393_cmd(hostdata, WD_CMD_SEL_ATN_XFER); | ||
| 1169 | } else { | ||
| 1170 | hostdata->state = S_CONNECTED; | ||
| 1171 | } | ||
| 1172 | break; | ||
| 1173 | |||
| 1174 | |||
| 1175 | case CSR_XFER_DONE | PHS_MESS_IN: | ||
| 1176 | case CSR_UNEXP | PHS_MESS_IN: | ||
| 1177 | case CSR_SRV_REQ | PHS_MESS_IN: | ||
| 1178 | DB(DB_INTR, printk("MSG_IN=")) | ||
| 1179 | |||
| 1180 | msg = read_1_byte(hostdata); | ||
| 1181 | sr = read_3393(hostdata, WD_SCSI_STATUS); /* clear interrupt */ | ||
| 1182 | |||
| 1183 | hostdata->incoming_msg[hostdata->incoming_ptr] = msg; | ||
| 1184 | if (hostdata->incoming_msg[0] == EXTENDED_MESSAGE) | ||
| 1185 | msg = EXTENDED_MESSAGE; | ||
| 1186 | else | ||
| 1187 | hostdata->incoming_ptr = 0; | ||
| 1188 | |||
| 1189 | cmd->SCp.Message = msg; | ||
| 1190 | switch (msg) { | ||
| 1191 | |||
| 1192 | case COMMAND_COMPLETE: | ||
| 1193 | DB(DB_INTR, printk("CCMP")) | ||
| 1194 | write_3393_cmd(hostdata, WD_CMD_NEGATE_ACK); | ||
| 1195 | hostdata->state = S_PRE_CMP_DISC; | ||
| 1196 | break; | ||
| 1197 | |||
| 1198 | case SAVE_POINTERS: | ||
| 1199 | DB(DB_INTR, printk("SDP")) | ||
| 1200 | write_3393_cmd(hostdata, WD_CMD_NEGATE_ACK); | ||
| 1201 | hostdata->state = S_CONNECTED; | ||
| 1202 | break; | ||
| 1203 | |||
| 1204 | case RESTORE_POINTERS: | ||
| 1205 | DB(DB_INTR, printk("RDP")) | ||
| 1206 | if (hostdata->level2 >= L2_BASIC) { | ||
| 1207 | write_3393(hostdata, WD_COMMAND_PHASE, 0x45); | ||
| 1208 | write_3393_cmd(hostdata, WD_CMD_SEL_ATN_XFER); | ||
| 1209 | hostdata->state = S_RUNNING_LEVEL2; | ||
| 1210 | } else { | ||
| 1211 | write_3393_cmd(hostdata, WD_CMD_NEGATE_ACK); | ||
| 1212 | hostdata->state = S_CONNECTED; | ||
| 1213 | } | ||
| 1214 | break; | ||
| 1215 | |||
| 1216 | case DISCONNECT: | ||
| 1217 | DB(DB_INTR, printk("DIS")) | ||
| 1218 | cmd->device->disconnect = 1; | ||
| 1219 | write_3393_cmd(hostdata, WD_CMD_NEGATE_ACK); | ||
| 1220 | hostdata->state = S_PRE_TMP_DISC; | ||
| 1221 | break; | ||
| 1222 | |||
| 1223 | case MESSAGE_REJECT: | ||
| 1224 | DB(DB_INTR, printk("REJ")) | ||
| 1225 | #ifdef SYNC_DEBUG | ||
| 1226 | printk("-REJ-"); | ||
| 1227 | #endif | ||
| 1228 | if (hostdata->sync_stat[cmd->device->id] == SS_WAITING) | ||
| 1229 | hostdata->sync_stat[cmd->device->id] = SS_SET; | ||
| 1230 | write_3393_cmd(hostdata, WD_CMD_NEGATE_ACK); | ||
| 1231 | hostdata->state = S_CONNECTED; | ||
| 1232 | break; | ||
| 1233 | |||
| 1234 | case EXTENDED_MESSAGE: | ||
| 1235 | DB(DB_INTR, printk("EXT")) | ||
| 1236 | |||
| 1237 | ucp = hostdata->incoming_msg; | ||
| 1238 | |||
| 1239 | #ifdef SYNC_DEBUG | ||
| 1240 | printk("%02x", ucp[hostdata->incoming_ptr]); | ||
| 1241 | #endif | ||
| 1242 | /* Is this the last byte of the extended message? */ | ||
| 1243 | |||
| 1244 | if ((hostdata->incoming_ptr >= 2) && (hostdata->incoming_ptr == (ucp[1] + 1))) { | ||
| 1245 | |||
| 1246 | switch (ucp[2]) { /* what's the EXTENDED code? */ | ||
| 1247 | case EXTENDED_SDTR: | ||
| 1248 | id = calc_sync_xfer(ucp[3], ucp[4]); | ||
| 1249 | if (hostdata->sync_stat[cmd->device->id] != SS_WAITING) { | ||
| 1250 | |||
| 1251 | /* A device has sent an unsolicited SDTR message; rather than go | ||
| 1252 | * through the effort of decoding it and then figuring out what | ||
| 1253 | * our reply should be, we're just gonna say that we have a | ||
| 1254 | * synchronous fifo depth of 0. This will result in asynchronous | ||
| 1255 | * transfers - not ideal but so much easier. | ||
| 1256 | * Actually, this is OK because it assures us that if we don't | ||
| 1257 | * specifically ask for sync transfers, we won't do any. | ||
| 1258 | */ | ||
| 1259 | |||
| 1260 | write_3393_cmd(hostdata, WD_CMD_ASSERT_ATN); /* want MESS_OUT */ | ||
| 1261 | hostdata->outgoing_msg[0] = EXTENDED_MESSAGE; | ||
| 1262 | hostdata->outgoing_msg[1] = 3; | ||
| 1263 | hostdata->outgoing_msg[2] = EXTENDED_SDTR; | ||
| 1264 | hostdata->outgoing_msg[3] = hostdata->default_sx_per / 4; | ||
| 1265 | hostdata->outgoing_msg[4] = 0; | ||
| 1266 | hostdata->outgoing_len = 5; | ||
| 1267 | hostdata->sync_xfer[cmd->device->id] = calc_sync_xfer(hostdata->default_sx_per / 4, 0); | ||
| 1268 | } else { | ||
| 1269 | hostdata->sync_xfer[cmd->device->id] = id; | ||
| 1270 | } | ||
| 1271 | #ifdef SYNC_DEBUG | ||
| 1272 | printk("sync_xfer=%02x", hostdata->sync_xfer[cmd->device->id]); | ||
| 1273 | #endif | ||
| 1274 | hostdata->sync_stat[cmd->device->id] = SS_SET; | ||
| 1275 | write_3393_cmd(hostdata, WD_CMD_NEGATE_ACK); | ||
| 1276 | hostdata->state = S_CONNECTED; | ||
| 1277 | break; | ||
| 1278 | case EXTENDED_WDTR: | ||
| 1279 | write_3393_cmd(hostdata, WD_CMD_ASSERT_ATN); /* want MESS_OUT */ | ||
| 1280 | printk("sending WDTR "); | ||
| 1281 | hostdata->outgoing_msg[0] = EXTENDED_MESSAGE; | ||
| 1282 | hostdata->outgoing_msg[1] = 2; | ||
| 1283 | hostdata->outgoing_msg[2] = EXTENDED_WDTR; | ||
| 1284 | hostdata->outgoing_msg[3] = 0; /* 8 bit transfer width */ | ||
| 1285 | hostdata->outgoing_len = 4; | ||
| 1286 | write_3393_cmd(hostdata, WD_CMD_NEGATE_ACK); | ||
| 1287 | hostdata->state = S_CONNECTED; | ||
| 1288 | break; | ||
| 1289 | default: | ||
| 1290 | write_3393_cmd(hostdata, WD_CMD_ASSERT_ATN); /* want MESS_OUT */ | ||
| 1291 | printk("Rejecting Unknown Extended Message(%02x). ", ucp[2]); | ||
| 1292 | hostdata->outgoing_msg[0] = MESSAGE_REJECT; | ||
| 1293 | hostdata->outgoing_len = 1; | ||
| 1294 | write_3393_cmd(hostdata, WD_CMD_NEGATE_ACK); | ||
| 1295 | hostdata->state = S_CONNECTED; | ||
| 1296 | break; | ||
| 1297 | } | ||
| 1298 | hostdata->incoming_ptr = 0; | ||
| 1299 | } | ||
| 1300 | |||
| 1301 | /* We need to read more MESS_IN bytes for the extended message */ | ||
| 1302 | |||
| 1303 | else { | ||
| 1304 | hostdata->incoming_ptr++; | ||
| 1305 | write_3393_cmd(hostdata, WD_CMD_NEGATE_ACK); | ||
| 1306 | hostdata->state = S_CONNECTED; | ||
| 1307 | } | ||
| 1308 | break; | ||
| 1309 | |||
| 1310 | default: | ||
| 1311 | printk("Rejecting Unknown Message(%02x) ", msg); | ||
| 1312 | write_3393_cmd(hostdata, WD_CMD_ASSERT_ATN); /* want MESS_OUT */ | ||
| 1313 | hostdata->outgoing_msg[0] = MESSAGE_REJECT; | ||
| 1314 | hostdata->outgoing_len = 1; | ||
| 1315 | write_3393_cmd(hostdata, WD_CMD_NEGATE_ACK); | ||
| 1316 | hostdata->state = S_CONNECTED; | ||
| 1317 | } | ||
| 1318 | break; | ||
| 1319 | |||
| 1320 | |||
| 1321 | /* Note: this interrupt will occur only after a LEVEL2 command */ | ||
| 1322 | |||
| 1323 | case CSR_SEL_XFER_DONE: | ||
| 1324 | |||
| 1325 | /* Make sure that reselection is enabled at this point - it may | ||
| 1326 | * have been turned off for the command that just completed. | ||
| 1327 | */ | ||
| 1328 | |||
| 1329 | write_3393(hostdata, WD_SOURCE_ID, SRCID_ER); | ||
| 1330 | if (phs == 0x60) { | ||
| 1331 | DB(DB_INTR, printk("SX-DONE")) | ||
| 1332 | cmd->SCp.Message = COMMAND_COMPLETE; | ||
| 1333 | lun = read_3393(hostdata, WD_TARGET_LUN); | ||
| 1334 | DB(DB_INTR, printk(":%d.%d", cmd->SCp.Status, lun)) | ||
| 1335 | hostdata->connected = NULL; | ||
| 1336 | hostdata->busy[cmd->device->id] &= ~(1 << cmd->device->lun); | ||
| 1337 | hostdata->state = S_UNCONNECTED; | ||
| 1338 | if (cmd->SCp.Status == ILLEGAL_STATUS_BYTE) | ||
| 1339 | cmd->SCp.Status = lun; | ||
| 1340 | if (cmd->cmnd[0] == REQUEST_SENSE && cmd->SCp.Status != GOOD) | ||
| 1341 | cmd->result = (cmd->result & 0x00ffff) | (DID_ERROR << 16); | ||
| 1342 | else | ||
| 1343 | cmd->result = cmd->SCp.Status | (cmd->SCp.Message << 8); | ||
| 1344 | cmd->scsi_done(cmd); | ||
| 1345 | |||
| 1346 | /* We are no longer connected to a target - check to see if | ||
| 1347 | * there are commands waiting to be executed. | ||
| 1348 | */ | ||
| 1349 | |||
| 1350 | in2000_execute(instance); | ||
| 1351 | } else { | ||
| 1352 | printk("%02x:%02x:%02x: Unknown SEL_XFER_DONE phase!!---", asr, sr, phs); | ||
| 1353 | } | ||
| 1354 | break; | ||
| 1355 | |||
| 1356 | |||
| 1357 | /* Note: this interrupt will occur only after a LEVEL2 command */ | ||
| 1358 | |||
| 1359 | case CSR_SDP: | ||
| 1360 | DB(DB_INTR, printk("SDP")) | ||
| 1361 | hostdata->state = S_RUNNING_LEVEL2; | ||
| 1362 | write_3393(hostdata, WD_COMMAND_PHASE, 0x41); | ||
| 1363 | write_3393_cmd(hostdata, WD_CMD_SEL_ATN_XFER); | ||
| 1364 | break; | ||
| 1365 | |||
| 1366 | |||
| 1367 | case CSR_XFER_DONE | PHS_MESS_OUT: | ||
| 1368 | case CSR_UNEXP | PHS_MESS_OUT: | ||
| 1369 | case CSR_SRV_REQ | PHS_MESS_OUT: | ||
| 1370 | DB(DB_INTR, printk("MSG_OUT=")) | ||
| 1371 | |||
| 1372 | /* To get here, we've probably requested MESSAGE_OUT and have | ||
| 1373 | * already put the correct bytes in outgoing_msg[] and filled | ||
| 1374 | * in outgoing_len. We simply send them out to the SCSI bus. | ||
| 1375 | * Sometimes we get MESSAGE_OUT phase when we're not expecting | ||
| 1376 | * it - like when our SDTR message is rejected by a target. Some | ||
| 1377 | * targets send the REJECT before receiving all of the extended | ||
| 1378 | * message, and then seem to go back to MESSAGE_OUT for a byte | ||
| 1379 | * or two. Not sure why, or if I'm doing something wrong to | ||
| 1380 | * cause this to happen. Regardless, it seems that sending | ||
| 1381 | * NOP messages in these situations results in no harm and | ||
| 1382 | * makes everyone happy. | ||
| 1383 | */ | ||
| 1384 | if (hostdata->outgoing_len == 0) { | ||
| 1385 | hostdata->outgoing_len = 1; | ||
| 1386 | hostdata->outgoing_msg[0] = NOP; | ||
| 1387 | } | ||
| 1388 | transfer_pio(hostdata->outgoing_msg, hostdata->outgoing_len, DATA_OUT_DIR, hostdata); | ||
| 1389 | DB(DB_INTR, printk("%02x", hostdata->outgoing_msg[0])) | ||
| 1390 | hostdata->outgoing_len = 0; | ||
| 1391 | hostdata->state = S_CONNECTED; | ||
| 1392 | break; | ||
| 1393 | |||
| 1394 | |||
| 1395 | case CSR_UNEXP_DISC: | ||
| 1396 | |||
| 1397 | /* I think I've seen this after a request-sense that was in response | ||
| 1398 | * to an error condition, but not sure. We certainly need to do | ||
| 1399 | * something when we get this interrupt - the question is 'what?'. | ||
| 1400 | * Let's think positively, and assume some command has finished | ||
| 1401 | * in a legal manner (like a command that provokes a request-sense), | ||
| 1402 | * so we treat it as a normal command-complete-disconnect. | ||
| 1403 | */ | ||
| 1404 | |||
| 1405 | |||
| 1406 | /* Make sure that reselection is enabled at this point - it may | ||
| 1407 | * have been turned off for the command that just completed. | ||
| 1408 | */ | ||
| 1409 | |||
| 1410 | write_3393(hostdata, WD_SOURCE_ID, SRCID_ER); | ||
| 1411 | if (cmd == NULL) { | ||
| 1412 | printk(" - Already disconnected! "); | ||
| 1413 | hostdata->state = S_UNCONNECTED; | ||
| 1414 | |||
| 1415 | /* release the SMP spin_lock and restore irq state */ | ||
| 1416 | spin_unlock_irqrestore(instance->host_lock, flags); | ||
| 1417 | return IRQ_HANDLED; | ||
| 1418 | } | ||
| 1419 | DB(DB_INTR, printk("UNEXP_DISC")) | ||
| 1420 | hostdata->connected = NULL; | ||
| 1421 | hostdata->busy[cmd->device->id] &= ~(1 << cmd->device->lun); | ||
| 1422 | hostdata->state = S_UNCONNECTED; | ||
| 1423 | if (cmd->cmnd[0] == REQUEST_SENSE && cmd->SCp.Status != GOOD) | ||
| 1424 | cmd->result = (cmd->result & 0x00ffff) | (DID_ERROR << 16); | ||
| 1425 | else | ||
| 1426 | cmd->result = cmd->SCp.Status | (cmd->SCp.Message << 8); | ||
| 1427 | cmd->scsi_done(cmd); | ||
| 1428 | |||
| 1429 | /* We are no longer connected to a target - check to see if | ||
| 1430 | * there are commands waiting to be executed. | ||
| 1431 | */ | ||
| 1432 | |||
| 1433 | in2000_execute(instance); | ||
| 1434 | break; | ||
| 1435 | |||
| 1436 | |||
| 1437 | case CSR_DISC: | ||
| 1438 | |||
| 1439 | /* Make sure that reselection is enabled at this point - it may | ||
| 1440 | * have been turned off for the command that just completed. | ||
| 1441 | */ | ||
| 1442 | |||
| 1443 | write_3393(hostdata, WD_SOURCE_ID, SRCID_ER); | ||
| 1444 | DB(DB_INTR, printk("DISC")) | ||
| 1445 | if (cmd == NULL) { | ||
| 1446 | printk(" - Already disconnected! "); | ||
| 1447 | hostdata->state = S_UNCONNECTED; | ||
| 1448 | } | ||
| 1449 | switch (hostdata->state) { | ||
| 1450 | case S_PRE_CMP_DISC: | ||
| 1451 | hostdata->connected = NULL; | ||
| 1452 | hostdata->busy[cmd->device->id] &= ~(1 << cmd->device->lun); | ||
| 1453 | hostdata->state = S_UNCONNECTED; | ||
| 1454 | DB(DB_INTR, printk(":%d", cmd->SCp.Status)) | ||
| 1455 | if (cmd->cmnd[0] == REQUEST_SENSE && cmd->SCp.Status != GOOD) | ||
| 1456 | cmd->result = (cmd->result & 0x00ffff) | (DID_ERROR << 16); | ||
| 1457 | else | ||
| 1458 | cmd->result = cmd->SCp.Status | (cmd->SCp.Message << 8); | ||
| 1459 | cmd->scsi_done(cmd); | ||
| 1460 | break; | ||
| 1461 | case S_PRE_TMP_DISC: | ||
| 1462 | case S_RUNNING_LEVEL2: | ||
| 1463 | cmd->host_scribble = (uchar *) hostdata->disconnected_Q; | ||
| 1464 | hostdata->disconnected_Q = cmd; | ||
| 1465 | hostdata->connected = NULL; | ||
| 1466 | hostdata->state = S_UNCONNECTED; | ||
| 1467 | |||
| 1468 | #ifdef PROC_STATISTICS | ||
| 1469 | hostdata->disc_done_cnt[cmd->device->id]++; | ||
| 1470 | #endif | ||
| 1471 | |||
| 1472 | break; | ||
| 1473 | default: | ||
| 1474 | printk("*** Unexpected DISCONNECT interrupt! ***"); | ||
| 1475 | hostdata->state = S_UNCONNECTED; | ||
| 1476 | } | ||
| 1477 | |||
| 1478 | /* We are no longer connected to a target - check to see if | ||
| 1479 | * there are commands waiting to be executed. | ||
| 1480 | */ | ||
| 1481 | |||
| 1482 | in2000_execute(instance); | ||
| 1483 | break; | ||
| 1484 | |||
| 1485 | |||
| 1486 | case CSR_RESEL_AM: | ||
| 1487 | DB(DB_INTR, printk("RESEL")) | ||
| 1488 | |||
| 1489 | /* First we have to make sure this reselection didn't */ | ||
| 1490 | /* happen during Arbitration/Selection of some other device. */ | ||
| 1491 | /* If yes, put losing command back on top of input_Q. */ | ||
| 1492 | if (hostdata->level2 <= L2_NONE) { | ||
| 1493 | |||
| 1494 | if (hostdata->selecting) { | ||
| 1495 | cmd = (Scsi_Cmnd *) hostdata->selecting; | ||
| 1496 | hostdata->selecting = NULL; | ||
| 1497 | hostdata->busy[cmd->device->id] &= ~(1 << cmd->device->lun); | ||
| 1498 | cmd->host_scribble = (uchar *) hostdata->input_Q; | ||
| 1499 | hostdata->input_Q = cmd; | ||
| 1500 | } | ||
| 1501 | } | ||
| 1502 | |||
| 1503 | else { | ||
| 1504 | |||
| 1505 | if (cmd) { | ||
| 1506 | if (phs == 0x00) { | ||
| 1507 | hostdata->busy[cmd->device->id] &= ~(1 << cmd->device->lun); | ||
| 1508 | cmd->host_scribble = (uchar *) hostdata->input_Q; | ||
| 1509 | hostdata->input_Q = cmd; | ||
| 1510 | } else { | ||
| 1511 | printk("---%02x:%02x:%02x-TROUBLE: Intrusive ReSelect!---", asr, sr, phs); | ||
| 1512 | while (1) | ||
| 1513 | printk("\r"); | ||
| 1514 | } | ||
| 1515 | } | ||
| 1516 | |||
| 1517 | } | ||
| 1518 | |||
| 1519 | /* OK - find out which device reselected us. */ | ||
| 1520 | |||
| 1521 | id = read_3393(hostdata, WD_SOURCE_ID); | ||
| 1522 | id &= SRCID_MASK; | ||
| 1523 | |||
| 1524 | /* and extract the lun from the ID message. (Note that we don't | ||
| 1525 | * bother to check for a valid message here - I guess this is | ||
| 1526 | * not the right way to go, but....) | ||
| 1527 | */ | ||
| 1528 | |||
| 1529 | lun = read_3393(hostdata, WD_DATA); | ||
| 1530 | if (hostdata->level2 < L2_RESELECT) | ||
| 1531 | write_3393_cmd(hostdata, WD_CMD_NEGATE_ACK); | ||
| 1532 | lun &= 7; | ||
| 1533 | |||
| 1534 | /* Now we look for the command that's reconnecting. */ | ||
| 1535 | |||
| 1536 | cmd = (Scsi_Cmnd *) hostdata->disconnected_Q; | ||
| 1537 | patch = NULL; | ||
| 1538 | while (cmd) { | ||
| 1539 | if (id == cmd->device->id && lun == cmd->device->lun) | ||
| 1540 | break; | ||
| 1541 | patch = cmd; | ||
| 1542 | cmd = (Scsi_Cmnd *) cmd->host_scribble; | ||
| 1543 | } | ||
| 1544 | |||
| 1545 | /* Hmm. Couldn't find a valid command.... What to do? */ | ||
| 1546 | |||
| 1547 | if (!cmd) { | ||
| 1548 | printk("---TROUBLE: target %d.%d not in disconnect queue---", id, lun); | ||
| 1549 | break; | ||
| 1550 | } | ||
| 1551 | |||
| 1552 | /* Ok, found the command - now start it up again. */ | ||
| 1553 | |||
| 1554 | if (patch) | ||
| 1555 | patch->host_scribble = cmd->host_scribble; | ||
| 1556 | else | ||
| 1557 | hostdata->disconnected_Q = (Scsi_Cmnd *) cmd->host_scribble; | ||
| 1558 | hostdata->connected = cmd; | ||
| 1559 | |||
| 1560 | /* We don't need to worry about 'initialize_SCp()' or 'hostdata->busy[]' | ||
| 1561 | * because these things are preserved over a disconnect. | ||
| 1562 | * But we DO need to fix the DPD bit so it's correct for this command. | ||
| 1563 | */ | ||
| 1564 | |||
| 1565 | if (is_dir_out(cmd)) | ||
| 1566 | write_3393(hostdata, WD_DESTINATION_ID, cmd->device->id); | ||
| 1567 | else | ||
| 1568 | write_3393(hostdata, WD_DESTINATION_ID, cmd->device->id | DSTID_DPD); | ||
| 1569 | if (hostdata->level2 >= L2_RESELECT) { | ||
| 1570 | write_3393_count(hostdata, 0); /* we want a DATA_PHASE interrupt */ | ||
| 1571 | write_3393(hostdata, WD_COMMAND_PHASE, 0x45); | ||
| 1572 | write_3393_cmd(hostdata, WD_CMD_SEL_ATN_XFER); | ||
| 1573 | hostdata->state = S_RUNNING_LEVEL2; | ||
| 1574 | } else | ||
| 1575 | hostdata->state = S_CONNECTED; | ||
| 1576 | |||
| 1577 | break; | ||
| 1578 | |||
| 1579 | default: | ||
| 1580 | printk("--UNKNOWN INTERRUPT:%02x:%02x:%02x--", asr, sr, phs); | ||
| 1581 | } | ||
| 1582 | |||
| 1583 | write1_io(0, IO_LED_OFF); | ||
| 1584 | |||
| 1585 | DB(DB_INTR, printk("} ")) | ||
| 1586 | |||
| 1587 | /* release the SMP spin_lock and restore irq state */ | ||
| 1588 | spin_unlock_irqrestore(instance->host_lock, flags); | ||
| 1589 | return IRQ_HANDLED; | ||
| 1590 | } | ||
| 1591 | |||
| 1592 | |||
| 1593 | |||
| 1594 | #define RESET_CARD 0 | ||
| 1595 | #define RESET_CARD_AND_BUS 1 | ||
| 1596 | #define B_FLAG 0x80 | ||
| 1597 | |||
| 1598 | /* | ||
| 1599 | * Caller must hold instance lock! | ||
| 1600 | */ | ||
| 1601 | |||
| 1602 | static int reset_hardware(struct Scsi_Host *instance, int type) | ||
| 1603 | { | ||
| 1604 | struct IN2000_hostdata *hostdata; | ||
| 1605 | int qt, x; | ||
| 1606 | |||
| 1607 | hostdata = (struct IN2000_hostdata *) instance->hostdata; | ||
| 1608 | |||
| 1609 | write1_io(0, IO_LED_ON); | ||
| 1610 | if (type == RESET_CARD_AND_BUS) { | ||
| 1611 | write1_io(0, IO_CARD_RESET); | ||
| 1612 | x = read1_io(IO_HARDWARE); | ||
| 1613 | } | ||
| 1614 | x = read_3393(hostdata, WD_SCSI_STATUS); /* clear any WD intrpt */ | ||
| 1615 | write_3393(hostdata, WD_OWN_ID, instance->this_id | OWNID_EAF | OWNID_RAF | OWNID_FS_8); | ||
| 1616 | write_3393(hostdata, WD_CONTROL, CTRL_IDI | CTRL_EDI | CTRL_POLLED); | ||
| 1617 | write_3393(hostdata, WD_SYNCHRONOUS_TRANSFER, calc_sync_xfer(hostdata->default_sx_per / 4, DEFAULT_SX_OFF)); | ||
| 1618 | |||
| 1619 | write1_io(0, IO_FIFO_WRITE); /* clear fifo counter */ | ||
| 1620 | write1_io(0, IO_FIFO_READ); /* start fifo out in read mode */ | ||
| 1621 | write_3393(hostdata, WD_COMMAND, WD_CMD_RESET); | ||
| 1622 | /* FIXME: timeout ?? */ | ||
| 1623 | while (!(READ_AUX_STAT() & ASR_INT)) | ||
| 1624 | cpu_relax(); /* wait for RESET to complete */ | ||
| 1625 | |||
| 1626 | x = read_3393(hostdata, WD_SCSI_STATUS); /* clear interrupt */ | ||
| 1627 | |||
| 1628 | write_3393(hostdata, WD_QUEUE_TAG, 0xa5); /* any random number */ | ||
| 1629 | qt = read_3393(hostdata, WD_QUEUE_TAG); | ||
| 1630 | if (qt == 0xa5) { | ||
| 1631 | x |= B_FLAG; | ||
| 1632 | write_3393(hostdata, WD_QUEUE_TAG, 0); | ||
| 1633 | } | ||
| 1634 | write_3393(hostdata, WD_TIMEOUT_PERIOD, TIMEOUT_PERIOD_VALUE); | ||
| 1635 | write_3393(hostdata, WD_CONTROL, CTRL_IDI | CTRL_EDI | CTRL_POLLED); | ||
| 1636 | write1_io(0, IO_LED_OFF); | ||
| 1637 | return x; | ||
| 1638 | } | ||
| 1639 | |||
| 1640 | |||
| 1641 | |||
| 1642 | static int in2000_bus_reset(Scsi_Cmnd * cmd) | ||
| 1643 | { | ||
| 1644 | struct Scsi_Host *instance; | ||
| 1645 | struct IN2000_hostdata *hostdata; | ||
| 1646 | int x; | ||
| 1647 | unsigned long flags; | ||
| 1648 | |||
| 1649 | instance = cmd->device->host; | ||
| 1650 | hostdata = (struct IN2000_hostdata *) instance->hostdata; | ||
| 1651 | |||
| 1652 | printk(KERN_WARNING "scsi%d: Reset. ", instance->host_no); | ||
| 1653 | |||
| 1654 | spin_lock_irqsave(instance->host_lock, flags); | ||
| 1655 | |||
| 1656 | /* do scsi-reset here */ | ||
| 1657 | reset_hardware(instance, RESET_CARD_AND_BUS); | ||
| 1658 | for (x = 0; x < 8; x++) { | ||
| 1659 | hostdata->busy[x] = 0; | ||
| 1660 | hostdata->sync_xfer[x] = calc_sync_xfer(DEFAULT_SX_PER / 4, DEFAULT_SX_OFF); | ||
| 1661 | hostdata->sync_stat[x] = SS_UNSET; /* using default sync values */ | ||
| 1662 | } | ||
| 1663 | hostdata->input_Q = NULL; | ||
| 1664 | hostdata->selecting = NULL; | ||
| 1665 | hostdata->connected = NULL; | ||
| 1666 | hostdata->disconnected_Q = NULL; | ||
| 1667 | hostdata->state = S_UNCONNECTED; | ||
| 1668 | hostdata->fifo = FI_FIFO_UNUSED; | ||
| 1669 | hostdata->incoming_ptr = 0; | ||
| 1670 | hostdata->outgoing_len = 0; | ||
| 1671 | |||
| 1672 | cmd->result = DID_RESET << 16; | ||
| 1673 | |||
| 1674 | spin_unlock_irqrestore(instance->host_lock, flags); | ||
| 1675 | return SUCCESS; | ||
| 1676 | } | ||
| 1677 | |||
| 1678 | static int __in2000_abort(Scsi_Cmnd * cmd) | ||
| 1679 | { | ||
| 1680 | struct Scsi_Host *instance; | ||
| 1681 | struct IN2000_hostdata *hostdata; | ||
| 1682 | Scsi_Cmnd *tmp, *prev; | ||
| 1683 | uchar sr, asr; | ||
| 1684 | unsigned long timeout; | ||
| 1685 | |||
| 1686 | instance = cmd->device->host; | ||
| 1687 | hostdata = (struct IN2000_hostdata *) instance->hostdata; | ||
| 1688 | |||
| 1689 | printk(KERN_DEBUG "scsi%d: Abort-", instance->host_no); | ||
| 1690 | printk("(asr=%02x,count=%ld,resid=%d,buf_resid=%d,have_data=%d,FC=%02x)- ", READ_AUX_STAT(), read_3393_count(hostdata), cmd->SCp.this_residual, cmd->SCp.buffers_residual, cmd->SCp.have_data_in, read1_io(IO_FIFO_COUNT)); | ||
| 1691 | |||
| 1692 | /* | ||
| 1693 | * Case 1 : If the command hasn't been issued yet, we simply remove it | ||
| 1694 | * from the inout_Q. | ||
| 1695 | */ | ||
| 1696 | |||
| 1697 | tmp = (Scsi_Cmnd *) hostdata->input_Q; | ||
| 1698 | prev = NULL; | ||
| 1699 | while (tmp) { | ||
| 1700 | if (tmp == cmd) { | ||
| 1701 | if (prev) | ||
| 1702 | prev->host_scribble = cmd->host_scribble; | ||
| 1703 | cmd->host_scribble = NULL; | ||
| 1704 | cmd->result = DID_ABORT << 16; | ||
| 1705 | printk(KERN_WARNING "scsi%d: Abort - removing command from input_Q. ", instance->host_no); | ||
| 1706 | cmd->scsi_done(cmd); | ||
| 1707 | return SUCCESS; | ||
| 1708 | } | ||
| 1709 | prev = tmp; | ||
| 1710 | tmp = (Scsi_Cmnd *) tmp->host_scribble; | ||
| 1711 | } | ||
| 1712 | |||
| 1713 | /* | ||
| 1714 | * Case 2 : If the command is connected, we're going to fail the abort | ||
| 1715 | * and let the high level SCSI driver retry at a later time or | ||
| 1716 | * issue a reset. | ||
| 1717 | * | ||
| 1718 | * Timeouts, and therefore aborted commands, will be highly unlikely | ||
| 1719 | * and handling them cleanly in this situation would make the common | ||
| 1720 | * case of noresets less efficient, and would pollute our code. So, | ||
| 1721 | * we fail. | ||
| 1722 | */ | ||
| 1723 | |||
| 1724 | if (hostdata->connected == cmd) { | ||
| 1725 | |||
| 1726 | printk(KERN_WARNING "scsi%d: Aborting connected command - ", instance->host_no); | ||
| 1727 | |||
| 1728 | printk("sending wd33c93 ABORT command - "); | ||
| 1729 | write_3393(hostdata, WD_CONTROL, CTRL_IDI | CTRL_EDI | CTRL_POLLED); | ||
| 1730 | write_3393_cmd(hostdata, WD_CMD_ABORT); | ||
| 1731 | |||
| 1732 | /* Now we have to attempt to flush out the FIFO... */ | ||
| 1733 | |||
| 1734 | printk("flushing fifo - "); | ||
| 1735 | timeout = 1000000; | ||
| 1736 | do { | ||
| 1737 | asr = READ_AUX_STAT(); | ||
| 1738 | if (asr & ASR_DBR) | ||
| 1739 | read_3393(hostdata, WD_DATA); | ||
| 1740 | } while (!(asr & ASR_INT) && timeout-- > 0); | ||
| 1741 | sr = read_3393(hostdata, WD_SCSI_STATUS); | ||
| 1742 | printk("asr=%02x, sr=%02x, %ld bytes un-transferred (timeout=%ld) - ", asr, sr, read_3393_count(hostdata), timeout); | ||
| 1743 | |||
| 1744 | /* | ||
| 1745 | * Abort command processed. | ||
| 1746 | * Still connected. | ||
| 1747 | * We must disconnect. | ||
| 1748 | */ | ||
| 1749 | |||
| 1750 | printk("sending wd33c93 DISCONNECT command - "); | ||
| 1751 | write_3393_cmd(hostdata, WD_CMD_DISCONNECT); | ||
| 1752 | |||
| 1753 | timeout = 1000000; | ||
| 1754 | asr = READ_AUX_STAT(); | ||
| 1755 | while ((asr & ASR_CIP) && timeout-- > 0) | ||
| 1756 | asr = READ_AUX_STAT(); | ||
| 1757 | sr = read_3393(hostdata, WD_SCSI_STATUS); | ||
| 1758 | printk("asr=%02x, sr=%02x.", asr, sr); | ||
| 1759 | |||
| 1760 | hostdata->busy[cmd->device->id] &= ~(1 << cmd->device->lun); | ||
| 1761 | hostdata->connected = NULL; | ||
| 1762 | hostdata->state = S_UNCONNECTED; | ||
| 1763 | cmd->result = DID_ABORT << 16; | ||
| 1764 | cmd->scsi_done(cmd); | ||
| 1765 | |||
| 1766 | in2000_execute(instance); | ||
| 1767 | |||
| 1768 | return SUCCESS; | ||
| 1769 | } | ||
| 1770 | |||
| 1771 | /* | ||
| 1772 | * Case 3: If the command is currently disconnected from the bus, | ||
| 1773 | * we're not going to expend much effort here: Let's just return | ||
| 1774 | * an ABORT_SNOOZE and hope for the best... | ||
| 1775 | */ | ||
| 1776 | |||
| 1777 | for (tmp = (Scsi_Cmnd *) hostdata->disconnected_Q; tmp; tmp = (Scsi_Cmnd *) tmp->host_scribble) | ||
| 1778 | if (cmd == tmp) { | ||
| 1779 | printk(KERN_DEBUG "scsi%d: unable to abort disconnected command.\n", instance->host_no); | ||
| 1780 | return FAILED; | ||
| 1781 | } | ||
| 1782 | |||
| 1783 | /* | ||
| 1784 | * Case 4 : If we reached this point, the command was not found in any of | ||
| 1785 | * the queues. | ||
| 1786 | * | ||
| 1787 | * We probably reached this point because of an unlikely race condition | ||
| 1788 | * between the command completing successfully and the abortion code, | ||
| 1789 | * so we won't panic, but we will notify the user in case something really | ||
| 1790 | * broke. | ||
| 1791 | */ | ||
| 1792 | |||
| 1793 | in2000_execute(instance); | ||
| 1794 | |||
| 1795 | printk("scsi%d: warning : SCSI command probably completed successfully" " before abortion. ", instance->host_no); | ||
| 1796 | return SUCCESS; | ||
| 1797 | } | ||
| 1798 | |||
| 1799 | static int in2000_abort(Scsi_Cmnd * cmd) | ||
| 1800 | { | ||
| 1801 | int rc; | ||
| 1802 | |||
| 1803 | spin_lock_irq(cmd->device->host->host_lock); | ||
| 1804 | rc = __in2000_abort(cmd); | ||
| 1805 | spin_unlock_irq(cmd->device->host->host_lock); | ||
| 1806 | |||
| 1807 | return rc; | ||
| 1808 | } | ||
| 1809 | |||
| 1810 | |||
| 1811 | #define MAX_IN2000_HOSTS 3 | ||
| 1812 | #define MAX_SETUP_ARGS ARRAY_SIZE(setup_args) | ||
| 1813 | #define SETUP_BUFFER_SIZE 200 | ||
| 1814 | static char setup_buffer[SETUP_BUFFER_SIZE]; | ||
| 1815 | static char setup_used[MAX_SETUP_ARGS]; | ||
| 1816 | static int done_setup = 0; | ||
| 1817 | |||
| 1818 | static void __init in2000_setup(char *str, int *ints) | ||
| 1819 | { | ||
| 1820 | int i; | ||
| 1821 | char *p1, *p2; | ||
| 1822 | |||
| 1823 | strlcpy(setup_buffer, str, SETUP_BUFFER_SIZE); | ||
| 1824 | p1 = setup_buffer; | ||
| 1825 | i = 0; | ||
| 1826 | while (*p1 && (i < MAX_SETUP_ARGS)) { | ||
| 1827 | p2 = strchr(p1, ','); | ||
| 1828 | if (p2) { | ||
| 1829 | *p2 = '\0'; | ||
| 1830 | if (p1 != p2) | ||
| 1831 | setup_args[i] = p1; | ||
| 1832 | p1 = p2 + 1; | ||
| 1833 | i++; | ||
| 1834 | } else { | ||
| 1835 | setup_args[i] = p1; | ||
| 1836 | break; | ||
| 1837 | } | ||
| 1838 | } | ||
| 1839 | for (i = 0; i < MAX_SETUP_ARGS; i++) | ||
| 1840 | setup_used[i] = 0; | ||
| 1841 | done_setup = 1; | ||
| 1842 | } | ||
| 1843 | |||
| 1844 | |||
| 1845 | /* check_setup_args() returns index if key found, 0 if not | ||
| 1846 | */ | ||
| 1847 | |||
| 1848 | static int __init check_setup_args(char *key, int *val, char *buf) | ||
| 1849 | { | ||
| 1850 | int x; | ||
| 1851 | char *cp; | ||
| 1852 | |||
| 1853 | for (x = 0; x < MAX_SETUP_ARGS; x++) { | ||
| 1854 | if (setup_used[x]) | ||
| 1855 | continue; | ||
| 1856 | if (!strncmp(setup_args[x], key, strlen(key))) | ||
| 1857 | break; | ||
| 1858 | } | ||
| 1859 | if (x == MAX_SETUP_ARGS) | ||
| 1860 | return 0; | ||
| 1861 | setup_used[x] = 1; | ||
| 1862 | cp = setup_args[x] + strlen(key); | ||
| 1863 | *val = -1; | ||
| 1864 | if (*cp != ':') | ||
| 1865 | return ++x; | ||
| 1866 | cp++; | ||
| 1867 | if ((*cp >= '0') && (*cp <= '9')) { | ||
| 1868 | *val = simple_strtoul(cp, NULL, 0); | ||
| 1869 | } | ||
| 1870 | return ++x; | ||
| 1871 | } | ||
| 1872 | |||
| 1873 | |||
| 1874 | |||
| 1875 | /* The "correct" (ie portable) way to access memory-mapped hardware | ||
| 1876 | * such as the IN2000 EPROM and dip switch is through the use of | ||
| 1877 | * special macros declared in 'asm/io.h'. We use readb() and readl() | ||
| 1878 | * when reading from the card's BIOS area in in2000_detect(). | ||
| 1879 | */ | ||
| 1880 | static u32 bios_tab[] in2000__INITDATA = { | ||
| 1881 | 0xc8000, | ||
| 1882 | 0xd0000, | ||
| 1883 | 0xd8000, | ||
| 1884 | 0 | ||
| 1885 | }; | ||
| 1886 | |||
| 1887 | static unsigned short base_tab[] in2000__INITDATA = { | ||
| 1888 | 0x220, | ||
| 1889 | 0x200, | ||
| 1890 | 0x110, | ||
| 1891 | 0x100, | ||
| 1892 | }; | ||
| 1893 | |||
| 1894 | static int int_tab[] in2000__INITDATA = { | ||
| 1895 | 15, | ||
| 1896 | 14, | ||
| 1897 | 11, | ||
| 1898 | 10 | ||
| 1899 | }; | ||
| 1900 | |||
| 1901 | static int probe_bios(u32 addr, u32 *s1, uchar *switches) | ||
| 1902 | { | ||
| 1903 | void __iomem *p = ioremap(addr, 0x34); | ||
| 1904 | if (!p) | ||
| 1905 | return 0; | ||
| 1906 | *s1 = readl(p + 0x10); | ||
| 1907 | if (*s1 == 0x41564f4e || readl(p + 0x30) == 0x61776c41) { | ||
| 1908 | /* Read the switch image that's mapped into EPROM space */ | ||
| 1909 | *switches = ~readb(p + 0x20); | ||
| 1910 | iounmap(p); | ||
| 1911 | return 1; | ||
| 1912 | } | ||
| 1913 | iounmap(p); | ||
| 1914 | return 0; | ||
| 1915 | } | ||
| 1916 | |||
| 1917 | static int __init in2000_detect(struct scsi_host_template * tpnt) | ||
| 1918 | { | ||
| 1919 | struct Scsi_Host *instance; | ||
| 1920 | struct IN2000_hostdata *hostdata; | ||
| 1921 | int detect_count; | ||
| 1922 | int bios; | ||
| 1923 | int x; | ||
| 1924 | unsigned short base; | ||
| 1925 | uchar switches; | ||
| 1926 | uchar hrev; | ||
| 1927 | unsigned long flags; | ||
| 1928 | int val; | ||
| 1929 | char buf[32]; | ||
| 1930 | |||
| 1931 | /* Thanks to help from Bill Earnest, probing for IN2000 cards is a | ||
| 1932 | * pretty straightforward and fool-proof operation. There are 3 | ||
| 1933 | * possible locations for the IN2000 EPROM in memory space - if we | ||
| 1934 | * find a BIOS signature, we can read the dip switch settings from | ||
| 1935 | * the byte at BIOS+32 (shadowed in by logic on the card). From 2 | ||
| 1936 | * of the switch bits we get the card's address in IO space. There's | ||
| 1937 | * an image of the dip switch there, also, so we have a way to back- | ||
| 1938 | * check that this really is an IN2000 card. Very nifty. Use the | ||
| 1939 | * 'ioport:xx' command-line parameter if your BIOS EPROM is absent | ||
| 1940 | * or disabled. | ||
| 1941 | */ | ||
| 1942 | |||
| 1943 | if (!done_setup && setup_strings) | ||
| 1944 | in2000_setup(setup_strings, NULL); | ||
| 1945 | |||
| 1946 | detect_count = 0; | ||
| 1947 | for (bios = 0; bios_tab[bios]; bios++) { | ||
| 1948 | u32 s1 = 0; | ||
| 1949 | if (check_setup_args("ioport", &val, buf)) { | ||
| 1950 | base = val; | ||
| 1951 | switches = ~inb(base + IO_SWITCHES) & 0xff; | ||
| 1952 | printk("Forcing IN2000 detection at IOport 0x%x ", base); | ||
| 1953 | bios = 2; | ||
| 1954 | } | ||
| 1955 | /* | ||
| 1956 | * There have been a couple of BIOS versions with different layouts | ||
| 1957 | * for the obvious ID strings. We look for the 2 most common ones and | ||
| 1958 | * hope that they cover all the cases... | ||
| 1959 | */ | ||
| 1960 | else if (probe_bios(bios_tab[bios], &s1, &switches)) { | ||
| 1961 | printk("Found IN2000 BIOS at 0x%x ", (unsigned int) bios_tab[bios]); | ||
| 1962 | |||
| 1963 | /* Find out where the IO space is */ | ||
| 1964 | |||
| 1965 | x = switches & (SW_ADDR0 | SW_ADDR1); | ||
| 1966 | base = base_tab[x]; | ||
| 1967 | |||
| 1968 | /* Check for the IN2000 signature in IO space. */ | ||
| 1969 | |||
| 1970 | x = ~inb(base + IO_SWITCHES) & 0xff; | ||
| 1971 | if (x != switches) { | ||
| 1972 | printk("Bad IO signature: %02x vs %02x.\n", x, switches); | ||
| 1973 | continue; | ||
| 1974 | } | ||
| 1975 | } else | ||
| 1976 | continue; | ||
| 1977 | |||
| 1978 | /* OK. We have a base address for the IO ports - run a few safety checks */ | ||
| 1979 | |||
| 1980 | if (!(switches & SW_BIT7)) { /* I _think_ all cards do this */ | ||
| 1981 | printk("There is no IN-2000 SCSI card at IOport 0x%03x!\n", base); | ||
| 1982 | continue; | ||
| 1983 | } | ||
| 1984 | |||
| 1985 | /* Let's assume any hardware version will work, although the driver | ||
| 1986 | * has only been tested on 0x21, 0x22, 0x25, 0x26, and 0x27. We'll | ||
| 1987 | * print out the rev number for reference later, but accept them all. | ||
| 1988 | */ | ||
| 1989 | |||
| 1990 | hrev = inb(base + IO_HARDWARE); | ||
| 1991 | |||
| 1992 | /* Bit 2 tells us if interrupts are disabled */ | ||
| 1993 | if (switches & SW_DISINT) { | ||
| 1994 | printk("The IN-2000 SCSI card at IOport 0x%03x ", base); | ||
| 1995 | printk("is not configured for interrupt operation!\n"); | ||
| 1996 | printk("This driver requires an interrupt: cancelling detection.\n"); | ||
| 1997 | continue; | ||
| 1998 | } | ||
| 1999 | |||
| 2000 | /* Ok. We accept that there's an IN2000 at ioaddr 'base'. Now | ||
| 2001 | * initialize it. | ||
| 2002 | */ | ||
| 2003 | |||
| 2004 | tpnt->proc_name = "in2000"; | ||
| 2005 | instance = scsi_register(tpnt, sizeof(struct IN2000_hostdata)); | ||
| 2006 | if (instance == NULL) | ||
| 2007 | continue; | ||
| 2008 | detect_count++; | ||
| 2009 | hostdata = (struct IN2000_hostdata *) instance->hostdata; | ||
| 2010 | instance->io_port = hostdata->io_base = base; | ||
| 2011 | hostdata->dip_switch = switches; | ||
| 2012 | hostdata->hrev = hrev; | ||
| 2013 | |||
| 2014 | write1_io(0, IO_FIFO_WRITE); /* clear fifo counter */ | ||
| 2015 | write1_io(0, IO_FIFO_READ); /* start fifo out in read mode */ | ||
| 2016 | write1_io(0, IO_INTR_MASK); /* allow all ints */ | ||
| 2017 | x = int_tab[(switches & (SW_INT0 | SW_INT1)) >> SW_INT_SHIFT]; | ||
| 2018 | if (request_irq(x, in2000_intr, 0, "in2000", instance)) { | ||
| 2019 | printk("in2000_detect: Unable to allocate IRQ.\n"); | ||
| 2020 | detect_count--; | ||
| 2021 | continue; | ||
| 2022 | } | ||
| 2023 | instance->irq = x; | ||
| 2024 | instance->n_io_port = 13; | ||
| 2025 | request_region(base, 13, "in2000"); /* lock in this IO space for our use */ | ||
| 2026 | |||
| 2027 | for (x = 0; x < 8; x++) { | ||
| 2028 | hostdata->busy[x] = 0; | ||
| 2029 | hostdata->sync_xfer[x] = calc_sync_xfer(DEFAULT_SX_PER / 4, DEFAULT_SX_OFF); | ||
| 2030 | hostdata->sync_stat[x] = SS_UNSET; /* using default sync values */ | ||
| 2031 | #ifdef PROC_STATISTICS | ||
| 2032 | hostdata->cmd_cnt[x] = 0; | ||
| 2033 | hostdata->disc_allowed_cnt[x] = 0; | ||
| 2034 | hostdata->disc_done_cnt[x] = 0; | ||
| 2035 | #endif | ||
| 2036 | } | ||
| 2037 | hostdata->input_Q = NULL; | ||
| 2038 | hostdata->selecting = NULL; | ||
| 2039 | hostdata->connected = NULL; | ||
| 2040 | hostdata->disconnected_Q = NULL; | ||
| 2041 | hostdata->state = S_UNCONNECTED; | ||
| 2042 | hostdata->fifo = FI_FIFO_UNUSED; | ||
| 2043 | hostdata->level2 = L2_BASIC; | ||
| 2044 | hostdata->disconnect = DIS_ADAPTIVE; | ||
| 2045 | hostdata->args = DEBUG_DEFAULTS; | ||
| 2046 | hostdata->incoming_ptr = 0; | ||
| 2047 | hostdata->outgoing_len = 0; | ||
| 2048 | hostdata->default_sx_per = DEFAULT_SX_PER; | ||
| 2049 | |||
| 2050 | /* Older BIOS's had a 'sync on/off' switch - use its setting */ | ||
| 2051 | |||
| 2052 | if (s1 == 0x41564f4e && (switches & SW_SYNC_DOS5)) | ||
| 2053 | hostdata->sync_off = 0x00; /* sync defaults to on */ | ||
| 2054 | else | ||
| 2055 | hostdata->sync_off = 0xff; /* sync defaults to off */ | ||
| 2056 | |||
| 2057 | #ifdef PROC_INTERFACE | ||
| 2058 | hostdata->proc = PR_VERSION | PR_INFO | PR_STATISTICS | PR_CONNECTED | PR_INPUTQ | PR_DISCQ | PR_STOP; | ||
| 2059 | #ifdef PROC_STATISTICS | ||
| 2060 | hostdata->int_cnt = 0; | ||
| 2061 | #endif | ||
| 2062 | #endif | ||
| 2063 | |||
| 2064 | if (check_setup_args("nosync", &val, buf)) | ||
| 2065 | hostdata->sync_off = val; | ||
| 2066 | |||
| 2067 | if (check_setup_args("period", &val, buf)) | ||
| 2068 | hostdata->default_sx_per = sx_table[round_period((unsigned int) val)].period_ns; | ||
| 2069 | |||
| 2070 | if (check_setup_args("disconnect", &val, buf)) { | ||
| 2071 | if ((val >= DIS_NEVER) && (val <= DIS_ALWAYS)) | ||
| 2072 | hostdata->disconnect = val; | ||
| 2073 | else | ||
| 2074 | hostdata->disconnect = DIS_ADAPTIVE; | ||
| 2075 | } | ||
| 2076 | |||
| 2077 | if (check_setup_args("noreset", &val, buf)) | ||
| 2078 | hostdata->args ^= A_NO_SCSI_RESET; | ||
| 2079 | |||
| 2080 | if (check_setup_args("level2", &val, buf)) | ||
| 2081 | hostdata->level2 = val; | ||
| 2082 | |||
| 2083 | if (check_setup_args("debug", &val, buf)) | ||
| 2084 | hostdata->args = (val & DB_MASK); | ||
| 2085 | |||
| 2086 | #ifdef PROC_INTERFACE | ||
| 2087 | if (check_setup_args("proc", &val, buf)) | ||
| 2088 | hostdata->proc = val; | ||
| 2089 | #endif | ||
| 2090 | |||
| 2091 | |||
| 2092 | /* FIXME: not strictly needed I think but the called code expects | ||
| 2093 | to be locked */ | ||
| 2094 | spin_lock_irqsave(instance->host_lock, flags); | ||
| 2095 | x = reset_hardware(instance, (hostdata->args & A_NO_SCSI_RESET) ? RESET_CARD : RESET_CARD_AND_BUS); | ||
| 2096 | spin_unlock_irqrestore(instance->host_lock, flags); | ||
| 2097 | |||
| 2098 | hostdata->microcode = read_3393(hostdata, WD_CDB_1); | ||
| 2099 | if (x & 0x01) { | ||
| 2100 | if (x & B_FLAG) | ||
| 2101 | hostdata->chip = C_WD33C93B; | ||
| 2102 | else | ||
| 2103 | hostdata->chip = C_WD33C93A; | ||
| 2104 | } else | ||
| 2105 | hostdata->chip = C_WD33C93; | ||
| 2106 | |||
| 2107 | printk("dip_switch=%02x irq=%d ioport=%02x floppy=%s sync/DOS5=%s ", (switches & 0x7f), instance->irq, hostdata->io_base, (switches & SW_FLOPPY) ? "Yes" : "No", (switches & SW_SYNC_DOS5) ? "Yes" : "No"); | ||
| 2108 | printk("hardware_ver=%02x chip=%s microcode=%02x\n", hrev, (hostdata->chip == C_WD33C93) ? "WD33c93" : (hostdata->chip == C_WD33C93A) ? "WD33c93A" : (hostdata->chip == C_WD33C93B) ? "WD33c93B" : "unknown", hostdata->microcode); | ||
| 2109 | #ifdef DEBUGGING_ON | ||
| 2110 | printk("setup_args = "); | ||
| 2111 | for (x = 0; x < MAX_SETUP_ARGS; x++) | ||
| 2112 | printk("%s,", setup_args[x]); | ||
| 2113 | printk("\n"); | ||
| 2114 | #endif | ||
| 2115 | if (hostdata->sync_off == 0xff) | ||
| 2116 | printk("Sync-transfer DISABLED on all devices: ENABLE from command-line\n"); | ||
| 2117 | printk("IN2000 driver version %s - %s\n", IN2000_VERSION, IN2000_DATE); | ||
| 2118 | } | ||
| 2119 | |||
| 2120 | return detect_count; | ||
| 2121 | } | ||
| 2122 | |||
| 2123 | static int in2000_release(struct Scsi_Host *shost) | ||
| 2124 | { | ||
| 2125 | if (shost->irq) | ||
| 2126 | free_irq(shost->irq, shost); | ||
| 2127 | if (shost->io_port && shost->n_io_port) | ||
| 2128 | release_region(shost->io_port, shost->n_io_port); | ||
| 2129 | return 0; | ||
| 2130 | } | ||
| 2131 | |||
| 2132 | /* NOTE: I lifted this function straight out of the old driver, | ||
| 2133 | * and have not tested it. Presumably it does what it's | ||
| 2134 | * supposed to do... | ||
| 2135 | */ | ||
| 2136 | |||
| 2137 | static int in2000_biosparam(struct scsi_device *sdev, struct block_device *bdev, sector_t capacity, int *iinfo) | ||
| 2138 | { | ||
| 2139 | int size; | ||
| 2140 | |||
| 2141 | size = capacity; | ||
| 2142 | iinfo[0] = 64; | ||
| 2143 | iinfo[1] = 32; | ||
| 2144 | iinfo[2] = size >> 11; | ||
| 2145 | |||
| 2146 | /* This should approximate the large drive handling that the DOS ASPI manager | ||
| 2147 | uses. Drives very near the boundaries may not be handled correctly (i.e. | ||
| 2148 | near 2.0 Gb and 4.0 Gb) */ | ||
| 2149 | |||
| 2150 | if (iinfo[2] > 1024) { | ||
| 2151 | iinfo[0] = 64; | ||
| 2152 | iinfo[1] = 63; | ||
| 2153 | iinfo[2] = (unsigned long) capacity / (iinfo[0] * iinfo[1]); | ||
| 2154 | } | ||
| 2155 | if (iinfo[2] > 1024) { | ||
| 2156 | iinfo[0] = 128; | ||
| 2157 | iinfo[1] = 63; | ||
| 2158 | iinfo[2] = (unsigned long) capacity / (iinfo[0] * iinfo[1]); | ||
| 2159 | } | ||
| 2160 | if (iinfo[2] > 1024) { | ||
| 2161 | iinfo[0] = 255; | ||
| 2162 | iinfo[1] = 63; | ||
| 2163 | iinfo[2] = (unsigned long) capacity / (iinfo[0] * iinfo[1]); | ||
| 2164 | } | ||
| 2165 | return 0; | ||
| 2166 | } | ||
| 2167 | |||
| 2168 | |||
| 2169 | static int in2000_write_info(struct Scsi_Host *instance, char *buf, int len) | ||
| 2170 | { | ||
| 2171 | |||
| 2172 | #ifdef PROC_INTERFACE | ||
| 2173 | |||
| 2174 | char *bp; | ||
| 2175 | struct IN2000_hostdata *hd; | ||
| 2176 | int x, i; | ||
| 2177 | |||
| 2178 | hd = (struct IN2000_hostdata *) instance->hostdata; | ||
| 2179 | |||
| 2180 | buf[len] = '\0'; | ||
| 2181 | bp = buf; | ||
| 2182 | if (!strncmp(bp, "debug:", 6)) { | ||
| 2183 | bp += 6; | ||
| 2184 | hd->args = simple_strtoul(bp, NULL, 0) & DB_MASK; | ||
| 2185 | } else if (!strncmp(bp, "disconnect:", 11)) { | ||
| 2186 | bp += 11; | ||
| 2187 | x = simple_strtoul(bp, NULL, 0); | ||
| 2188 | if (x < DIS_NEVER || x > DIS_ALWAYS) | ||
| 2189 | x = DIS_ADAPTIVE; | ||
| 2190 | hd->disconnect = x; | ||
| 2191 | } else if (!strncmp(bp, "period:", 7)) { | ||
| 2192 | bp += 7; | ||
| 2193 | x = simple_strtoul(bp, NULL, 0); | ||
| 2194 | hd->default_sx_per = sx_table[round_period((unsigned int) x)].period_ns; | ||
| 2195 | } else if (!strncmp(bp, "resync:", 7)) { | ||
| 2196 | bp += 7; | ||
| 2197 | x = simple_strtoul(bp, NULL, 0); | ||
| 2198 | for (i = 0; i < 7; i++) | ||
| 2199 | if (x & (1 << i)) | ||
| 2200 | hd->sync_stat[i] = SS_UNSET; | ||
| 2201 | } else if (!strncmp(bp, "proc:", 5)) { | ||
| 2202 | bp += 5; | ||
| 2203 | hd->proc = simple_strtoul(bp, NULL, 0); | ||
| 2204 | } else if (!strncmp(bp, "level2:", 7)) { | ||
| 2205 | bp += 7; | ||
| 2206 | hd->level2 = simple_strtoul(bp, NULL, 0); | ||
| 2207 | } | ||
| 2208 | #endif | ||
| 2209 | return len; | ||
| 2210 | } | ||
| 2211 | |||
| 2212 | static int in2000_show_info(struct seq_file *m, struct Scsi_Host *instance) | ||
| 2213 | { | ||
| 2214 | |||
| 2215 | #ifdef PROC_INTERFACE | ||
| 2216 | unsigned long flags; | ||
| 2217 | struct IN2000_hostdata *hd; | ||
| 2218 | Scsi_Cmnd *cmd; | ||
| 2219 | int x; | ||
| 2220 | |||
| 2221 | hd = (struct IN2000_hostdata *) instance->hostdata; | ||
| 2222 | |||
| 2223 | spin_lock_irqsave(instance->host_lock, flags); | ||
| 2224 | if (hd->proc & PR_VERSION) | ||
| 2225 | seq_printf(m, "\nVersion %s - %s.", IN2000_VERSION, IN2000_DATE); | ||
| 2226 | |||
| 2227 | if (hd->proc & PR_INFO) { | ||
| 2228 | seq_printf(m, "\ndip_switch=%02x: irq=%d io=%02x floppy=%s sync/DOS5=%s", (hd->dip_switch & 0x7f), instance->irq, hd->io_base, (hd->dip_switch & 0x40) ? "Yes" : "No", (hd->dip_switch & 0x20) ? "Yes" : "No"); | ||
| 2229 | seq_puts(m, "\nsync_xfer[] = "); | ||
| 2230 | for (x = 0; x < 7; x++) | ||
| 2231 | seq_printf(m, "\t%02x", hd->sync_xfer[x]); | ||
| 2232 | seq_puts(m, "\nsync_stat[] = "); | ||
| 2233 | for (x = 0; x < 7; x++) | ||
| 2234 | seq_printf(m, "\t%02x", hd->sync_stat[x]); | ||
| 2235 | } | ||
| 2236 | #ifdef PROC_STATISTICS | ||
| 2237 | if (hd->proc & PR_STATISTICS) { | ||
| 2238 | seq_puts(m, "\ncommands issued: "); | ||
| 2239 | for (x = 0; x < 7; x++) | ||
| 2240 | seq_printf(m, "\t%ld", hd->cmd_cnt[x]); | ||
| 2241 | seq_puts(m, "\ndisconnects allowed:"); | ||
| 2242 | for (x = 0; x < 7; x++) | ||
| 2243 | seq_printf(m, "\t%ld", hd->disc_allowed_cnt[x]); | ||
| 2244 | seq_puts(m, "\ndisconnects done: "); | ||
| 2245 | for (x = 0; x < 7; x++) | ||
| 2246 | seq_printf(m, "\t%ld", hd->disc_done_cnt[x]); | ||
| 2247 | seq_printf(m, "\ninterrupts: \t%ld", hd->int_cnt); | ||
| 2248 | } | ||
| 2249 | #endif | ||
| 2250 | if (hd->proc & PR_CONNECTED) { | ||
| 2251 | seq_puts(m, "\nconnected: "); | ||
| 2252 | if (hd->connected) { | ||
| 2253 | cmd = (Scsi_Cmnd *) hd->connected; | ||
| 2254 | seq_printf(m, " %d:%llu(%02x)", cmd->device->id, cmd->device->lun, cmd->cmnd[0]); | ||
| 2255 | } | ||
| 2256 | } | ||
| 2257 | if (hd->proc & PR_INPUTQ) { | ||
| 2258 | seq_puts(m, "\ninput_Q: "); | ||
| 2259 | cmd = (Scsi_Cmnd *) hd->input_Q; | ||
| 2260 | while (cmd) { | ||
| 2261 | seq_printf(m, " %d:%llu(%02x)", cmd->device->id, cmd->device->lun, cmd->cmnd[0]); | ||
| 2262 | cmd = (Scsi_Cmnd *) cmd->host_scribble; | ||
| 2263 | } | ||
| 2264 | } | ||
| 2265 | if (hd->proc & PR_DISCQ) { | ||
| 2266 | seq_puts(m, "\ndisconnected_Q:"); | ||
| 2267 | cmd = (Scsi_Cmnd *) hd->disconnected_Q; | ||
| 2268 | while (cmd) { | ||
| 2269 | seq_printf(m, " %d:%llu(%02x)", cmd->device->id, cmd->device->lun, cmd->cmnd[0]); | ||
| 2270 | cmd = (Scsi_Cmnd *) cmd->host_scribble; | ||
| 2271 | } | ||
| 2272 | } | ||
| 2273 | if (hd->proc & PR_TEST) { | ||
| 2274 | ; /* insert your own custom function here */ | ||
| 2275 | } | ||
| 2276 | seq_putc(m, '\n'); | ||
| 2277 | spin_unlock_irqrestore(instance->host_lock, flags); | ||
| 2278 | #endif /* PROC_INTERFACE */ | ||
| 2279 | return 0; | ||
| 2280 | } | ||
| 2281 | |||
| 2282 | MODULE_LICENSE("GPL"); | ||
| 2283 | |||
| 2284 | |||
| 2285 | static struct scsi_host_template driver_template = { | ||
| 2286 | .proc_name = "in2000", | ||
| 2287 | .write_info = in2000_write_info, | ||
| 2288 | .show_info = in2000_show_info, | ||
| 2289 | .name = "Always IN2000", | ||
| 2290 | .detect = in2000_detect, | ||
| 2291 | .release = in2000_release, | ||
| 2292 | .queuecommand = in2000_queuecommand, | ||
| 2293 | .eh_abort_handler = in2000_abort, | ||
| 2294 | .eh_bus_reset_handler = in2000_bus_reset, | ||
| 2295 | .bios_param = in2000_biosparam, | ||
| 2296 | .can_queue = IN2000_CAN_Q, | ||
| 2297 | .this_id = IN2000_HOST_ID, | ||
| 2298 | .sg_tablesize = IN2000_SG, | ||
| 2299 | .cmd_per_lun = IN2000_CPL, | ||
| 2300 | .use_clustering = DISABLE_CLUSTERING, | ||
| 2301 | }; | ||
| 2302 | #include "scsi_module.c" | ||
| @@ -1,412 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * in2000.h - Linux device driver definitions for the | ||
| 3 | * Always IN2000 ISA SCSI card. | ||
| 4 | * | ||
| 5 | * IMPORTANT: This file is for version 1.33 - 26/Aug/1998 | ||
| 6 | * | ||
| 7 | * Copyright (c) 1996 John Shifflett, GeoLog Consulting | ||
| 8 | * john@geolog.com | ||
| 9 | * jshiffle@netcom.com | ||
| 10 | * | ||
| 11 | * This program is free software; you can redistribute it and/or modify | ||
| 12 | * it under the terms of the GNU General Public License as published by | ||
| 13 | * the Free Software Foundation; either version 2, or (at your option) | ||
| 14 | * any later version. | ||
| 15 | * | ||
| 16 | * This program is distributed in the hope that it will be useful, | ||
| 17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 19 | * GNU General Public License for more details. | ||
| 20 | * | ||
| 21 | */ | ||
| 22 | |||
| 23 | #ifndef IN2000_H | ||
| 24 | #define IN2000_H | ||
| 25 | |||
| 26 | #include <asm/io.h> | ||
| 27 | |||
| 28 | #define PROC_INTERFACE /* add code for /proc/scsi/in2000/xxx interface */ | ||
| 29 | #ifdef PROC_INTERFACE | ||
| 30 | #define PROC_STATISTICS /* add code for keeping various real time stats */ | ||
| 31 | #endif | ||
| 32 | |||
| 33 | #define SYNC_DEBUG /* extra info on sync negotiation printed */ | ||
| 34 | #define DEBUGGING_ON /* enable command-line debugging bitmask */ | ||
| 35 | #define DEBUG_DEFAULTS 0 /* default bitmask - change from command-line */ | ||
| 36 | |||
| 37 | #ifdef __i386__ | ||
| 38 | #define FAST_READ_IO /* No problems with these on my machine */ | ||
| 39 | #define FAST_WRITE_IO | ||
| 40 | #endif | ||
| 41 | |||
| 42 | #ifdef DEBUGGING_ON | ||
| 43 | #define DB(f,a) if (hostdata->args & (f)) a; | ||
| 44 | #define CHECK_NULL(p,s) /* if (!(p)) {printk("\n"); while (1) printk("NP:%s\r",(s));} */ | ||
| 45 | #else | ||
| 46 | #define DB(f,a) | ||
| 47 | #define CHECK_NULL(p,s) | ||
| 48 | #endif | ||
| 49 | |||
| 50 | #define uchar unsigned char | ||
| 51 | |||
| 52 | #define read1_io(a) (inb(hostdata->io_base+(a))) | ||
| 53 | #define read2_io(a) (inw(hostdata->io_base+(a))) | ||
| 54 | #define write1_io(b,a) (outb((b),hostdata->io_base+(a))) | ||
| 55 | #define write2_io(w,a) (outw((w),hostdata->io_base+(a))) | ||
| 56 | |||
| 57 | #ifdef __i386__ | ||
| 58 | /* These inline assembly defines are derived from a patch | ||
| 59 | * sent to me by Bill Earnest. He's done a lot of very | ||
| 60 | * valuable thinking, testing, and coding during his effort | ||
| 61 | * to squeeze more speed out of this driver. I really think | ||
| 62 | * that we are doing IO at close to the maximum now with | ||
| 63 | * the fifo. (And yes, insw uses 'edi' while outsw uses | ||
| 64 | * 'esi'. Thanks Bill!) | ||
| 65 | */ | ||
| 66 | |||
| 67 | #define FAST_READ2_IO() \ | ||
| 68 | ({ \ | ||
| 69 | int __dummy_1,__dummy_2; \ | ||
| 70 | __asm__ __volatile__ ("\n \ | ||
| 71 | cld \n \ | ||
| 72 | orl %%ecx, %%ecx \n \ | ||
| 73 | jz 1f \n \ | ||
| 74 | rep \n \ | ||
| 75 | insw (%%dx),%%es:(%%edi) \n \ | ||
| 76 | 1: " \ | ||
| 77 | : "=D" (sp) ,"=c" (__dummy_1) ,"=d" (__dummy_2) /* output */ \ | ||
| 78 | : "2" (f), "0" (sp), "1" (i) /* input */ \ | ||
| 79 | ); /* trashed */ \ | ||
| 80 | }) | ||
| 81 | |||
| 82 | #define FAST_WRITE2_IO() \ | ||
| 83 | ({ \ | ||
| 84 | int __dummy_1,__dummy_2; \ | ||
| 85 | __asm__ __volatile__ ("\n \ | ||
| 86 | cld \n \ | ||
| 87 | orl %%ecx, %%ecx \n \ | ||
| 88 | jz 1f \n \ | ||
| 89 | rep \n \ | ||
| 90 | outsw %%ds:(%%esi),(%%dx) \n \ | ||
| 91 | 1: " \ | ||
| 92 | : "=S" (sp) ,"=c" (__dummy_1) ,"=d" (__dummy_2)/* output */ \ | ||
| 93 | : "2" (f), "0" (sp), "1" (i) /* input */ \ | ||
| 94 | ); /* trashed */ \ | ||
| 95 | }) | ||
| 96 | #endif | ||
| 97 | |||
| 98 | /* IN2000 io_port offsets */ | ||
| 99 | #define IO_WD_ASR 0x00 /* R - 3393 auxstat reg */ | ||
| 100 | #define ASR_INT 0x80 | ||
| 101 | #define ASR_LCI 0x40 | ||
| 102 | #define ASR_BSY 0x20 | ||
| 103 | #define ASR_CIP 0x10 | ||
| 104 | #define ASR_PE 0x02 | ||
| 105 | #define ASR_DBR 0x01 | ||
| 106 | #define IO_WD_ADDR 0x00 /* W - 3393 address reg */ | ||
| 107 | #define IO_WD_DATA 0x01 /* R/W - rest of 3393 regs */ | ||
| 108 | #define IO_FIFO 0x02 /* R/W - in2000 dual-port fifo (16 bits) */ | ||
| 109 | #define IN2000_FIFO_SIZE 2048 /* fifo capacity in bytes */ | ||
| 110 | #define IO_CARD_RESET 0x03 /* W - in2000 start master reset */ | ||
| 111 | #define IO_FIFO_COUNT 0x04 /* R - in2000 fifo counter */ | ||
| 112 | #define IO_FIFO_WRITE 0x05 /* W - clear fifo counter, start write */ | ||
| 113 | #define IO_FIFO_READ 0x07 /* W - start fifo read */ | ||
| 114 | #define IO_LED_OFF 0x08 /* W - turn off in2000 activity LED */ | ||
| 115 | #define IO_SWITCHES 0x08 /* R - read in2000 dip switch */ | ||
| 116 | #define SW_ADDR0 0x01 /* bit 0 = bit 0 of index to io addr */ | ||
| 117 | #define SW_ADDR1 0x02 /* bit 1 = bit 1 of index io addr */ | ||
| 118 | #define SW_DISINT 0x04 /* bit 2 true if ints disabled */ | ||
| 119 | #define SW_INT0 0x08 /* bit 3 = bit 0 of index to interrupt */ | ||
| 120 | #define SW_INT1 0x10 /* bit 4 = bit 1 of index to interrupt */ | ||
| 121 | #define SW_INT_SHIFT 3 /* shift right this amount to right justify int bits */ | ||
| 122 | #define SW_SYNC_DOS5 0x20 /* bit 5 used by Always BIOS */ | ||
| 123 | #define SW_FLOPPY 0x40 /* bit 6 true if floppy enabled */ | ||
| 124 | #define SW_BIT7 0x80 /* bit 7 hardwired true (ground) */ | ||
| 125 | #define IO_LED_ON 0x09 /* W - turn on in2000 activity LED */ | ||
| 126 | #define IO_HARDWARE 0x0a /* R - read in2000 hardware rev, stop reset */ | ||
| 127 | #define IO_INTR_MASK 0x0c /* W - in2000 interrupt mask reg */ | ||
| 128 | #define IMASK_WD 0x01 /* WD33c93 interrupt mask */ | ||
| 129 | #define IMASK_FIFO 0x02 /* FIFO interrupt mask */ | ||
| 130 | |||
| 131 | /* wd register names */ | ||
| 132 | #define WD_OWN_ID 0x00 | ||
| 133 | #define WD_CONTROL 0x01 | ||
| 134 | #define WD_TIMEOUT_PERIOD 0x02 | ||
| 135 | #define WD_CDB_1 0x03 | ||
| 136 | #define WD_CDB_2 0x04 | ||
| 137 | #define WD_CDB_3 0x05 | ||
| 138 | #define WD_CDB_4 0x06 | ||
| 139 | #define WD_CDB_5 0x07 | ||
| 140 | #define WD_CDB_6 0x08 | ||
| 141 | #define WD_CDB_7 0x09 | ||
| 142 | #define WD_CDB_8 0x0a | ||
| 143 | #define WD_CDB_9 0x0b | ||
| 144 | #define WD_CDB_10 0x0c | ||
| 145 | #define WD_CDB_11 0x0d | ||
| 146 | #define WD_CDB_12 0x0e | ||
| 147 | #define WD_TARGET_LUN 0x0f | ||
| 148 | #define WD_COMMAND_PHASE 0x10 | ||
| 149 | #define WD_SYNCHRONOUS_TRANSFER 0x11 | ||
| 150 | #define WD_TRANSFER_COUNT_MSB 0x12 | ||
| 151 | #define WD_TRANSFER_COUNT 0x13 | ||
| 152 | #define WD_TRANSFER_COUNT_LSB 0x14 | ||
| 153 | #define WD_DESTINATION_ID 0x15 | ||
| 154 | #define WD_SOURCE_ID 0x16 | ||
| 155 | #define WD_SCSI_STATUS 0x17 | ||
| 156 | #define WD_COMMAND 0x18 | ||
| 157 | #define WD_DATA 0x19 | ||
| 158 | #define WD_QUEUE_TAG 0x1a | ||
| 159 | #define WD_AUXILIARY_STATUS 0x1f | ||
| 160 | |||
| 161 | /* WD commands */ | ||
| 162 | #define WD_CMD_RESET 0x00 | ||
| 163 | #define WD_CMD_ABORT 0x01 | ||
| 164 | #define WD_CMD_ASSERT_ATN 0x02 | ||
| 165 | #define WD_CMD_NEGATE_ACK 0x03 | ||
| 166 | #define WD_CMD_DISCONNECT 0x04 | ||
| 167 | #define WD_CMD_RESELECT 0x05 | ||
| 168 | #define WD_CMD_SEL_ATN 0x06 | ||
| 169 | #define WD_CMD_SEL 0x07 | ||
| 170 | #define WD_CMD_SEL_ATN_XFER 0x08 | ||
| 171 | #define WD_CMD_SEL_XFER 0x09 | ||
| 172 | #define WD_CMD_RESEL_RECEIVE 0x0a | ||
| 173 | #define WD_CMD_RESEL_SEND 0x0b | ||
| 174 | #define WD_CMD_WAIT_SEL_RECEIVE 0x0c | ||
| 175 | #define WD_CMD_TRANS_ADDR 0x18 | ||
| 176 | #define WD_CMD_TRANS_INFO 0x20 | ||
| 177 | #define WD_CMD_TRANSFER_PAD 0x21 | ||
| 178 | #define WD_CMD_SBT_MODE 0x80 | ||
| 179 | |||
| 180 | /* SCSI Bus Phases */ | ||
| 181 | #define PHS_DATA_OUT 0x00 | ||
| 182 | #define PHS_DATA_IN 0x01 | ||
| 183 | #define PHS_COMMAND 0x02 | ||
| 184 | #define PHS_STATUS 0x03 | ||
| 185 | #define PHS_MESS_OUT 0x06 | ||
| 186 | #define PHS_MESS_IN 0x07 | ||
| 187 | |||
| 188 | /* Command Status Register definitions */ | ||
| 189 | |||
| 190 | /* reset state interrupts */ | ||
| 191 | #define CSR_RESET 0x00 | ||
| 192 | #define CSR_RESET_AF 0x01 | ||
| 193 | |||
| 194 | /* successful completion interrupts */ | ||
| 195 | #define CSR_RESELECT 0x10 | ||
| 196 | #define CSR_SELECT 0x11 | ||
| 197 | #define CSR_SEL_XFER_DONE 0x16 | ||
| 198 | #define CSR_XFER_DONE 0x18 | ||
| 199 | |||
| 200 | /* paused or aborted interrupts */ | ||
| 201 | #define CSR_MSGIN 0x20 | ||
| 202 | #define CSR_SDP 0x21 | ||
| 203 | #define CSR_SEL_ABORT 0x22 | ||
| 204 | #define CSR_RESEL_ABORT 0x25 | ||
| 205 | #define CSR_RESEL_ABORT_AM 0x27 | ||
| 206 | #define CSR_ABORT 0x28 | ||
| 207 | |||
| 208 | /* terminated interrupts */ | ||
| 209 | #define CSR_INVALID 0x40 | ||
| 210 | #define CSR_UNEXP_DISC 0x41 | ||
| 211 | #define CSR_TIMEOUT 0x42 | ||
| 212 | #define CSR_PARITY 0x43 | ||
| 213 | #define CSR_PARITY_ATN 0x44 | ||
| 214 | #define CSR_BAD_STATUS 0x45 | ||
| 215 | #define CSR_UNEXP 0x48 | ||
| 216 | |||
| 217 | /* service required interrupts */ | ||
| 218 | #define CSR_RESEL 0x80 | ||
| 219 | #define CSR_RESEL_AM 0x81 | ||
| 220 | #define CSR_DISC 0x85 | ||
| 221 | #define CSR_SRV_REQ 0x88 | ||
| 222 | |||
| 223 | /* Own ID/CDB Size register */ | ||
| 224 | #define OWNID_EAF 0x08 | ||
| 225 | #define OWNID_EHP 0x10 | ||
| 226 | #define OWNID_RAF 0x20 | ||
| 227 | #define OWNID_FS_8 0x00 | ||
| 228 | #define OWNID_FS_12 0x40 | ||
| 229 | #define OWNID_FS_16 0x80 | ||
| 230 | |||
| 231 | /* Control register */ | ||
| 232 | #define CTRL_HSP 0x01 | ||
| 233 | #define CTRL_HA 0x02 | ||
| 234 | #define CTRL_IDI 0x04 | ||
| 235 | #define CTRL_EDI 0x08 | ||
| 236 | #define CTRL_HHP 0x10 | ||
| 237 | #define CTRL_POLLED 0x00 | ||
| 238 | #define CTRL_BURST 0x20 | ||
| 239 | #define CTRL_BUS 0x40 | ||
| 240 | #define CTRL_DMA 0x80 | ||
| 241 | |||
| 242 | /* Timeout Period register */ | ||
| 243 | #define TIMEOUT_PERIOD_VALUE 20 /* results in 200 ms. */ | ||
| 244 | |||
| 245 | /* Synchronous Transfer Register */ | ||
| 246 | #define STR_FSS 0x80 | ||
| 247 | |||
| 248 | /* Destination ID register */ | ||
| 249 | #define DSTID_DPD 0x40 | ||
| 250 | #define DATA_OUT_DIR 0 | ||
| 251 | #define DATA_IN_DIR 1 | ||
| 252 | #define DSTID_SCC 0x80 | ||
| 253 | |||
| 254 | /* Source ID register */ | ||
| 255 | #define SRCID_MASK 0x07 | ||
| 256 | #define SRCID_SIV 0x08 | ||
| 257 | #define SRCID_DSP 0x20 | ||
| 258 | #define SRCID_ES 0x40 | ||
| 259 | #define SRCID_ER 0x80 | ||
| 260 | |||
| 261 | |||
| 262 | |||
| 263 | #define ILLEGAL_STATUS_BYTE 0xff | ||
| 264 | |||
| 265 | |||
| 266 | #define DEFAULT_SX_PER 500 /* (ns) fairly safe */ | ||
| 267 | #define DEFAULT_SX_OFF 0 /* aka async */ | ||
| 268 | |||
| 269 | #define OPTIMUM_SX_PER 252 /* (ns) best we can do (mult-of-4) */ | ||
| 270 | #define OPTIMUM_SX_OFF 12 /* size of in2000 fifo */ | ||
| 271 | |||
| 272 | struct sx_period { | ||
| 273 | unsigned int period_ns; | ||
| 274 | uchar reg_value; | ||
| 275 | }; | ||
| 276 | |||
| 277 | |||
| 278 | struct IN2000_hostdata { | ||
| 279 | struct Scsi_Host *next; | ||
| 280 | uchar chip; /* what kind of wd33c93 chip? */ | ||
| 281 | uchar microcode; /* microcode rev if 'B' */ | ||
| 282 | unsigned short io_base; /* IO port base */ | ||
| 283 | unsigned int dip_switch; /* dip switch settings */ | ||
| 284 | unsigned int hrev; /* hardware revision of card */ | ||
| 285 | volatile uchar busy[8]; /* index = target, bit = lun */ | ||
| 286 | volatile Scsi_Cmnd *input_Q; /* commands waiting to be started */ | ||
| 287 | volatile Scsi_Cmnd *selecting; /* trying to select this command */ | ||
| 288 | volatile Scsi_Cmnd *connected; /* currently connected command */ | ||
| 289 | volatile Scsi_Cmnd *disconnected_Q;/* commands waiting for reconnect */ | ||
| 290 | uchar state; /* what we are currently doing */ | ||
| 291 | uchar fifo; /* what the FIFO is up to */ | ||
| 292 | uchar level2; /* extent to which Level-2 commands are used */ | ||
| 293 | uchar disconnect; /* disconnect/reselect policy */ | ||
| 294 | unsigned int args; /* set from command-line argument */ | ||
| 295 | uchar incoming_msg[8]; /* filled during message_in phase */ | ||
| 296 | int incoming_ptr; /* mainly used with EXTENDED messages */ | ||
| 297 | uchar outgoing_msg[8]; /* send this during next message_out */ | ||
| 298 | int outgoing_len; /* length of outgoing message */ | ||
| 299 | unsigned int default_sx_per; /* default transfer period for SCSI bus */ | ||
| 300 | uchar sync_xfer[8]; /* sync_xfer reg settings per target */ | ||
| 301 | uchar sync_stat[8]; /* status of sync negotiation per target */ | ||
| 302 | uchar sync_off; /* bit mask: don't use sync with these targets */ | ||
| 303 | #ifdef PROC_INTERFACE | ||
| 304 | uchar proc; /* bit mask: what's in proc output */ | ||
| 305 | #ifdef PROC_STATISTICS | ||
| 306 | unsigned long cmd_cnt[8]; /* # of commands issued per target */ | ||
| 307 | unsigned long int_cnt; /* # of interrupts serviced */ | ||
| 308 | unsigned long disc_allowed_cnt[8]; /* # of disconnects allowed per target */ | ||
| 309 | unsigned long disc_done_cnt[8]; /* # of disconnects done per target*/ | ||
| 310 | #endif | ||
| 311 | #endif | ||
| 312 | }; | ||
| 313 | |||
| 314 | |||
| 315 | /* defines for hostdata->chip */ | ||
| 316 | |||
| 317 | #define C_WD33C93 0 | ||
| 318 | #define C_WD33C93A 1 | ||
| 319 | #define C_WD33C93B 2 | ||
| 320 | #define C_UNKNOWN_CHIP 100 | ||
| 321 | |||
| 322 | /* defines for hostdata->state */ | ||
| 323 | |||
| 324 | #define S_UNCONNECTED 0 | ||
| 325 | #define S_SELECTING 1 | ||
| 326 | #define S_RUNNING_LEVEL2 2 | ||
| 327 | #define S_CONNECTED 3 | ||
| 328 | #define S_PRE_TMP_DISC 4 | ||
| 329 | #define S_PRE_CMP_DISC 5 | ||
| 330 | |||
| 331 | /* defines for hostdata->fifo */ | ||
| 332 | |||
| 333 | #define FI_FIFO_UNUSED 0 | ||
| 334 | #define FI_FIFO_READING 1 | ||
| 335 | #define FI_FIFO_WRITING 2 | ||
| 336 | |||
| 337 | /* defines for hostdata->level2 */ | ||
| 338 | /* NOTE: only the first 3 are trustworthy at this point - | ||
| 339 | * having trouble when more than 1 device is reading/writing | ||
| 340 | * at the same time... | ||
| 341 | */ | ||
| 342 | |||
| 343 | #define L2_NONE 0 /* no combination commands - we get lots of ints */ | ||
| 344 | #define L2_SELECT 1 /* start with SEL_ATN_XFER, but never resume it */ | ||
| 345 | #define L2_BASIC 2 /* resume after STATUS ints & RDP messages */ | ||
| 346 | #define L2_DATA 3 /* resume after DATA_IN/OUT ints */ | ||
| 347 | #define L2_MOST 4 /* resume after anything except a RESELECT int */ | ||
| 348 | #define L2_RESELECT 5 /* resume after everything, including RESELECT ints */ | ||
| 349 | #define L2_ALL 6 /* always resume */ | ||
| 350 | |||
| 351 | /* defines for hostdata->disconnect */ | ||
| 352 | |||
| 353 | #define DIS_NEVER 0 | ||
| 354 | #define DIS_ADAPTIVE 1 | ||
| 355 | #define DIS_ALWAYS 2 | ||
| 356 | |||
| 357 | /* defines for hostdata->args */ | ||
| 358 | |||
| 359 | #define DB_TEST 1<<0 | ||
| 360 | #define DB_FIFO 1<<1 | ||
| 361 | #define DB_QUEUE_COMMAND 1<<2 | ||
| 362 | #define DB_EXECUTE 1<<3 | ||
| 363 | #define DB_INTR 1<<4 | ||
| 364 | #define DB_TRANSFER 1<<5 | ||
| 365 | #define DB_MASK 0x3f | ||
| 366 | |||
| 367 | #define A_NO_SCSI_RESET 1<<15 | ||
| 368 | |||
| 369 | |||
| 370 | /* defines for hostdata->sync_xfer[] */ | ||
| 371 | |||
| 372 | #define SS_UNSET 0 | ||
| 373 | #define SS_FIRST 1 | ||
| 374 | #define SS_WAITING 2 | ||
| 375 | #define SS_SET 3 | ||
| 376 | |||
| 377 | /* defines for hostdata->proc */ | ||
| 378 | |||
| 379 | #define PR_VERSION 1<<0 | ||
| 380 | #define PR_INFO 1<<1 | ||
| 381 | #define PR_STATISTICS 1<<2 | ||
| 382 | #define PR_CONNECTED 1<<3 | ||
| 383 | #define PR_INPUTQ 1<<4 | ||
| 384 | #define PR_DISCQ 1<<5 | ||
| 385 | #define PR_TEST 1<<6 | ||
| 386 | #define PR_STOP 1<<7 | ||
| 387 | |||
| 388 | |||
| 389 | # include <linux/init.h> | ||
| 390 | # include <linux/spinlock.h> | ||
| 391 | # define in2000__INITFUNC(function) __initfunc(function) | ||
| 392 | # define in2000__INIT __init | ||
| 393 | # define in2000__INITDATA __initdata | ||
| 394 | # define CLISPIN_LOCK(host,flags) spin_lock_irqsave(host->host_lock, flags) | ||
| 395 | # define CLISPIN_UNLOCK(host,flags) spin_unlock_irqrestore(host->host_lock, \ | ||
| 396 | flags) | ||
| 397 | |||
| 398 | static int in2000_detect(struct scsi_host_template *) in2000__INIT; | ||
| 399 | static int in2000_queuecommand(struct Scsi_Host *, struct scsi_cmnd *); | ||
| 400 | static int in2000_abort(Scsi_Cmnd *); | ||
| 401 | static void in2000_setup(char *, int *) in2000__INIT; | ||
| 402 | static int in2000_biosparam(struct scsi_device *, struct block_device *, | ||
| 403 | sector_t, int *); | ||
| 404 | static int in2000_bus_reset(Scsi_Cmnd *); | ||
| 405 | |||
| 406 | |||
| 407 | #define IN2000_CAN_Q 16 | ||
| 408 | #define IN2000_SG SG_ALL | ||
| 409 | #define IN2000_CPL 2 | ||
| 410 | #define IN2000_HOST_ID 7 | ||
| 411 | |||
| 412 | #endif /* IN2000_H */ | ||
| @@ -493,15 +493,15 @@ struct ipr_error_table_t ipr_error_table[] = { · 492 unmodified lines | |||
| 493 | "9072: Link not operational transition"}, | 493 | "9072: Link not operational transition"}, |
| 494 | {0x066B8200, 0, IPR_DEFAULT_LOG_LEVEL, | 494 | {0x066B8200, 0, IPR_DEFAULT_LOG_LEVEL, |
| 495 | "9032: Array exposed but still protected"}, | 495 | "9032: Array exposed but still protected"}, |
| 496 | {0x066B8300, 0, IPR_DEFAULT_LOG_LEVEL + 1, | 496 | {0x066B8300, 0, IPR_DEBUG_LOG_LEVEL, |
| 497 | "70DD: Device forced failed by disrupt device command"}, | 497 | "70DD: Device forced failed by disrupt device command"}, |
| 498 | {0x066B9100, 0, IPR_DEFAULT_LOG_LEVEL, | 498 | {0x066B9100, 0, IPR_DEFAULT_LOG_LEVEL, |
| 499 | "4061: Multipath redundancy level got better"}, | 499 | "4061: Multipath redundancy level got better"}, |
| 500 | {0x066B9200, 0, IPR_DEFAULT_LOG_LEVEL, | 500 | {0x066B9200, 0, IPR_DEFAULT_LOG_LEVEL, |
| 501 | "4060: Multipath redundancy level got worse"}, | 501 | "4060: Multipath redundancy level got worse"}, |
| 502 | {0x06808100, 0, IPR_DEFAULT_LOG_LEVEL, | 502 | {0x06808100, 0, IPR_DEBUG_LOG_LEVEL, |
| 503 | "9083: Device raw mode enabled"}, | 503 | "9083: Device raw mode enabled"}, |
| 504 | {0x06808200, 0, IPR_DEFAULT_LOG_LEVEL, | 504 | {0x06808200, 0, IPR_DEBUG_LOG_LEVEL, |
| 505 | "9084: Device raw mode disabled"}, | 505 | "9084: Device raw mode disabled"}, |
| 506 | {0x07270000, 0, 0, | 506 | {0x07270000, 0, 0, |
| 507 | "Failure due to other device"}, | 507 | "Failure due to other device"}, |
| @@ -1473,7 +1473,7 @@ static void ipr_process_ccn(struct ipr_cmnd *ipr_cmd) · 965 unmodified lines | |||
| 1473 | struct ipr_hostrcb *hostrcb = ipr_cmd->u.hostrcb; | 1473 | struct ipr_hostrcb *hostrcb = ipr_cmd->u.hostrcb; |
| 1474 | u32 ioasc = be32_to_cpu(ipr_cmd->s.ioasa.hdr.ioasc); | 1474 | u32 ioasc = be32_to_cpu(ipr_cmd->s.ioasa.hdr.ioasc); |
| 1475 | 1475 | ||
| 1476 | list_del(&hostrcb->queue); | 1476 | list_del_init(&hostrcb->queue); |
| 1477 | list_add_tail(&ipr_cmd->queue, &ipr_cmd->hrrq->hrrq_free_q); | 1477 | list_add_tail(&ipr_cmd->queue, &ipr_cmd->hrrq->hrrq_free_q); |
| 1478 | 1478 | ||
| 1479 | if (ioasc) { | 1479 | if (ioasc) { |
| @@ -2552,6 +2552,23 @@ static void ipr_handle_log_data(struct ipr_ioa_cfg *ioa_cfg, · 1072 unmodified lines | |||
| 2552 | } | 2552 | } |
| 2553 | } | 2553 | } |
| 2554 | 2554 | ||
| 2555 | static struct ipr_hostrcb *ipr_get_free_hostrcb(struct ipr_ioa_cfg *ioa) | ||
| 2556 | { | ||
| 2557 | struct ipr_hostrcb *hostrcb; | ||
| 2558 | |||
| 2559 | hostrcb = list_first_entry_or_null(&ioa->hostrcb_free_q, | ||
| 2560 | struct ipr_hostrcb, queue); | ||
| 2561 | |||
| 2562 | if (unlikely(!hostrcb)) { | ||
| 2563 | dev_info(&ioa->pdev->dev, "Reclaiming async error buffers."); | ||
| 2564 | hostrcb = list_first_entry_or_null(&ioa->hostrcb_report_q, | ||
| 2565 | struct ipr_hostrcb, queue); | ||
| 2566 | } | ||
| 2567 | |||
| 2568 | list_del_init(&hostrcb->queue); | ||
| 2569 | return hostrcb; | ||
| 2570 | } | ||
| 2571 | |||
| 2555 | /** | 2572 | /** |
| 2556 | * ipr_process_error - Op done function for an adapter error log. | 2573 | * ipr_process_error - Op done function for an adapter error log. |
| 2557 | * @ipr_cmd: ipr command struct | 2574 | * @ipr_cmd: ipr command struct |
| @@ -2569,13 +2586,14 @@ static void ipr_process_error(struct ipr_cmnd *ipr_cmd) · 11 unmodified lines | |||
| 2569 | struct ipr_hostrcb *hostrcb = ipr_cmd->u.hostrcb; | 2586 | struct ipr_hostrcb *hostrcb = ipr_cmd->u.hostrcb; |
| 2570 | u32 ioasc = be32_to_cpu(ipr_cmd->s.ioasa.hdr.ioasc); | 2587 | u32 ioasc = be32_to_cpu(ipr_cmd->s.ioasa.hdr.ioasc); |
| 2571 | u32 fd_ioasc; | 2588 | u32 fd_ioasc; |
| 2589 | char *envp[] = { "ASYNC_ERR_LOG=1", NULL }; | ||
| 2572 | 2590 | ||
| 2573 | if (ioa_cfg->sis64) | 2591 | if (ioa_cfg->sis64) |
| 2574 | fd_ioasc = be32_to_cpu(hostrcb->hcam.u.error64.fd_ioasc); | 2592 | fd_ioasc = be32_to_cpu(hostrcb->hcam.u.error64.fd_ioasc); |
| 2575 | else | 2593 | else |
| 2576 | fd_ioasc = be32_to_cpu(hostrcb->hcam.u.error.fd_ioasc); | 2594 | fd_ioasc = be32_to_cpu(hostrcb->hcam.u.error.fd_ioasc); |
| 2577 | 2595 | ||
| 2578 | list_del(&hostrcb->queue); | 2596 | list_del_init(&hostrcb->queue); |
| 2579 | list_add_tail(&ipr_cmd->queue, &ipr_cmd->hrrq->hrrq_free_q); | 2597 | list_add_tail(&ipr_cmd->queue, &ipr_cmd->hrrq->hrrq_free_q); |
| 2580 | 2598 | ||
| 2581 | if (!ioasc) { | 2599 | if (!ioasc) { |
| @@ -2588,6 +2606,10 @@ static void ipr_process_error(struct ipr_cmnd *ipr_cmd) · 6 unmodified lines | |||
| 2588 | "Host RCB failed with IOASC: 0x%08X\n", ioasc); | 2606 | "Host RCB failed with IOASC: 0x%08X\n", ioasc); |
| 2589 | } | 2607 | } |
| 2590 | 2608 | ||
| 2609 | list_add_tail(&hostrcb->queue, &ioa_cfg->hostrcb_report_q); | ||
| 2610 | hostrcb = ipr_get_free_hostrcb(ioa_cfg); | ||
| 2611 | kobject_uevent_env(&ioa_cfg->host->shost_dev.kobj, KOBJ_CHANGE, envp); | ||
| 2612 | |||
| 2591 | ipr_send_hcam(ioa_cfg, IPR_HCAM_CDB_OP_CODE_LOG_DATA, hostrcb); | 2613 | ipr_send_hcam(ioa_cfg, IPR_HCAM_CDB_OP_CODE_LOG_DATA, hostrcb); |
| 2592 | } | 2614 | } |
| 2593 | 2615 | ||
| @@ -4095,6 +4117,64 @@ static struct device_attribute ipr_ioa_fw_type_attr = { · 1501 unmodified lines | |||
| 4095 | .show = ipr_show_fw_type | 4117 | .show = ipr_show_fw_type |
| 4096 | }; | 4118 | }; |
| 4097 | 4119 | ||
| 4120 | static ssize_t ipr_read_async_err_log(struct file *filep, struct kobject *kobj, | ||
| 4121 | struct bin_attribute *bin_attr, char *buf, | ||
| 4122 | loff_t off, size_t count) | ||
| 4123 | { | ||
| 4124 | struct device *cdev = container_of(kobj, struct device, kobj); | ||
| 4125 | struct Scsi_Host *shost = class_to_shost(cdev); | ||
| 4126 | struct ipr_ioa_cfg *ioa_cfg = (struct ipr_ioa_cfg *)shost->hostdata; | ||
| 4127 | struct ipr_hostrcb *hostrcb; | ||
| 4128 | unsigned long lock_flags = 0; | ||
| 4129 | int ret; | ||
| 4130 | |||
| 4131 | spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags); | ||
| 4132 | hostrcb = list_first_entry_or_null(&ioa_cfg->hostrcb_report_q, | ||
| 4133 | struct ipr_hostrcb, queue); | ||
| 4134 | if (!hostrcb) { | ||
| 4135 | spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags); | ||
| 4136 | return 0; | ||
| 4137 | } | ||
| 4138 | ret = memory_read_from_buffer(buf, count, &off, &hostrcb->hcam, | ||
| 4139 | sizeof(hostrcb->hcam)); | ||
| 4140 | spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags); | ||
| 4141 | return ret; | ||
| 4142 | } | ||
| 4143 | |||
| 4144 | static ssize_t ipr_next_async_err_log(struct file *filep, struct kobject *kobj, | ||
| 4145 | struct bin_attribute *bin_attr, char *buf, | ||
| 4146 | loff_t off, size_t count) | ||
| 4147 | { | ||
| 4148 | struct device *cdev = container_of(kobj, struct device, kobj); | ||
| 4149 | struct Scsi_Host *shost = class_to_shost(cdev); | ||
| 4150 | struct ipr_ioa_cfg *ioa_cfg = (struct ipr_ioa_cfg *)shost->hostdata; | ||
| 4151 | struct ipr_hostrcb *hostrcb; | ||
| 4152 | unsigned long lock_flags = 0; | ||
| 4153 | |||
| 4154 | spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags); | ||
| 4155 | hostrcb = list_first_entry_or_null(&ioa_cfg->hostrcb_report_q, | ||
| 4156 | struct ipr_hostrcb, queue); | ||
| 4157 | if (!hostrcb) { | ||
| 4158 | spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags); | ||
| 4159 | return count; | ||
| 4160 | } | ||
| 4161 | |||
| 4162 | /* Reclaim hostrcb before exit */ | ||
| 4163 | list_move_tail(&hostrcb->queue, &ioa_cfg->hostrcb_free_q); | ||
| 4164 | spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags); | ||
| 4165 | return count; | ||
| 4166 | } | ||
| 4167 | |||
| 4168 | static struct bin_attribute ipr_ioa_async_err_log = { | ||
| 4169 | .attr = { | ||
| 4170 | .name = "async_err_log", | ||
| 4171 | .mode = S_IRUGO | S_IWUSR, | ||
| 4172 | }, | ||
| 4173 | .size = 0, | ||
| 4174 | .read = ipr_read_async_err_log, | ||
| 4175 | .write = ipr_next_async_err_log | ||
| 4176 | }; | ||
| 4177 | |||
| 4098 | static struct device_attribute *ipr_ioa_attrs[] = { | 4178 | static struct device_attribute *ipr_ioa_attrs[] = { |
| 4099 | &ipr_fw_version_attr, | 4179 | &ipr_fw_version_attr, |
| 4100 | &ipr_log_level_attr, | 4180 | &ipr_log_level_attr, |
| @@ -7026,8 +7106,7 @@ static int ipr_ioa_reset_done(struct ipr_cmnd *ipr_cmd) · 2925 unmodified lines | |||
| 7026 | { | 7106 | { |
| 7027 | struct ipr_ioa_cfg *ioa_cfg = ipr_cmd->ioa_cfg; | 7107 | struct ipr_ioa_cfg *ioa_cfg = ipr_cmd->ioa_cfg; |
| 7028 | struct ipr_resource_entry *res; | 7108 | struct ipr_resource_entry *res; |
| 7029 | struct ipr_hostrcb *hostrcb, *temp; | 7109 | int j; |
| 7030 | int i = 0, j; | ||
| 7031 | 7110 | ||
| 7032 | ENTER; | 7111 | ENTER; |
| 7033 | ioa_cfg->in_reset_reload = 0; | 7112 | ioa_cfg->in_reset_reload = 0; |
| @@ -7048,12 +7127,16 @@ static int ipr_ioa_reset_done(struct ipr_cmnd *ipr_cmd) · 14 unmodified lines | |||
| 7048 | } | 7127 | } |
| 7049 | schedule_work(&ioa_cfg->work_q); | 7128 | schedule_work(&ioa_cfg->work_q); |
| 7050 | 7129 | ||
| 7051 | list_for_each_entry_safe(hostrcb, temp, &ioa_cfg->hostrcb_free_q, queue) { | 7130 | for (j = 0; j < IPR_NUM_HCAMS; j++) { |
| 7052 | list_del(&hostrcb->queue); | 7131 | list_del_init(&ioa_cfg->hostrcb[j]->queue); |
| 7053 | if (i++ < IPR_NUM_LOG_HCAMS) | 7132 | if (j < IPR_NUM_LOG_HCAMS) |
| 7054 | ipr_send_hcam(ioa_cfg, IPR_HCAM_CDB_OP_CODE_LOG_DATA, hostrcb); | 7133 | ipr_send_hcam(ioa_cfg, |
| 7134 | IPR_HCAM_CDB_OP_CODE_LOG_DATA, | ||
| 7135 | ioa_cfg->hostrcb[j]); | ||
| 7055 | else | 7136 | else |
| 7056 | ipr_send_hcam(ioa_cfg, IPR_HCAM_CDB_OP_CODE_CONFIG_CHANGE, hostrcb); | 7137 | ipr_send_hcam(ioa_cfg, |
| 7138 | IPR_HCAM_CDB_OP_CODE_CONFIG_CHANGE, | ||
| 7139 | ioa_cfg->hostrcb[j]); | ||
| 7057 | } | 7140 | } |
| 7058 | 7141 | ||
| 7059 | scsi_report_bus_reset(ioa_cfg->host, IPR_VSET_BUS); | 7142 | scsi_report_bus_reset(ioa_cfg->host, IPR_VSET_BUS); |
| @@ -7966,7 +8049,8 @@ static int ipr_ioafp_identify_hrrq(struct ipr_cmnd *ipr_cmd) · 906 unmodified lines | |||
| 7966 | 8049 | ||
| 7967 | ENTER; | 8050 | ENTER; |
| 7968 | ipr_cmd->job_step = ipr_ioafp_std_inquiry; | 8051 | ipr_cmd->job_step = ipr_ioafp_std_inquiry; |
| 7969 | dev_info(&ioa_cfg->pdev->dev, "Starting IOA initialization sequence.\n"); | 8052 | if (ioa_cfg->identify_hrrq_index == 0) |
| 8053 | dev_info(&ioa_cfg->pdev->dev, "Starting IOA initialization sequence.\n"); | ||
| 7970 | 8054 | ||
| 7971 | if (ioa_cfg->identify_hrrq_index < ioa_cfg->hrrq_num) { | 8055 | if (ioa_cfg->identify_hrrq_index < ioa_cfg->hrrq_num) { |
| 7972 | hrrq = &ioa_cfg->hrrq[ioa_cfg->identify_hrrq_index]; | 8056 | hrrq = &ioa_cfg->hrrq[ioa_cfg->identify_hrrq_index]; |
| @@ -8335,7 +8419,7 @@ static void ipr_get_unit_check_buffer(struct ipr_ioa_cfg *ioa_cfg) · 362 unmodified lines | |||
| 8335 | 8419 | ||
| 8336 | hostrcb = list_entry(ioa_cfg->hostrcb_free_q.next, | 8420 | hostrcb = list_entry(ioa_cfg->hostrcb_free_q.next, |
| 8337 | struct ipr_hostrcb, queue); | 8421 | struct ipr_hostrcb, queue); |
| 8338 | list_del(&hostrcb->queue); | 8422 | list_del_init(&hostrcb->queue); |
| 8339 | memset(&hostrcb->hcam, 0, sizeof(hostrcb->hcam)); | 8423 | memset(&hostrcb->hcam, 0, sizeof(hostrcb->hcam)); |
| 8340 | 8424 | ||
| 8341 | rc = ipr_get_ldump_data_section(ioa_cfg, | 8425 | rc = ipr_get_ldump_data_section(ioa_cfg, |
| @@ -9332,7 +9416,7 @@ static void ipr_free_mem(struct ipr_ioa_cfg *ioa_cfg) · 990 unmodified lines | |||
| 9332 | dma_free_coherent(&ioa_cfg->pdev->dev, ioa_cfg->cfg_table_size, | 9416 | dma_free_coherent(&ioa_cfg->pdev->dev, ioa_cfg->cfg_table_size, |
| 9333 | ioa_cfg->u.cfg_table, ioa_cfg->cfg_table_dma); | 9417 | ioa_cfg->u.cfg_table, ioa_cfg->cfg_table_dma); |
| 9334 | 9418 | ||
| 9335 | for (i = 0; i < IPR_NUM_HCAMS; i++) { | 9419 | for (i = 0; i < IPR_MAX_HCAMS; i++) { |
| 9336 | dma_free_coherent(&ioa_cfg->pdev->dev, | 9420 | dma_free_coherent(&ioa_cfg->pdev->dev, |
| 9337 | sizeof(struct ipr_hostrcb), | 9421 | sizeof(struct ipr_hostrcb), |
| 9338 | ioa_cfg->hostrcb[i], | 9422 | ioa_cfg->hostrcb[i], |
| @@ -9572,7 +9656,7 @@ static int ipr_alloc_mem(struct ipr_ioa_cfg *ioa_cfg) · 233 unmodified lines | |||
| 9572 | if (!ioa_cfg->u.cfg_table) | 9656 | if (!ioa_cfg->u.cfg_table) |
| 9573 | goto out_free_host_rrq; | 9657 | goto out_free_host_rrq; |
| 9574 | 9658 | ||
| 9575 | for (i = 0; i < IPR_NUM_HCAMS; i++) { | 9659 | for (i = 0; i < IPR_MAX_HCAMS; i++) { |
| 9576 | ioa_cfg->hostrcb[i] = dma_alloc_coherent(&pdev->dev, | 9660 | ioa_cfg->hostrcb[i] = dma_alloc_coherent(&pdev->dev, |
| 9577 | sizeof(struct ipr_hostrcb), | 9661 | sizeof(struct ipr_hostrcb), |
| 9578 | &ioa_cfg->hostrcb_dma[i], | 9662 | &ioa_cfg->hostrcb_dma[i], |
| @@ -9714,6 +9798,7 @@ static void ipr_init_ioa_cfg(struct ipr_ioa_cfg *ioa_cfg, · 135 unmodified lines | |||
| 9714 | 9798 | ||
| 9715 | INIT_LIST_HEAD(&ioa_cfg->hostrcb_free_q); | 9799 | INIT_LIST_HEAD(&ioa_cfg->hostrcb_free_q); |
| 9716 | INIT_LIST_HEAD(&ioa_cfg->hostrcb_pending_q); | 9800 | INIT_LIST_HEAD(&ioa_cfg->hostrcb_pending_q); |
| 9801 | INIT_LIST_HEAD(&ioa_cfg->hostrcb_report_q); | ||
| 9717 | INIT_LIST_HEAD(&ioa_cfg->free_res_q); | 9802 | INIT_LIST_HEAD(&ioa_cfg->free_res_q); |
| 9718 | INIT_LIST_HEAD(&ioa_cfg->used_res_q); | 9803 | INIT_LIST_HEAD(&ioa_cfg->used_res_q); |
| 9719 | INIT_WORK(&ioa_cfg->work_q, ipr_worker_thread); | 9804 | INIT_WORK(&ioa_cfg->work_q, ipr_worker_thread); |
| @@ -10352,6 +10437,8 @@ static void ipr_remove(struct pci_dev *pdev) · 632 unmodified lines | |||
| 10352 | &ipr_trace_attr); | 10437 | &ipr_trace_attr); |
| 10353 | ipr_remove_dump_file(&ioa_cfg->host->shost_dev.kobj, | 10438 | ipr_remove_dump_file(&ioa_cfg->host->shost_dev.kobj, |
| 10354 | &ipr_dump_attr); | 10439 | &ipr_dump_attr); |
| 10440 | sysfs_remove_bin_file(&ioa_cfg->host->shost_dev.kobj, | ||
| 10441 | &ipr_ioa_async_err_log); | ||
| 10355 | scsi_remove_host(ioa_cfg->host); | 10442 | scsi_remove_host(ioa_cfg->host); |
| 10356 | 10443 | ||
| 10357 | __ipr_remove(pdev); | 10444 | __ipr_remove(pdev); |
| @@ -10400,10 +10487,25 @@ static int ipr_probe(struct pci_dev *pdev, const struct pci_device_id *dev_id) · 42 unmodified lines | |||
| 10400 | return rc; | 10487 | return rc; |
| 10401 | } | 10488 | } |
| 10402 | 10489 | ||
| 10490 | rc = sysfs_create_bin_file(&ioa_cfg->host->shost_dev.kobj, | ||
| 10491 | &ipr_ioa_async_err_log); | ||
| 10492 | |||
| 10493 | if (rc) { | ||
| 10494 | ipr_remove_dump_file(&ioa_cfg->host->shost_dev.kobj, | ||
| 10495 | &ipr_dump_attr); | ||
| 10496 | ipr_remove_trace_file(&ioa_cfg->host->shost_dev.kobj, | ||
| 10497 | &ipr_trace_attr); | ||
| 10498 | scsi_remove_host(ioa_cfg->host); | ||
| 10499 | __ipr_remove(pdev); | ||
| 10500 | return rc; | ||
| 10501 | } | ||
| 10502 | |||
| 10403 | rc = ipr_create_dump_file(&ioa_cfg->host->shost_dev.kobj, | 10503 | rc = ipr_create_dump_file(&ioa_cfg->host->shost_dev.kobj, |
| 10404 | &ipr_dump_attr); | 10504 | &ipr_dump_attr); |
| 10405 | 10505 | ||
| 10406 | if (rc) { | 10506 | if (rc) { |
| 10507 | sysfs_remove_bin_file(&ioa_cfg->host->shost_dev.kobj, | ||
| 10508 | &ipr_ioa_async_err_log); | ||
| 10407 | ipr_remove_trace_file(&ioa_cfg->host->shost_dev.kobj, | 10509 | ipr_remove_trace_file(&ioa_cfg->host->shost_dev.kobj, |
| 10408 | &ipr_trace_attr); | 10510 | &ipr_trace_attr); |
| 10409 | scsi_remove_host(ioa_cfg->host); | 10511 | scsi_remove_host(ioa_cfg->host); |
| @@ -154,7 +154,9 @@ · 153 unmodified lines | |||
| 154 | #define IPR_DEFAULT_MAX_ERROR_DUMP 984 | 154 | #define IPR_DEFAULT_MAX_ERROR_DUMP 984 |
| 155 | #define IPR_NUM_LOG_HCAMS 2 | 155 | #define IPR_NUM_LOG_HCAMS 2 |
| 156 | #define IPR_NUM_CFG_CHG_HCAMS 2 | 156 | #define IPR_NUM_CFG_CHG_HCAMS 2 |
| 157 | #define IPR_NUM_HCAM_QUEUE 12 | ||
| 157 | #define IPR_NUM_HCAMS (IPR_NUM_LOG_HCAMS + IPR_NUM_CFG_CHG_HCAMS) | 158 | #define IPR_NUM_HCAMS (IPR_NUM_LOG_HCAMS + IPR_NUM_CFG_CHG_HCAMS) |
| 159 | #define IPR_MAX_HCAMS (IPR_NUM_HCAMS + IPR_NUM_HCAM_QUEUE) | ||
| 158 | 160 | ||
| 159 | #define IPR_MAX_SIS64_TARGETS_PER_BUS 1024 | 161 | #define IPR_MAX_SIS64_TARGETS_PER_BUS 1024 |
| 160 | #define IPR_MAX_SIS64_LUNS_PER_TARGET 0xffffffff | 162 | #define IPR_MAX_SIS64_LUNS_PER_TARGET 0xffffffff |
| @@ -1504,6 +1506,7 @@ struct ipr_ioa_cfg { · 1343 unmodified lines | |||
| 1504 | u8 log_level; | 1506 | u8 log_level; |
| 1505 | #define IPR_MAX_LOG_LEVEL 4 | 1507 | #define IPR_MAX_LOG_LEVEL 4 |
| 1506 | #define IPR_DEFAULT_LOG_LEVEL 2 | 1508 | #define IPR_DEFAULT_LOG_LEVEL 2 |
| 1509 | #define IPR_DEBUG_LOG_LEVEL 3 | ||
| 1507 | 1510 | ||
| 1508 | #define IPR_NUM_TRACE_INDEX_BITS 8 | 1511 | #define IPR_NUM_TRACE_INDEX_BITS 8 |
| 1509 | #define IPR_NUM_TRACE_ENTRIES (1 << IPR_NUM_TRACE_INDEX_BITS) | 1512 | #define IPR_NUM_TRACE_ENTRIES (1 << IPR_NUM_TRACE_INDEX_BITS) |
| @@ -1532,10 +1535,11 @@ struct ipr_ioa_cfg { · 22 unmodified lines | |||
| 1532 | 1535 | ||
| 1533 | char ipr_hcam_label[8]; | 1536 | char ipr_hcam_label[8]; |
| 1534 | #define IPR_HCAM_LABEL "hcams" | 1537 | #define IPR_HCAM_LABEL "hcams" |
| 1535 | struct ipr_hostrcb *hostrcb[IPR_NUM_HCAMS]; | 1538 | struct ipr_hostrcb *hostrcb[IPR_MAX_HCAMS]; |
| 1536 | dma_addr_t hostrcb_dma[IPR_NUM_HCAMS]; | 1539 | dma_addr_t hostrcb_dma[IPR_MAX_HCAMS]; |
| 1537 | struct list_head hostrcb_free_q; | 1540 | struct list_head hostrcb_free_q; |
| 1538 | struct list_head hostrcb_pending_q; | 1541 | struct list_head hostrcb_pending_q; |
| 1542 | struct list_head hostrcb_report_q; | ||
| 1539 | 1543 | ||
| 1540 | struct ipr_hrr_queue hrrq[IPR_MAX_HRRQ_NUM]; | 1544 | struct ipr_hrr_queue hrrq[IPR_MAX_HRRQ_NUM]; |
| 1541 | u32 hrrq_num; | 1545 | u32 hrrq_num; |
| @@ -1837,7 +1837,6 @@ static void fc_exch_reset(struct fc_exch *ep) · 1836 unmodified lines | |||
| 1837 | int rc = 1; | 1837 | int rc = 1; |
| 1838 | 1838 | ||
| 1839 | spin_lock_bh(&ep->ex_lock); | 1839 | spin_lock_bh(&ep->ex_lock); |
| 1840 | fc_exch_abort_locked(ep, 0); | ||
| 1841 | ep->state |= FC_EX_RST_CLEANUP; | 1840 | ep->state |= FC_EX_RST_CLEANUP; |
| 1842 | fc_exch_timer_cancel(ep); | 1841 | fc_exch_timer_cancel(ep); |
| 1843 | if (ep->esb_stat & ESB_ST_REC_QUAL) | 1842 | if (ep->esb_stat & ESB_ST_REC_QUAL) |
| @@ -457,6 +457,9 @@ static void fc_rport_enter_delete(struct fc_rport_priv *rdata, · 456 unmodified lines | |||
| 457 | */ | 457 | */ |
| 458 | static int fc_rport_logoff(struct fc_rport_priv *rdata) | 458 | static int fc_rport_logoff(struct fc_rport_priv *rdata) |
| 459 | { | 459 | { |
| 460 | struct fc_lport *lport = rdata->local_port; | ||
| 461 | u32 port_id = rdata->ids.port_id; | ||
| 462 | |||
| 460 | mutex_lock(&rdata->rp_mutex); | 463 | mutex_lock(&rdata->rp_mutex); |
| 461 | 464 | ||
| 462 | FC_RPORT_DBG(rdata, "Remove port\n"); | 465 | FC_RPORT_DBG(rdata, "Remove port\n"); |
| @@ -466,6 +469,15 @@ static int fc_rport_logoff(struct fc_rport_priv *rdata) · 3 unmodified lines | |||
| 466 | FC_RPORT_DBG(rdata, "Port in Delete state, not removing\n"); | 469 | FC_RPORT_DBG(rdata, "Port in Delete state, not removing\n"); |
| 467 | goto out; | 470 | goto out; |
| 468 | } | 471 | } |
| 472 | /* | ||
| 473 | * FC-LS states: | ||
| 474 | * To explicitly Logout, the initiating Nx_Port shall terminate | ||
| 475 | * other open Sequences that it initiated with the destination | ||
| 476 | * Nx_Port prior to performing Logout. | ||
| 477 | */ | ||
| 478 | lport->tt.exch_mgr_reset(lport, 0, port_id); | ||
| 479 | lport->tt.exch_mgr_reset(lport, port_id, 0); | ||
| 480 | |||
| 469 | fc_rport_enter_logo(rdata); | 481 | fc_rport_enter_logo(rdata); |
| 470 | 482 | ||
| 471 | /* | 483 | /* |
| @@ -547,16 +559,24 @@ static void fc_rport_timeout(struct work_struct *work) · 75 unmodified lines | |||
| 547 | */ | 559 | */ |
| 548 | static void fc_rport_error(struct fc_rport_priv *rdata, struct fc_frame *fp) | 560 | static void fc_rport_error(struct fc_rport_priv *rdata, struct fc_frame *fp) |
| 549 | { | 561 | { |
| 562 | struct fc_lport *lport = rdata->local_port; | ||
| 563 | |||
| 550 | FC_RPORT_DBG(rdata, "Error %ld in state %s, retries %d\n", | 564 | FC_RPORT_DBG(rdata, "Error %ld in state %s, retries %d\n", |
| 551 | IS_ERR(fp) ? -PTR_ERR(fp) : 0, | 565 | IS_ERR(fp) ? -PTR_ERR(fp) : 0, |
| 552 | fc_rport_state(rdata), rdata->retries); | 566 | fc_rport_state(rdata), rdata->retries); |
| 553 | 567 | ||
| 554 | switch (rdata->rp_state) { | 568 | switch (rdata->rp_state) { |
| 555 | case RPORT_ST_FLOGI: | 569 | case RPORT_ST_FLOGI: |
| 556 | case RPORT_ST_PLOGI: | ||
| 557 | rdata->flags &= ~FC_RP_STARTED; | 570 | rdata->flags &= ~FC_RP_STARTED; |
| 558 | fc_rport_enter_delete(rdata, RPORT_EV_FAILED); | 571 | fc_rport_enter_delete(rdata, RPORT_EV_FAILED); |
| 559 | break; | 572 | break; |
| 573 | case RPORT_ST_PLOGI: | ||
| 574 | if (lport->point_to_multipoint) { | ||
| 575 | rdata->flags &= ~FC_RP_STARTED; | ||
| 576 | fc_rport_enter_delete(rdata, RPORT_EV_FAILED); | ||
| 577 | } else | ||
| 578 | fc_rport_enter_logo(rdata); | ||
| 579 | break; | ||
| 560 | case RPORT_ST_RTV: | 580 | case RPORT_ST_RTV: |
| 561 | fc_rport_enter_ready(rdata); | 581 | fc_rport_enter_ready(rdata); |
| 562 | break; | 582 | break; |
| @@ -1877,7 +1897,7 @@ static void fc_rport_recv_prlo_req(struct fc_rport_priv *rdata, · 1314 unmodified lines | |||
| 1877 | spp->spp_type_ext = rspp->spp_type_ext; | 1897 | spp->spp_type_ext = rspp->spp_type_ext; |
| 1878 | spp->spp_flags = FC_SPP_RESP_ACK; | 1898 | spp->spp_flags = FC_SPP_RESP_ACK; |
| 1879 | 1899 | ||
| 1880 | fc_rport_enter_delete(rdata, RPORT_EV_LOGO); | 1900 | fc_rport_enter_prli(rdata); |
| 1881 | 1901 | ||
| 1882 | fc_fill_reply_hdr(fp, rx_fp, FC_RCTL_ELS_REP, 0); | 1902 | fc_fill_reply_hdr(fp, rx_fp, FC_RCTL_ELS_REP, 0); |
| 1883 | lport->tt.frame_send(lport, fp); | 1903 | lport->tt.frame_send(lport, fp); |
| @@ -1915,7 +1935,7 @@ static void fc_rport_recv_logo_req(struct fc_lport *lport, struct fc_frame *fp) · 31 unmodified lines | |||
| 1915 | FC_RPORT_DBG(rdata, "Received LOGO request while in state %s\n", | 1935 | FC_RPORT_DBG(rdata, "Received LOGO request while in state %s\n", |
| 1916 | fc_rport_state(rdata)); | 1936 | fc_rport_state(rdata)); |
| 1917 | 1937 | ||
| 1918 | fc_rport_enter_delete(rdata, RPORT_EV_LOGO); | 1938 | fc_rport_enter_delete(rdata, RPORT_EV_STOP); |
| 1919 | mutex_unlock(&rdata->rp_mutex); | 1939 | mutex_unlock(&rdata->rp_mutex); |
| 1920 | kref_put(&rdata->kref, rdata->local_port->tt.rport_destroy); | 1940 | kref_put(&rdata->kref, rdata->local_port->tt.rport_destroy); |
| 1921 | } else | 1941 | } else |
| @@ -1535,7 +1535,7 @@ lpfc_fdmi_num_disc_check(struct lpfc_vport *vport) · 1534 unmodified lines | |||
| 1535 | } | 1535 | } |
| 1536 | 1536 | ||
| 1537 | /* Routines for all individual HBA attributes */ | 1537 | /* Routines for all individual HBA attributes */ |
| 1538 | int | 1538 | static int |
| 1539 | lpfc_fdmi_hba_attr_wwnn(struct lpfc_vport *vport, struct lpfc_fdmi_attr_def *ad) | 1539 | lpfc_fdmi_hba_attr_wwnn(struct lpfc_vport *vport, struct lpfc_fdmi_attr_def *ad) |
| 1540 | { | 1540 | { |
| 1541 | struct lpfc_fdmi_attr_entry *ae; | 1541 | struct lpfc_fdmi_attr_entry *ae; |
| @@ -1551,7 +1551,7 @@ lpfc_fdmi_hba_attr_wwnn(struct lpfc_vport *vport, struct lpfc_fdmi_attr_def *ad) · 9 unmodified lines | |||
| 1551 | ad->AttrType = cpu_to_be16(RHBA_NODENAME); | 1551 | ad->AttrType = cpu_to_be16(RHBA_NODENAME); |
| 1552 | return size; | 1552 | return size; |
| 1553 | } | 1553 | } |
| 1554 | int | 1554 | static int |
| 1555 | lpfc_fdmi_hba_attr_manufacturer(struct lpfc_vport *vport, | 1555 | lpfc_fdmi_hba_attr_manufacturer(struct lpfc_vport *vport, |
| 1556 | struct lpfc_fdmi_attr_def *ad) | 1556 | struct lpfc_fdmi_attr_def *ad) |
| 1557 | { | 1557 | { |
| @@ -1573,7 +1573,7 @@ lpfc_fdmi_hba_attr_manufacturer(struct lpfc_vport *vport, · 15 unmodified lines | |||
| 1573 | return size; | 1573 | return size; |
| 1574 | } | 1574 | } |
| 1575 | 1575 | ||
| 1576 | int | 1576 | static int |
| 1577 | lpfc_fdmi_hba_attr_sn(struct lpfc_vport *vport, struct lpfc_fdmi_attr_def *ad) | 1577 | lpfc_fdmi_hba_attr_sn(struct lpfc_vport *vport, struct lpfc_fdmi_attr_def *ad) |
| 1578 | { | 1578 | { |
| 1579 | struct lpfc_hba *phba = vport->phba; | 1579 | struct lpfc_hba *phba = vport->phba; |
| @@ -1594,7 +1594,7 @@ lpfc_fdmi_hba_attr_sn(struct lpfc_vport *vport, struct lpfc_fdmi_attr_def *ad) · 14 unmodified lines | |||
| 1594 | return size; | 1594 | return size; |
| 1595 | } | 1595 | } |
| 1596 | 1596 | ||
| 1597 | int | 1597 | static int |
| 1598 | lpfc_fdmi_hba_attr_model(struct lpfc_vport *vport, | 1598 | lpfc_fdmi_hba_attr_model(struct lpfc_vport *vport, |
| 1599 | struct lpfc_fdmi_attr_def *ad) | 1599 | struct lpfc_fdmi_attr_def *ad) |
| 1600 | { | 1600 | { |
| @@ -1615,7 +1615,7 @@ lpfc_fdmi_hba_attr_model(struct lpfc_vport *vport, · 14 unmodified lines | |||
| 1615 | return size; | 1615 | return size; |
| 1616 | } | 1616 | } |
| 1617 | 1617 | ||
| 1618 | int | 1618 | static int |
| 1619 | lpfc_fdmi_hba_attr_description(struct lpfc_vport *vport, | 1619 | lpfc_fdmi_hba_attr_description(struct lpfc_vport *vport, |
| 1620 | struct lpfc_fdmi_attr_def *ad) | 1620 | struct lpfc_fdmi_attr_def *ad) |
| 1621 | { | 1621 | { |
| @@ -1637,7 +1637,7 @@ lpfc_fdmi_hba_attr_description(struct lpfc_vport *vport, · 15 unmodified lines | |||
| 1637 | return size; | 1637 | return size; |
| 1638 | } | 1638 | } |
| 1639 | 1639 | ||
| 1640 | int | 1640 | static int |
| 1641 | lpfc_fdmi_hba_attr_hdw_ver(struct lpfc_vport *vport, | 1641 | lpfc_fdmi_hba_attr_hdw_ver(struct lpfc_vport *vport, |
| 1642 | struct lpfc_fdmi_attr_def *ad) | 1642 | struct lpfc_fdmi_attr_def *ad) |
| 1643 | { | 1643 | { |
| @@ -1669,7 +1669,7 @@ lpfc_fdmi_hba_attr_hdw_ver(struct lpfc_vport *vport, · 25 unmodified lines | |||
| 1669 | return size; | 1669 | return size; |
| 1670 | } | 1670 | } |
| 1671 | 1671 | ||
| 1672 | int | 1672 | static int |
| 1673 | lpfc_fdmi_hba_attr_drvr_ver(struct lpfc_vport *vport, | 1673 | lpfc_fdmi_hba_attr_drvr_ver(struct lpfc_vport *vport, |
| 1674 | struct lpfc_fdmi_attr_def *ad) | 1674 | struct lpfc_fdmi_attr_def *ad) |
| 1675 | { | 1675 | { |
| @@ -1690,7 +1690,7 @@ lpfc_fdmi_hba_attr_drvr_ver(struct lpfc_vport *vport, · 14 unmodified lines | |||
| 1690 | return size; | 1690 | return size; |
| 1691 | } | 1691 | } |
| 1692 | 1692 | ||
| 1693 | int | 1693 | static int |
| 1694 | lpfc_fdmi_hba_attr_rom_ver(struct lpfc_vport *vport, | 1694 | lpfc_fdmi_hba_attr_rom_ver(struct lpfc_vport *vport, |
| 1695 | struct lpfc_fdmi_attr_def *ad) | 1695 | struct lpfc_fdmi_attr_def *ad) |
| 1696 | { | 1696 | { |
| @@ -1715,7 +1715,7 @@ lpfc_fdmi_hba_attr_rom_ver(struct lpfc_vport *vport, · 18 unmodified lines | |||
| 1715 | return size; | 1715 | return size; |
| 1716 | } | 1716 | } |
| 1717 | 1717 | ||
| 1718 | int | 1718 | static int |
| 1719 | lpfc_fdmi_hba_attr_fmw_ver(struct lpfc_vport *vport, | 1719 | lpfc_fdmi_hba_attr_fmw_ver(struct lpfc_vport *vport, |
| 1720 | struct lpfc_fdmi_attr_def *ad) | 1720 | struct lpfc_fdmi_attr_def *ad) |
| 1721 | { | 1721 | { |
| @@ -1736,7 +1736,7 @@ lpfc_fdmi_hba_attr_fmw_ver(struct lpfc_vport *vport, · 14 unmodified lines | |||
| 1736 | return size; | 1736 | return size; |
| 1737 | } | 1737 | } |
| 1738 | 1738 | ||
| 1739 | int | 1739 | static int |
| 1740 | lpfc_fdmi_hba_attr_os_ver(struct lpfc_vport *vport, | 1740 | lpfc_fdmi_hba_attr_os_ver(struct lpfc_vport *vport, |
| 1741 | struct lpfc_fdmi_attr_def *ad) | 1741 | struct lpfc_fdmi_attr_def *ad) |
| 1742 | { | 1742 | { |
| @@ -1759,7 +1759,7 @@ lpfc_fdmi_hba_attr_os_ver(struct lpfc_vport *vport, · 16 unmodified lines | |||
| 1759 | return size; | 1759 | return size; |
| 1760 | } | 1760 | } |
| 1761 | 1761 | ||
| 1762 | int | 1762 | static int |
| 1763 | lpfc_fdmi_hba_attr_ct_len(struct lpfc_vport *vport, | 1763 | lpfc_fdmi_hba_attr_ct_len(struct lpfc_vport *vport, |
| 1764 | struct lpfc_fdmi_attr_def *ad) | 1764 | struct lpfc_fdmi_attr_def *ad) |
| 1765 | { | 1765 | { |
| @@ -1775,7 +1775,7 @@ lpfc_fdmi_hba_attr_ct_len(struct lpfc_vport *vport, · 9 unmodified lines | |||
| 1775 | return size; | 1775 | return size; |
| 1776 | } | 1776 | } |
| 1777 | 1777 | ||
| 1778 | int | 1778 | static int |
| 1779 | lpfc_fdmi_hba_attr_symbolic_name(struct lpfc_vport *vport, | 1779 | lpfc_fdmi_hba_attr_symbolic_name(struct lpfc_vport *vport, |
| 1780 | struct lpfc_fdmi_attr_def *ad) | 1780 | struct lpfc_fdmi_attr_def *ad) |
| 1781 | { | 1781 | { |
| @@ -1794,7 +1794,7 @@ lpfc_fdmi_hba_attr_symbolic_name(struct lpfc_vport *vport, · 12 unmodified lines | |||
| 1794 | return size; | 1794 | return size; |
| 1795 | } | 1795 | } |
| 1796 | 1796 | ||
| 1797 | int | 1797 | static int |
| 1798 | lpfc_fdmi_hba_attr_vendor_info(struct lpfc_vport *vport, | 1798 | lpfc_fdmi_hba_attr_vendor_info(struct lpfc_vport *vport, |
| 1799 | struct lpfc_fdmi_attr_def *ad) | 1799 | struct lpfc_fdmi_attr_def *ad) |
| 1800 | { | 1800 | { |
| @@ -1811,7 +1811,7 @@ lpfc_fdmi_hba_attr_vendor_info(struct lpfc_vport *vport, · 10 unmodified lines | |||
| 1811 | return size; | 1811 | return size; |
| 1812 | } | 1812 | } |
| 1813 | 1813 | ||
| 1814 | int | 1814 | static int |
| 1815 | lpfc_fdmi_hba_attr_num_ports(struct lpfc_vport *vport, | 1815 | lpfc_fdmi_hba_attr_num_ports(struct lpfc_vport *vport, |
| 1816 | struct lpfc_fdmi_attr_def *ad) | 1816 | struct lpfc_fdmi_attr_def *ad) |
| 1817 | { | 1817 | { |
| @@ -1828,7 +1828,7 @@ lpfc_fdmi_hba_attr_num_ports(struct lpfc_vport *vport, · 10 unmodified lines | |||
| 1828 | return size; | 1828 | return size; |
| 1829 | } | 1829 | } |
| 1830 | 1830 | ||
| 1831 | int | 1831 | static int |
| 1832 | lpfc_fdmi_hba_attr_fabric_wwnn(struct lpfc_vport *vport, | 1832 | lpfc_fdmi_hba_attr_fabric_wwnn(struct lpfc_vport *vport, |
| 1833 | struct lpfc_fdmi_attr_def *ad) | 1833 | struct lpfc_fdmi_attr_def *ad) |
| 1834 | { | 1834 | { |
| @@ -1846,7 +1846,7 @@ lpfc_fdmi_hba_attr_fabric_wwnn(struct lpfc_vport *vport, · 11 unmodified lines | |||
| 1846 | return size; | 1846 | return size; |
| 1847 | } | 1847 | } |
| 1848 | 1848 | ||
| 1849 | int | 1849 | static int |
| 1850 | lpfc_fdmi_hba_attr_bios_ver(struct lpfc_vport *vport, | 1850 | lpfc_fdmi_hba_attr_bios_ver(struct lpfc_vport *vport, |
| 1851 | struct lpfc_fdmi_attr_def *ad) | 1851 | struct lpfc_fdmi_attr_def *ad) |
| 1852 | { | 1852 | { |
| @@ -1867,7 +1867,7 @@ lpfc_fdmi_hba_attr_bios_ver(struct lpfc_vport *vport, · 14 unmodified lines | |||
| 1867 | return size; | 1867 | return size; |
| 1868 | } | 1868 | } |
| 1869 | 1869 | ||
| 1870 | int | 1870 | static int |
| 1871 | lpfc_fdmi_hba_attr_bios_state(struct lpfc_vport *vport, | 1871 | lpfc_fdmi_hba_attr_bios_state(struct lpfc_vport *vport, |
| 1872 | struct lpfc_fdmi_attr_def *ad) | 1872 | struct lpfc_fdmi_attr_def *ad) |
| 1873 | { | 1873 | { |
| @@ -1884,7 +1884,7 @@ lpfc_fdmi_hba_attr_bios_state(struct lpfc_vport *vport, · 10 unmodified lines | |||
| 1884 | return size; | 1884 | return size; |
| 1885 | } | 1885 | } |
| 1886 | 1886 | ||
| 1887 | int | 1887 | static int |
| 1888 | lpfc_fdmi_hba_attr_vendor_id(struct lpfc_vport *vport, | 1888 | lpfc_fdmi_hba_attr_vendor_id(struct lpfc_vport *vport, |
| 1889 | struct lpfc_fdmi_attr_def *ad) | 1889 | struct lpfc_fdmi_attr_def *ad) |
| 1890 | { | 1890 | { |
| @@ -1906,7 +1906,7 @@ lpfc_fdmi_hba_attr_vendor_id(struct lpfc_vport *vport, · 15 unmodified lines | |||
| 1906 | } | 1906 | } |
| 1907 | 1907 | ||
| 1908 | /* Routines for all individual PORT attributes */ | 1908 | /* Routines for all individual PORT attributes */ |
| 1909 | int | 1909 | static int |
| 1910 | lpfc_fdmi_port_attr_fc4type(struct lpfc_vport *vport, | 1910 | lpfc_fdmi_port_attr_fc4type(struct lpfc_vport *vport, |
| 1911 | struct lpfc_fdmi_attr_def *ad) | 1911 | struct lpfc_fdmi_attr_def *ad) |
| 1912 | { | 1912 | { |
| @@ -1925,7 +1925,7 @@ lpfc_fdmi_port_attr_fc4type(struct lpfc_vport *vport, · 12 unmodified lines | |||
| 1925 | return size; | 1925 | return size; |
| 1926 | } | 1926 | } |
| 1927 | 1927 | ||
| 1928 | int | 1928 | static int |
| 1929 | lpfc_fdmi_port_attr_support_speed(struct lpfc_vport *vport, | 1929 | lpfc_fdmi_port_attr_support_speed(struct lpfc_vport *vport, |
| 1930 | struct lpfc_fdmi_attr_def *ad) | 1930 | struct lpfc_fdmi_attr_def *ad) |
| 1931 | { | 1931 | { |
| @@ -1975,7 +1975,7 @@ lpfc_fdmi_port_attr_support_speed(struct lpfc_vport *vport, · 43 unmodified lines | |||
| 1975 | return size; | 1975 | return size; |
| 1976 | } | 1976 | } |
| 1977 | 1977 | ||
| 1978 | int | 1978 | static int |
| 1979 | lpfc_fdmi_port_attr_speed(struct lpfc_vport *vport, | 1979 | lpfc_fdmi_port_attr_speed(struct lpfc_vport *vport, |
| 1980 | struct lpfc_fdmi_attr_def *ad) | 1980 | struct lpfc_fdmi_attr_def *ad) |
| 1981 | { | 1981 | { |
| @@ -2039,7 +2039,7 @@ lpfc_fdmi_port_attr_speed(struct lpfc_vport *vport, · 57 unmodified lines | |||
| 2039 | return size; | 2039 | return size; |
| 2040 | } | 2040 | } |
| 2041 | 2041 | ||
| 2042 | int | 2042 | static int |
| 2043 | lpfc_fdmi_port_attr_max_frame(struct lpfc_vport *vport, | 2043 | lpfc_fdmi_port_attr_max_frame(struct lpfc_vport *vport, |
| 2044 | struct lpfc_fdmi_attr_def *ad) | 2044 | struct lpfc_fdmi_attr_def *ad) |
| 2045 | { | 2045 | { |
| @@ -2059,7 +2059,7 @@ lpfc_fdmi_port_attr_max_frame(struct lpfc_vport *vport, · 13 unmodified lines | |||
| 2059 | return size; | 2059 | return size; |
| 2060 | } | 2060 | } |
| 2061 | 2061 | ||
| 2062 | int | 2062 | static int |
| 2063 | lpfc_fdmi_port_attr_os_devname(struct lpfc_vport *vport, | 2063 | lpfc_fdmi_port_attr_os_devname(struct lpfc_vport *vport, |
| 2064 | struct lpfc_fdmi_attr_def *ad) | 2064 | struct lpfc_fdmi_attr_def *ad) |
| 2065 | { | 2065 | { |
| @@ -2081,7 +2081,7 @@ lpfc_fdmi_port_attr_os_devname(struct lpfc_vport *vport, · 15 unmodified lines | |||
| 2081 | return size; | 2081 | return size; |
| 2082 | } | 2082 | } |
| 2083 | 2083 | ||
| 2084 | int | 2084 | static int |
| 2085 | lpfc_fdmi_port_attr_host_name(struct lpfc_vport *vport, | 2085 | lpfc_fdmi_port_attr_host_name(struct lpfc_vport *vport, |
| 2086 | struct lpfc_fdmi_attr_def *ad) | 2086 | struct lpfc_fdmi_attr_def *ad) |
| 2087 | { | 2087 | { |
| @@ -2102,7 +2102,7 @@ lpfc_fdmi_port_attr_host_name(struct lpfc_vport *vport, · 14 unmodified lines | |||
| 2102 | return size; | 2102 | return size; |
| 2103 | } | 2103 | } |
| 2104 | 2104 | ||
| 2105 | int | 2105 | static int |
| 2106 | lpfc_fdmi_port_attr_wwnn(struct lpfc_vport *vport, | 2106 | lpfc_fdmi_port_attr_wwnn(struct lpfc_vport *vport, |
| 2107 | struct lpfc_fdmi_attr_def *ad) | 2107 | struct lpfc_fdmi_attr_def *ad) |
| 2108 | { | 2108 | { |
| @@ -2120,7 +2120,7 @@ lpfc_fdmi_port_attr_wwnn(struct lpfc_vport *vport, · 11 unmodified lines | |||
| 2120 | return size; | 2120 | return size; |
| 2121 | } | 2121 | } |
| 2122 | 2122 | ||
| 2123 | int | 2123 | static int |
| 2124 | lpfc_fdmi_port_attr_wwpn(struct lpfc_vport *vport, | 2124 | lpfc_fdmi_port_attr_wwpn(struct lpfc_vport *vport, |
| 2125 | struct lpfc_fdmi_attr_def *ad) | 2125 | struct lpfc_fdmi_attr_def *ad) |
| 2126 | { | 2126 | { |
| @@ -2138,7 +2138,7 @@ lpfc_fdmi_port_attr_wwpn(struct lpfc_vport *vport, · 11 unmodified lines | |||
| 2138 | return size; | 2138 | return size; |
| 2139 | } | 2139 | } |
| 2140 | 2140 | ||
| 2141 | int | 2141 | static int |
| 2142 | lpfc_fdmi_port_attr_symbolic_name(struct lpfc_vport *vport, | 2142 | lpfc_fdmi_port_attr_symbolic_name(struct lpfc_vport *vport, |
| 2143 | struct lpfc_fdmi_attr_def *ad) | 2143 | struct lpfc_fdmi_attr_def *ad) |
| 2144 | { | 2144 | { |
| @@ -2156,7 +2156,7 @@ lpfc_fdmi_port_attr_symbolic_name(struct lpfc_vport *vport, · 11 unmodified lines | |||
| 2156 | return size; | 2156 | return size; |
| 2157 | } | 2157 | } |
| 2158 | 2158 | ||
| 2159 | int | 2159 | static int |
| 2160 | lpfc_fdmi_port_attr_port_type(struct lpfc_vport *vport, | 2160 | lpfc_fdmi_port_attr_port_type(struct lpfc_vport *vport, |
| 2161 | struct lpfc_fdmi_attr_def *ad) | 2161 | struct lpfc_fdmi_attr_def *ad) |
| 2162 | { | 2162 | { |
| @@ -2175,7 +2175,7 @@ lpfc_fdmi_port_attr_port_type(struct lpfc_vport *vport, · 12 unmodified lines | |||
| 2175 | return size; | 2175 | return size; |
| 2176 | } | 2176 | } |
| 2177 | 2177 | ||
| 2178 | int | 2178 | static int |
| 2179 | lpfc_fdmi_port_attr_class(struct lpfc_vport *vport, | 2179 | lpfc_fdmi_port_attr_class(struct lpfc_vport *vport, |
| 2180 | struct lpfc_fdmi_attr_def *ad) | 2180 | struct lpfc_fdmi_attr_def *ad) |
| 2181 | { | 2181 | { |
| @@ -2190,7 +2190,7 @@ lpfc_fdmi_port_attr_class(struct lpfc_vport *vport, · 8 unmodified lines | |||
| 2190 | return size; | 2190 | return size; |
| 2191 | } | 2191 | } |
| 2192 | 2192 | ||
| 2193 | int | 2193 | static int |
| 2194 | lpfc_fdmi_port_attr_fabric_wwpn(struct lpfc_vport *vport, | 2194 | lpfc_fdmi_port_attr_fabric_wwpn(struct lpfc_vport *vport, |
| 2195 | struct lpfc_fdmi_attr_def *ad) | 2195 | struct lpfc_fdmi_attr_def *ad) |
| 2196 | { | 2196 | { |
| @@ -2208,7 +2208,7 @@ lpfc_fdmi_port_attr_fabric_wwpn(struct lpfc_vport *vport, · 11 unmodified lines | |||
| 2208 | return size; | 2208 | return size; |
| 2209 | } | 2209 | } |
| 2210 | 2210 | ||
| 2211 | int | 2211 | static int |
| 2212 | lpfc_fdmi_port_attr_active_fc4type(struct lpfc_vport *vport, | 2212 | lpfc_fdmi_port_attr_active_fc4type(struct lpfc_vport *vport, |
| 2213 | struct lpfc_fdmi_attr_def *ad) | 2213 | struct lpfc_fdmi_attr_def *ad) |
| 2214 | { | 2214 | { |
| @@ -2227,7 +2227,7 @@ lpfc_fdmi_port_attr_active_fc4type(struct lpfc_vport *vport, · 12 unmodified lines | |||
| 2227 | return size; | 2227 | return size; |
| 2228 | } | 2228 | } |
| 2229 | 2229 | ||
| 2230 | int | 2230 | static int |
| 2231 | lpfc_fdmi_port_attr_port_state(struct lpfc_vport *vport, | 2231 | lpfc_fdmi_port_attr_port_state(struct lpfc_vport *vport, |
| 2232 | struct lpfc_fdmi_attr_def *ad) | 2232 | struct lpfc_fdmi_attr_def *ad) |
| 2233 | { | 2233 | { |
| @@ -2243,7 +2243,7 @@ lpfc_fdmi_port_attr_port_state(struct lpfc_vport *vport, · 9 unmodified lines | |||
| 2243 | return size; | 2243 | return size; |
| 2244 | } | 2244 | } |
| 2245 | 2245 | ||
| 2246 | int | 2246 | static int |
| 2247 | lpfc_fdmi_port_attr_num_disc(struct lpfc_vport *vport, | 2247 | lpfc_fdmi_port_attr_num_disc(struct lpfc_vport *vport, |
| 2248 | struct lpfc_fdmi_attr_def *ad) | 2248 | struct lpfc_fdmi_attr_def *ad) |
| 2249 | { | 2249 | { |
| @@ -2259,7 +2259,7 @@ lpfc_fdmi_port_attr_num_disc(struct lpfc_vport *vport, · 9 unmodified lines | |||
| 2259 | return size; | 2259 | return size; |
| 2260 | } | 2260 | } |
| 2261 | 2261 | ||
| 2262 | int | 2262 | static int |
| 2263 | lpfc_fdmi_port_attr_nportid(struct lpfc_vport *vport, | 2263 | lpfc_fdmi_port_attr_nportid(struct lpfc_vport *vport, |
| 2264 | struct lpfc_fdmi_attr_def *ad) | 2264 | struct lpfc_fdmi_attr_def *ad) |
| 2265 | { | 2265 | { |
| @@ -2274,7 +2274,7 @@ lpfc_fdmi_port_attr_nportid(struct lpfc_vport *vport, · 8 unmodified lines | |||
| 2274 | return size; | 2274 | return size; |
| 2275 | } | 2275 | } |
| 2276 | 2276 | ||
| 2277 | int | 2277 | static int |
| 2278 | lpfc_fdmi_smart_attr_service(struct lpfc_vport *vport, | 2278 | lpfc_fdmi_smart_attr_service(struct lpfc_vport *vport, |
| 2279 | struct lpfc_fdmi_attr_def *ad) | 2279 | struct lpfc_fdmi_attr_def *ad) |
| 2280 | { | 2280 | { |
| @@ -2295,7 +2295,7 @@ lpfc_fdmi_smart_attr_service(struct lpfc_vport *vport, · 14 unmodified lines | |||
| 2295 | return size; | 2295 | return size; |
| 2296 | } | 2296 | } |
| 2297 | 2297 | ||
| 2298 | int | 2298 | static int |
| 2299 | lpfc_fdmi_smart_attr_guid(struct lpfc_vport *vport, | 2299 | lpfc_fdmi_smart_attr_guid(struct lpfc_vport *vport, |
| 2300 | struct lpfc_fdmi_attr_def *ad) | 2300 | struct lpfc_fdmi_attr_def *ad) |
| 2301 | { | 2301 | { |
| @@ -2316,7 +2316,7 @@ lpfc_fdmi_smart_attr_guid(struct lpfc_vport *vport, · 14 unmodified lines | |||
| 2316 | return size; | 2316 | return size; |
| 2317 | } | 2317 | } |
| 2318 | 2318 | ||
| 2319 | int | 2319 | static int |
| 2320 | lpfc_fdmi_smart_attr_version(struct lpfc_vport *vport, | 2320 | lpfc_fdmi_smart_attr_version(struct lpfc_vport *vport, |
| 2321 | struct lpfc_fdmi_attr_def *ad) | 2321 | struct lpfc_fdmi_attr_def *ad) |
| 2322 | { | 2322 | { |
| @@ -2337,7 +2337,7 @@ lpfc_fdmi_smart_attr_version(struct lpfc_vport *vport, · 14 unmodified lines | |||
| 2337 | return size; | 2337 | return size; |
| 2338 | } | 2338 | } |
| 2339 | 2339 | ||
| 2340 | int | 2340 | static int |
| 2341 | lpfc_fdmi_smart_attr_model(struct lpfc_vport *vport, | 2341 | lpfc_fdmi_smart_attr_model(struct lpfc_vport *vport, |
| 2342 | struct lpfc_fdmi_attr_def *ad) | 2342 | struct lpfc_fdmi_attr_def *ad) |
| 2343 | { | 2343 | { |
| @@ -2358,7 +2358,7 @@ lpfc_fdmi_smart_attr_model(struct lpfc_vport *vport, · 14 unmodified lines | |||
| 2358 | return size; | 2358 | return size; |
| 2359 | } | 2359 | } |
| 2360 | 2360 | ||
| 2361 | int | 2361 | static int |
| 2362 | lpfc_fdmi_smart_attr_port_info(struct lpfc_vport *vport, | 2362 | lpfc_fdmi_smart_attr_port_info(struct lpfc_vport *vport, |
| 2363 | struct lpfc_fdmi_attr_def *ad) | 2363 | struct lpfc_fdmi_attr_def *ad) |
| 2364 | { | 2364 | { |
| @@ -2378,7 +2378,7 @@ lpfc_fdmi_smart_attr_port_info(struct lpfc_vport *vport, · 13 unmodified lines | |||
| 2378 | return size; | 2378 | return size; |
| 2379 | } | 2379 | } |
| 2380 | 2380 | ||
| 2381 | int | 2381 | static int |
| 2382 | lpfc_fdmi_smart_attr_qos(struct lpfc_vport *vport, | 2382 | lpfc_fdmi_smart_attr_qos(struct lpfc_vport *vport, |
| 2383 | struct lpfc_fdmi_attr_def *ad) | 2383 | struct lpfc_fdmi_attr_def *ad) |
| 2384 | { | 2384 | { |
| @@ -2393,7 +2393,7 @@ lpfc_fdmi_smart_attr_qos(struct lpfc_vport *vport, · 8 unmodified lines | |||
| 2393 | return size; | 2393 | return size; |
| 2394 | } | 2394 | } |
| 2395 | 2395 | ||
| 2396 | int | 2396 | static int |
| 2397 | lpfc_fdmi_smart_attr_security(struct lpfc_vport *vport, | 2397 | lpfc_fdmi_smart_attr_security(struct lpfc_vport *vport, |
| 2398 | struct lpfc_fdmi_attr_def *ad) | 2398 | struct lpfc_fdmi_attr_def *ad) |
| 2399 | { | 2399 | { |
| @@ -4617,7 +4617,7 @@ lpfc_els_disc_plogi(struct lpfc_vport *vport) · 4616 unmodified lines | |||
| 4617 | return sentplogi; | 4617 | return sentplogi; |
| 4618 | } | 4618 | } |
| 4619 | 4619 | ||
| 4620 | uint32_t | 4620 | static uint32_t |
| 4621 | lpfc_rdp_res_link_service(struct fc_rdp_link_service_desc *desc, | 4621 | lpfc_rdp_res_link_service(struct fc_rdp_link_service_desc *desc, |
| 4622 | uint32_t word0) | 4622 | uint32_t word0) |
| 4623 | { | 4623 | { |
| @@ -4629,7 +4629,7 @@ lpfc_rdp_res_link_service(struct fc_rdp_link_service_desc *desc, · 5 unmodified lines | |||
| 4629 | return sizeof(struct fc_rdp_link_service_desc); | 4629 | return sizeof(struct fc_rdp_link_service_desc); |
| 4630 | } | 4630 | } |
| 4631 | 4631 | ||
| 4632 | uint32_t | 4632 | static uint32_t |
| 4633 | lpfc_rdp_res_sfp_desc(struct fc_rdp_sfp_desc *desc, | 4633 | lpfc_rdp_res_sfp_desc(struct fc_rdp_sfp_desc *desc, |
| 4634 | uint8_t *page_a0, uint8_t *page_a2) | 4634 | uint8_t *page_a0, uint8_t *page_a2) |
| 4635 | { | 4635 | { |
| @@ -4694,7 +4694,7 @@ lpfc_rdp_res_sfp_desc(struct fc_rdp_sfp_desc *desc, · 58 unmodified lines | |||
| 4694 | return sizeof(struct fc_rdp_sfp_desc); | 4694 | return sizeof(struct fc_rdp_sfp_desc); |
| 4695 | } | 4695 | } |
| 4696 | 4696 | ||
| 4697 | uint32_t | 4697 | static uint32_t |
| 4698 | lpfc_rdp_res_link_error(struct fc_rdp_link_error_status_desc *desc, | 4698 | lpfc_rdp_res_link_error(struct fc_rdp_link_error_status_desc *desc, |
| 4699 | READ_LNK_VAR *stat) | 4699 | READ_LNK_VAR *stat) |
| 4700 | { | 4700 | { |
| @@ -4723,7 +4723,7 @@ lpfc_rdp_res_link_error(struct fc_rdp_link_error_status_desc *desc, · 22 unmodified lines | |||
| 4723 | return sizeof(struct fc_rdp_link_error_status_desc); | 4723 | return sizeof(struct fc_rdp_link_error_status_desc); |
| 4724 | } | 4724 | } |
| 4725 | 4725 | ||
| 4726 | uint32_t | 4726 | static uint32_t |
| 4727 | lpfc_rdp_res_bbc_desc(struct fc_rdp_bbc_desc *desc, READ_LNK_VAR *stat, | 4727 | lpfc_rdp_res_bbc_desc(struct fc_rdp_bbc_desc *desc, READ_LNK_VAR *stat, |
| 4728 | struct lpfc_vport *vport) | 4728 | struct lpfc_vport *vport) |
| 4729 | { | 4729 | { |
| @@ -4748,7 +4748,7 @@ lpfc_rdp_res_bbc_desc(struct fc_rdp_bbc_desc *desc, READ_LNK_VAR *stat, · 18 unmodified lines | |||
| 4748 | return sizeof(struct fc_rdp_bbc_desc); | 4748 | return sizeof(struct fc_rdp_bbc_desc); |
| 4749 | } | 4749 | } |
| 4750 | 4750 | ||
| 4751 | uint32_t | 4751 | static uint32_t |
| 4752 | lpfc_rdp_res_oed_temp_desc(struct lpfc_hba *phba, | 4752 | lpfc_rdp_res_oed_temp_desc(struct lpfc_hba *phba, |
| 4753 | struct fc_rdp_oed_sfp_desc *desc, uint8_t *page_a2) | 4753 | struct fc_rdp_oed_sfp_desc *desc, uint8_t *page_a2) |
| 4754 | { | 4754 | { |
| @@ -4776,7 +4776,7 @@ lpfc_rdp_res_oed_temp_desc(struct lpfc_hba *phba, · 21 unmodified lines | |||
| 4776 | return sizeof(struct fc_rdp_oed_sfp_desc); | 4776 | return sizeof(struct fc_rdp_oed_sfp_desc); |
| 4777 | } | 4777 | } |
| 4778 | 4778 | ||
| 4779 | uint32_t | 4779 | static uint32_t |
| 4780 | lpfc_rdp_res_oed_voltage_desc(struct lpfc_hba *phba, | 4780 | lpfc_rdp_res_oed_voltage_desc(struct lpfc_hba *phba, |
| 4781 | struct fc_rdp_oed_sfp_desc *desc, | 4781 | struct fc_rdp_oed_sfp_desc *desc, |
| 4782 | uint8_t *page_a2) | 4782 | uint8_t *page_a2) |
| @@ -4805,7 +4805,7 @@ lpfc_rdp_res_oed_voltage_desc(struct lpfc_hba *phba, · 22 unmodified lines | |||
| 4805 | return sizeof(struct fc_rdp_oed_sfp_desc); | 4805 | return sizeof(struct fc_rdp_oed_sfp_desc); |
| 4806 | } | 4806 | } |
| 4807 | 4807 | ||
| 4808 | uint32_t | 4808 | static uint32_t |
| 4809 | lpfc_rdp_res_oed_txbias_desc(struct lpfc_hba *phba, | 4809 | lpfc_rdp_res_oed_txbias_desc(struct lpfc_hba *phba, |
| 4810 | struct fc_rdp_oed_sfp_desc *desc, | 4810 | struct fc_rdp_oed_sfp_desc *desc, |
| 4811 | uint8_t *page_a2) | 4811 | uint8_t *page_a2) |
| @@ -4834,7 +4834,7 @@ lpfc_rdp_res_oed_txbias_desc(struct lpfc_hba *phba, · 22 unmodified lines | |||
| 4834 | return sizeof(struct fc_rdp_oed_sfp_desc); | 4834 | return sizeof(struct fc_rdp_oed_sfp_desc); |
| 4835 | } | 4835 | } |
| 4836 | 4836 | ||
| 4837 | uint32_t | 4837 | static uint32_t |
| 4838 | lpfc_rdp_res_oed_txpower_desc(struct lpfc_hba *phba, | 4838 | lpfc_rdp_res_oed_txpower_desc(struct lpfc_hba *phba, |
| 4839 | struct fc_rdp_oed_sfp_desc *desc, | 4839 | struct fc_rdp_oed_sfp_desc *desc, |
| 4840 | uint8_t *page_a2) | 4840 | uint8_t *page_a2) |
| @@ -4864,7 +4864,7 @@ lpfc_rdp_res_oed_txpower_desc(struct lpfc_hba *phba, · 23 unmodified lines | |||
| 4864 | } | 4864 | } |
| 4865 | 4865 | ||
| 4866 | 4866 | ||
| 4867 | uint32_t | 4867 | static uint32_t |
| 4868 | lpfc_rdp_res_oed_rxpower_desc(struct lpfc_hba *phba, | 4868 | lpfc_rdp_res_oed_rxpower_desc(struct lpfc_hba *phba, |
| 4869 | struct fc_rdp_oed_sfp_desc *desc, | 4869 | struct fc_rdp_oed_sfp_desc *desc, |
| 4870 | uint8_t *page_a2) | 4870 | uint8_t *page_a2) |
| @@ -4893,7 +4893,7 @@ lpfc_rdp_res_oed_rxpower_desc(struct lpfc_hba *phba, · 22 unmodified lines | |||
| 4893 | return sizeof(struct fc_rdp_oed_sfp_desc); | 4893 | return sizeof(struct fc_rdp_oed_sfp_desc); |
| 4894 | } | 4894 | } |
| 4895 | 4895 | ||
| 4896 | uint32_t | 4896 | static uint32_t |
| 4897 | lpfc_rdp_res_opd_desc(struct fc_rdp_opd_sfp_desc *desc, | 4897 | lpfc_rdp_res_opd_desc(struct fc_rdp_opd_sfp_desc *desc, |
| 4898 | uint8_t *page_a0, struct lpfc_vport *vport) | 4898 | uint8_t *page_a0, struct lpfc_vport *vport) |
| 4899 | { | 4899 | { |
| @@ -4907,7 +4907,7 @@ lpfc_rdp_res_opd_desc(struct fc_rdp_opd_sfp_desc *desc, · 7 unmodified lines | |||
| 4907 | return sizeof(struct fc_rdp_opd_sfp_desc); | 4907 | return sizeof(struct fc_rdp_opd_sfp_desc); |
| 4908 | } | 4908 | } |
| 4909 | 4909 | ||
| 4910 | uint32_t | 4910 | static uint32_t |
| 4911 | lpfc_rdp_res_fec_desc(struct fc_fec_rdp_desc *desc, READ_LNK_VAR *stat) | 4911 | lpfc_rdp_res_fec_desc(struct fc_fec_rdp_desc *desc, READ_LNK_VAR *stat) |
| 4912 | { | 4912 | { |
| 4913 | if (bf_get(lpfc_read_link_stat_gec2, stat) == 0) | 4913 | if (bf_get(lpfc_read_link_stat_gec2, stat) == 0) |
| @@ -4924,7 +4924,7 @@ lpfc_rdp_res_fec_desc(struct fc_fec_rdp_desc *desc, READ_LNK_VAR *stat) · 10 unmodified lines | |||
| 4924 | return sizeof(struct fc_fec_rdp_desc); | 4924 | return sizeof(struct fc_fec_rdp_desc); |
| 4925 | } | 4925 | } |
| 4926 | 4926 | ||
| 4927 | uint32_t | 4927 | static uint32_t |
| 4928 | lpfc_rdp_res_speed(struct fc_rdp_port_speed_desc *desc, struct lpfc_hba *phba) | 4928 | lpfc_rdp_res_speed(struct fc_rdp_port_speed_desc *desc, struct lpfc_hba *phba) |
| 4929 | { | 4929 | { |
| 4930 | uint16_t rdp_cap = 0; | 4930 | uint16_t rdp_cap = 0; |
| @@ -4986,7 +4986,7 @@ lpfc_rdp_res_speed(struct fc_rdp_port_speed_desc *desc, struct lpfc_hba *phba) · 55 unmodified lines | |||
| 4986 | return sizeof(struct fc_rdp_port_speed_desc); | 4986 | return sizeof(struct fc_rdp_port_speed_desc); |
| 4987 | } | 4987 | } |
| 4988 | 4988 | ||
| 4989 | uint32_t | 4989 | static uint32_t |
| 4990 | lpfc_rdp_res_diag_port_names(struct fc_rdp_port_name_desc *desc, | 4990 | lpfc_rdp_res_diag_port_names(struct fc_rdp_port_name_desc *desc, |
| 4991 | struct lpfc_hba *phba) | 4991 | struct lpfc_hba *phba) |
| 4992 | { | 4992 | { |
| @@ -5003,7 +5003,7 @@ lpfc_rdp_res_diag_port_names(struct fc_rdp_port_name_desc *desc, · 10 unmodified lines | |||
| 5003 | return sizeof(struct fc_rdp_port_name_desc); | 5003 | return sizeof(struct fc_rdp_port_name_desc); |
| 5004 | } | 5004 | } |
| 5005 | 5005 | ||
| 5006 | uint32_t | 5006 | static uint32_t |
| 5007 | lpfc_rdp_res_attach_port_names(struct fc_rdp_port_name_desc *desc, | 5007 | lpfc_rdp_res_attach_port_names(struct fc_rdp_port_name_desc *desc, |
| 5008 | struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) | 5008 | struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) |
| 5009 | { | 5009 | { |
| @@ -5027,7 +5027,7 @@ lpfc_rdp_res_attach_port_names(struct fc_rdp_port_name_desc *desc, · 17 unmodified lines | |||
| 5027 | return sizeof(struct fc_rdp_port_name_desc); | 5027 | return sizeof(struct fc_rdp_port_name_desc); |
| 5028 | } | 5028 | } |
| 5029 | 5029 | ||
| 5030 | void | 5030 | static void |
| 5031 | lpfc_els_rdp_cmpl(struct lpfc_hba *phba, struct lpfc_rdp_context *rdp_context, | 5031 | lpfc_els_rdp_cmpl(struct lpfc_hba *phba, struct lpfc_rdp_context *rdp_context, |
| 5032 | int status) | 5032 | int status) |
| 5033 | { | 5033 | { |
| @@ -5165,7 +5165,7 @@ free_rdp_context: · 131 unmodified lines | |||
| 5165 | kfree(rdp_context); | 5165 | kfree(rdp_context); |
| 5166 | } | 5166 | } |
| 5167 | 5167 | ||
| 5168 | int | 5168 | static int |
| 5169 | lpfc_get_rdp_info(struct lpfc_hba *phba, struct lpfc_rdp_context *rdp_context) | 5169 | lpfc_get_rdp_info(struct lpfc_hba *phba, struct lpfc_rdp_context *rdp_context) |
| 5170 | { | 5170 | { |
| 5171 | LPFC_MBOXQ_t *mbox = NULL; | 5171 | LPFC_MBOXQ_t *mbox = NULL; |
| @@ -7995,7 +7995,7 @@ lpfc_els_unsol_event(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, · 2823 unmodified lines | |||
| 7995 | } | 7995 | } |
| 7996 | } | 7996 | } |
| 7997 | 7997 | ||
| 7998 | void | 7998 | static void |
| 7999 | lpfc_start_fdmi(struct lpfc_vport *vport) | 7999 | lpfc_start_fdmi(struct lpfc_vport *vport) |
| 8000 | { | 8000 | { |
| 8001 | struct lpfc_hba *phba = vport->phba; | 8001 | struct lpfc_hba *phba = vport->phba; |
| @@ -2260,7 +2260,7 @@ lpfc_sli4_dump_cfg_rg23(struct lpfc_hba *phba, struct lpfcMboxq *mbox) · 2259 unmodified lines | |||
| 2260 | return 0; | 2260 | return 0; |
| 2261 | } | 2261 | } |
| 2262 | 2262 | ||
| 2263 | void | 2263 | static void |
| 2264 | lpfc_mbx_cmpl_rdp_link_stat(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq) | 2264 | lpfc_mbx_cmpl_rdp_link_stat(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq) |
| 2265 | { | 2265 | { |
| 2266 | MAILBOX_t *mb; | 2266 | MAILBOX_t *mb; |
| @@ -2281,7 +2281,7 @@ mbx_failed: · 14 unmodified lines | |||
| 2281 | rdp_context->cmpl(phba, rdp_context, rc); | 2281 | rdp_context->cmpl(phba, rdp_context, rc); |
| 2282 | } | 2282 | } |
| 2283 | 2283 | ||
| 2284 | void | 2284 | static void |
| 2285 | lpfc_mbx_cmpl_rdp_page_a2(struct lpfc_hba *phba, LPFC_MBOXQ_t *mbox) | 2285 | lpfc_mbx_cmpl_rdp_page_a2(struct lpfc_hba *phba, LPFC_MBOXQ_t *mbox) |
| 2286 | { | 2286 | { |
| 2287 | struct lpfc_dmabuf *mp = (struct lpfc_dmabuf *) mbox->context1; | 2287 | struct lpfc_dmabuf *mp = (struct lpfc_dmabuf *) mbox->context1; |
| @@ -5689,7 +5689,7 @@ lpfc_sli4_dealloc_extent(struct lpfc_hba *phba, uint16_t type) · 5688 unmodified lines | |||
| 5689 | return rc; | 5689 | return rc; |
| 5690 | } | 5690 | } |
| 5691 | 5691 | ||
| 5692 | void | 5692 | static void |
| 5693 | lpfc_set_features(struct lpfc_hba *phba, LPFC_MBOXQ_t *mbox, | 5693 | lpfc_set_features(struct lpfc_hba *phba, LPFC_MBOXQ_t *mbox, |
| 5694 | uint32_t feature) | 5694 | uint32_t feature) |
| 5695 | { | 5695 | { |
| @@ -8968,7 +8968,7 @@ lpfc_sli_api_table_setup(struct lpfc_hba *phba, uint8_t dev_grp) · 3272 unmodified lines | |||
| 8968 | * Since ABORTS must go on the same WQ of the command they are | 8968 | * Since ABORTS must go on the same WQ of the command they are |
| 8969 | * aborting, we use command's fcp_wqidx. | 8969 | * aborting, we use command's fcp_wqidx. |
| 8970 | */ | 8970 | */ |
| 8971 | int | 8971 | static int |
| 8972 | lpfc_sli_calc_ring(struct lpfc_hba *phba, uint32_t ring_number, | 8972 | lpfc_sli_calc_ring(struct lpfc_hba *phba, uint32_t ring_number, |
| 8973 | struct lpfc_iocbq *piocb) | 8973 | struct lpfc_iocbq *piocb) |
| 8974 | { | 8974 | { |
| @@ -189,25 +189,12 @@ u32 · 188 unmodified lines | |||
| 189 | megasas_build_and_issue_cmd(struct megasas_instance *instance, | 189 | megasas_build_and_issue_cmd(struct megasas_instance *instance, |
| 190 | struct scsi_cmnd *scmd); | 190 | struct scsi_cmnd *scmd); |
| 191 | static void megasas_complete_cmd_dpc(unsigned long instance_addr); | 191 | static void megasas_complete_cmd_dpc(unsigned long instance_addr); |
| 192 | void | ||
| 193 | megasas_release_fusion(struct megasas_instance *instance); | ||
| 194 | int | ||
| 195 | megasas_ioc_init_fusion(struct megasas_instance *instance); | ||
| 196 | void | ||
| 197 | megasas_free_cmds_fusion(struct megasas_instance *instance); | ||
| 198 | u8 | ||
| 199 | megasas_get_map_info(struct megasas_instance *instance); | ||
| 200 | int | ||
| 201 | megasas_sync_map_info(struct megasas_instance *instance); | ||
| 202 | int | 192 | int |
| 203 | wait_and_poll(struct megasas_instance *instance, struct megasas_cmd *cmd, | 193 | wait_and_poll(struct megasas_instance *instance, struct megasas_cmd *cmd, |
| 204 | int seconds); | 194 | int seconds); |
| 205 | void megasas_reset_reply_desc(struct megasas_instance *instance); | ||
| 206 | void megasas_fusion_ocr_wq(struct work_struct *work); | 195 | void megasas_fusion_ocr_wq(struct work_struct *work); |
| 207 | static int megasas_get_ld_vf_affiliation(struct megasas_instance *instance, | 196 | static int megasas_get_ld_vf_affiliation(struct megasas_instance *instance, |
| 208 | int initial); | 197 | int initial); |
| 209 | int megasas_check_mpio_paths(struct megasas_instance *instance, | ||
| 210 | struct scsi_cmnd *scmd); | ||
| 211 | 198 | ||
| 212 | int | 199 | int |
| 213 | megasas_issue_dcmd(struct megasas_instance *instance, struct megasas_cmd *cmd) | 200 | megasas_issue_dcmd(struct megasas_instance *instance, struct megasas_cmd *cmd) |
| @@ -5036,7 +5023,7 @@ static int megasas_init_fw(struct megasas_instance *instance) · 4822 unmodified lines | |||
| 5036 | 5023 | ||
| 5037 | /* Find first memory bar */ | 5024 | /* Find first memory bar */ |
| 5038 | bar_list = pci_select_bars(instance->pdev, IORESOURCE_MEM); | 5025 | bar_list = pci_select_bars(instance->pdev, IORESOURCE_MEM); |
| 5039 | instance->bar = find_first_bit(&bar_list, sizeof(unsigned long)); | 5026 | instance->bar = find_first_bit(&bar_list, BITS_PER_LONG); |
| 5040 | if (pci_request_selected_regions(instance->pdev, 1<<instance->bar, | 5027 | if (pci_request_selected_regions(instance->pdev, 1<<instance->bar, |
| 5041 | "megasas: LSI")) { | 5028 | "megasas: LSI")) { |
| 5042 | dev_printk(KERN_DEBUG, &instance->pdev->dev, "IO memory region busy!\n"); | 5029 | dev_printk(KERN_DEBUG, &instance->pdev->dev, "IO memory region busy!\n"); |
| @@ -5782,7 +5769,7 @@ static int megasas_probe_one(struct pci_dev *pdev, · 739 unmodified lines | |||
| 5782 | &instance->consumer_h); | 5769 | &instance->consumer_h); |
| 5783 | 5770 | ||
| 5784 | if (!instance->producer || !instance->consumer) { | 5771 | if (!instance->producer || !instance->consumer) { |
| 5785 | dev_printk(KERN_DEBUG, &pdev->dev, "Failed to allocate" | 5772 | dev_printk(KERN_DEBUG, &pdev->dev, "Failed to allocate " |
| 5786 | "memory for producer, consumer\n"); | 5773 | "memory for producer, consumer\n"); |
| 5787 | goto fail_alloc_dma_buf; | 5774 | goto fail_alloc_dma_buf; |
| 5788 | } | 5775 | } |
| @@ -6711,14 +6698,9 @@ static int megasas_mgmt_ioctl_fw(struct file *file, unsigned long arg) · 922 unmodified lines | |||
| 6711 | unsigned long flags; | 6698 | unsigned long flags; |
| 6712 | u32 wait_time = MEGASAS_RESET_WAIT_TIME; | 6699 | u32 wait_time = MEGASAS_RESET_WAIT_TIME; |
| 6713 | 6700 | ||
| 6714 | ioc = kmalloc(sizeof(*ioc), GFP_KERNEL); | 6701 | ioc = memdup_user(user_ioc, sizeof(*ioc)); |
| 6715 | if (!ioc) | 6702 | if (IS_ERR(ioc)) |
| 6716 | return -ENOMEM; | 6703 | return PTR_ERR(ioc); |
| 6717 | |||
| 6718 | if (copy_from_user(ioc, user_ioc, sizeof(*ioc))) { | ||
| 6719 | error = -EFAULT; | ||
| 6720 | goto out_kfree_ioc; | ||
| 6721 | } | ||
| 6722 | 6704 | ||
| 6723 | instance = megasas_lookup_instance(ioc->host_no); | 6705 | instance = megasas_lookup_instance(ioc->host_no); |
| 6724 | if (!instance) { | 6706 | if (!instance) { |
| @@ -991,5 +991,14 @@ union desc_value { · 990 unmodified lines | |||
| 991 | } u; | 991 | } u; |
| 992 | }; | 992 | }; |
| 993 | 993 | ||
| 994 | void megasas_free_cmds_fusion(struct megasas_instance *instance); | ||
| 995 | int megasas_ioc_init_fusion(struct megasas_instance *instance); | ||
| 996 | u8 megasas_get_map_info(struct megasas_instance *instance); | ||
| 997 | int megasas_sync_map_info(struct megasas_instance *instance); | ||
| 998 | void megasas_release_fusion(struct megasas_instance *instance); | ||
| 999 | void megasas_reset_reply_desc(struct megasas_instance *instance); | ||
| 1000 | int megasas_check_mpio_paths(struct megasas_instance *instance, | ||
| 1001 | struct scsi_cmnd *scmd); | ||
| 1002 | void megasas_fusion_ocr_wq(struct work_struct *work); | ||
| 994 | 1003 | ||
| 995 | #endif /* _MEGARAID_SAS_FUSION_H_ */ | 1004 | #endif /* _MEGARAID_SAS_FUSION_H_ */ |
| @@ -98,7 +98,7 @@ MODULE_PARM_DESC(mpt3sas_fwfault_debug, · 97 unmodified lines | |||
| 98 | " enable detection of firmware fault and halt firmware - (default=0)"); | 98 | " enable detection of firmware fault and halt firmware - (default=0)"); |
| 99 | 99 | ||
| 100 | static int | 100 | static int |
| 101 | _base_get_ioc_facts(struct MPT3SAS_ADAPTER *ioc, int sleep_flag); | 101 | _base_get_ioc_facts(struct MPT3SAS_ADAPTER *ioc); |
| 102 | 102 | ||
| 103 | /** | 103 | /** |
| 104 | * _scsih_set_fwfault_debug - global setting of ioc->fwfault_debug. | 104 | * _scsih_set_fwfault_debug - global setting of ioc->fwfault_debug. |
| @@ -218,8 +218,7 @@ _base_fault_reset_work(struct work_struct *work) · 113 unmodified lines | |||
| 218 | ioc->non_operational_loop = 0; | 218 | ioc->non_operational_loop = 0; |
| 219 | 219 | ||
| 220 | if ((doorbell & MPI2_IOC_STATE_MASK) != MPI2_IOC_STATE_OPERATIONAL) { | 220 | if ((doorbell & MPI2_IOC_STATE_MASK) != MPI2_IOC_STATE_OPERATIONAL) { |
| 221 | rc = mpt3sas_base_hard_reset_handler(ioc, CAN_SLEEP, | 221 | rc = mpt3sas_base_hard_reset_handler(ioc, FORCE_BIG_HAMMER); |
| 222 | FORCE_BIG_HAMMER); | ||
| 223 | pr_warn(MPT3SAS_FMT "%s: hard reset: %s\n", ioc->name, | 222 | pr_warn(MPT3SAS_FMT "%s: hard reset: %s\n", ioc->name, |
| 224 | __func__, (rc == 0) ? "success" : "failed"); | 223 | __func__, (rc == 0) ? "success" : "failed"); |
| 225 | doorbell = mpt3sas_base_get_iocstate(ioc, 0); | 224 | doorbell = mpt3sas_base_get_iocstate(ioc, 0); |
| @@ -2040,7 +2039,7 @@ _base_enable_msix(struct MPT3SAS_ADAPTER *ioc) · 1814 unmodified lines | |||
| 2040 | * mpt3sas_base_unmap_resources - free controller resources | 2039 | * mpt3sas_base_unmap_resources - free controller resources |
| 2041 | * @ioc: per adapter object | 2040 | * @ioc: per adapter object |
| 2042 | */ | 2041 | */ |
| 2043 | void | 2042 | static void |
| 2044 | mpt3sas_base_unmap_resources(struct MPT3SAS_ADAPTER *ioc) | 2043 | mpt3sas_base_unmap_resources(struct MPT3SAS_ADAPTER *ioc) |
| 2045 | { | 2044 | { |
| 2046 | struct pci_dev *pdev = ioc->pdev; | 2045 | struct pci_dev *pdev = ioc->pdev; |
| @@ -2145,7 +2144,7 @@ mpt3sas_base_map_resources(struct MPT3SAS_ADAPTER *ioc) · 98 unmodified lines | |||
| 2145 | 2144 | ||
| 2146 | _base_mask_interrupts(ioc); | 2145 | _base_mask_interrupts(ioc); |
| 2147 | 2146 | ||
| 2148 | r = _base_get_ioc_facts(ioc, CAN_SLEEP); | 2147 | r = _base_get_ioc_facts(ioc); |
| 2149 | if (r) | 2148 | if (r) |
| 2150 | goto out_fail; | 2149 | goto out_fail; |
| 2151 | 2150 | ||
| @@ -3183,12 +3182,11 @@ _base_release_memory_pools(struct MPT3SAS_ADAPTER *ioc) · 1031 unmodified lines | |||
| 3183 | /** | 3182 | /** |
| 3184 | * _base_allocate_memory_pools - allocate start of day memory pools | 3183 | * _base_allocate_memory_pools - allocate start of day memory pools |
| 3185 | * @ioc: per adapter object | 3184 | * @ioc: per adapter object |
| 3186 | * @sleep_flag: CAN_SLEEP or NO_SLEEP | ||
| 3187 | * | 3185 | * |
| 3188 | * Returns 0 success, anything else error | 3186 | * Returns 0 success, anything else error |
| 3189 | */ | 3187 | */ |
| 3190 | static int | 3188 | static int |
| 3191 | _base_allocate_memory_pools(struct MPT3SAS_ADAPTER *ioc, int sleep_flag) | 3189 | _base_allocate_memory_pools(struct MPT3SAS_ADAPTER *ioc) |
| 3192 | { | 3190 | { |
| 3193 | struct mpt3sas_facts *facts; | 3191 | struct mpt3sas_facts *facts; |
| 3194 | u16 max_sge_elements; | 3192 | u16 max_sge_elements; |
| @@ -3658,29 +3656,25 @@ mpt3sas_base_get_iocstate(struct MPT3SAS_ADAPTER *ioc, int cooked) · 463 unmodified lines | |||
| 3658 | * _base_wait_on_iocstate - waiting on a particular ioc state | 3656 | * _base_wait_on_iocstate - waiting on a particular ioc state |
| 3659 | * @ioc_state: controller state { READY, OPERATIONAL, or RESET } | 3657 | * @ioc_state: controller state { READY, OPERATIONAL, or RESET } |
| 3660 | * @timeout: timeout in second | 3658 | * @timeout: timeout in second |
| 3661 | * @sleep_flag: CAN_SLEEP or NO_SLEEP | ||
| 3662 | * | 3659 | * |
| 3663 | * Returns 0 for success, non-zero for failure. | 3660 | * Returns 0 for success, non-zero for failure. |
| 3664 | */ | 3661 | */ |
| 3665 | static int | 3662 | static int |
| 3666 | _base_wait_on_iocstate(struct MPT3SAS_ADAPTER *ioc, u32 ioc_state, int timeout, | 3663 | _base_wait_on_iocstate(struct MPT3SAS_ADAPTER *ioc, u32 ioc_state, int timeout) |
| 3667 | int sleep_flag) | ||
| 3668 | { | 3664 | { |
| 3669 | u32 count, cntdn; | 3665 | u32 count, cntdn; |
| 3670 | u32 current_state; | 3666 | u32 current_state; |
| 3671 | 3667 | ||
| 3672 | count = 0; | 3668 | count = 0; |
| 3673 | cntdn = (sleep_flag == CAN_SLEEP) ? 1000*timeout : 2000*timeout; | 3669 | cntdn = 1000 * timeout; |
| 3674 | do { | 3670 | do { |
| 3675 | current_state = mpt3sas_base_get_iocstate(ioc, 1); | 3671 | current_state = mpt3sas_base_get_iocstate(ioc, 1); |
| 3676 | if (current_state == ioc_state) | 3672 | if (current_state == ioc_state) |
| 3677 | return 0; | 3673 | return 0; |
| 3678 | if (count && current_state == MPI2_IOC_STATE_FAULT) | 3674 | if (count && current_state == MPI2_IOC_STATE_FAULT) |
| 3679 | break; | 3675 | break; |
| 3680 | if (sleep_flag == CAN_SLEEP) | 3676 | |
| 3681 | usleep_range(1000, 1500); | 3677 | usleep_range(1000, 1500); |
| 3682 | else | ||
| 3683 | udelay(500); | ||
| 3684 | count++; | 3678 | count++; |
| 3685 | } while (--cntdn); | 3679 | } while (--cntdn); |
| 3686 | 3680 | ||
| @@ -3692,24 +3686,22 @@ _base_wait_on_iocstate(struct MPT3SAS_ADAPTER *ioc, u32 ioc_state, int timeout, · 5 unmodified lines | |||
| 3692 | * a write to the doorbell) | 3686 | * a write to the doorbell) |
| 3693 | * @ioc: per adapter object | 3687 | * @ioc: per adapter object |
| 3694 | * @timeout: timeout in second | 3688 | * @timeout: timeout in second |
| 3695 | * @sleep_flag: CAN_SLEEP or NO_SLEEP | ||
| 3696 | * | 3689 | * |
| 3697 | * Returns 0 for success, non-zero for failure. | 3690 | * Returns 0 for success, non-zero for failure. |
| 3698 | * | 3691 | * |
| 3699 | * Notes: MPI2_HIS_IOC2SYS_DB_STATUS - set to one when IOC writes to doorbell. | 3692 | * Notes: MPI2_HIS_IOC2SYS_DB_STATUS - set to one when IOC writes to doorbell. |
| 3700 | */ | 3693 | */ |
| 3701 | static int | 3694 | static int |
| 3702 | _base_diag_reset(struct MPT3SAS_ADAPTER *ioc, int sleep_flag); | 3695 | _base_diag_reset(struct MPT3SAS_ADAPTER *ioc); |
| 3703 | 3696 | ||
| 3704 | static int | 3697 | static int |
| 3705 | _base_wait_for_doorbell_int(struct MPT3SAS_ADAPTER *ioc, int timeout, | 3698 | _base_wait_for_doorbell_int(struct MPT3SAS_ADAPTER *ioc, int timeout) |
| 3706 | int sleep_flag) | ||
| 3707 | { | 3699 | { |
| 3708 | u32 cntdn, count; | 3700 | u32 cntdn, count; |
| 3709 | u32 int_status; | 3701 | u32 int_status; |
| 3710 | 3702 | ||
| 3711 | count = 0; | 3703 | count = 0; |
| 3712 | cntdn = (sleep_flag == CAN_SLEEP) ? 1000*timeout : 2000*timeout; | 3704 | cntdn = 1000 * timeout; |
| 3713 | do { | 3705 | do { |
| 3714 | int_status = readl(&ioc->chip->HostInterruptStatus); | 3706 | int_status = readl(&ioc->chip->HostInterruptStatus); |
| 3715 | if (int_status & MPI2_HIS_IOC2SYS_DB_STATUS) { | 3707 | if (int_status & MPI2_HIS_IOC2SYS_DB_STATUS) { |
| @@ -3718,10 +3710,35 @@ _base_wait_for_doorbell_int(struct MPT3SAS_ADAPTER *ioc, int timeout, · 2 unmodified lines | |||
| 3718 | ioc->name, __func__, count, timeout)); | 3710 | ioc->name, __func__, count, timeout)); |
| 3719 | return 0; | 3711 | return 0; |
| 3720 | } | 3712 | } |
| 3721 | if (sleep_flag == CAN_SLEEP) | 3713 | |
| 3722 | usleep_range(1000, 1500); | 3714 | usleep_range(1000, 1500); |
| 3723 | else | 3715 | count++; |
| 3724 | udelay(500); | 3716 | } while (--cntdn); |
| 3717 | |||
| 3718 | pr_err(MPT3SAS_FMT | ||
| 3719 | "%s: failed due to timeout count(%d), int_status(%x)!\n", | ||
| 3720 | ioc->name, __func__, count, int_status); | ||
| 3721 | return -EFAULT; | ||
| 3722 | } | ||
| 3723 | |||
| 3724 | static int | ||
| 3725 | _base_spin_on_doorbell_int(struct MPT3SAS_ADAPTER *ioc, int timeout) | ||
| 3726 | { | ||
| 3727 | u32 cntdn, count; | ||
| 3728 | u32 int_status; | ||
| 3729 | |||
| 3730 | count = 0; | ||
| 3731 | cntdn = 2000 * timeout; | ||
| 3732 | do { | ||
| 3733 | int_status = readl(&ioc->chip->HostInterruptStatus); | ||
| 3734 | if (int_status & MPI2_HIS_IOC2SYS_DB_STATUS) { | ||
| 3735 | dhsprintk(ioc, pr_info(MPT3SAS_FMT | ||
| 3736 | "%s: successful count(%d), timeout(%d)\n", | ||
| 3737 | ioc->name, __func__, count, timeout)); | ||
| 3738 | return 0; | ||
| 3739 | } | ||
| 3740 | |||
| 3741 | udelay(500); | ||
| 3725 | count++; | 3742 | count++; |
| 3726 | } while (--cntdn); | 3743 | } while (--cntdn); |
| 3727 | 3744 | ||
| @@ -3729,13 +3746,13 @@ _base_wait_for_doorbell_int(struct MPT3SAS_ADAPTER *ioc, int timeout, · 1 unmodified line | |||
| 3729 | "%s: failed due to timeout count(%d), int_status(%x)!\n", | 3746 | "%s: failed due to timeout count(%d), int_status(%x)!\n", |
| 3730 | ioc->name, __func__, count, int_status); | 3747 | ioc->name, __func__, count, int_status); |
| 3731 | return -EFAULT; | 3748 | return -EFAULT; |
| 3749 | |||
| 3732 | } | 3750 | } |
| 3733 | 3751 | ||
| 3734 | /** | 3752 | /** |
| 3735 | * _base_wait_for_doorbell_ack - waiting for controller to read the doorbell. | 3753 | * _base_wait_for_doorbell_ack - waiting for controller to read the doorbell. |
| 3736 | * @ioc: per adapter object | 3754 | * @ioc: per adapter object |
| 3737 | * @timeout: timeout in second | 3755 | * @timeout: timeout in second |
| 3738 | * @sleep_flag: CAN_SLEEP or NO_SLEEP | ||
| 3739 | * | 3756 | * |
| 3740 | * Returns 0 for success, non-zero for failure. | 3757 | * Returns 0 for success, non-zero for failure. |
| 3741 | * | 3758 | * |
| @@ -3743,15 +3760,14 @@ _base_wait_for_doorbell_int(struct MPT3SAS_ADAPTER *ioc, int timeout, · 1 unmodified line | |||
| 3743 | * doorbell. | 3760 | * doorbell. |
| 3744 | */ | 3761 | */ |
| 3745 | static int | 3762 | static int |
| 3746 | _base_wait_for_doorbell_ack(struct MPT3SAS_ADAPTER *ioc, int timeout, | 3763 | _base_wait_for_doorbell_ack(struct MPT3SAS_ADAPTER *ioc, int timeout) |
| 3747 | int sleep_flag) | ||
| 3748 | { | 3764 | { |
| 3749 | u32 cntdn, count; | 3765 | u32 cntdn, count; |
| 3750 | u32 int_status; | 3766 | u32 int_status; |
| 3751 | u32 doorbell; | 3767 | u32 doorbell; |
| 3752 | 3768 | ||
| 3753 | count = 0; | 3769 | count = 0; |
| 3754 | cntdn = (sleep_flag == CAN_SLEEP) ? 1000*timeout : 2000*timeout; | 3770 | cntdn = 1000 * timeout; |
| 3755 | do { | 3771 | do { |
| 3756 | int_status = readl(&ioc->chip->HostInterruptStatus); | 3772 | int_status = readl(&ioc->chip->HostInterruptStatus); |
| 3757 | if (!(int_status & MPI2_HIS_SYS2IOC_DB_STATUS)) { | 3773 | if (!(int_status & MPI2_HIS_SYS2IOC_DB_STATUS)) { |
| @@ -3769,10 +3785,7 @@ _base_wait_for_doorbell_ack(struct MPT3SAS_ADAPTER *ioc, int timeout, · 11 unmodified lines | |||
| 3769 | } else if (int_status == 0xFFFFFFFF) | 3785 | } else if (int_status == 0xFFFFFFFF) |
| 3770 | goto out; | 3786 | goto out; |
| 3771 | 3787 | ||
| 3772 | if (sleep_flag == CAN_SLEEP) | 3788 | usleep_range(1000, 1500); |
| 3773 | usleep_range(1000, 1500); | ||
| 3774 | else | ||
| 3775 | udelay(500); | ||
| 3776 | count++; | 3789 | count++; |
| 3777 | } while (--cntdn); | 3790 | } while (--cntdn); |
| 3778 | 3791 | ||
| @@ -3787,20 +3800,18 @@ _base_wait_for_doorbell_ack(struct MPT3SAS_ADAPTER *ioc, int timeout, · 8 unmodified lines | |||
| 3787 | * _base_wait_for_doorbell_not_used - waiting for doorbell to not be in use | 3800 | * _base_wait_for_doorbell_not_used - waiting for doorbell to not be in use |
| 3788 | * @ioc: per adapter object | 3801 | * @ioc: per adapter object |
| 3789 | * @timeout: timeout in second | 3802 | * @timeout: timeout in second |
| 3790 | * @sleep_flag: CAN_SLEEP or NO_SLEEP | ||
| 3791 | * | 3803 | * |
| 3792 | * Returns 0 for success, non-zero for failure. | 3804 | * Returns 0 for success, non-zero for failure. |
| 3793 | * | 3805 | * |
| 3794 | */ | 3806 | */ |
| 3795 | static int | 3807 | static int |
| 3796 | _base_wait_for_doorbell_not_used(struct MPT3SAS_ADAPTER *ioc, int timeout, | 3808 | _base_wait_for_doorbell_not_used(struct MPT3SAS_ADAPTER *ioc, int timeout) |
| 3797 | int sleep_flag) | ||
| 3798 | { | 3809 | { |
| 3799 | u32 cntdn, count; | 3810 | u32 cntdn, count; |
| 3800 | u32 doorbell_reg; | 3811 | u32 doorbell_reg; |
| 3801 | 3812 | ||
| 3802 | count = 0; | 3813 | count = 0; |
| 3803 | cntdn = (sleep_flag == CAN_SLEEP) ? 1000*timeout : 2000*timeout; | 3814 | cntdn = 1000 * timeout; |
| 3804 | do { | 3815 | do { |
| 3805 | doorbell_reg = readl(&ioc->chip->Doorbell); | 3816 | doorbell_reg = readl(&ioc->chip->Doorbell); |
| 3806 | if (!(doorbell_reg & MPI2_DOORBELL_USED)) { | 3817 | if (!(doorbell_reg & MPI2_DOORBELL_USED)) { |
| @@ -3809,10 +3820,8 @@ _base_wait_for_doorbell_not_used(struct MPT3SAS_ADAPTER *ioc, int timeout, · 2 unmodified lines | |||
| 3809 | ioc->name, __func__, count, timeout)); | 3820 | ioc->name, __func__, count, timeout)); |
| 3810 | return 0; | 3821 | return 0; |
| 3811 | } | 3822 | } |
| 3812 | if (sleep_flag == CAN_SLEEP) | 3823 | |
| 3813 | usleep_range(1000, 1500); | 3824 | usleep_range(1000, 1500); |
| 3814 | else | ||
| 3815 | udelay(500); | ||
| 3816 | count++; | 3825 | count++; |
| 3817 | } while (--cntdn); | 3826 | } while (--cntdn); |
| 3818 | 3827 | ||
| @@ -3827,13 +3836,11 @@ _base_wait_for_doorbell_not_used(struct MPT3SAS_ADAPTER *ioc, int timeout, · 8 unmodified lines | |||
| 3827 | * @ioc: per adapter object | 3836 | * @ioc: per adapter object |
| 3828 | * @reset_type: currently only supports: MPI2_FUNCTION_IOC_MESSAGE_UNIT_RESET | 3837 | * @reset_type: currently only supports: MPI2_FUNCTION_IOC_MESSAGE_UNIT_RESET |
| 3829 | * @timeout: timeout in second | 3838 | * @timeout: timeout in second |
| 3830 | * @sleep_flag: CAN_SLEEP or NO_SLEEP | ||
| 3831 | * | 3839 | * |
| 3832 | * Returns 0 for success, non-zero for failure. | 3840 | * Returns 0 for success, non-zero for failure. |
| 3833 | */ | 3841 | */ |
| 3834 | static int | 3842 | static int |
| 3835 | _base_send_ioc_reset(struct MPT3SAS_ADAPTER *ioc, u8 reset_type, int timeout, | 3843 | _base_send_ioc_reset(struct MPT3SAS_ADAPTER *ioc, u8 reset_type, int timeout) |
| 3836 | int sleep_flag) | ||
| 3837 | { | 3844 | { |
| 3838 | u32 ioc_state; | 3845 | u32 ioc_state; |
| 3839 | int r = 0; | 3846 | int r = 0; |
| @@ -3852,12 +3859,11 @@ _base_send_ioc_reset(struct MPT3SAS_ADAPTER *ioc, u8 reset_type, int timeout, · 12 unmodified lines | |||
| 3852 | 3859 | ||
| 3853 | writel(reset_type << MPI2_DOORBELL_FUNCTION_SHIFT, | 3860 | writel(reset_type << MPI2_DOORBELL_FUNCTION_SHIFT, |
| 3854 | &ioc->chip->Doorbell); | 3861 | &ioc->chip->Doorbell); |
| 3855 | if ((_base_wait_for_doorbell_ack(ioc, 15, sleep_flag))) { | 3862 | if ((_base_wait_for_doorbell_ack(ioc, 15))) { |
| 3856 | r = -EFAULT; | 3863 | r = -EFAULT; |
| 3857 | goto out; | 3864 | goto out; |
| 3858 | } | 3865 | } |
| 3859 | ioc_state = _base_wait_on_iocstate(ioc, MPI2_IOC_STATE_READY, | 3866 | ioc_state = _base_wait_on_iocstate(ioc, MPI2_IOC_STATE_READY, timeout); |
| 3860 | timeout, sleep_flag); | ||
| 3861 | if (ioc_state) { | 3867 | if (ioc_state) { |
| 3862 | pr_err(MPT3SAS_FMT | 3868 | pr_err(MPT3SAS_FMT |
| 3863 | "%s: failed going to ready state (ioc_state=0x%x)\n", | 3869 | "%s: failed going to ready state (ioc_state=0x%x)\n", |
| @@ -3879,18 +3885,16 @@ _base_send_ioc_reset(struct MPT3SAS_ADAPTER *ioc, u8 reset_type, int timeout, · 15 unmodified lines | |||
| 3879 | * @reply_bytes: reply length | 3885 | * @reply_bytes: reply length |
| 3880 | * @reply: pointer to reply payload | 3886 | * @reply: pointer to reply payload |
| 3881 | * @timeout: timeout in second | 3887 | * @timeout: timeout in second |
| 3882 | * @sleep_flag: CAN_SLEEP or NO_SLEEP | ||
| 3883 | * | 3888 | * |
| 3884 | * Returns 0 for success, non-zero for failure. | 3889 | * Returns 0 for success, non-zero for failure. |
| 3885 | */ | 3890 | */ |
| 3886 | static int | 3891 | static int |
| 3887 | _base_handshake_req_reply_wait(struct MPT3SAS_ADAPTER *ioc, int request_bytes, | 3892 | _base_handshake_req_reply_wait(struct MPT3SAS_ADAPTER *ioc, int request_bytes, |
| 3888 | u32 *request, int reply_bytes, u16 *reply, int timeout, int sleep_flag) | 3893 | u32 *request, int reply_bytes, u16 *reply, int timeout) |
| 3889 | { | 3894 | { |
| 3890 | MPI2DefaultReply_t *default_reply = (MPI2DefaultReply_t *)reply; | 3895 | MPI2DefaultReply_t *default_reply = (MPI2DefaultReply_t *)reply; |
| 3891 | int i; | 3896 | int i; |
| 3892 | u8 failed; | 3897 | u8 failed; |
| 3893 | u16 dummy; | ||
| 3894 | __le32 *mfp; | 3898 | __le32 *mfp; |
| 3895 | 3899 | ||
| 3896 | /* make sure doorbell is not in use */ | 3900 | /* make sure doorbell is not in use */ |
| @@ -3911,7 +3915,7 @@ _base_handshake_req_reply_wait(struct MPT3SAS_ADAPTER *ioc, int request_bytes, · 14 unmodified lines | |||
| 3911 | ((request_bytes/4)<<MPI2_DOORBELL_ADD_DWORDS_SHIFT)), | 3915 | ((request_bytes/4)<<MPI2_DOORBELL_ADD_DWORDS_SHIFT)), |
| 3912 | &ioc->chip->Doorbell); | 3916 | &ioc->chip->Doorbell); |
| 3913 | 3917 | ||
| 3914 | if ((_base_wait_for_doorbell_int(ioc, 5, NO_SLEEP))) { | 3918 | if ((_base_spin_on_doorbell_int(ioc, 5))) { |
| 3915 | pr_err(MPT3SAS_FMT | 3919 | pr_err(MPT3SAS_FMT |
| 3916 | "doorbell handshake int failed (line=%d)\n", | 3920 | "doorbell handshake int failed (line=%d)\n", |
| 3917 | ioc->name, __LINE__); | 3921 | ioc->name, __LINE__); |
| @@ -3919,7 +3923,7 @@ _base_handshake_req_reply_wait(struct MPT3SAS_ADAPTER *ioc, int request_bytes, · 1 unmodified line | |||
| 3919 | } | 3923 | } |
| 3920 | writel(0, &ioc->chip->HostInterruptStatus); | 3924 | writel(0, &ioc->chip->HostInterruptStatus); |
| 3921 | 3925 | ||
| 3922 | if ((_base_wait_for_doorbell_ack(ioc, 5, sleep_flag))) { | 3926 | if ((_base_wait_for_doorbell_ack(ioc, 5))) { |
| 3923 | pr_err(MPT3SAS_FMT | 3927 | pr_err(MPT3SAS_FMT |
| 3924 | "doorbell handshake ack failed (line=%d)\n", | 3928 | "doorbell handshake ack failed (line=%d)\n", |
| 3925 | ioc->name, __LINE__); | 3929 | ioc->name, __LINE__); |
| @@ -3929,7 +3933,7 @@ _base_handshake_req_reply_wait(struct MPT3SAS_ADAPTER *ioc, int request_bytes, · 3 unmodified lines | |||
| 3929 | /* send message 32-bits at a time */ | 3933 | /* send message 32-bits at a time */ |
| 3930 | for (i = 0, failed = 0; i < request_bytes/4 && !failed; i++) { | 3934 | for (i = 0, failed = 0; i < request_bytes/4 && !failed; i++) { |
| 3931 | writel(cpu_to_le32(request[i]), &ioc->chip->Doorbell); | 3935 | writel(cpu_to_le32(request[i]), &ioc->chip->Doorbell); |
| 3932 | if ((_base_wait_for_doorbell_ack(ioc, 5, sleep_flag))) | 3936 | if ((_base_wait_for_doorbell_ack(ioc, 5))) |
| 3933 | failed = 1; | 3937 | failed = 1; |
| 3934 | } | 3938 | } |
| 3935 | 3939 | ||
| @@ -3941,7 +3945,7 @@ _base_handshake_req_reply_wait(struct MPT3SAS_ADAPTER *ioc, int request_bytes, · 5 unmodified lines | |||
| 3941 | } | 3945 | } |
| 3942 | 3946 | ||
| 3943 | /* now wait for the reply */ | 3947 | /* now wait for the reply */ |
| 3944 | if ((_base_wait_for_doorbell_int(ioc, timeout, sleep_flag))) { | 3948 | if ((_base_wait_for_doorbell_int(ioc, timeout))) { |
| 3945 | pr_err(MPT3SAS_FMT | 3949 | pr_err(MPT3SAS_FMT |
| 3946 | "doorbell handshake int failed (line=%d)\n", | 3950 | "doorbell handshake int failed (line=%d)\n", |
| 3947 | ioc->name, __LINE__); | 3951 | ioc->name, __LINE__); |
| @@ -3952,7 +3956,7 @@ _base_handshake_req_reply_wait(struct MPT3SAS_ADAPTER *ioc, int request_bytes, · 4 unmodified lines | |||
| 3952 | reply[0] = le16_to_cpu(readl(&ioc->chip->Doorbell) | 3956 | reply[0] = le16_to_cpu(readl(&ioc->chip->Doorbell) |
| 3953 | & MPI2_DOORBELL_DATA_MASK); | 3957 | & MPI2_DOORBELL_DATA_MASK); |
| 3954 | writel(0, &ioc->chip->HostInterruptStatus); | 3958 | writel(0, &ioc->chip->HostInterruptStatus); |
| 3955 | if ((_base_wait_for_doorbell_int(ioc, 5, sleep_flag))) { | 3959 | if ((_base_wait_for_doorbell_int(ioc, 5))) { |
| 3956 | pr_err(MPT3SAS_FMT | 3960 | pr_err(MPT3SAS_FMT |
| 3957 | "doorbell handshake int failed (line=%d)\n", | 3961 | "doorbell handshake int failed (line=%d)\n", |
| 3958 | ioc->name, __LINE__); | 3962 | ioc->name, __LINE__); |
| @@ -3963,22 +3967,22 @@ _base_handshake_req_reply_wait(struct MPT3SAS_ADAPTER *ioc, int request_bytes, · 4 unmodified lines | |||
| 3963 | writel(0, &ioc->chip->HostInterruptStatus); | 3967 | writel(0, &ioc->chip->HostInterruptStatus); |
| 3964 | 3968 | ||
| 3965 | for (i = 2; i < default_reply->MsgLength * 2; i++) { | 3969 | for (i = 2; i < default_reply->MsgLength * 2; i++) { |
| 3966 | if ((_base_wait_for_doorbell_int(ioc, 5, sleep_flag))) { | 3970 | if ((_base_wait_for_doorbell_int(ioc, 5))) { |
| 3967 | pr_err(MPT3SAS_FMT | 3971 | pr_err(MPT3SAS_FMT |
| 3968 | "doorbell handshake int failed (line=%d)\n", | 3972 | "doorbell handshake int failed (line=%d)\n", |
| 3969 | ioc->name, __LINE__); | 3973 | ioc->name, __LINE__); |
| 3970 | return -EFAULT; | 3974 | return -EFAULT; |
| 3971 | } | 3975 | } |
| 3972 | if (i >= reply_bytes/2) /* overflow case */ | 3976 | if (i >= reply_bytes/2) /* overflow case */ |
| 3973 | dummy = readl(&ioc->chip->Doorbell); | 3977 | readl(&ioc->chip->Doorbell); |
| 3974 | else | 3978 | else |
| 3975 | reply[i] = le16_to_cpu(readl(&ioc->chip->Doorbell) | 3979 | reply[i] = le16_to_cpu(readl(&ioc->chip->Doorbell) |
| 3976 | & MPI2_DOORBELL_DATA_MASK); | 3980 | & MPI2_DOORBELL_DATA_MASK); |
| 3977 | writel(0, &ioc->chip->HostInterruptStatus); | 3981 | writel(0, &ioc->chip->HostInterruptStatus); |
| 3978 | } | 3982 | } |
| 3979 | 3983 | ||
| 3980 | _base_wait_for_doorbell_int(ioc, 5, sleep_flag); | 3984 | _base_wait_for_doorbell_int(ioc, 5); |
| 3981 | if (_base_wait_for_doorbell_not_used(ioc, 5, sleep_flag) != 0) { | 3985 | if (_base_wait_for_doorbell_not_used(ioc, 5) != 0) { |
| 3982 | dhsprintk(ioc, pr_info(MPT3SAS_FMT | 3986 | dhsprintk(ioc, pr_info(MPT3SAS_FMT |
| 3983 | "doorbell is in use (line=%d)\n", ioc->name, __LINE__)); | 3987 | "doorbell is in use (line=%d)\n", ioc->name, __LINE__)); |
| 3984 | } | 3988 | } |
| @@ -4015,7 +4019,6 @@ mpt3sas_base_sas_iounit_control(struct MPT3SAS_ADAPTER *ioc, · 30 unmodified lines | |||
| 4015 | { | 4019 | { |
| 4016 | u16 smid; | 4020 | u16 smid; |
| 4017 | u32 ioc_state; | 4021 | u32 ioc_state; |
| 4018 | unsigned long timeleft; | ||
| 4019 | bool issue_reset = false; | 4022 | bool issue_reset = false; |
| 4020 | int rc; | 4023 | int rc; |
| 4021 | void *request; | 4024 | void *request; |
| @@ -4068,7 +4071,7 @@ mpt3sas_base_sas_iounit_control(struct MPT3SAS_ADAPTER *ioc, · 46 unmodified lines | |||
| 4068 | ioc->ioc_link_reset_in_progress = 1; | 4071 | ioc->ioc_link_reset_in_progress = 1; |
| 4069 | init_completion(&ioc->base_cmds.done); | 4072 | init_completion(&ioc->base_cmds.done); |
| 4070 | mpt3sas_base_put_smid_default(ioc, smid); | 4073 | mpt3sas_base_put_smid_default(ioc, smid); |
| 4071 | timeleft = wait_for_completion_timeout(&ioc->base_cmds.done, | 4074 | wait_for_completion_timeout(&ioc->base_cmds.done, |
| 4072 | msecs_to_jiffies(10000)); | 4075 | msecs_to_jiffies(10000)); |
| 4073 | if ((mpi_request->Operation == MPI2_SAS_OP_PHY_HARD_RESET || | 4076 | if ((mpi_request->Operation == MPI2_SAS_OP_PHY_HARD_RESET || |
| 4074 | mpi_request->Operation == MPI2_SAS_OP_PHY_LINK_RESET) && | 4077 | mpi_request->Operation == MPI2_SAS_OP_PHY_LINK_RESET) && |
| @@ -4093,8 +4096,7 @@ mpt3sas_base_sas_iounit_control(struct MPT3SAS_ADAPTER *ioc, · 18 unmodified lines | |||
| 4093 | 4096 | ||
| 4094 | issue_host_reset: | 4097 | issue_host_reset: |
| 4095 | if (issue_reset) | 4098 | if (issue_reset) |
| 4096 | mpt3sas_base_hard_reset_handler(ioc, CAN_SLEEP, | 4099 | mpt3sas_base_hard_reset_handler(ioc, FORCE_BIG_HAMMER); |
| 4097 | FORCE_BIG_HAMMER); | ||
| 4098 | ioc->base_cmds.status = MPT3_CMD_NOT_USED; | 4100 | ioc->base_cmds.status = MPT3_CMD_NOT_USED; |
| 4099 | rc = -EFAULT; | 4101 | rc = -EFAULT; |
| 4100 | out: | 4102 | out: |
| @@ -4119,7 +4121,6 @@ mpt3sas_base_scsi_enclosure_processor(struct MPT3SAS_ADAPTER *ioc, · 18 unmodified lines | |||
| 4119 | { | 4121 | { |
| 4120 | u16 smid; | 4122 | u16 smid; |
| 4121 | u32 ioc_state; | 4123 | u32 ioc_state; |
| 4122 | unsigned long timeleft; | ||
| 4123 | bool issue_reset = false; | 4124 | bool issue_reset = false; |
| 4124 | int rc; | 4125 | int rc; |
| 4125 | void *request; | 4126 | void *request; |
| @@ -4170,7 +4171,7 @@ mpt3sas_base_scsi_enclosure_processor(struct MPT3SAS_ADAPTER *ioc, · 44 unmodified lines | |||
| 4170 | memcpy(request, mpi_request, sizeof(Mpi2SepReply_t)); | 4171 | memcpy(request, mpi_request, sizeof(Mpi2SepReply_t)); |
| 4171 | init_completion(&ioc->base_cmds.done); | 4172 | init_completion(&ioc->base_cmds.done); |
| 4172 | mpt3sas_base_put_smid_default(ioc, smid); | 4173 | mpt3sas_base_put_smid_default(ioc, smid); |
| 4173 | timeleft = wait_for_completion_timeout(&ioc->base_cmds.done, | 4174 | wait_for_completion_timeout(&ioc->base_cmds.done, |
| 4174 | msecs_to_jiffies(10000)); | 4175 | msecs_to_jiffies(10000)); |
| 4175 | if (!(ioc->base_cmds.status & MPT3_CMD_COMPLETE)) { | 4176 | if (!(ioc->base_cmds.status & MPT3_CMD_COMPLETE)) { |
| 4176 | pr_err(MPT3SAS_FMT "%s: timeout\n", | 4177 | pr_err(MPT3SAS_FMT "%s: timeout\n", |
| @@ -4191,8 +4192,7 @@ mpt3sas_base_scsi_enclosure_processor(struct MPT3SAS_ADAPTER *ioc, · 14 unmodified lines | |||
| 4191 | 4192 | ||
| 4192 | issue_host_reset: | 4193 | issue_host_reset: |
| 4193 | if (issue_reset) | 4194 | if (issue_reset) |
| 4194 | mpt3sas_base_hard_reset_handler(ioc, CAN_SLEEP, | 4195 | mpt3sas_base_hard_reset_handler(ioc, FORCE_BIG_HAMMER); |
| 4195 | FORCE_BIG_HAMMER); | ||
| 4196 | ioc->base_cmds.status = MPT3_CMD_NOT_USED; | 4196 | ioc->base_cmds.status = MPT3_CMD_NOT_USED; |
| 4197 | rc = -EFAULT; | 4197 | rc = -EFAULT; |
| 4198 | out: | 4198 | out: |
| @@ -4203,12 +4203,11 @@ mpt3sas_base_scsi_enclosure_processor(struct MPT3SAS_ADAPTER *ioc, · 4 unmodified lines | |||
| 4203 | /** | 4203 | /** |
| 4204 | * _base_get_port_facts - obtain port facts reply and save in ioc | 4204 | * _base_get_port_facts - obtain port facts reply and save in ioc |
| 4205 | * @ioc: per adapter object | 4205 | * @ioc: per adapter object |
| 4206 | * @sleep_flag: CAN_SLEEP or NO_SLEEP | ||
| 4207 | * | 4206 | * |
| 4208 | * Returns 0 for success, non-zero for failure. | 4207 | * Returns 0 for success, non-zero for failure. |
| 4209 | */ | 4208 | */ |
| 4210 | static int | 4209 | static int |
| 4211 | _base_get_port_facts(struct MPT3SAS_ADAPTER *ioc, int port, int sleep_flag) | 4210 | _base_get_port_facts(struct MPT3SAS_ADAPTER *ioc, int port) |
| 4212 | { | 4211 | { |
| 4213 | Mpi2PortFactsRequest_t mpi_request; | 4212 | Mpi2PortFactsRequest_t mpi_request; |
| 4214 | Mpi2PortFactsReply_t mpi_reply; | 4213 | Mpi2PortFactsReply_t mpi_reply; |
| @@ -4224,7 +4223,7 @@ _base_get_port_facts(struct MPT3SAS_ADAPTER *ioc, int port, int sleep_flag) · 9 unmodified lines | |||
| 4224 | mpi_request.Function = MPI2_FUNCTION_PORT_FACTS; | 4223 | mpi_request.Function = MPI2_FUNCTION_PORT_FACTS; |
| 4225 | mpi_request.PortNumber = port; | 4224 | mpi_request.PortNumber = port; |
| 4226 | r = _base_handshake_req_reply_wait(ioc, mpi_request_sz, | 4225 | r = _base_handshake_req_reply_wait(ioc, mpi_request_sz, |
| 4227 | (u32 *)&mpi_request, mpi_reply_sz, (u16 *)&mpi_reply, 5, CAN_SLEEP); | 4226 | (u32 *)&mpi_request, mpi_reply_sz, (u16 *)&mpi_reply, 5); |
| 4228 | 4227 | ||
| 4229 | if (r != 0) { | 4228 | if (r != 0) { |
| 4230 | pr_err(MPT3SAS_FMT "%s: handshake failed (r=%d)\n", | 4229 | pr_err(MPT3SAS_FMT "%s: handshake failed (r=%d)\n", |
| @@ -4247,13 +4246,11 @@ _base_get_port_facts(struct MPT3SAS_ADAPTER *ioc, int port, int sleep_flag) · 16 unmodified lines | |||
| 4247 | * _base_wait_for_iocstate - Wait until the card is in READY or OPERATIONAL | 4246 | * _base_wait_for_iocstate - Wait until the card is in READY or OPERATIONAL |
| 4248 | * @ioc: per adapter object | 4247 | * @ioc: per adapter object |
| 4249 | * @timeout: | 4248 | * @timeout: |
| 4250 | * @sleep_flag: CAN_SLEEP or NO_SLEEP | ||
| 4251 | * | 4249 | * |
| 4252 | * Returns 0 for success, non-zero for failure. | 4250 | * Returns 0 for success, non-zero for failure. |
| 4253 | */ | 4251 | */ |
| 4254 | static int | 4252 | static int |
| 4255 | _base_wait_for_iocstate(struct MPT3SAS_ADAPTER *ioc, int timeout, | 4253 | _base_wait_for_iocstate(struct MPT3SAS_ADAPTER *ioc, int timeout) |
| 4256 | int sleep_flag) | ||
| 4257 | { | 4254 | { |
| 4258 | u32 ioc_state; | 4255 | u32 ioc_state; |
| 4259 | int rc; | 4256 | int rc; |
| @@ -4287,8 +4284,7 @@ _base_wait_for_iocstate(struct MPT3SAS_ADAPTER *ioc, int timeout, · 27 unmodified lines | |||
| 4287 | goto issue_diag_reset; | 4284 | goto issue_diag_reset; |
| 4288 | } | 4285 | } |
| 4289 | 4286 | ||
| 4290 | ioc_state = _base_wait_on_iocstate(ioc, MPI2_IOC_STATE_READY, | 4287 | ioc_state = _base_wait_on_iocstate(ioc, MPI2_IOC_STATE_READY, timeout); |
| 4291 | timeout, sleep_flag); | ||
| 4292 | if (ioc_state) { | 4288 | if (ioc_state) { |
| 4293 | dfailprintk(ioc, printk(MPT3SAS_FMT | 4289 | dfailprintk(ioc, printk(MPT3SAS_FMT |
| 4294 | "%s: failed going to ready state (ioc_state=0x%x)\n", | 4290 | "%s: failed going to ready state (ioc_state=0x%x)\n", |
| @@ -4297,19 +4293,18 @@ _base_wait_for_iocstate(struct MPT3SAS_ADAPTER *ioc, int timeout, · 2 unmodified lines | |||
| 4297 | } | 4293 | } |
| 4298 | 4294 | ||
| 4299 | issue_diag_reset: | 4295 | issue_diag_reset: |
| 4300 | rc = _base_diag_reset(ioc, sleep_flag); | 4296 | rc = _base_diag_reset(ioc); |
| 4301 | return rc; | 4297 | return rc; |
| 4302 | } | 4298 | } |
| 4303 | 4299 | ||
| 4304 | /** | 4300 | /** |
| 4305 | * _base_get_ioc_facts - obtain ioc facts reply and save in ioc | 4301 | * _base_get_ioc_facts - obtain ioc facts reply and save in ioc |
| 4306 | * @ioc: per adapter object | 4302 | * @ioc: per adapter object |
| 4307 | * @sleep_flag: CAN_SLEEP or NO_SLEEP | ||
| 4308 | * | 4303 | * |
| 4309 | * Returns 0 for success, non-zero for failure. | 4304 | * Returns 0 for success, non-zero for failure. |
| 4310 | */ | 4305 | */ |
| 4311 | static int | 4306 | static int |
| 4312 | _base_get_ioc_facts(struct MPT3SAS_ADAPTER *ioc, int sleep_flag) | 4307 | _base_get_ioc_facts(struct MPT3SAS_ADAPTER *ioc) |
| 4313 | { | 4308 | { |
| 4314 | Mpi2IOCFactsRequest_t mpi_request; | 4309 | Mpi2IOCFactsRequest_t mpi_request; |
| 4315 | Mpi2IOCFactsReply_t mpi_reply; | 4310 | Mpi2IOCFactsReply_t mpi_reply; |
| @@ -4319,7 +4314,7 @@ _base_get_ioc_facts(struct MPT3SAS_ADAPTER *ioc, int sleep_flag) · 3 unmodified lines | |||
| 4319 | dinitprintk(ioc, pr_info(MPT3SAS_FMT "%s\n", ioc->name, | 4314 | dinitprintk(ioc, pr_info(MPT3SAS_FMT "%s\n", ioc->name, |
| 4320 | __func__)); | 4315 | __func__)); |
| 4321 | 4316 | ||
| 4322 | r = _base_wait_for_iocstate(ioc, 10, sleep_flag); | 4317 | r = _base_wait_for_iocstate(ioc, 10); |
| 4323 | if (r) { | 4318 | if (r) { |
| 4324 | dfailprintk(ioc, printk(MPT3SAS_FMT | 4319 | dfailprintk(ioc, printk(MPT3SAS_FMT |
| 4325 | "%s: failed getting to correct state\n", | 4320 | "%s: failed getting to correct state\n", |
| @@ -4331,7 +4326,7 @@ _base_get_ioc_facts(struct MPT3SAS_ADAPTER *ioc, int sleep_flag) · 5 unmodified lines | |||
| 4331 | memset(&mpi_request, 0, mpi_request_sz); | 4326 | memset(&mpi_request, 0, mpi_request_sz); |
| 4332 | mpi_request.Function = MPI2_FUNCTION_IOC_FACTS; | 4327 | mpi_request.Function = MPI2_FUNCTION_IOC_FACTS; |
| 4333 | r = _base_handshake_req_reply_wait(ioc, mpi_request_sz, | 4328 | r = _base_handshake_req_reply_wait(ioc, mpi_request_sz, |
| 4334 | (u32 *)&mpi_request, mpi_reply_sz, (u16 *)&mpi_reply, 5, CAN_SLEEP); | 4329 | (u32 *)&mpi_request, mpi_reply_sz, (u16 *)&mpi_reply, 5); |
| 4335 | 4330 | ||
| 4336 | if (r != 0) { | 4331 | if (r != 0) { |
| 4337 | pr_err(MPT3SAS_FMT "%s: handshake failed (r=%d)\n", | 4332 | pr_err(MPT3SAS_FMT "%s: handshake failed (r=%d)\n", |
| @@ -4391,12 +4386,11 @@ _base_get_ioc_facts(struct MPT3SAS_ADAPTER *ioc, int sleep_flag) · 53 unmodified lines | |||
| 4391 | /** | 4386 | /** |
| 4392 | * _base_send_ioc_init - send ioc_init to firmware | 4387 | * _base_send_ioc_init - send ioc_init to firmware |
| 4393 | * @ioc: per adapter object | 4388 | * @ioc: per adapter object |
| 4394 | * @sleep_flag: CAN_SLEEP or NO_SLEEP | ||
| 4395 | * | 4389 | * |
| 4396 | * Returns 0 for success, non-zero for failure. | 4390 | * Returns 0 for success, non-zero for failure. |
| 4397 | */ | 4391 | */ |
| 4398 | static int | 4392 | static int |
| 4399 | _base_send_ioc_init(struct MPT3SAS_ADAPTER *ioc, int sleep_flag) | 4393 | _base_send_ioc_init(struct MPT3SAS_ADAPTER *ioc) |
| 4400 | { | 4394 | { |
| 4401 | Mpi2IOCInitRequest_t mpi_request; | 4395 | Mpi2IOCInitRequest_t mpi_request; |
| 4402 | Mpi2IOCInitReply_t mpi_reply; | 4396 | Mpi2IOCInitReply_t mpi_reply; |
| @@ -4479,8 +4473,7 @@ _base_send_ioc_init(struct MPT3SAS_ADAPTER *ioc, int sleep_flag) · 76 unmodified lines | |||
| 4479 | 4473 | ||
| 4480 | r = _base_handshake_req_reply_wait(ioc, | 4474 | r = _base_handshake_req_reply_wait(ioc, |
| 4481 | sizeof(Mpi2IOCInitRequest_t), (u32 *)&mpi_request, | 4475 | sizeof(Mpi2IOCInitRequest_t), (u32 *)&mpi_request, |
| 4482 | sizeof(Mpi2IOCInitReply_t), (u16 *)&mpi_reply, 10, | 4476 | sizeof(Mpi2IOCInitReply_t), (u16 *)&mpi_reply, 10); |
| 4483 | sleep_flag); | ||
| 4484 | 4477 | ||
| 4485 | if (r != 0) { | 4478 | if (r != 0) { |
| 4486 | pr_err(MPT3SAS_FMT "%s: handshake failed (r=%d)\n", | 4479 | pr_err(MPT3SAS_FMT "%s: handshake failed (r=%d)\n", |
| @@ -4555,16 +4548,14 @@ mpt3sas_port_enable_done(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index, · 68 unmodified lines | |||
| 4555 | /** | 4548 | /** |
| 4556 | * _base_send_port_enable - send port_enable(discovery stuff) to firmware | 4549 | * _base_send_port_enable - send port_enable(discovery stuff) to firmware |
| 4557 | * @ioc: per adapter object | 4550 | * @ioc: per adapter object |
| 4558 | * @sleep_flag: CAN_SLEEP or NO_SLEEP | ||
| 4559 | * | 4551 | * |
| 4560 | * Returns 0 for success, non-zero for failure. | 4552 | * Returns 0 for success, non-zero for failure. |
| 4561 | */ | 4553 | */ |
| 4562 | static int | 4554 | static int |
| 4563 | _base_send_port_enable(struct MPT3SAS_ADAPTER *ioc, int sleep_flag) | 4555 | _base_send_port_enable(struct MPT3SAS_ADAPTER *ioc) |
| 4564 | { | 4556 | { |
| 4565 | Mpi2PortEnableRequest_t *mpi_request; | 4557 | Mpi2PortEnableRequest_t *mpi_request; |
| 4566 | Mpi2PortEnableReply_t *mpi_reply; | 4558 | Mpi2PortEnableReply_t *mpi_reply; |
| 4567 | unsigned long timeleft; | ||
| 4568 | int r = 0; | 4559 | int r = 0; |
| 4569 | u16 smid; | 4560 | u16 smid; |
| 4570 | u16 ioc_status; | 4561 | u16 ioc_status; |
| @@ -4592,8 +4583,7 @@ _base_send_port_enable(struct MPT3SAS_ADAPTER *ioc, int sleep_flag) · 21 unmodified lines | |||
| 4592 | 4583 | ||
| 4593 | init_completion(&ioc->port_enable_cmds.done); | 4584 | init_completion(&ioc->port_enable_cmds.done); |
| 4594 | mpt3sas_base_put_smid_default(ioc, smid); | 4585 | mpt3sas_base_put_smid_default(ioc, smid); |
| 4595 | timeleft = wait_for_completion_timeout(&ioc->port_enable_cmds.done, | 4586 | wait_for_completion_timeout(&ioc->port_enable_cmds.done, 300*HZ); |
| 4596 | 300*HZ); | ||
| 4597 | if (!(ioc->port_enable_cmds.status & MPT3_CMD_COMPLETE)) { | 4587 | if (!(ioc->port_enable_cmds.status & MPT3_CMD_COMPLETE)) { |
| 4598 | pr_err(MPT3SAS_FMT "%s: timeout\n", | 4588 | pr_err(MPT3SAS_FMT "%s: timeout\n", |
| 4599 | ioc->name, __func__); | 4589 | ioc->name, __func__); |
| @@ -4737,15 +4727,13 @@ _base_unmask_events(struct MPT3SAS_ADAPTER *ioc, u16 event) · 137 unmodified lines | |||
| 4737 | /** | 4727 | /** |
| 4738 | * _base_event_notification - send event notification | 4728 | * _base_event_notification - send event notification |
| 4739 | * @ioc: per adapter object | 4729 | * @ioc: per adapter object |
| 4740 | * @sleep_flag: CAN_SLEEP or NO_SLEEP | ||
| 4741 | * | 4730 | * |
| 4742 | * Returns 0 for success, non-zero for failure. | 4731 | * Returns 0 for success, non-zero for failure. |
| 4743 | */ | 4732 | */ |
| 4744 | static int | 4733 | static int |
| 4745 | _base_event_notification(struct MPT3SAS_ADAPTER *ioc, int sleep_flag) | 4734 | _base_event_notification(struct MPT3SAS_ADAPTER *ioc) |
| 4746 | { | 4735 | { |
| 4747 | Mpi2EventNotificationRequest_t *mpi_request; | 4736 | Mpi2EventNotificationRequest_t *mpi_request; |
| 4748 | unsigned long timeleft; | ||
| 4749 | u16 smid; | 4737 | u16 smid; |
| 4750 | int r = 0; | 4738 | int r = 0; |
| 4751 | int i; | 4739 | int i; |
| @@ -4777,7 +4765,7 @@ _base_event_notification(struct MPT3SAS_ADAPTER *ioc, int sleep_flag) · 25 unmodified lines | |||
| 4777 | cpu_to_le32(ioc->event_masks[i]); | 4765 | cpu_to_le32(ioc->event_masks[i]); |
| 4778 | init_completion(&ioc->base_cmds.done); | 4766 | init_completion(&ioc->base_cmds.done); |
| 4779 | mpt3sas_base_put_smid_default(ioc, smid); | 4767 | mpt3sas_base_put_smid_default(ioc, smid); |
| 4780 | timeleft = wait_for_completion_timeout(&ioc->base_cmds.done, 30*HZ); | 4768 | wait_for_completion_timeout(&ioc->base_cmds.done, 30*HZ); |
| 4781 | if (!(ioc->base_cmds.status & MPT3_CMD_COMPLETE)) { | 4769 | if (!(ioc->base_cmds.status & MPT3_CMD_COMPLETE)) { |
| 4782 | pr_err(MPT3SAS_FMT "%s: timeout\n", | 4770 | pr_err(MPT3SAS_FMT "%s: timeout\n", |
| 4783 | ioc->name, __func__); | 4771 | ioc->name, __func__); |
| @@ -4827,19 +4815,18 @@ mpt3sas_base_validate_event_type(struct MPT3SAS_ADAPTER *ioc, u32 *event_type) · 43 unmodified lines | |||
| 4827 | return; | 4815 | return; |
| 4828 | 4816 | ||
| 4829 | mutex_lock(&ioc->base_cmds.mutex); | 4817 | mutex_lock(&ioc->base_cmds.mutex); |
| 4830 | _base_event_notification(ioc, CAN_SLEEP); | 4818 | _base_event_notification(ioc); |
| 4831 | mutex_unlock(&ioc->base_cmds.mutex); | 4819 | mutex_unlock(&ioc->base_cmds.mutex); |
| 4832 | } | 4820 | } |
| 4833 | 4821 | ||
| 4834 | /** | 4822 | /** |
| 4835 | * _base_diag_reset - the "big hammer" start of day reset | 4823 | * _base_diag_reset - the "big hammer" start of day reset |
| 4836 | * @ioc: per adapter object | 4824 | * @ioc: per adapter object |
| 4837 | * @sleep_flag: CAN_SLEEP or NO_SLEEP | ||
| 4838 | * | 4825 | * |
| 4839 | * Returns 0 for success, non-zero for failure. | 4826 | * Returns 0 for success, non-zero for failure. |
| 4840 | */ | 4827 | */ |
| 4841 | static int | 4828 | static int |
| 4842 | _base_diag_reset(struct MPT3SAS_ADAPTER *ioc, int sleep_flag) | 4829 | _base_diag_reset(struct MPT3SAS_ADAPTER *ioc) |
| 4843 | { | 4830 | { |
| 4844 | u32 host_diagnostic; | 4831 | u32 host_diagnostic; |
| 4845 | u32 ioc_state; | 4832 | u32 ioc_state; |
| @@ -4867,10 +4854,7 @@ _base_diag_reset(struct MPT3SAS_ADAPTER *ioc, int sleep_flag) · 21 unmodified lines | |||
| 4867 | writel(MPI2_WRSEQ_6TH_KEY_VALUE, &ioc->chip->WriteSequence); | 4854 | writel(MPI2_WRSEQ_6TH_KEY_VALUE, &ioc->chip->WriteSequence); |
| 4868 | 4855 | ||
| 4869 | /* wait 100 msec */ | 4856 | /* wait 100 msec */ |
| 4870 | if (sleep_flag == CAN_SLEEP) | 4857 | msleep(100); |
| 4871 | msleep(100); | ||
| 4872 | else | ||
| 4873 | mdelay(100); | ||
| 4874 | 4858 | ||
| 4875 | if (count++ > 20) | 4859 | if (count++ > 20) |
| 4876 | goto out; | 4860 | goto out; |
| @@ -4890,10 +4874,7 @@ _base_diag_reset(struct MPT3SAS_ADAPTER *ioc, int sleep_flag) · 13 unmodified lines | |||
| 4890 | &ioc->chip->HostDiagnostic); | 4874 | &ioc->chip->HostDiagnostic); |
| 4891 | 4875 | ||
| 4892 | /*This delay allows the chip PCIe hardware time to finish reset tasks*/ | 4876 | /*This delay allows the chip PCIe hardware time to finish reset tasks*/ |
| 4893 | if (sleep_flag == CAN_SLEEP) | 4877 | msleep(MPI2_HARD_RESET_PCIE_FIRST_READ_DELAY_MICRO_SEC/1000); |
| 4894 | msleep(MPI2_HARD_RESET_PCIE_FIRST_READ_DELAY_MICRO_SEC/1000); | ||
| 4895 | else | ||
| 4896 | mdelay(MPI2_HARD_RESET_PCIE_FIRST_READ_DELAY_MICRO_SEC/1000); | ||
| 4897 | 4878 | ||
| 4898 | /* Approximately 300 second max wait */ | 4879 | /* Approximately 300 second max wait */ |
| 4899 | for (count = 0; count < (300000000 / | 4880 | for (count = 0; count < (300000000 / |
| @@ -4906,13 +4887,7 @@ _base_diag_reset(struct MPT3SAS_ADAPTER *ioc, int sleep_flag) · 6 unmodified lines | |||
| 4906 | if (!(host_diagnostic & MPI2_DIAG_RESET_ADAPTER)) | 4887 | if (!(host_diagnostic & MPI2_DIAG_RESET_ADAPTER)) |
| 4907 | break; | 4888 | break; |
| 4908 | 4889 | ||
| 4909 | /* Wait to pass the second read delay window */ | 4890 | msleep(MPI2_HARD_RESET_PCIE_SECOND_READ_DELAY_MICRO_SEC / 1000); |
| 4910 | if (sleep_flag == CAN_SLEEP) | ||
| 4911 | msleep(MPI2_HARD_RESET_PCIE_SECOND_READ_DELAY_MICRO_SEC | ||
| 4912 | / 1000); | ||
| 4913 | else | ||
| 4914 | mdelay(MPI2_HARD_RESET_PCIE_SECOND_READ_DELAY_MICRO_SEC | ||
| 4915 | / 1000); | ||
| 4916 | } | 4891 | } |
| 4917 | 4892 | ||
| 4918 | if (host_diagnostic & MPI2_DIAG_HCB_MODE) { | 4893 | if (host_diagnostic & MPI2_DIAG_HCB_MODE) { |
| @@ -4941,8 +4916,7 @@ _base_diag_reset(struct MPT3SAS_ADAPTER *ioc, int sleep_flag) · 22 unmodified lines | |||
| 4941 | 4916 | ||
| 4942 | drsprintk(ioc, pr_info(MPT3SAS_FMT | 4917 | drsprintk(ioc, pr_info(MPT3SAS_FMT |
| 4943 | "Wait for FW to go to the READY state\n", ioc->name)); | 4918 | "Wait for FW to go to the READY state\n", ioc->name)); |
| 4944 | ioc_state = _base_wait_on_iocstate(ioc, MPI2_IOC_STATE_READY, 20, | 4919 | ioc_state = _base_wait_on_iocstate(ioc, MPI2_IOC_STATE_READY, 20); |
| 4945 | sleep_flag); | ||
| 4946 | if (ioc_state) { | 4920 | if (ioc_state) { |
| 4947 | pr_err(MPT3SAS_FMT | 4921 | pr_err(MPT3SAS_FMT |
| 4948 | "%s: failed going to ready state (ioc_state=0x%x)\n", | 4922 | "%s: failed going to ready state (ioc_state=0x%x)\n", |
| @@ -4961,14 +4935,12 @@ _base_diag_reset(struct MPT3SAS_ADAPTER *ioc, int sleep_flag) · 12 unmodified lines | |||
| 4961 | /** | 4935 | /** |
| 4962 | * _base_make_ioc_ready - put controller in READY state | 4936 | * _base_make_ioc_ready - put controller in READY state |
| 4963 | * @ioc: per adapter object | 4937 | * @ioc: per adapter object |
| 4964 | * @sleep_flag: CAN_SLEEP or NO_SLEEP | ||
| 4965 | * @type: FORCE_BIG_HAMMER or SOFT_RESET | 4938 | * @type: FORCE_BIG_HAMMER or SOFT_RESET |
| 4966 | * | 4939 | * |
| 4967 | * Returns 0 for success, non-zero for failure. | 4940 | * Returns 0 for success, non-zero for failure. |
| 4968 | */ | 4941 | */ |
| 4969 | static int | 4942 | static int |
| 4970 | _base_make_ioc_ready(struct MPT3SAS_ADAPTER *ioc, int sleep_flag, | 4943 | _base_make_ioc_ready(struct MPT3SAS_ADAPTER *ioc, enum reset_type type) |
| 4971 | enum reset_type type) | ||
| 4972 | { | 4944 | { |
| 4973 | u32 ioc_state; | 4945 | u32 ioc_state; |
| 4974 | int rc; | 4946 | int rc; |
| @@ -4995,10 +4967,7 @@ _base_make_ioc_ready(struct MPT3SAS_ADAPTER *ioc, int sleep_flag, · 20 unmodified lines | |||
| 4995 | ioc->name, __func__, ioc_state); | 4967 | ioc->name, __func__, ioc_state); |
| 4996 | return -EFAULT; | 4968 | return -EFAULT; |
| 4997 | } | 4969 | } |
| 4998 | if (sleep_flag == CAN_SLEEP) | 4970 | ssleep(1); |
| 4999 | ssleep(1); | ||
| 5000 | else | ||
| 5001 | mdelay(1000); | ||
| 5002 | ioc_state = mpt3sas_base_get_iocstate(ioc, 0); | 4971 | ioc_state = mpt3sas_base_get_iocstate(ioc, 0); |
| 5003 | } | 4972 | } |
| 5004 | } | 4973 | } |
| @@ -5024,24 +4993,23 @@ _base_make_ioc_ready(struct MPT3SAS_ADAPTER *ioc, int sleep_flag, · 19 unmodified lines | |||
| 5024 | 4993 | ||
| 5025 | if ((ioc_state & MPI2_IOC_STATE_MASK) == MPI2_IOC_STATE_OPERATIONAL) | 4994 | if ((ioc_state & MPI2_IOC_STATE_MASK) == MPI2_IOC_STATE_OPERATIONAL) |
| 5026 | if (!(_base_send_ioc_reset(ioc, | 4995 | if (!(_base_send_ioc_reset(ioc, |
| 5027 | MPI2_FUNCTION_IOC_MESSAGE_UNIT_RESET, 15, CAN_SLEEP))) { | 4996 | MPI2_FUNCTION_IOC_MESSAGE_UNIT_RESET, 15))) { |
| 5028 | return 0; | 4997 | return 0; |
| 5029 | } | 4998 | } |
| 5030 | 4999 | ||
| 5031 | issue_diag_reset: | 5000 | issue_diag_reset: |
| 5032 | rc = _base_diag_reset(ioc, CAN_SLEEP); | 5001 | rc = _base_diag_reset(ioc); |
| 5033 | return rc; | 5002 | return rc; |
| 5034 | } | 5003 | } |
| 5035 | 5004 | ||
| 5036 | /** | 5005 | /** |
| 5037 | * _base_make_ioc_operational - put controller in OPERATIONAL state | 5006 | * _base_make_ioc_operational - put controller in OPERATIONAL state |
| 5038 | * @ioc: per adapter object | 5007 | * @ioc: per adapter object |
| 5039 | * @sleep_flag: CAN_SLEEP or NO_SLEEP | ||
| 5040 | * | 5008 | * |
| 5041 | * Returns 0 for success, non-zero for failure. | 5009 | * Returns 0 for success, non-zero for failure. |
| 5042 | */ | 5010 | */ |
| 5043 | static int | 5011 | static int |
| 5044 | _base_make_ioc_operational(struct MPT3SAS_ADAPTER *ioc, int sleep_flag) | 5012 | _base_make_ioc_operational(struct MPT3SAS_ADAPTER *ioc) |
| 5045 | { | 5013 | { |
| 5046 | int r, i, index; | 5014 | int r, i, index; |
| 5047 | unsigned long flags; | 5015 | unsigned long flags; |
| @@ -5160,7 +5128,7 @@ _base_make_ioc_operational(struct MPT3SAS_ADAPTER *ioc, int sleep_flag) · 112 unmodified lines | |||
| 5160 | } | 5128 | } |
| 5161 | skip_init_reply_post_free_queue: | 5129 | skip_init_reply_post_free_queue: |
| 5162 | 5130 | ||
| 5163 | r = _base_send_ioc_init(ioc, sleep_flag); | 5131 | r = _base_send_ioc_init(ioc); |
| 5164 | if (r) | 5132 | if (r) |
| 5165 | return r; | 5133 | return r; |
| 5166 | 5134 | ||
| @@ -5186,13 +5154,11 @@ _base_make_ioc_operational(struct MPT3SAS_ADAPTER *ioc, int sleep_flag) · 19 unmodified lines | |||
| 5186 | skip_init_reply_post_host_index: | 5154 | skip_init_reply_post_host_index: |
| 5187 | 5155 | ||
| 5188 | _base_unmask_interrupts(ioc); | 5156 | _base_unmask_interrupts(ioc); |
| 5189 | r = _base_event_notification(ioc, sleep_flag); | 5157 | r = _base_event_notification(ioc); |
| 5190 | if (r) | 5158 | if (r) |
| 5191 | return r; | 5159 | return r; |
| 5192 | 5160 | ||
| 5193 | if (sleep_flag == CAN_SLEEP) | 5161 | _base_static_config_pages(ioc); |
| 5194 | _base_static_config_pages(ioc); | ||
| 5195 | |||
| 5196 | 5162 | ||
| 5197 | if (ioc->is_driver_loading) { | 5163 | if (ioc->is_driver_loading) { |
| 5198 | 5164 | ||
| @@ -5211,7 +5177,7 @@ _base_make_ioc_operational(struct MPT3SAS_ADAPTER *ioc, int sleep_flag) · 12 unmodified lines | |||
| 5211 | return r; /* scan_start and scan_finished support */ | 5177 | return r; /* scan_start and scan_finished support */ |
| 5212 | } | 5178 | } |
| 5213 | 5179 | ||
| 5214 | r = _base_send_port_enable(ioc, sleep_flag); | 5180 | r = _base_send_port_enable(ioc); |
| 5215 | if (r) | 5181 | if (r) |
| 5216 | return r; | 5182 | return r; |
| 5217 | 5183 | ||
| @@ -5235,7 +5201,7 @@ mpt3sas_base_free_resources(struct MPT3SAS_ADAPTER *ioc) · 17 unmodified lines | |||
| 5235 | if (ioc->chip_phys && ioc->chip) { | 5201 | if (ioc->chip_phys && ioc->chip) { |
| 5236 | _base_mask_interrupts(ioc); | 5202 | _base_mask_interrupts(ioc); |
| 5237 | ioc->shost_recovery = 1; | 5203 | ioc->shost_recovery = 1; |
| 5238 | _base_make_ioc_ready(ioc, CAN_SLEEP, SOFT_RESET); | 5204 | _base_make_ioc_ready(ioc, SOFT_RESET); |
| 5239 | ioc->shost_recovery = 0; | 5205 | ioc->shost_recovery = 0; |
| 5240 | } | 5206 | } |
| 5241 | 5207 | ||
| @@ -5292,7 +5258,7 @@ mpt3sas_base_attach(struct MPT3SAS_ADAPTER *ioc) · 50 unmodified lines | |||
| 5292 | goto out_free_resources; | 5258 | goto out_free_resources; |
| 5293 | 5259 | ||
| 5294 | pci_set_drvdata(ioc->pdev, ioc->shost); | 5260 | pci_set_drvdata(ioc->pdev, ioc->shost); |
| 5295 | r = _base_get_ioc_facts(ioc, CAN_SLEEP); | 5261 | r = _base_get_ioc_facts(ioc); |
| 5296 | if (r) | 5262 | if (r) |
| 5297 | goto out_free_resources; | 5263 | goto out_free_resources; |
| 5298 | 5264 | ||
| @@ -5326,7 +5292,7 @@ mpt3sas_base_attach(struct MPT3SAS_ADAPTER *ioc) · 27 unmodified lines | |||
| 5326 | ioc->build_sg_mpi = &_base_build_sg; | 5292 | ioc->build_sg_mpi = &_base_build_sg; |
| 5327 | ioc->build_zero_len_sge_mpi = &_base_build_zero_len_sge; | 5293 | ioc->build_zero_len_sge_mpi = &_base_build_zero_len_sge; |
| 5328 | 5294 | ||
| 5329 | r = _base_make_ioc_ready(ioc, CAN_SLEEP, SOFT_RESET); | 5295 | r = _base_make_ioc_ready(ioc, SOFT_RESET); |
| 5330 | if (r) | 5296 | if (r) |
| 5331 | goto out_free_resources; | 5297 | goto out_free_resources; |
| 5332 | 5298 | ||
| @@ -5338,12 +5304,12 @@ mpt3sas_base_attach(struct MPT3SAS_ADAPTER *ioc) · 5 unmodified lines | |||
| 5338 | } | 5304 | } |
| 5339 | 5305 | ||
| 5340 | for (i = 0 ; i < ioc->facts.NumberOfPorts; i++) { | 5306 | for (i = 0 ; i < ioc->facts.NumberOfPorts; i++) { |
| 5341 | r = _base_get_port_facts(ioc, i, CAN_SLEEP); | 5307 | r = _base_get_port_facts(ioc, i); |
| 5342 | if (r) | 5308 | if (r) |
| 5343 | goto out_free_resources; | 5309 | goto out_free_resources; |
| 5344 | } | 5310 | } |
| 5345 | 5311 | ||
| 5346 | r = _base_allocate_memory_pools(ioc, CAN_SLEEP); | 5312 | r = _base_allocate_memory_pools(ioc); |
| 5347 | if (r) | 5313 | if (r) |
| 5348 | goto out_free_resources; | 5314 | goto out_free_resources; |
| 5349 | 5315 | ||
| @@ -5429,7 +5395,7 @@ mpt3sas_base_attach(struct MPT3SAS_ADAPTER *ioc) · 79 unmodified lines | |||
| 5429 | if (ioc->hba_mpi_version_belonged == MPI26_VERSION) | 5395 | if (ioc->hba_mpi_version_belonged == MPI26_VERSION) |
| 5430 | _base_unmask_events(ioc, MPI2_EVENT_ACTIVE_CABLE_EXCEPTION); | 5396 | _base_unmask_events(ioc, MPI2_EVENT_ACTIVE_CABLE_EXCEPTION); |
| 5431 | 5397 | ||
| 5432 | r = _base_make_ioc_operational(ioc, CAN_SLEEP); | 5398 | r = _base_make_ioc_operational(ioc); |
| 5433 | if (r) | 5399 | if (r) |
| 5434 | goto out_free_resources; | 5400 | goto out_free_resources; |
| 5435 | 5401 | ||
| @@ -5565,21 +5531,18 @@ _base_reset_handler(struct MPT3SAS_ADAPTER *ioc, int reset_phase) · 129 unmodified lines | |||
| 5565 | /** | 5531 | /** |
| 5566 | * _wait_for_commands_to_complete - reset controller | 5532 | * _wait_for_commands_to_complete - reset controller |
| 5567 | * @ioc: Pointer to MPT_ADAPTER structure | 5533 | * @ioc: Pointer to MPT_ADAPTER structure |
| 5568 | * @sleep_flag: CAN_SLEEP or NO_SLEEP | ||
| 5569 | * | 5534 | * |
| 5570 | * This function waiting(3s) for all pending commands to complete | 5535 | * This function waiting(3s) for all pending commands to complete |
| 5571 | * prior to putting controller in reset. | 5536 | * prior to putting controller in reset. |
| 5572 | */ | 5537 | */ |
| 5573 | static void | 5538 | static void |
| 5574 | _wait_for_commands_to_complete(struct MPT3SAS_ADAPTER *ioc, int sleep_flag) | 5539 | _wait_for_commands_to_complete(struct MPT3SAS_ADAPTER *ioc) |
| 5575 | { | 5540 | { |
| 5576 | u32 ioc_state; | 5541 | u32 ioc_state; |
| 5577 | unsigned long flags; | 5542 | unsigned long flags; |
| 5578 | u16 i; | 5543 | u16 i; |
| 5579 | 5544 | ||
| 5580 | ioc->pending_io_count = 0; | 5545 | ioc->pending_io_count = 0; |
| 5581 | if (sleep_flag != CAN_SLEEP) | ||
| 5582 | return; | ||
| 5583 | 5546 | ||
| 5584 | ioc_state = mpt3sas_base_get_iocstate(ioc, 0); | 5547 | ioc_state = mpt3sas_base_get_iocstate(ioc, 0); |
| 5585 | if ((ioc_state & MPI2_IOC_STATE_MASK) != MPI2_IOC_STATE_OPERATIONAL) | 5548 | if ((ioc_state & MPI2_IOC_STATE_MASK) != MPI2_IOC_STATE_OPERATIONAL) |
| @@ -5602,13 +5565,12 @@ _wait_for_commands_to_complete(struct MPT3SAS_ADAPTER *ioc, int sleep_flag) · 16 unmodified lines | |||
| 5602 | /** | 5565 | /** |
| 5603 | * mpt3sas_base_hard_reset_handler - reset controller | 5566 | * mpt3sas_base_hard_reset_handler - reset controller |
| 5604 | * @ioc: Pointer to MPT_ADAPTER structure | 5567 | * @ioc: Pointer to MPT_ADAPTER structure |
| 5605 | * @sleep_flag: CAN_SLEEP or NO_SLEEP | ||
| 5606 | * @type: FORCE_BIG_HAMMER or SOFT_RESET | 5568 | * @type: FORCE_BIG_HAMMER or SOFT_RESET |
| 5607 | * | 5569 | * |
| 5608 | * Returns 0 for success, non-zero for failure. | 5570 | * Returns 0 for success, non-zero for failure. |
| 5609 | */ | 5571 | */ |
| 5610 | int | 5572 | int |
| 5611 | mpt3sas_base_hard_reset_handler(struct MPT3SAS_ADAPTER *ioc, int sleep_flag, | 5573 | mpt3sas_base_hard_reset_handler(struct MPT3SAS_ADAPTER *ioc, |
| 5612 | enum reset_type type) | 5574 | enum reset_type type) |
| 5613 | { | 5575 | { |
| 5614 | int r; | 5576 | int r; |
| @@ -5629,13 +5591,6 @@ mpt3sas_base_hard_reset_handler(struct MPT3SAS_ADAPTER *ioc, int sleep_flag, · 14 unmodified lines | |||
| 5629 | if (mpt3sas_fwfault_debug) | 5591 | if (mpt3sas_fwfault_debug) |
| 5630 | mpt3sas_halt_firmware(ioc); | 5592 | mpt3sas_halt_firmware(ioc); |
| 5631 | 5593 | ||
| 5632 | /* TODO - What we really should be doing is pulling | ||
| 5633 | * out all the code associated with NO_SLEEP; its never used. | ||
| 5634 | * That is legacy code from mpt fusion driver, ported over. | ||
| 5635 | * I will leave this BUG_ON here for now till its been resolved. | ||
| 5636 | */ | ||
| 5637 | BUG_ON(sleep_flag == NO_SLEEP); | ||
| 5638 | |||
| 5639 | /* wait for an active reset in progress to complete */ | 5594 | /* wait for an active reset in progress to complete */ |
| 5640 | if (!mutex_trylock(&ioc->reset_in_progress_mutex)) { | 5595 | if (!mutex_trylock(&ioc->reset_in_progress_mutex)) { |
| 5641 | do { | 5596 | do { |
| @@ -5660,9 +5615,9 @@ mpt3sas_base_hard_reset_handler(struct MPT3SAS_ADAPTER *ioc, int sleep_flag, · 18 unmodified lines | |||
| 5660 | is_fault = 1; | 5615 | is_fault = 1; |
| 5661 | } | 5616 | } |
| 5662 | _base_reset_handler(ioc, MPT3_IOC_PRE_RESET); | 5617 | _base_reset_handler(ioc, MPT3_IOC_PRE_RESET); |
| 5663 | _wait_for_commands_to_complete(ioc, sleep_flag); | 5618 | _wait_for_commands_to_complete(ioc); |
| 5664 | _base_mask_interrupts(ioc); | 5619 | _base_mask_interrupts(ioc); |
| 5665 | r = _base_make_ioc_ready(ioc, sleep_flag, type); | 5620 | r = _base_make_ioc_ready(ioc, type); |
| 5666 | if (r) | 5621 | if (r) |
| 5667 | goto out; | 5622 | goto out; |
| 5668 | _base_reset_handler(ioc, MPT3_IOC_AFTER_RESET); | 5623 | _base_reset_handler(ioc, MPT3_IOC_AFTER_RESET); |
| @@ -5675,7 +5630,7 @@ mpt3sas_base_hard_reset_handler(struct MPT3SAS_ADAPTER *ioc, int sleep_flag, · 6 unmodified lines | |||
| 5675 | r = -EFAULT; | 5630 | r = -EFAULT; |
| 5676 | goto out; | 5631 | goto out; |
| 5677 | } | 5632 | } |
| 5678 | r = _base_get_ioc_facts(ioc, CAN_SLEEP); | 5633 | r = _base_get_ioc_facts(ioc); |
| 5679 | if (r) | 5634 | if (r) |
| 5680 | goto out; | 5635 | goto out; |
| 5681 | 5636 | ||
| @@ -5684,7 +5639,7 @@ mpt3sas_base_hard_reset_handler(struct MPT3SAS_ADAPTER *ioc, int sleep_flag, · 2 unmodified lines | |||
| 5684 | "Please reboot the system and ensure that the correct" | 5639 | "Please reboot the system and ensure that the correct" |
| 5685 | " firmware version is running\n", ioc->name); | 5640 | " firmware version is running\n", ioc->name); |
| 5686 | 5641 | ||
| 5687 | r = _base_make_ioc_operational(ioc, sleep_flag); | 5642 | r = _base_make_ioc_operational(ioc); |
| 5688 | if (!r) | 5643 | if (!r) |
| 5689 | _base_reset_handler(ioc, MPT3_IOC_DONE_RESET); | 5644 | _base_reset_handler(ioc, MPT3_IOC_DONE_RESET); |
| 5690 | 5645 | ||
| @@ -119,10 +119,6 @@ · 118 unmodified lines | |||
| 119 | 119 | ||
| 120 | #define MPT_MAX_CALLBACKS 32 | 120 | #define MPT_MAX_CALLBACKS 32 |
| 121 | 121 | ||
| 122 | |||
| 123 | #define CAN_SLEEP 1 | ||
| 124 | #define NO_SLEEP 0 | ||
| 125 | |||
| 126 | #define INTERNAL_CMDS_COUNT 10 /* reserved cmds */ | 122 | #define INTERNAL_CMDS_COUNT 10 /* reserved cmds */ |
| 127 | /* reserved for issuing internally framed scsi io cmds */ | 123 | /* reserved for issuing internally framed scsi io cmds */ |
| 128 | #define INTERNAL_SCSIIO_CMDS_COUNT 3 | 124 | #define INTERNAL_SCSIIO_CMDS_COUNT 3 |
| @@ -478,7 +474,7 @@ struct _sas_device { · 349 unmodified lines | |||
| 478 | u8 pfa_led_on; | 474 | u8 pfa_led_on; |
| 479 | u8 pend_sas_rphy_add; | 475 | u8 pend_sas_rphy_add; |
| 480 | u8 enclosure_level; | 476 | u8 enclosure_level; |
| 481 | u8 connector_name[4]; | 477 | u8 connector_name[5]; |
| 482 | struct kref refcount; | 478 | struct kref refcount; |
| 483 | }; | 479 | }; |
| 484 | 480 | ||
| @@ -794,16 +790,6 @@ struct reply_post_struct { · 309 unmodified lines | |||
| 794 | dma_addr_t reply_post_free_dma; | 790 | dma_addr_t reply_post_free_dma; |
| 795 | }; | 791 | }; |
| 796 | 792 | ||
| 797 | /** | ||
| 798 | * enum mutex_type - task management mutex type | ||
| 799 | * @TM_MUTEX_OFF: mutex is not required becuase calling function is acquiring it | ||
| 800 | * @TM_MUTEX_ON: mutex is required | ||
| 801 | */ | ||
| 802 | enum mutex_type { | ||
| 803 | TM_MUTEX_OFF = 0, | ||
| 804 | TM_MUTEX_ON = 1, | ||
| 805 | }; | ||
| 806 | |||
| 807 | typedef void (*MPT3SAS_FLUSH_RUNNING_CMDS)(struct MPT3SAS_ADAPTER *ioc); | 793 | typedef void (*MPT3SAS_FLUSH_RUNNING_CMDS)(struct MPT3SAS_ADAPTER *ioc); |
| 808 | /** | 794 | /** |
| 809 | * struct MPT3SAS_ADAPTER - per adapter struct | 795 | * struct MPT3SAS_ADAPTER - per adapter struct |
| @@ -1229,7 +1215,7 @@ int mpt3sas_base_attach(struct MPT3SAS_ADAPTER *ioc); · 419 unmodified lines | |||
| 1229 | void mpt3sas_base_detach(struct MPT3SAS_ADAPTER *ioc); | 1215 | void mpt3sas_base_detach(struct MPT3SAS_ADAPTER *ioc); |
| 1230 | int mpt3sas_base_map_resources(struct MPT3SAS_ADAPTER *ioc); | 1216 | int mpt3sas_base_map_resources(struct MPT3SAS_ADAPTER *ioc); |
| 1231 | void mpt3sas_base_free_resources(struct MPT3SAS_ADAPTER *ioc); | 1217 | void mpt3sas_base_free_resources(struct MPT3SAS_ADAPTER *ioc); |
| 1232 | int mpt3sas_base_hard_reset_handler(struct MPT3SAS_ADAPTER *ioc, int sleep_flag, | 1218 | int mpt3sas_base_hard_reset_handler(struct MPT3SAS_ADAPTER *ioc, |
| 1233 | enum reset_type type); | 1219 | enum reset_type type); |
| 1234 | 1220 | ||
| 1235 | void *mpt3sas_base_get_msg_frame(struct MPT3SAS_ADAPTER *ioc, u16 smid); | 1221 | void *mpt3sas_base_get_msg_frame(struct MPT3SAS_ADAPTER *ioc, u16 smid); |
| @@ -1291,7 +1277,11 @@ void mpt3sas_scsih_reset_handler(struct MPT3SAS_ADAPTER *ioc, int reset_phase); · 55 unmodified lines | |||
| 1291 | 1277 | ||
| 1292 | int mpt3sas_scsih_issue_tm(struct MPT3SAS_ADAPTER *ioc, u16 handle, | 1278 | int mpt3sas_scsih_issue_tm(struct MPT3SAS_ADAPTER *ioc, u16 handle, |
| 1293 | uint channel, uint id, uint lun, u8 type, u16 smid_task, | 1279 | uint channel, uint id, uint lun, u8 type, u16 smid_task, |
| 1294 | ulong timeout, enum mutex_type m_type); | 1280 | ulong timeout); |
| 1281 | int mpt3sas_scsih_issue_locked_tm(struct MPT3SAS_ADAPTER *ioc, u16 handle, | ||
| 1282 | uint channel, uint id, uint lun, u8 type, u16 smid_task, | ||
| 1283 | ulong timeout); | ||
| 1284 | |||
| 1295 | void mpt3sas_scsih_set_tm_flag(struct MPT3SAS_ADAPTER *ioc, u16 handle); | 1285 | void mpt3sas_scsih_set_tm_flag(struct MPT3SAS_ADAPTER *ioc, u16 handle); |
| 1296 | void mpt3sas_scsih_clear_tm_flag(struct MPT3SAS_ADAPTER *ioc, u16 handle); | 1286 | void mpt3sas_scsih_clear_tm_flag(struct MPT3SAS_ADAPTER *ioc, u16 handle); |
| 1297 | void mpt3sas_expander_remove(struct MPT3SAS_ADAPTER *ioc, u64 sas_address); | 1287 | void mpt3sas_expander_remove(struct MPT3SAS_ADAPTER *ioc, u64 sas_address); |
| @@ -285,7 +285,6 @@ _config_request(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigRequest_t · 284 unmodified lines | |||
| 285 | { | 285 | { |
| 286 | u16 smid; | 286 | u16 smid; |
| 287 | u32 ioc_state; | 287 | u32 ioc_state; |
| 288 | unsigned long timeleft; | ||
| 289 | Mpi2ConfigRequest_t *config_request; | 288 | Mpi2ConfigRequest_t *config_request; |
| 290 | int r; | 289 | int r; |
| 291 | u8 retry_count, issue_host_reset = 0; | 290 | u8 retry_count, issue_host_reset = 0; |
| @@ -386,8 +385,7 @@ _config_request(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigRequest_t · 94 unmodified lines | |||
| 386 | _config_display_some_debug(ioc, smid, "config_request", NULL); | 385 | _config_display_some_debug(ioc, smid, "config_request", NULL); |
| 387 | init_completion(&ioc->config_cmds.done); | 386 | init_completion(&ioc->config_cmds.done); |
| 388 | mpt3sas_base_put_smid_default(ioc, smid); | 387 | mpt3sas_base_put_smid_default(ioc, smid); |
| 389 | timeleft = wait_for_completion_timeout(&ioc->config_cmds.done, | 388 | wait_for_completion_timeout(&ioc->config_cmds.done, timeout*HZ); |
| 390 | timeout*HZ); | ||
| 391 | if (!(ioc->config_cmds.status & MPT3_CMD_COMPLETE)) { | 389 | if (!(ioc->config_cmds.status & MPT3_CMD_COMPLETE)) { |
| 392 | pr_err(MPT3SAS_FMT "%s: timeout\n", | 390 | pr_err(MPT3SAS_FMT "%s: timeout\n", |
| 393 | ioc->name, __func__); | 391 | ioc->name, __func__); |
| @@ -491,8 +489,7 @@ _config_request(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigRequest_t · 97 unmodified lines | |||
| 491 | mutex_unlock(&ioc->config_cmds.mutex); | 489 | mutex_unlock(&ioc->config_cmds.mutex); |
| 492 | 490 | ||
| 493 | if (issue_host_reset) | 491 | if (issue_host_reset) |
| 494 | mpt3sas_base_hard_reset_handler(ioc, CAN_SLEEP, | 492 | mpt3sas_base_hard_reset_handler(ioc, FORCE_BIG_HAMMER); |
| 495 | FORCE_BIG_HAMMER); | ||
| 496 | return r; | 493 | return r; |
| 497 | } | 494 | } |
| 498 | 495 | ||
| @@ -518,7 +518,7 @@ mpt3sas_ctl_reset_handler(struct MPT3SAS_ADAPTER *ioc, int reset_phase) · 517 unmodified lines | |||
| 518 | * | 518 | * |
| 519 | * Called when application request fasyn callback handler. | 519 | * Called when application request fasyn callback handler. |
| 520 | */ | 520 | */ |
| 521 | int | 521 | static int |
| 522 | _ctl_fasync(int fd, struct file *filep, int mode) | 522 | _ctl_fasync(int fd, struct file *filep, int mode) |
| 523 | { | 523 | { |
| 524 | return fasync_helper(fd, filep, mode, &async_queue); | 524 | return fasync_helper(fd, filep, mode, &async_queue); |
| @@ -530,7 +530,7 @@ _ctl_fasync(int fd, struct file *filep, int mode) · 5 unmodified lines | |||
| 530 | * @wait - | 530 | * @wait - |
| 531 | * | 531 | * |
| 532 | */ | 532 | */ |
| 533 | unsigned int | 533 | static unsigned int |
| 534 | _ctl_poll(struct file *filep, poll_table *wait) | 534 | _ctl_poll(struct file *filep, poll_table *wait) |
| 535 | { | 535 | { |
| 536 | struct MPT3SAS_ADAPTER *ioc; | 536 | struct MPT3SAS_ADAPTER *ioc; |
| @@ -641,9 +641,8 @@ _ctl_do_mpt_command(struct MPT3SAS_ADAPTER *ioc, struct mpt3_ioctl_command karg, · 104 unmodified lines | |||
| 641 | MPI2RequestHeader_t *mpi_request = NULL, *request; | 641 | MPI2RequestHeader_t *mpi_request = NULL, *request; |
| 642 | MPI2DefaultReply_t *mpi_reply; | 642 | MPI2DefaultReply_t *mpi_reply; |
| 643 | u32 ioc_state; | 643 | u32 ioc_state; |
| 644 | u16 ioc_status; | ||
| 645 | u16 smid; | 644 | u16 smid; |
| 646 | unsigned long timeout, timeleft; | 645 | unsigned long timeout; |
| 647 | u8 issue_reset; | 646 | u8 issue_reset; |
| 648 | u32 sz; | 647 | u32 sz; |
| 649 | void *psge; | 648 | void *psge; |
| @@ -914,8 +913,7 @@ _ctl_do_mpt_command(struct MPT3SAS_ADAPTER *ioc, struct mpt3_ioctl_command karg, · 264 unmodified lines | |||
| 914 | timeout = MPT3_IOCTL_DEFAULT_TIMEOUT; | 913 | timeout = MPT3_IOCTL_DEFAULT_TIMEOUT; |
| 915 | else | 914 | else |
| 916 | timeout = karg.timeout; | 915 | timeout = karg.timeout; |
| 917 | timeleft = wait_for_completion_timeout(&ioc->ctl_cmds.done, | 916 | wait_for_completion_timeout(&ioc->ctl_cmds.done, timeout*HZ); |
| 918 | timeout*HZ); | ||
| 919 | if (mpi_request->Function == MPI2_FUNCTION_SCSI_TASK_MGMT) { | 917 | if (mpi_request->Function == MPI2_FUNCTION_SCSI_TASK_MGMT) { |
| 920 | Mpi2SCSITaskManagementRequest_t *tm_request = | 918 | Mpi2SCSITaskManagementRequest_t *tm_request = |
| 921 | (Mpi2SCSITaskManagementRequest_t *)mpi_request; | 919 | (Mpi2SCSITaskManagementRequest_t *)mpi_request; |
| @@ -938,7 +936,6 @@ _ctl_do_mpt_command(struct MPT3SAS_ADAPTER *ioc, struct mpt3_ioctl_command karg, · 16 unmodified lines | |||
| 938 | } | 936 | } |
| 939 | 937 | ||
| 940 | mpi_reply = ioc->ctl_cmds.reply; | 938 | mpi_reply = ioc->ctl_cmds.reply; |
| 941 | ioc_status = le16_to_cpu(mpi_reply->IOCStatus) & MPI2_IOCSTATUS_MASK; | ||
| 942 | 939 | ||
| 943 | if (mpi_reply->Function == MPI2_FUNCTION_SCSI_TASK_MGMT && | 940 | if (mpi_reply->Function == MPI2_FUNCTION_SCSI_TASK_MGMT && |
| 944 | (ioc->logging_level & MPT_DEBUG_TM)) { | 941 | (ioc->logging_level & MPT_DEBUG_TM)) { |
| @@ -1001,13 +998,11 @@ _ctl_do_mpt_command(struct MPT3SAS_ADAPTER *ioc, struct mpt3_ioctl_command karg, · 56 unmodified lines | |||
| 1001 | ioc->name, | 998 | ioc->name, |
| 1002 | le16_to_cpu(mpi_request->FunctionDependent1)); | 999 | le16_to_cpu(mpi_request->FunctionDependent1)); |
| 1003 | mpt3sas_halt_firmware(ioc); | 1000 | mpt3sas_halt_firmware(ioc); |
| 1004 | mpt3sas_scsih_issue_tm(ioc, | 1001 | mpt3sas_scsih_issue_locked_tm(ioc, |
| 1005 | le16_to_cpu(mpi_request->FunctionDependent1), 0, 0, | 1002 | le16_to_cpu(mpi_request->FunctionDependent1), 0, 0, |
| 1006 | 0, MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET, 0, 30, | 1003 | 0, MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET, 0, 30); |
| 1007 | TM_MUTEX_ON); | ||
| 1008 | } else | 1004 | } else |
| 1009 | mpt3sas_base_hard_reset_handler(ioc, CAN_SLEEP, | 1005 | mpt3sas_base_hard_reset_handler(ioc, FORCE_BIG_HAMMER); |
| 1010 | FORCE_BIG_HAMMER); | ||
| 1011 | } | 1006 | } |
| 1012 | 1007 | ||
| 1013 | out: | 1008 | out: |
| @@ -1220,8 +1215,7 @@ _ctl_do_reset(struct MPT3SAS_ADAPTER *ioc, void __user *arg) · 206 unmodified lines | |||
| 1220 | dctlprintk(ioc, pr_info(MPT3SAS_FMT "%s: enter\n", ioc->name, | 1215 | dctlprintk(ioc, pr_info(MPT3SAS_FMT "%s: enter\n", ioc->name, |
| 1221 | __func__)); | 1216 | __func__)); |
| 1222 | 1217 | ||
| 1223 | retval = mpt3sas_base_hard_reset_handler(ioc, CAN_SLEEP, | 1218 | retval = mpt3sas_base_hard_reset_handler(ioc, FORCE_BIG_HAMMER); |
| 1224 | FORCE_BIG_HAMMER); | ||
| 1225 | pr_info(MPT3SAS_FMT "host reset: %s\n", | 1219 | pr_info(MPT3SAS_FMT "host reset: %s\n", |
| 1226 | ioc->name, ((!retval) ? "SUCCESS" : "FAILED")); | 1220 | ioc->name, ((!retval) ? "SUCCESS" : "FAILED")); |
| 1227 | return 0; | 1221 | return 0; |
| @@ -1381,7 +1375,6 @@ _ctl_diag_register_2(struct MPT3SAS_ADAPTER *ioc, · 153 unmodified lines | |||
| 1381 | Mpi2DiagBufferPostRequest_t *mpi_request; | 1375 | Mpi2DiagBufferPostRequest_t *mpi_request; |
| 1382 | Mpi2DiagBufferPostReply_t *mpi_reply; | 1376 | Mpi2DiagBufferPostReply_t *mpi_reply; |
| 1383 | u8 buffer_type; | 1377 | u8 buffer_type; |
| 1384 | unsigned long timeleft; | ||
| 1385 | u16 smid; | 1378 | u16 smid; |
| 1386 | u16 ioc_status; | 1379 | u16 ioc_status; |
| 1387 | u32 ioc_state; | 1380 | u32 ioc_state; |
| @@ -1499,7 +1492,7 @@ _ctl_diag_register_2(struct MPT3SAS_ADAPTER *ioc, · 111 unmodified lines | |||
| 1499 | 1492 | ||
| 1500 | init_completion(&ioc->ctl_cmds.done); | 1493 | init_completion(&ioc->ctl_cmds.done); |
| 1501 | mpt3sas_base_put_smid_default(ioc, smid); | 1494 | mpt3sas_base_put_smid_default(ioc, smid); |
| 1502 | timeleft = wait_for_completion_timeout(&ioc->ctl_cmds.done, | 1495 | wait_for_completion_timeout(&ioc->ctl_cmds.done, |
| 1503 | MPT3_IOCTL_DEFAULT_TIMEOUT*HZ); | 1496 | MPT3_IOCTL_DEFAULT_TIMEOUT*HZ); |
| 1504 | 1497 | ||
| 1505 | if (!(ioc->ctl_cmds.status & MPT3_CMD_COMPLETE)) { | 1498 | if (!(ioc->ctl_cmds.status & MPT3_CMD_COMPLETE)) { |
| @@ -1538,8 +1531,7 @@ _ctl_diag_register_2(struct MPT3SAS_ADAPTER *ioc, · 32 unmodified lines | |||
| 1538 | 1531 | ||
| 1539 | issue_host_reset: | 1532 | issue_host_reset: |
| 1540 | if (issue_reset) | 1533 | if (issue_reset) |
| 1541 | mpt3sas_base_hard_reset_handler(ioc, CAN_SLEEP, | 1534 | mpt3sas_base_hard_reset_handler(ioc, FORCE_BIG_HAMMER); |
| 1542 | FORCE_BIG_HAMMER); | ||
| 1543 | 1535 | ||
| 1544 | out: | 1536 | out: |
| 1545 | 1537 | ||
| @@ -1800,7 +1792,6 @@ mpt3sas_send_diag_release(struct MPT3SAS_ADAPTER *ioc, u8 buffer_type, · 254 unmodified lines | |||
| 1800 | u16 ioc_status; | 1792 | u16 ioc_status; |
| 1801 | u32 ioc_state; | 1793 | u32 ioc_state; |
| 1802 | int rc; | 1794 | int rc; |
| 1803 | unsigned long timeleft; | ||
| 1804 | 1795 | ||
| 1805 | dctlprintk(ioc, pr_info(MPT3SAS_FMT "%s\n", ioc->name, | 1796 | dctlprintk(ioc, pr_info(MPT3SAS_FMT "%s\n", ioc->name, |
| 1806 | __func__)); | 1797 | __func__)); |
| @@ -1848,7 +1839,7 @@ mpt3sas_send_diag_release(struct MPT3SAS_ADAPTER *ioc, u8 buffer_type, · 41 unmodified lines | |||
| 1848 | 1839 | ||
| 1849 | init_completion(&ioc->ctl_cmds.done); | 1840 | init_completion(&ioc->ctl_cmds.done); |
| 1850 | mpt3sas_base_put_smid_default(ioc, smid); | 1841 | mpt3sas_base_put_smid_default(ioc, smid); |
| 1851 | timeleft = wait_for_completion_timeout(&ioc->ctl_cmds.done, | 1842 | wait_for_completion_timeout(&ioc->ctl_cmds.done, |
| 1852 | MPT3_IOCTL_DEFAULT_TIMEOUT*HZ); | 1843 | MPT3_IOCTL_DEFAULT_TIMEOUT*HZ); |
| 1853 | 1844 | ||
| 1854 | if (!(ioc->ctl_cmds.status & MPT3_CMD_COMPLETE)) { | 1845 | if (!(ioc->ctl_cmds.status & MPT3_CMD_COMPLETE)) { |
| @@ -1974,8 +1965,7 @@ _ctl_diag_release(struct MPT3SAS_ADAPTER *ioc, void __user *arg) · 119 unmodified lines | |||
| 1974 | rc = mpt3sas_send_diag_release(ioc, buffer_type, &issue_reset); | 1965 | rc = mpt3sas_send_diag_release(ioc, buffer_type, &issue_reset); |
| 1975 | 1966 | ||
| 1976 | if (issue_reset) | 1967 | if (issue_reset) |
| 1977 | mpt3sas_base_hard_reset_handler(ioc, CAN_SLEEP, | 1968 | mpt3sas_base_hard_reset_handler(ioc, FORCE_BIG_HAMMER); |
| 1978 | FORCE_BIG_HAMMER); | ||
| 1979 | 1969 | ||
| 1980 | return rc; | 1970 | return rc; |
| 1981 | } | 1971 | } |
| @@ -1995,7 +1985,7 @@ _ctl_diag_read_buffer(struct MPT3SAS_ADAPTER *ioc, void __user *arg) · 13 unmodified lines | |||
| 1995 | Mpi2DiagBufferPostReply_t *mpi_reply; | 1985 | Mpi2DiagBufferPostReply_t *mpi_reply; |
| 1996 | int rc, i; | 1986 | int rc, i; |
| 1997 | u8 buffer_type; | 1987 | u8 buffer_type; |
| 1998 | unsigned long timeleft, request_size, copy_size; | 1988 | unsigned long request_size, copy_size; |
| 1999 | u16 smid; | 1989 | u16 smid; |
| 2000 | u16 ioc_status; | 1990 | u16 ioc_status; |
| 2001 | u8 issue_reset = 0; | 1991 | u8 issue_reset = 0; |
| @@ -2116,7 +2106,7 @@ _ctl_diag_read_buffer(struct MPT3SAS_ADAPTER *ioc, void __user *arg) · 114 unmodified lines | |||
| 2116 | 2106 | ||
| 2117 | init_completion(&ioc->ctl_cmds.done); | 2107 | init_completion(&ioc->ctl_cmds.done); |
| 2118 | mpt3sas_base_put_smid_default(ioc, smid); | 2108 | mpt3sas_base_put_smid_default(ioc, smid); |
| 2119 | timeleft = wait_for_completion_timeout(&ioc->ctl_cmds.done, | 2109 | wait_for_completion_timeout(&ioc->ctl_cmds.done, |
| 2120 | MPT3_IOCTL_DEFAULT_TIMEOUT*HZ); | 2110 | MPT3_IOCTL_DEFAULT_TIMEOUT*HZ); |
| 2121 | 2111 | ||
| 2122 | if (!(ioc->ctl_cmds.status & MPT3_CMD_COMPLETE)) { | 2112 | if (!(ioc->ctl_cmds.status & MPT3_CMD_COMPLETE)) { |
| @@ -2155,8 +2145,7 @@ _ctl_diag_read_buffer(struct MPT3SAS_ADAPTER *ioc, void __user *arg) · 32 unmodified lines | |||
| 2155 | 2145 | ||
| 2156 | issue_host_reset: | 2146 | issue_host_reset: |
| 2157 | if (issue_reset) | 2147 | if (issue_reset) |
| 2158 | mpt3sas_base_hard_reset_handler(ioc, CAN_SLEEP, | 2148 | mpt3sas_base_hard_reset_handler(ioc, FORCE_BIG_HAMMER); |
| 2159 | FORCE_BIG_HAMMER); | ||
| 2160 | 2149 | ||
| 2161 | out: | 2150 | out: |
| 2162 | 2151 | ||
| @@ -2352,7 +2341,7 @@ out_unlock_pciaccess: · 189 unmodified lines | |||
| 2352 | * @cmd - ioctl opcode | 2341 | * @cmd - ioctl opcode |
| 2353 | * @arg - | 2342 | * @arg - |
| 2354 | */ | 2343 | */ |
| 2355 | long | 2344 | static long |
| 2356 | _ctl_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | 2345 | _ctl_ioctl(struct file *file, unsigned int cmd, unsigned long arg) |
| 2357 | { | 2346 | { |
| 2358 | long ret; | 2347 | long ret; |
| @@ -2372,7 +2361,7 @@ _ctl_ioctl(struct file *file, unsigned int cmd, unsigned long arg) · 13 unmodified lines | |||
| 2372 | * @cmd - ioctl opcode | 2361 | * @cmd - ioctl opcode |
| 2373 | * @arg - | 2362 | * @arg - |
| 2374 | */ | 2363 | */ |
| 2375 | long | 2364 | static long |
| 2376 | _ctl_mpt2_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | 2365 | _ctl_mpt2_ioctl(struct file *file, unsigned int cmd, unsigned long arg) |
| 2377 | { | 2366 | { |
| 2378 | long ret; | 2367 | long ret; |
| @@ -2392,7 +2381,7 @@ _ctl_mpt2_ioctl(struct file *file, unsigned int cmd, unsigned long arg) · 13 unmodified lines | |||
| 2392 | * | 2381 | * |
| 2393 | * This routine handles 32 bit applications in 64bit os. | 2382 | * This routine handles 32 bit applications in 64bit os. |
| 2394 | */ | 2383 | */ |
| 2395 | long | 2384 | static long |
| 2396 | _ctl_ioctl_compat(struct file *file, unsigned cmd, unsigned long arg) | 2385 | _ctl_ioctl_compat(struct file *file, unsigned cmd, unsigned long arg) |
| 2397 | { | 2386 | { |
| 2398 | long ret; | 2387 | long ret; |
| @@ -2410,7 +2399,7 @@ _ctl_ioctl_compat(struct file *file, unsigned cmd, unsigned long arg) · 11 unmodified lines | |||
| 2410 | * | 2399 | * |
| 2411 | * This routine handles 32 bit applications in 64bit os. | 2400 | * This routine handles 32 bit applications in 64bit os. |
| 2412 | */ | 2401 | */ |
| 2413 | long | 2402 | static long |
| 2414 | _ctl_mpt2_ioctl_compat(struct file *file, unsigned cmd, unsigned long arg) | 2403 | _ctl_mpt2_ioctl_compat(struct file *file, unsigned cmd, unsigned long arg) |
| 2415 | { | 2404 | { |
| 2416 | long ret; | 2405 | long ret; |
| @@ -1195,7 +1195,7 @@ _scsih_scsi_lookup_find_by_lun(struct MPT3SAS_ADAPTER *ioc, int id, · 1194 unmodified lines | |||
| 1195 | * | 1195 | * |
| 1196 | * Returns queue depth. | 1196 | * Returns queue depth. |
| 1197 | */ | 1197 | */ |
| 1198 | int | 1198 | static int |
| 1199 | scsih_change_queue_depth(struct scsi_device *sdev, int qdepth) | 1199 | scsih_change_queue_depth(struct scsi_device *sdev, int qdepth) |
| 1200 | { | 1200 | { |
| 1201 | struct Scsi_Host *shost = sdev->host; | 1201 | struct Scsi_Host *shost = sdev->host; |
| @@ -1244,7 +1244,7 @@ scsih_change_queue_depth(struct scsi_device *sdev, int qdepth) · 42 unmodified lines | |||
| 1244 | * Returns 0 if ok. Any other return is assumed to be an error and | 1244 | * Returns 0 if ok. Any other return is assumed to be an error and |
| 1245 | * the device is ignored. | 1245 | * the device is ignored. |
| 1246 | */ | 1246 | */ |
| 1247 | int | 1247 | static int |
| 1248 | scsih_target_alloc(struct scsi_target *starget) | 1248 | scsih_target_alloc(struct scsi_target *starget) |
| 1249 | { | 1249 | { |
| 1250 | struct Scsi_Host *shost = dev_to_shost(&starget->dev); | 1250 | struct Scsi_Host *shost = dev_to_shost(&starget->dev); |
| @@ -1311,7 +1311,7 @@ scsih_target_alloc(struct scsi_target *starget) · 60 unmodified lines | |||
| 1311 | * | 1311 | * |
| 1312 | * Returns nothing. | 1312 | * Returns nothing. |
| 1313 | */ | 1313 | */ |
| 1314 | void | 1314 | static void |
| 1315 | scsih_target_destroy(struct scsi_target *starget) | 1315 | scsih_target_destroy(struct scsi_target *starget) |
| 1316 | { | 1316 | { |
| 1317 | struct Scsi_Host *shost = dev_to_shost(&starget->dev); | 1317 | struct Scsi_Host *shost = dev_to_shost(&starget->dev); |
| @@ -1320,7 +1320,6 @@ scsih_target_destroy(struct scsi_target *starget) · 2 unmodified lines | |||
| 1320 | struct _sas_device *sas_device; | 1320 | struct _sas_device *sas_device; |
| 1321 | struct _raid_device *raid_device; | 1321 | struct _raid_device *raid_device; |
| 1322 | unsigned long flags; | 1322 | unsigned long flags; |
| 1323 | struct sas_rphy *rphy; | ||
| 1324 | 1323 | ||
| 1325 | sas_target_priv_data = starget->hostdata; | 1324 | sas_target_priv_data = starget->hostdata; |
| 1326 | if (!sas_target_priv_data) | 1325 | if (!sas_target_priv_data) |
| @@ -1339,7 +1338,6 @@ scsih_target_destroy(struct scsi_target *starget) · 12 unmodified lines | |||
| 1339 | } | 1338 | } |
| 1340 | 1339 | ||
| 1341 | spin_lock_irqsave(&ioc->sas_device_lock, flags); | 1340 | spin_lock_irqsave(&ioc->sas_device_lock, flags); |
| 1342 | rphy = dev_to_rphy(starget->dev.parent); | ||
| 1343 | sas_device = __mpt3sas_get_sdev_from_target(ioc, sas_target_priv_data); | 1341 | sas_device = __mpt3sas_get_sdev_from_target(ioc, sas_target_priv_data); |
| 1344 | if (sas_device && (sas_device->starget == starget) && | 1342 | if (sas_device && (sas_device->starget == starget) && |
| 1345 | (sas_device->id == starget->id) && | 1343 | (sas_device->id == starget->id) && |
| @@ -1369,7 +1367,7 @@ scsih_target_destroy(struct scsi_target *starget) · 23 unmodified lines | |||
| 1369 | * Returns 0 if ok. Any other return is assumed to be an error and | 1367 | * Returns 0 if ok. Any other return is assumed to be an error and |
| 1370 | * the device is ignored. | 1368 | * the device is ignored. |
| 1371 | */ | 1369 | */ |
| 1372 | int | 1370 | static int |
| 1373 | scsih_slave_alloc(struct scsi_device *sdev) | 1371 | scsih_slave_alloc(struct scsi_device *sdev) |
| 1374 | { | 1372 | { |
| 1375 | struct Scsi_Host *shost; | 1373 | struct Scsi_Host *shost; |
| @@ -1434,7 +1432,7 @@ scsih_slave_alloc(struct scsi_device *sdev) · 58 unmodified lines | |||
| 1434 | * | 1432 | * |
| 1435 | * Returns nothing. | 1433 | * Returns nothing. |
| 1436 | */ | 1434 | */ |
| 1437 | void | 1435 | static void |
| 1438 | scsih_slave_destroy(struct scsi_device *sdev) | 1436 | scsih_slave_destroy(struct scsi_device *sdev) |
| 1439 | { | 1437 | { |
| 1440 | struct MPT3SAS_TARGET *sas_target_priv_data; | 1438 | struct MPT3SAS_TARGET *sas_target_priv_data; |
| @@ -1527,7 +1525,7 @@ _scsih_display_sata_capabilities(struct MPT3SAS_ADAPTER *ioc, · 86 unmodified lines | |||
| 1527 | * scsih_is_raid - return boolean indicating device is raid volume | 1525 | * scsih_is_raid - return boolean indicating device is raid volume |
| 1528 | * @dev the device struct object | 1526 | * @dev the device struct object |
| 1529 | */ | 1527 | */ |
| 1530 | int | 1528 | static int |
| 1531 | scsih_is_raid(struct device *dev) | 1529 | scsih_is_raid(struct device *dev) |
| 1532 | { | 1530 | { |
| 1533 | struct scsi_device *sdev = to_scsi_device(dev); | 1531 | struct scsi_device *sdev = to_scsi_device(dev); |
| @@ -1542,7 +1540,7 @@ scsih_is_raid(struct device *dev) · 8 unmodified lines | |||
| 1542 | * scsih_get_resync - get raid volume resync percent complete | 1540 | * scsih_get_resync - get raid volume resync percent complete |
| 1543 | * @dev the device struct object | 1541 | * @dev the device struct object |
| 1544 | */ | 1542 | */ |
| 1545 | void | 1543 | static void |
| 1546 | scsih_get_resync(struct device *dev) | 1544 | scsih_get_resync(struct device *dev) |
| 1547 | { | 1545 | { |
| 1548 | struct scsi_device *sdev = to_scsi_device(dev); | 1546 | struct scsi_device *sdev = to_scsi_device(dev); |
| @@ -1603,7 +1601,7 @@ scsih_get_resync(struct device *dev) · 54 unmodified lines | |||
| 1603 | * scsih_get_state - get raid volume level | 1601 | * scsih_get_state - get raid volume level |
| 1604 | * @dev the device struct object | 1602 | * @dev the device struct object |
| 1605 | */ | 1603 | */ |
| 1606 | void | 1604 | static void |
| 1607 | scsih_get_state(struct device *dev) | 1605 | scsih_get_state(struct device *dev) |
| 1608 | { | 1606 | { |
| 1609 | struct scsi_device *sdev = to_scsi_device(dev); | 1607 | struct scsi_device *sdev = to_scsi_device(dev); |
| @@ -1805,7 +1803,7 @@ _scsih_enable_tlr(struct MPT3SAS_ADAPTER *ioc, struct scsi_device *sdev) · 195 unmodified lines | |||
| 1805 | * Returns 0 if ok. Any other return is assumed to be an error and | 1803 | * Returns 0 if ok. Any other return is assumed to be an error and |
| 1806 | * the device is ignored. | 1804 | * the device is ignored. |
| 1807 | */ | 1805 | */ |
| 1808 | int | 1806 | static int |
| 1809 | scsih_slave_configure(struct scsi_device *sdev) | 1807 | scsih_slave_configure(struct scsi_device *sdev) |
| 1810 | { | 1808 | { |
| 1811 | struct Scsi_Host *shost = sdev->host; | 1809 | struct Scsi_Host *shost = sdev->host; |
| @@ -2021,7 +2019,7 @@ scsih_slave_configure(struct scsi_device *sdev) · 209 unmodified lines | |||
| 2021 | * | 2019 | * |
| 2022 | * Return nothing. | 2020 | * Return nothing. |
| 2023 | */ | 2021 | */ |
| 2024 | int | 2022 | static int |
| 2025 | scsih_bios_param(struct scsi_device *sdev, struct block_device *bdev, | 2023 | scsih_bios_param(struct scsi_device *sdev, struct block_device *bdev, |
| 2026 | sector_t capacity, int params[]) | 2024 | sector_t capacity, int params[]) |
| 2027 | { | 2025 | { |
| @@ -2201,7 +2199,6 @@ mpt3sas_scsih_clear_tm_flag(struct MPT3SAS_ADAPTER *ioc, u16 handle) · 173 unmodified lines | |||
| 2201 | * @type: MPI2_SCSITASKMGMT_TASKTYPE__XXX (defined in mpi2_init.h) | 2199 | * @type: MPI2_SCSITASKMGMT_TASKTYPE__XXX (defined in mpi2_init.h) |
| 2202 | * @smid_task: smid assigned to the task | 2200 | * @smid_task: smid assigned to the task |
| 2203 | * @timeout: timeout in seconds | 2201 | * @timeout: timeout in seconds |
| 2204 | * @m_type: TM_MUTEX_ON or TM_MUTEX_OFF | ||
| 2205 | * Context: user | 2202 | * Context: user |
| 2206 | * | 2203 | * |
| 2207 | * A generic API for sending task management requests to firmware. | 2204 | * A generic API for sending task management requests to firmware. |
| @@ -2212,60 +2209,51 @@ mpt3sas_scsih_clear_tm_flag(struct MPT3SAS_ADAPTER *ioc, u16 handle) · 4 unmodified lines | |||
| 2212 | */ | 2209 | */ |
| 2213 | int | 2210 | int |
| 2214 | mpt3sas_scsih_issue_tm(struct MPT3SAS_ADAPTER *ioc, u16 handle, uint channel, | 2211 | mpt3sas_scsih_issue_tm(struct MPT3SAS_ADAPTER *ioc, u16 handle, uint channel, |
| 2215 | uint id, uint lun, u8 type, u16 smid_task, ulong timeout, | 2212 | uint id, uint lun, u8 type, u16 smid_task, ulong timeout) |
| 2216 | enum mutex_type m_type) | ||
| 2217 | { | 2213 | { |
| 2218 | Mpi2SCSITaskManagementRequest_t *mpi_request; | 2214 | Mpi2SCSITaskManagementRequest_t *mpi_request; |
| 2219 | Mpi2SCSITaskManagementReply_t *mpi_reply; | 2215 | Mpi2SCSITaskManagementReply_t *mpi_reply; |
| 2220 | u16 smid = 0; | 2216 | u16 smid = 0; |
| 2221 | u32 ioc_state; | 2217 | u32 ioc_state; |
| 2222 | unsigned long timeleft; | ||
| 2223 | struct scsiio_tracker *scsi_lookup = NULL; | 2218 | struct scsiio_tracker *scsi_lookup = NULL; |
| 2224 | int rc; | 2219 | int rc; |
| 2225 | u16 msix_task = 0; | 2220 | u16 msix_task = 0; |
| 2226 | 2221 | ||
| 2227 | if (m_type == TM_MUTEX_ON) | 2222 | lockdep_assert_held(&ioc->tm_cmds.mutex); |
| 2228 | mutex_lock(&ioc->tm_cmds.mutex); | 2223 | |
| 2229 | if (ioc->tm_cmds.status != MPT3_CMD_NOT_USED) { | 2224 | if (ioc->tm_cmds.status != MPT3_CMD_NOT_USED) { |
| 2230 | pr_info(MPT3SAS_FMT "%s: tm_cmd busy!!!\n", | 2225 | pr_info(MPT3SAS_FMT "%s: tm_cmd busy!!!\n", |
| 2231 | __func__, ioc->name); | 2226 | __func__, ioc->name); |
| 2232 | rc = FAILED; | 2227 | return FAILED; |
| 2233 | goto err_out; | ||
| 2234 | } | 2228 | } |
| 2235 | 2229 | ||
| 2236 | if (ioc->shost_recovery || ioc->remove_host || | 2230 | if (ioc->shost_recovery || ioc->remove_host || |
| 2237 | ioc->pci_error_recovery) { | 2231 | ioc->pci_error_recovery) { |
| 2238 | pr_info(MPT3SAS_FMT "%s: host reset in progress!\n", | 2232 | pr_info(MPT3SAS_FMT "%s: host reset in progress!\n", |
| 2239 | __func__, ioc->name); | 2233 | __func__, ioc->name); |
| 2240 | rc = FAILED; | 2234 | return FAILED; |
| 2241 | goto err_out; | ||
| 2242 | } | 2235 | } |
| 2243 | 2236 | ||
| 2244 | ioc_state = mpt3sas_base_get_iocstate(ioc, 0); | 2237 | ioc_state = mpt3sas_base_get_iocstate(ioc, 0); |
| 2245 | if (ioc_state & MPI2_DOORBELL_USED) { | 2238 | if (ioc_state & MPI2_DOORBELL_USED) { |
| 2246 | dhsprintk(ioc, pr_info(MPT3SAS_FMT | 2239 | dhsprintk(ioc, pr_info(MPT3SAS_FMT |
| 2247 | "unexpected doorbell active!\n", ioc->name)); | 2240 | "unexpected doorbell active!\n", ioc->name)); |
| 2248 | rc = mpt3sas_base_hard_reset_handler(ioc, CAN_SLEEP, | 2241 | rc = mpt3sas_base_hard_reset_handler(ioc, FORCE_BIG_HAMMER); |
| 2249 | FORCE_BIG_HAMMER); | 2242 | return (!rc) ? SUCCESS : FAILED; |
| 2250 | rc = (!rc) ? SUCCESS : FAILED; | ||
| 2251 | goto err_out; | ||
| 2252 | } | 2243 | } |
| 2253 | 2244 | ||
| 2254 | if ((ioc_state & MPI2_IOC_STATE_MASK) == MPI2_IOC_STATE_FAULT) { | 2245 | if ((ioc_state & MPI2_IOC_STATE_MASK) == MPI2_IOC_STATE_FAULT) { |
| 2255 | mpt3sas_base_fault_info(ioc, ioc_state & | 2246 | mpt3sas_base_fault_info(ioc, ioc_state & |
| 2256 | MPI2_DOORBELL_DATA_MASK); | 2247 | MPI2_DOORBELL_DATA_MASK); |
| 2257 | rc = mpt3sas_base_hard_reset_handler(ioc, CAN_SLEEP, | 2248 | rc = mpt3sas_base_hard_reset_handler(ioc, FORCE_BIG_HAMMER); |
| 2258 | FORCE_BIG_HAMMER); | 2249 | return (!rc) ? SUCCESS : FAILED; |
| 2259 | rc = (!rc) ? SUCCESS : FAILED; | ||
| 2260 | goto err_out; | ||
| 2261 | } | 2250 | } |
| 2262 | 2251 | ||
| 2263 | smid = mpt3sas_base_get_smid_hpr(ioc, ioc->tm_cb_idx); | 2252 | smid = mpt3sas_base_get_smid_hpr(ioc, ioc->tm_cb_idx); |
| 2264 | if (!smid) { | 2253 | if (!smid) { |
| 2265 | pr_err(MPT3SAS_FMT "%s: failed obtaining a smid\n", | 2254 | pr_err(MPT3SAS_FMT "%s: failed obtaining a smid\n", |
| 2266 | ioc->name, __func__); | 2255 | ioc->name, __func__); |
| 2267 | rc = FAILED; | 2256 | return FAILED; |
| 2268 | goto err_out; | ||
| 2269 | } | 2257 | } |
| 2270 | 2258 | ||
| 2271 | if (type == MPI2_SCSITASKMGMT_TASKTYPE_ABORT_TASK) | 2259 | if (type == MPI2_SCSITASKMGMT_TASKTYPE_ABORT_TASK) |
| @@ -2292,19 +2280,17 @@ mpt3sas_scsih_issue_tm(struct MPT3SAS_ADAPTER *ioc, u16 handle, uint channel, · 20 unmodified lines | |||
| 2292 | else | 2280 | else |
| 2293 | msix_task = 0; | 2281 | msix_task = 0; |
| 2294 | mpt3sas_base_put_smid_hi_priority(ioc, smid, msix_task); | 2282 | mpt3sas_base_put_smid_hi_priority(ioc, smid, msix_task); |
| 2295 | timeleft = wait_for_completion_timeout(&ioc->tm_cmds.done, timeout*HZ); | 2283 | wait_for_completion_timeout(&ioc->tm_cmds.done, timeout*HZ); |
| 2296 | if (!(ioc->tm_cmds.status & MPT3_CMD_COMPLETE)) { | 2284 | if (!(ioc->tm_cmds.status & MPT3_CMD_COMPLETE)) { |
| 2297 | pr_err(MPT3SAS_FMT "%s: timeout\n", | 2285 | pr_err(MPT3SAS_FMT "%s: timeout\n", |
| 2298 | ioc->name, __func__); | 2286 | ioc->name, __func__); |
| 2299 | _debug_dump_mf(mpi_request, | 2287 | _debug_dump_mf(mpi_request, |
| 2300 | sizeof(Mpi2SCSITaskManagementRequest_t)/4); | 2288 | sizeof(Mpi2SCSITaskManagementRequest_t)/4); |
| 2301 | if (!(ioc->tm_cmds.status & MPT3_CMD_RESET)) { | 2289 | if (!(ioc->tm_cmds.status & MPT3_CMD_RESET)) { |
| 2302 | rc = mpt3sas_base_hard_reset_handler(ioc, CAN_SLEEP, | 2290 | rc = mpt3sas_base_hard_reset_handler(ioc, |
| 2303 | FORCE_BIG_HAMMER); | 2291 | FORCE_BIG_HAMMER); |
| 2304 | rc = (!rc) ? SUCCESS : FAILED; | 2292 | rc = (!rc) ? SUCCESS : FAILED; |
| 2305 | ioc->tm_cmds.status = MPT3_CMD_NOT_USED; | 2293 | goto out; |
| 2306 | mpt3sas_scsih_clear_tm_flag(ioc, handle); | ||
| 2307 | goto err_out; | ||
| 2308 | } | 2294 | } |
| 2309 | } | 2295 | } |
| 2310 | 2296 | ||
| @@ -2356,17 +2342,23 @@ mpt3sas_scsih_issue_tm(struct MPT3SAS_ADAPTER *ioc, u16 handle, uint channel, · 45 unmodified lines | |||
| 2356 | break; | 2342 | break; |
| 2357 | } | 2343 | } |
| 2358 | 2344 | ||
| 2345 | out: | ||
| 2359 | mpt3sas_scsih_clear_tm_flag(ioc, handle); | 2346 | mpt3sas_scsih_clear_tm_flag(ioc, handle); |
| 2360 | ioc->tm_cmds.status = MPT3_CMD_NOT_USED; | 2347 | ioc->tm_cmds.status = MPT3_CMD_NOT_USED; |
| 2361 | if (m_type == TM_MUTEX_ON) | ||
| 2362 | mutex_unlock(&ioc->tm_cmds.mutex); | ||
| 2363 | |||
| 2364 | return rc; | 2348 | return rc; |
| 2349 | } | ||
| 2365 | 2350 | ||
| 2366 | err_out: | 2351 | int mpt3sas_scsih_issue_locked_tm(struct MPT3SAS_ADAPTER *ioc, u16 handle, |
| 2367 | if (m_type == TM_MUTEX_ON) | 2352 | uint channel, uint id, uint lun, u8 type, u16 smid_task, ulong timeout) |
| 2368 | mutex_unlock(&ioc->tm_cmds.mutex); | 2353 | { |
| 2369 | return rc; | 2354 | int ret; |
| 2355 | |||
| 2356 | mutex_lock(&ioc->tm_cmds.mutex); | ||
| 2357 | ret = mpt3sas_scsih_issue_tm(ioc, handle, channel, id, lun, type, | ||
| 2358 | smid_task, timeout); | ||
| 2359 | mutex_unlock(&ioc->tm_cmds.mutex); | ||
| 2360 | |||
| 2361 | return ret; | ||
| 2370 | } | 2362 | } |
| 2371 | 2363 | ||
| 2372 | /** | 2364 | /** |
| @@ -2439,7 +2431,7 @@ _scsih_tm_display_info(struct MPT3SAS_ADAPTER *ioc, struct scsi_cmnd *scmd) · 66 unmodified lines | |||
| 2439 | * | 2431 | * |
| 2440 | * Returns SUCCESS if command aborted else FAILED | 2432 | * Returns SUCCESS if command aborted else FAILED |
| 2441 | */ | 2433 | */ |
| 2442 | int | 2434 | static int |
| 2443 | scsih_abort(struct scsi_cmnd *scmd) | 2435 | scsih_abort(struct scsi_cmnd *scmd) |
| 2444 | { | 2436 | { |
| 2445 | struct MPT3SAS_ADAPTER *ioc = shost_priv(scmd->device->host); | 2437 | struct MPT3SAS_ADAPTER *ioc = shost_priv(scmd->device->host); |
| @@ -2482,9 +2474,9 @@ scsih_abort(struct scsi_cmnd *scmd) · 36 unmodified lines | |||
| 2482 | mpt3sas_halt_firmware(ioc); | 2474 | mpt3sas_halt_firmware(ioc); |
| 2483 | 2475 | ||
| 2484 | handle = sas_device_priv_data->sas_target->handle; | 2476 | handle = sas_device_priv_data->sas_target->handle; |
| 2485 | r = mpt3sas_scsih_issue_tm(ioc, handle, scmd->device->channel, | 2477 | r = mpt3sas_scsih_issue_locked_tm(ioc, handle, scmd->device->channel, |
| 2486 | scmd->device->id, scmd->device->lun, | 2478 | scmd->device->id, scmd->device->lun, |
| 2487 | MPI2_SCSITASKMGMT_TASKTYPE_ABORT_TASK, smid, 30, TM_MUTEX_ON); | 2479 | MPI2_SCSITASKMGMT_TASKTYPE_ABORT_TASK, smid, 30); |
| 2488 | 2480 | ||
| 2489 | out: | 2481 | out: |
| 2490 | sdev_printk(KERN_INFO, scmd->device, "task abort: %s scmd(%p)\n", | 2482 | sdev_printk(KERN_INFO, scmd->device, "task abort: %s scmd(%p)\n", |
| @@ -2498,7 +2490,7 @@ scsih_abort(struct scsi_cmnd *scmd) · 7 unmodified lines | |||
| 2498 | * | 2490 | * |
| 2499 | * Returns SUCCESS if command aborted else FAILED | 2491 | * Returns SUCCESS if command aborted else FAILED |
| 2500 | */ | 2492 | */ |
| 2501 | int | 2493 | static int |
| 2502 | scsih_dev_reset(struct scsi_cmnd *scmd) | 2494 | scsih_dev_reset(struct scsi_cmnd *scmd) |
| 2503 | { | 2495 | { |
| 2504 | struct MPT3SAS_ADAPTER *ioc = shost_priv(scmd->device->host); | 2496 | struct MPT3SAS_ADAPTER *ioc = shost_priv(scmd->device->host); |
| @@ -2541,9 +2533,9 @@ scsih_dev_reset(struct scsi_cmnd *scmd) · 36 unmodified lines | |||
| 2541 | goto out; | 2533 | goto out; |
| 2542 | } | 2534 | } |
| 2543 | 2535 | ||
| 2544 | r = mpt3sas_scsih_issue_tm(ioc, handle, scmd->device->channel, | 2536 | r = mpt3sas_scsih_issue_locked_tm(ioc, handle, scmd->device->channel, |
| 2545 | scmd->device->id, scmd->device->lun, | 2537 | scmd->device->id, scmd->device->lun, |
| 2546 | MPI2_SCSITASKMGMT_TASKTYPE_LOGICAL_UNIT_RESET, 0, 30, TM_MUTEX_ON); | 2538 | MPI2_SCSITASKMGMT_TASKTYPE_LOGICAL_UNIT_RESET, 0, 30); |
| 2547 | 2539 | ||
| 2548 | out: | 2540 | out: |
| 2549 | sdev_printk(KERN_INFO, scmd->device, "device reset: %s scmd(%p)\n", | 2541 | sdev_printk(KERN_INFO, scmd->device, "device reset: %s scmd(%p)\n", |
| @@ -2561,7 +2553,7 @@ scsih_dev_reset(struct scsi_cmnd *scmd) · 11 unmodified lines | |||
| 2561 | * | 2553 | * |
| 2562 | * Returns SUCCESS if command aborted else FAILED | 2554 | * Returns SUCCESS if command aborted else FAILED |
| 2563 | */ | 2555 | */ |
| 2564 | int | 2556 | static int |
| 2565 | scsih_target_reset(struct scsi_cmnd *scmd) | 2557 | scsih_target_reset(struct scsi_cmnd *scmd) |
| 2566 | { | 2558 | { |
| 2567 | struct MPT3SAS_ADAPTER *ioc = shost_priv(scmd->device->host); | 2559 | struct MPT3SAS_ADAPTER *ioc = shost_priv(scmd->device->host); |
| @@ -2603,9 +2595,9 @@ scsih_target_reset(struct scsi_cmnd *scmd) · 35 unmodified lines | |||
| 2603 | goto out; | 2595 | goto out; |
| 2604 | } | 2596 | } |
| 2605 | 2597 | ||
| 2606 | r = mpt3sas_scsih_issue_tm(ioc, handle, scmd->device->channel, | 2598 | r = mpt3sas_scsih_issue_locked_tm(ioc, handle, scmd->device->channel, |
| 2607 | scmd->device->id, 0, MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET, 0, | 2599 | scmd->device->id, 0, MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET, 0, |
| 2608 | 30, TM_MUTEX_ON); | 2600 | 30); |
| 2609 | 2601 | ||
| 2610 | out: | 2602 | out: |
| 2611 | starget_printk(KERN_INFO, starget, "target reset: %s scmd(%p)\n", | 2603 | starget_printk(KERN_INFO, starget, "target reset: %s scmd(%p)\n", |
| @@ -2624,7 +2616,7 @@ scsih_target_reset(struct scsi_cmnd *scmd) · 12 unmodified lines | |||
| 2624 | * | 2616 | * |
| 2625 | * Returns SUCCESS if command aborted else FAILED | 2617 | * Returns SUCCESS if command aborted else FAILED |
| 2626 | */ | 2618 | */ |
| 2627 | int | 2619 | static int |
| 2628 | scsih_host_reset(struct scsi_cmnd *scmd) | 2620 | scsih_host_reset(struct scsi_cmnd *scmd) |
| 2629 | { | 2621 | { |
| 2630 | struct MPT3SAS_ADAPTER *ioc = shost_priv(scmd->device->host); | 2622 | struct MPT3SAS_ADAPTER *ioc = shost_priv(scmd->device->host); |
| @@ -2641,8 +2633,7 @@ scsih_host_reset(struct scsi_cmnd *scmd) · 10 unmodified lines | |||
| 2641 | goto out; | 2633 | goto out; |
| 2642 | } | 2634 | } |
| 2643 | 2635 | ||
| 2644 | retval = mpt3sas_base_hard_reset_handler(ioc, CAN_SLEEP, | 2636 | retval = mpt3sas_base_hard_reset_handler(ioc, FORCE_BIG_HAMMER); |
| 2645 | FORCE_BIG_HAMMER); | ||
| 2646 | r = (retval < 0) ? FAILED : SUCCESS; | 2637 | r = (retval < 0) ? FAILED : SUCCESS; |
| 2647 | out: | 2638 | out: |
| 2648 | pr_info(MPT3SAS_FMT "host reset: %s scmd(%p)\n", | 2639 | pr_info(MPT3SAS_FMT "host reset: %s scmd(%p)\n", |
| @@ -3455,7 +3446,7 @@ _scsih_tm_volume_tr_complete(struct MPT3SAS_ADAPTER *ioc, u16 smid, · 806 unmodified lines | |||
| 3455 | * | 3446 | * |
| 3456 | * Context - processed in interrupt context. | 3447 | * Context - processed in interrupt context. |
| 3457 | */ | 3448 | */ |
| 3458 | void | 3449 | static void |
| 3459 | _scsih_issue_delayed_event_ack(struct MPT3SAS_ADAPTER *ioc, u16 smid, u16 event, | 3450 | _scsih_issue_delayed_event_ack(struct MPT3SAS_ADAPTER *ioc, u16 smid, u16 event, |
| 3460 | u32 event_context) | 3451 | u32 event_context) |
| 3461 | { | 3452 | { |
| @@ -3494,7 +3485,7 @@ _scsih_issue_delayed_event_ack(struct MPT3SAS_ADAPTER *ioc, u16 smid, u16 event, · 32 unmodified lines | |||
| 3494 | * | 3485 | * |
| 3495 | * Context - processed in interrupt context. | 3486 | * Context - processed in interrupt context. |
| 3496 | */ | 3487 | */ |
| 3497 | void | 3488 | static void |
| 3498 | _scsih_issue_delayed_sas_io_unit_ctrl(struct MPT3SAS_ADAPTER *ioc, | 3489 | _scsih_issue_delayed_sas_io_unit_ctrl(struct MPT3SAS_ADAPTER *ioc, |
| 3499 | u16 smid, u16 handle) | 3490 | u16 smid, u16 handle) |
| 3500 | { | 3491 | { |
| @@ -4032,7 +4023,7 @@ _scsih_eedp_error_handling(struct scsi_cmnd *scmd, u16 ioc_status) · 531 unmodified lines | |||
| 4032 | * SCSI_MLQUEUE_DEVICE_BUSY if the device queue is full, or | 4023 | * SCSI_MLQUEUE_DEVICE_BUSY if the device queue is full, or |
| 4033 | * SCSI_MLQUEUE_HOST_BUSY if the entire host queue is full | 4024 | * SCSI_MLQUEUE_HOST_BUSY if the entire host queue is full |
| 4034 | */ | 4025 | */ |
| 4035 | int | 4026 | static int |
| 4036 | scsih_qcmd(struct Scsi_Host *shost, struct scsi_cmnd *scmd) | 4027 | scsih_qcmd(struct Scsi_Host *shost, struct scsi_cmnd *scmd) |
| 4037 | { | 4028 | { |
| 4038 | struct MPT3SAS_ADAPTER *ioc = shost_priv(shost); | 4029 | struct MPT3SAS_ADAPTER *ioc = shost_priv(shost); |
| @@ -4701,7 +4692,7 @@ _scsih_io_done(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index, u32 reply) · 662 unmodified lines | |||
| 4701 | le16_to_cpu(mpi_reply->DevHandle)); | 4692 | le16_to_cpu(mpi_reply->DevHandle)); |
| 4702 | mpt3sas_trigger_scsi(ioc, data.skey, data.asc, data.ascq); | 4693 | mpt3sas_trigger_scsi(ioc, data.skey, data.asc, data.ascq); |
| 4703 | 4694 | ||
| 4704 | if (!(ioc->logging_level & MPT_DEBUG_REPLY) && | 4695 | if ((ioc->logging_level & MPT_DEBUG_REPLY) && |
| 4705 | ((scmd->sense_buffer[2] == UNIT_ATTENTION) || | 4696 | ((scmd->sense_buffer[2] == UNIT_ATTENTION) || |
| 4706 | (scmd->sense_buffer[2] == MEDIUM_ERROR) || | 4697 | (scmd->sense_buffer[2] == MEDIUM_ERROR) || |
| 4707 | (scmd->sense_buffer[2] == HARDWARE_ERROR))) | 4698 | (scmd->sense_buffer[2] == HARDWARE_ERROR))) |
| @@ -5380,8 +5371,9 @@ _scsih_check_device(struct MPT3SAS_ADAPTER *ioc, · 672 unmodified lines | |||
| 5380 | MPI2_SAS_DEVICE0_FLAGS_ENCL_LEVEL_VALID) { | 5371 | MPI2_SAS_DEVICE0_FLAGS_ENCL_LEVEL_VALID) { |
| 5381 | sas_device->enclosure_level = | 5372 | sas_device->enclosure_level = |
| 5382 | le16_to_cpu(sas_device_pg0.EnclosureLevel); | 5373 | le16_to_cpu(sas_device_pg0.EnclosureLevel); |
| 5383 | memcpy(&sas_device->connector_name[0], | 5374 | memcpy(sas_device->connector_name, |
| 5384 | &sas_device_pg0.ConnectorName[0], 4); | 5375 | sas_device_pg0.ConnectorName, 4); |
| 5376 | sas_device->connector_name[4] = '\0'; | ||
| 5385 | } else { | 5377 | } else { |
| 5386 | sas_device->enclosure_level = 0; | 5378 | sas_device->enclosure_level = 0; |
| 5387 | sas_device->connector_name[0] = '\0'; | 5379 | sas_device->connector_name[0] = '\0'; |
| @@ -5508,8 +5500,9 @@ _scsih_add_device(struct MPT3SAS_ADAPTER *ioc, u16 handle, u8 phy_num, · 120 unmodified lines | |||
| 5508 | if (sas_device_pg0.Flags & MPI2_SAS_DEVICE0_FLAGS_ENCL_LEVEL_VALID) { | 5500 | if (sas_device_pg0.Flags & MPI2_SAS_DEVICE0_FLAGS_ENCL_LEVEL_VALID) { |
| 5509 | sas_device->enclosure_level = | 5501 | sas_device->enclosure_level = |
| 5510 | le16_to_cpu(sas_device_pg0.EnclosureLevel); | 5502 | le16_to_cpu(sas_device_pg0.EnclosureLevel); |
| 5511 | memcpy(&sas_device->connector_name[0], | 5503 | memcpy(sas_device->connector_name, |
| 5512 | &sas_device_pg0.ConnectorName[0], 4); | 5504 | sas_device_pg0.ConnectorName, 4); |
| 5505 | sas_device->connector_name[4] = '\0'; | ||
| 5513 | } else { | 5506 | } else { |
| 5514 | sas_device->enclosure_level = 0; | 5507 | sas_device->enclosure_level = 0; |
| 5515 | sas_device->connector_name[0] = '\0'; | 5508 | sas_device->connector_name[0] = '\0'; |
| @@ -6087,8 +6080,7 @@ _scsih_sas_broadcast_primitive_event(struct MPT3SAS_ADAPTER *ioc, · 571 unmodified lines | |||
| 6087 | 6080 | ||
| 6088 | spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags); | 6081 | spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags); |
| 6089 | r = mpt3sas_scsih_issue_tm(ioc, handle, 0, 0, lun, | 6082 | r = mpt3sas_scsih_issue_tm(ioc, handle, 0, 0, lun, |
| 6090 | MPI2_SCSITASKMGMT_TASKTYPE_QUERY_TASK, smid, 30, | 6083 | MPI2_SCSITASKMGMT_TASKTYPE_QUERY_TASK, smid, 30); |
| 6091 | TM_MUTEX_OFF); | ||
| 6092 | if (r == FAILED) { | 6084 | if (r == FAILED) { |
| 6093 | sdev_printk(KERN_WARNING, sdev, | 6085 | sdev_printk(KERN_WARNING, sdev, |
| 6094 | "mpt3sas_scsih_issue_tm: FAILED when sending " | 6086 | "mpt3sas_scsih_issue_tm: FAILED when sending " |
| @@ -6128,8 +6120,8 @@ _scsih_sas_broadcast_primitive_event(struct MPT3SAS_ADAPTER *ioc, · 33 unmodified lines | |||
| 6128 | goto out_no_lock; | 6120 | goto out_no_lock; |
| 6129 | 6121 | ||
| 6130 | r = mpt3sas_scsih_issue_tm(ioc, handle, sdev->channel, sdev->id, | 6122 | r = mpt3sas_scsih_issue_tm(ioc, handle, sdev->channel, sdev->id, |
| 6131 | sdev->lun, MPI2_SCSITASKMGMT_TASKTYPE_ABORT_TASK, smid, 30, | 6123 | sdev->lun, MPI2_SCSITASKMGMT_TASKTYPE_ABORT_TASK, smid, |
| 6132 | TM_MUTEX_OFF); | 6124 | 30); |
| 6133 | if (r == FAILED) { | 6125 | if (r == FAILED) { |
| 6134 | sdev_printk(KERN_WARNING, sdev, | 6126 | sdev_printk(KERN_WARNING, sdev, |
| 6135 | "mpt3sas_scsih_issue_tm: ABORT_TASK: FAILED : " | 6127 | "mpt3sas_scsih_issue_tm: ABORT_TASK: FAILED : " |
| @@ -6297,8 +6289,7 @@ _scsih_ir_fastpath(struct MPT3SAS_ADAPTER *ioc, u16 handle, u8 phys_disk_num) · 161 unmodified lines | |||
| 6297 | mutex_unlock(&ioc->scsih_cmds.mutex); | 6289 | mutex_unlock(&ioc->scsih_cmds.mutex); |
| 6298 | 6290 | ||
| 6299 | if (issue_reset) | 6291 | if (issue_reset) |
| 6300 | mpt3sas_base_hard_reset_handler(ioc, CAN_SLEEP, | 6292 | mpt3sas_base_hard_reset_handler(ioc, FORCE_BIG_HAMMER); |
| 6301 | FORCE_BIG_HAMMER); | ||
| 6302 | return rc; | 6293 | return rc; |
| 6303 | } | 6294 | } |
| 6304 | 6295 | ||
| @@ -6311,11 +6302,10 @@ _scsih_ir_fastpath(struct MPT3SAS_ADAPTER *ioc, u16 handle, u8 phys_disk_num) · 6 unmodified lines | |||
| 6311 | static void | 6302 | static void |
| 6312 | _scsih_reprobe_lun(struct scsi_device *sdev, void *no_uld_attach) | 6303 | _scsih_reprobe_lun(struct scsi_device *sdev, void *no_uld_attach) |
| 6313 | { | 6304 | { |
| 6314 | int rc; | ||
| 6315 | sdev->no_uld_attach = no_uld_attach ? 1 : 0; | 6305 | sdev->no_uld_attach = no_uld_attach ? 1 : 0; |
| 6316 | sdev_printk(KERN_INFO, sdev, "%s raid component\n", | 6306 | sdev_printk(KERN_INFO, sdev, "%s raid component\n", |
| 6317 | sdev->no_uld_attach ? "hidding" : "exposing"); | 6307 | sdev->no_uld_attach ? "hidding" : "exposing"); |
| 6318 | rc = scsi_device_reprobe(sdev); | 6308 | WARN_ON(scsi_device_reprobe(sdev)); |
| 6319 | } | 6309 | } |
| 6320 | 6310 | ||
| 6321 | /** | 6311 | /** |
| @@ -8137,7 +8127,7 @@ _scsih_ir_shutdown(struct MPT3SAS_ADAPTER *ioc) · 1815 unmodified lines | |||
| 8137 | * Routine called when unloading the driver. | 8127 | * Routine called when unloading the driver. |
| 8138 | * Return nothing. | 8128 | * Return nothing. |
| 8139 | */ | 8129 | */ |
| 8140 | void scsih_remove(struct pci_dev *pdev) | 8130 | static void scsih_remove(struct pci_dev *pdev) |
| 8141 | { | 8131 | { |
| 8142 | struct Scsi_Host *shost = pci_get_drvdata(pdev); | 8132 | struct Scsi_Host *shost = pci_get_drvdata(pdev); |
| 8143 | struct MPT3SAS_ADAPTER *ioc = shost_priv(shost); | 8133 | struct MPT3SAS_ADAPTER *ioc = shost_priv(shost); |
| @@ -8210,7 +8200,7 @@ void scsih_remove(struct pci_dev *pdev) · 66 unmodified lines | |||
| 8210 | * | 8200 | * |
| 8211 | * Return nothing. | 8201 | * Return nothing. |
| 8212 | */ | 8202 | */ |
| 8213 | void | 8203 | static void |
| 8214 | scsih_shutdown(struct pci_dev *pdev) | 8204 | scsih_shutdown(struct pci_dev *pdev) |
| 8215 | { | 8205 | { |
| 8216 | struct Scsi_Host *shost = pci_get_drvdata(pdev); | 8206 | struct Scsi_Host *shost = pci_get_drvdata(pdev); |
| @@ -8451,7 +8441,7 @@ _scsih_probe_devices(struct MPT3SAS_ADAPTER *ioc) · 234 unmodified lines | |||
| 8451 | * of scanning the entire bus. In our implemention, we will kick off | 8441 | * of scanning the entire bus. In our implemention, we will kick off |
| 8452 | * firmware discovery. | 8442 | * firmware discovery. |
| 8453 | */ | 8443 | */ |
| 8454 | void | 8444 | static void |
| 8455 | scsih_scan_start(struct Scsi_Host *shost) | 8445 | scsih_scan_start(struct Scsi_Host *shost) |
| 8456 | { | 8446 | { |
| 8457 | struct MPT3SAS_ADAPTER *ioc = shost_priv(shost); | 8447 | struct MPT3SAS_ADAPTER *ioc = shost_priv(shost); |
| @@ -8478,7 +8468,7 @@ scsih_scan_start(struct Scsi_Host *shost) · 20 unmodified lines | |||
| 8478 | * scsi_host and the elapsed time of the scan in jiffies. In our implemention, | 8468 | * scsi_host and the elapsed time of the scan in jiffies. In our implemention, |
| 8479 | * we wait for firmware discovery to complete, then return 1. | 8469 | * we wait for firmware discovery to complete, then return 1. |
| 8480 | */ | 8470 | */ |
| 8481 | int | 8471 | static int |
| 8482 | scsih_scan_finished(struct Scsi_Host *shost, unsigned long time) | 8472 | scsih_scan_finished(struct Scsi_Host *shost, unsigned long time) |
| 8483 | { | 8473 | { |
| 8484 | struct MPT3SAS_ADAPTER *ioc = shost_priv(shost); | 8474 | struct MPT3SAS_ADAPTER *ioc = shost_priv(shost); |
| @@ -8608,7 +8598,7 @@ static struct raid_function_template mpt3sas_raid_functions = { · 123 unmodified lines | |||
| 8608 | * MPI25_VERSION for SAS 3.0 HBA devices, and | 8598 | * MPI25_VERSION for SAS 3.0 HBA devices, and |
| 8609 | * MPI26 VERSION for Cutlass & Invader SAS 3.0 HBA devices | 8599 | * MPI26 VERSION for Cutlass & Invader SAS 3.0 HBA devices |
| 8610 | */ | 8600 | */ |
| 8611 | u16 | 8601 | static u16 |
| 8612 | _scsih_determine_hba_mpi_version(struct pci_dev *pdev) | 8602 | _scsih_determine_hba_mpi_version(struct pci_dev *pdev) |
| 8613 | { | 8603 | { |
| 8614 | 8604 | ||
| @@ -8660,7 +8650,7 @@ _scsih_determine_hba_mpi_version(struct pci_dev *pdev) · 45 unmodified lines | |||
| 8660 | * | 8650 | * |
| 8661 | * Returns 0 success, anything else error. | 8651 | * Returns 0 success, anything else error. |
| 8662 | */ | 8652 | */ |
| 8663 | int | 8653 | static int |
| 8664 | _scsih_probe(struct pci_dev *pdev, const struct pci_device_id *id) | 8654 | _scsih_probe(struct pci_dev *pdev, const struct pci_device_id *id) |
| 8665 | { | 8655 | { |
| 8666 | struct MPT3SAS_ADAPTER *ioc; | 8656 | struct MPT3SAS_ADAPTER *ioc; |
| @@ -8869,7 +8859,7 @@ out_add_shost_fail: · 202 unmodified lines | |||
| 8869 | * | 8859 | * |
| 8870 | * Returns 0 success, anything else error. | 8860 | * Returns 0 success, anything else error. |
| 8871 | */ | 8861 | */ |
| 8872 | int | 8862 | static int |
| 8873 | scsih_suspend(struct pci_dev *pdev, pm_message_t state) | 8863 | scsih_suspend(struct pci_dev *pdev, pm_message_t state) |
| 8874 | { | 8864 | { |
| 8875 | struct Scsi_Host *shost = pci_get_drvdata(pdev); | 8865 | struct Scsi_Host *shost = pci_get_drvdata(pdev); |
| @@ -8896,7 +8886,7 @@ scsih_suspend(struct pci_dev *pdev, pm_message_t state) · 20 unmodified lines | |||
| 8896 | * | 8886 | * |
| 8897 | * Returns 0 success, anything else error. | 8887 | * Returns 0 success, anything else error. |
| 8898 | */ | 8888 | */ |
| 8899 | int | 8889 | static int |
| 8900 | scsih_resume(struct pci_dev *pdev) | 8890 | scsih_resume(struct pci_dev *pdev) |
| 8901 | { | 8891 | { |
| 8902 | struct Scsi_Host *shost = pci_get_drvdata(pdev); | 8892 | struct Scsi_Host *shost = pci_get_drvdata(pdev); |
| @@ -8916,7 +8906,7 @@ scsih_resume(struct pci_dev *pdev) · 13 unmodified lines | |||
| 8916 | if (r) | 8906 | if (r) |
| 8917 | return r; | 8907 | return r; |
| 8918 | 8908 | ||
| 8919 | mpt3sas_base_hard_reset_handler(ioc, CAN_SLEEP, SOFT_RESET); | 8909 | mpt3sas_base_hard_reset_handler(ioc, SOFT_RESET); |
| 8920 | scsi_unblock_requests(shost); | 8910 | scsi_unblock_requests(shost); |
| 8921 | mpt3sas_base_start_watchdog(ioc); | 8911 | mpt3sas_base_start_watchdog(ioc); |
| 8922 | return 0; | 8912 | return 0; |
| @@ -8933,7 +8923,7 @@ scsih_resume(struct pci_dev *pdev) · 10 unmodified lines | |||
| 8933 | * Return value: | 8923 | * Return value: |
| 8934 | * PCI_ERS_RESULT_NEED_RESET or PCI_ERS_RESULT_DISCONNECT | 8924 | * PCI_ERS_RESULT_NEED_RESET or PCI_ERS_RESULT_DISCONNECT |
| 8935 | */ | 8925 | */ |
| 8936 | pci_ers_result_t | 8926 | static pci_ers_result_t |
| 8937 | scsih_pci_error_detected(struct pci_dev *pdev, pci_channel_state_t state) | 8927 | scsih_pci_error_detected(struct pci_dev *pdev, pci_channel_state_t state) |
| 8938 | { | 8928 | { |
| 8939 | struct Scsi_Host *shost = pci_get_drvdata(pdev); | 8929 | struct Scsi_Host *shost = pci_get_drvdata(pdev); |
| @@ -8970,7 +8960,7 @@ scsih_pci_error_detected(struct pci_dev *pdev, pci_channel_state_t state) · 30 unmodified lines | |||
| 8970 | * code after the PCI slot has been reset, just before we | 8960 | * code after the PCI slot has been reset, just before we |
| 8971 | * should resume normal operations. | 8961 | * should resume normal operations. |
| 8972 | */ | 8962 | */ |
| 8973 | pci_ers_result_t | 8963 | static pci_ers_result_t |
| 8974 | scsih_pci_slot_reset(struct pci_dev *pdev) | 8964 | scsih_pci_slot_reset(struct pci_dev *pdev) |
| 8975 | { | 8965 | { |
| 8976 | struct Scsi_Host *shost = pci_get_drvdata(pdev); | 8966 | struct Scsi_Host *shost = pci_get_drvdata(pdev); |
| @@ -8987,8 +8977,7 @@ scsih_pci_slot_reset(struct pci_dev *pdev) · 10 unmodified lines | |||
| 8987 | if (rc) | 8977 | if (rc) |
| 8988 | return PCI_ERS_RESULT_DISCONNECT; | 8978 | return PCI_ERS_RESULT_DISCONNECT; |
| 8989 | 8979 | ||
| 8990 | rc = mpt3sas_base_hard_reset_handler(ioc, CAN_SLEEP, | 8980 | rc = mpt3sas_base_hard_reset_handler(ioc, FORCE_BIG_HAMMER); |
| 8991 | FORCE_BIG_HAMMER); | ||
| 8992 | 8981 | ||
| 8993 | pr_warn(MPT3SAS_FMT "hard reset: %s\n", ioc->name, | 8982 | pr_warn(MPT3SAS_FMT "hard reset: %s\n", ioc->name, |
| 8994 | (rc == 0) ? "success" : "failed"); | 8983 | (rc == 0) ? "success" : "failed"); |
| @@ -9007,7 +8996,7 @@ scsih_pci_slot_reset(struct pci_dev *pdev) · 12 unmodified lines | |||
| 9007 | * OK to resume normal operation. Use completion to allow | 8996 | * OK to resume normal operation. Use completion to allow |
| 9008 | * halted scsi ops to resume. | 8997 | * halted scsi ops to resume. |
| 9009 | */ | 8998 | */ |
| 9010 | void | 8999 | static void |
| 9011 | scsih_pci_resume(struct pci_dev *pdev) | 9000 | scsih_pci_resume(struct pci_dev *pdev) |
| 9012 | { | 9001 | { |
| 9013 | struct Scsi_Host *shost = pci_get_drvdata(pdev); | 9002 | struct Scsi_Host *shost = pci_get_drvdata(pdev); |
| @@ -9024,7 +9013,7 @@ scsih_pci_resume(struct pci_dev *pdev) · 10 unmodified lines | |||
| 9024 | * scsih_pci_mmio_enabled - Enable MMIO and dump debug registers | 9013 | * scsih_pci_mmio_enabled - Enable MMIO and dump debug registers |
| 9025 | * @pdev: pointer to PCI device | 9014 | * @pdev: pointer to PCI device |
| 9026 | */ | 9015 | */ |
| 9027 | pci_ers_result_t | 9016 | static pci_ers_result_t |
| 9028 | scsih_pci_mmio_enabled(struct pci_dev *pdev) | 9017 | scsih_pci_mmio_enabled(struct pci_dev *pdev) |
| 9029 | { | 9018 | { |
| 9030 | struct Scsi_Host *shost = pci_get_drvdata(pdev); | 9019 | struct Scsi_Host *shost = pci_get_drvdata(pdev); |
| @@ -9152,7 +9141,7 @@ static struct pci_driver mpt3sas_driver = { · 121 unmodified lines | |||
| 9152 | * | 9141 | * |
| 9153 | * Returns 0 success, anything else error. | 9142 | * Returns 0 success, anything else error. |
| 9154 | */ | 9143 | */ |
| 9155 | int | 9144 | static int |
| 9156 | scsih_init(void) | 9145 | scsih_init(void) |
| 9157 | { | 9146 | { |
| 9158 | mpt2_ids = 0; | 9147 | mpt2_ids = 0; |
| @@ -9202,7 +9191,7 @@ scsih_init(void) · 43 unmodified lines | |||
| 9202 | * | 9191 | * |
| 9203 | * Returns 0 success, anything else error. | 9192 | * Returns 0 success, anything else error. |
| 9204 | */ | 9193 | */ |
| 9205 | void | 9194 | static void |
| 9206 | scsih_exit(void) | 9195 | scsih_exit(void) |
| 9207 | { | 9196 | { |
| 9208 | 9197 | ||
| @@ -300,7 +300,6 @@ _transport_expander_report_manufacture(struct MPT3SAS_ADAPTER *ioc, · 299 unmodified lines | |||
| 300 | int rc; | 300 | int rc; |
| 301 | u16 smid; | 301 | u16 smid; |
| 302 | u32 ioc_state; | 302 | u32 ioc_state; |
| 303 | unsigned long timeleft; | ||
| 304 | void *psge; | 303 | void *psge; |
| 305 | u8 issue_reset = 0; | 304 | u8 issue_reset = 0; |
| 306 | void *data_out = NULL; | 305 | void *data_out = NULL; |
| @@ -394,8 +393,7 @@ _transport_expander_report_manufacture(struct MPT3SAS_ADAPTER *ioc, · 87 unmodified lines | |||
| 394 | ioc->name, (unsigned long long)sas_address)); | 393 | ioc->name, (unsigned long long)sas_address)); |
| 395 | init_completion(&ioc->transport_cmds.done); | 394 | init_completion(&ioc->transport_cmds.done); |
| 396 | mpt3sas_base_put_smid_default(ioc, smid); | 395 | mpt3sas_base_put_smid_default(ioc, smid); |
| 397 | timeleft = wait_for_completion_timeout(&ioc->transport_cmds.done, | 396 | wait_for_completion_timeout(&ioc->transport_cmds.done, 10*HZ); |
| 398 | 10*HZ); | ||
| 399 | 397 | ||
| 400 | if (!(ioc->transport_cmds.status & MPT3_CMD_COMPLETE)) { | 398 | if (!(ioc->transport_cmds.status & MPT3_CMD_COMPLETE)) { |
| 401 | pr_err(MPT3SAS_FMT "%s: timeout\n", | 399 | pr_err(MPT3SAS_FMT "%s: timeout\n", |
| @@ -446,8 +444,7 @@ _transport_expander_report_manufacture(struct MPT3SAS_ADAPTER *ioc, · 44 unmodified lines | |||
| 446 | 444 | ||
| 447 | issue_host_reset: | 445 | issue_host_reset: |
| 448 | if (issue_reset) | 446 | if (issue_reset) |
| 449 | mpt3sas_base_hard_reset_handler(ioc, CAN_SLEEP, | 447 | mpt3sas_base_hard_reset_handler(ioc, FORCE_BIG_HAMMER); |
| 450 | FORCE_BIG_HAMMER); | ||
| 451 | out: | 448 | out: |
| 452 | ioc->transport_cmds.status = MPT3_CMD_NOT_USED; | 449 | ioc->transport_cmds.status = MPT3_CMD_NOT_USED; |
| 453 | if (data_out) | 450 | if (data_out) |
| @@ -1107,7 +1104,6 @@ _transport_get_expander_phy_error_log(struct MPT3SAS_ADAPTER *ioc, · 653 unmodified lines | |||
| 1107 | int rc; | 1104 | int rc; |
| 1108 | u16 smid; | 1105 | u16 smid; |
| 1109 | u32 ioc_state; | 1106 | u32 ioc_state; |
| 1110 | unsigned long timeleft; | ||
| 1111 | void *psge; | 1107 | void *psge; |
| 1112 | u8 issue_reset = 0; | 1108 | u8 issue_reset = 0; |
| 1113 | void *data_out = NULL; | 1109 | void *data_out = NULL; |
| @@ -1203,8 +1199,7 @@ _transport_get_expander_phy_error_log(struct MPT3SAS_ADAPTER *ioc, · 89 unmodified lines | |||
| 1203 | phy->number)); | 1199 | phy->number)); |
| 1204 | init_completion(&ioc->transport_cmds.done); | 1200 | init_completion(&ioc->transport_cmds.done); |
| 1205 | mpt3sas_base_put_smid_default(ioc, smid); | 1201 | mpt3sas_base_put_smid_default(ioc, smid); |
| 1206 | timeleft = wait_for_completion_timeout(&ioc->transport_cmds.done, | 1202 | wait_for_completion_timeout(&ioc->transport_cmds.done, 10*HZ); |
| 1207 | 10*HZ); | ||
| 1208 | 1203 | ||
| 1209 | if (!(ioc->transport_cmds.status & MPT3_CMD_COMPLETE)) { | 1204 | if (!(ioc->transport_cmds.status & MPT3_CMD_COMPLETE)) { |
| 1210 | pr_err(MPT3SAS_FMT "%s: timeout\n", | 1205 | pr_err(MPT3SAS_FMT "%s: timeout\n", |
| @@ -1253,8 +1248,7 @@ _transport_get_expander_phy_error_log(struct MPT3SAS_ADAPTER *ioc, · 42 unmodified lines | |||
| 1253 | 1248 | ||
| 1254 | issue_host_reset: | 1249 | issue_host_reset: |
| 1255 | if (issue_reset) | 1250 | if (issue_reset) |
| 1256 | mpt3sas_base_hard_reset_handler(ioc, CAN_SLEEP, | 1251 | mpt3sas_base_hard_reset_handler(ioc, FORCE_BIG_HAMMER); |
| 1257 | FORCE_BIG_HAMMER); | ||
| 1258 | out: | 1252 | out: |
| 1259 | ioc->transport_cmds.status = MPT3_CMD_NOT_USED; | 1253 | ioc->transport_cmds.status = MPT3_CMD_NOT_USED; |
| 1260 | if (data_out) | 1254 | if (data_out) |
| @@ -1421,7 +1415,6 @@ _transport_expander_phy_control(struct MPT3SAS_ADAPTER *ioc, · 160 unmodified lines | |||
| 1421 | int rc; | 1415 | int rc; |
| 1422 | u16 smid; | 1416 | u16 smid; |
| 1423 | u32 ioc_state; | 1417 | u32 ioc_state; |
| 1424 | unsigned long timeleft; | ||
| 1425 | void *psge; | 1418 | void *psge; |
| 1426 | u8 issue_reset = 0; | 1419 | u8 issue_reset = 0; |
| 1427 | void *data_out = NULL; | 1420 | void *data_out = NULL; |
| @@ -1522,8 +1515,7 @@ _transport_expander_phy_control(struct MPT3SAS_ADAPTER *ioc, · 94 unmodified lines | |||
| 1522 | phy->number, phy_operation)); | 1515 | phy->number, phy_operation)); |
| 1523 | init_completion(&ioc->transport_cmds.done); | 1516 | init_completion(&ioc->transport_cmds.done); |
| 1524 | mpt3sas_base_put_smid_default(ioc, smid); | 1517 | mpt3sas_base_put_smid_default(ioc, smid); |
| 1525 | timeleft = wait_for_completion_timeout(&ioc->transport_cmds.done, | 1518 | wait_for_completion_timeout(&ioc->transport_cmds.done, 10*HZ); |
| 1526 | 10*HZ); | ||
| 1527 | 1519 | ||
| 1528 | if (!(ioc->transport_cmds.status & MPT3_CMD_COMPLETE)) { | 1520 | if (!(ioc->transport_cmds.status & MPT3_CMD_COMPLETE)) { |
| 1529 | pr_err(MPT3SAS_FMT "%s: timeout\n", | 1521 | pr_err(MPT3SAS_FMT "%s: timeout\n", |
| @@ -1564,8 +1556,7 @@ _transport_expander_phy_control(struct MPT3SAS_ADAPTER *ioc, · 34 unmodified lines | |||
| 1564 | 1556 | ||
| 1565 | issue_host_reset: | 1557 | issue_host_reset: |
| 1566 | if (issue_reset) | 1558 | if (issue_reset) |
| 1567 | mpt3sas_base_hard_reset_handler(ioc, CAN_SLEEP, | 1559 | mpt3sas_base_hard_reset_handler(ioc, FORCE_BIG_HAMMER); |
| 1568 | FORCE_BIG_HAMMER); | ||
| 1569 | out: | 1560 | out: |
| 1570 | ioc->transport_cmds.status = MPT3_CMD_NOT_USED; | 1561 | ioc->transport_cmds.status = MPT3_CMD_NOT_USED; |
| 1571 | if (data_out) | 1562 | if (data_out) |
| @@ -1899,7 +1890,6 @@ _transport_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy, · 327 unmodified lines | |||
| 1899 | int rc; | 1890 | int rc; |
| 1900 | u16 smid; | 1891 | u16 smid; |
| 1901 | u32 ioc_state; | 1892 | u32 ioc_state; |
| 1902 | unsigned long timeleft; | ||
| 1903 | void *psge; | 1893 | void *psge; |
| 1904 | u8 issue_reset = 0; | 1894 | u8 issue_reset = 0; |
| 1905 | dma_addr_t dma_addr_in = 0; | 1895 | dma_addr_t dma_addr_in = 0; |
| @@ -2043,8 +2033,7 @@ _transport_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy, · 137 unmodified lines | |||
| 2043 | 2033 | ||
| 2044 | init_completion(&ioc->transport_cmds.done); | 2034 | init_completion(&ioc->transport_cmds.done); |
| 2045 | mpt3sas_base_put_smid_default(ioc, smid); | 2035 | mpt3sas_base_put_smid_default(ioc, smid); |
| 2046 | timeleft = wait_for_completion_timeout(&ioc->transport_cmds.done, | 2036 | wait_for_completion_timeout(&ioc->transport_cmds.done, 10*HZ); |
| 2047 | 10*HZ); | ||
| 2048 | 2037 | ||
| 2049 | if (!(ioc->transport_cmds.status & MPT3_CMD_COMPLETE)) { | 2038 | if (!(ioc->transport_cmds.status & MPT3_CMD_COMPLETE)) { |
| 2050 | pr_err(MPT3SAS_FMT "%s : timeout\n", | 2039 | pr_err(MPT3SAS_FMT "%s : timeout\n", |
| @@ -2103,8 +2092,7 @@ _transport_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy, · 52 unmodified lines | |||
| 2103 | 2092 | ||
| 2104 | issue_host_reset: | 2093 | issue_host_reset: |
| 2105 | if (issue_reset) { | 2094 | if (issue_reset) { |
| 2106 | mpt3sas_base_hard_reset_handler(ioc, CAN_SLEEP, | 2095 | mpt3sas_base_hard_reset_handler(ioc, FORCE_BIG_HAMMER); |
| 2107 | FORCE_BIG_HAMMER); | ||
| 2108 | rc = -ETIMEDOUT; | 2096 | rc = -ETIMEDOUT; |
| 2109 | } | 2097 | } |
| 2110 | 2098 | ||
| @@ -136,7 +136,8 @@ static void mvs_64xx_phy_reset(struct mvs_info *mvi, u32 phy_id, int hard) · 135 unmodified lines | |||
| 136 | } | 136 | } |
| 137 | } | 137 | } |
| 138 | 138 | ||
| 139 | void mvs_64xx_clear_srs_irq(struct mvs_info *mvi, u8 reg_set, u8 clear_all) | 139 | static void |
| 140 | mvs_64xx_clear_srs_irq(struct mvs_info *mvi, u8 reg_set, u8 clear_all) | ||
| 140 | { | 141 | { |
| 141 | void __iomem *regs = mvi->regs; | 142 | void __iomem *regs = mvi->regs; |
| 142 | u32 tmp; | 143 | u32 tmp; |
| @@ -563,7 +564,7 @@ static u8 mvs_64xx_assign_reg_set(struct mvs_info *mvi, u8 *tfs) · 420 unmodified lines | |||
| 563 | return MVS_ID_NOT_MAPPED; | 564 | return MVS_ID_NOT_MAPPED; |
| 564 | } | 565 | } |
| 565 | 566 | ||
| 566 | void mvs_64xx_make_prd(struct scatterlist *scatter, int nr, void *prd) | 567 | static void mvs_64xx_make_prd(struct scatterlist *scatter, int nr, void *prd) |
| 567 | { | 568 | { |
| 568 | int i; | 569 | int i; |
| 569 | struct scatterlist *sg; | 570 | struct scatterlist *sg; |
| @@ -633,7 +634,7 @@ static void mvs_64xx_phy_work_around(struct mvs_info *mvi, int i) · 63 unmodified lines | |||
| 633 | mvs_write_port_vsr_data(mvi, i, tmp); | 634 | mvs_write_port_vsr_data(mvi, i, tmp); |
| 634 | } | 635 | } |
| 635 | 636 | ||
| 636 | void mvs_64xx_phy_set_link_rate(struct mvs_info *mvi, u32 phy_id, | 637 | static void mvs_64xx_phy_set_link_rate(struct mvs_info *mvi, u32 phy_id, |
| 637 | struct sas_phy_linkrates *rates) | 638 | struct sas_phy_linkrates *rates) |
| 638 | { | 639 | { |
| 639 | u32 lrmin = 0, lrmax = 0; | 640 | u32 lrmin = 0, lrmax = 0; |
| @@ -668,20 +669,20 @@ static void mvs_64xx_clear_active_cmds(struct mvs_info *mvi) · 28 unmodified lines | |||
| 668 | } | 669 | } |
| 669 | 670 | ||
| 670 | 671 | ||
| 671 | u32 mvs_64xx_spi_read_data(struct mvs_info *mvi) | 672 | static u32 mvs_64xx_spi_read_data(struct mvs_info *mvi) |
| 672 | { | 673 | { |
| 673 | void __iomem *regs = mvi->regs_ex; | 674 | void __iomem *regs = mvi->regs_ex; |
| 674 | return ior32(SPI_DATA_REG_64XX); | 675 | return ior32(SPI_DATA_REG_64XX); |
| 675 | } | 676 | } |
| 676 | 677 | ||
| 677 | void mvs_64xx_spi_write_data(struct mvs_info *mvi, u32 data) | 678 | static void mvs_64xx_spi_write_data(struct mvs_info *mvi, u32 data) |
| 678 | { | 679 | { |
| 679 | void __iomem *regs = mvi->regs_ex; | 680 | void __iomem *regs = mvi->regs_ex; |
| 680 | iow32(SPI_DATA_REG_64XX, data); | 681 | iow32(SPI_DATA_REG_64XX, data); |
| 681 | } | 682 | } |
| 682 | 683 | ||
| 683 | 684 | ||
| 684 | int mvs_64xx_spi_buildcmd(struct mvs_info *mvi, | 685 | static int mvs_64xx_spi_buildcmd(struct mvs_info *mvi, |
| 685 | u32 *dwCmd, | 686 | u32 *dwCmd, |
| 686 | u8 cmd, | 687 | u8 cmd, |
| 687 | u8 read, | 688 | u8 read, |
| @@ -705,7 +706,7 @@ int mvs_64xx_spi_buildcmd(struct mvs_info *mvi, · 17 unmodified lines | |||
| 705 | } | 706 | } |
| 706 | 707 | ||
| 707 | 708 | ||
| 708 | int mvs_64xx_spi_issuecmd(struct mvs_info *mvi, u32 cmd) | 709 | static int mvs_64xx_spi_issuecmd(struct mvs_info *mvi, u32 cmd) |
| 709 | { | 710 | { |
| 710 | void __iomem *regs = mvi->regs_ex; | 711 | void __iomem *regs = mvi->regs_ex; |
| 711 | int retry; | 712 | int retry; |
| @@ -720,7 +721,7 @@ int mvs_64xx_spi_issuecmd(struct mvs_info *mvi, u32 cmd) · 8 unmodified lines | |||
| 720 | return 0; | 721 | return 0; |
| 721 | } | 722 | } |
| 722 | 723 | ||
| 723 | int mvs_64xx_spi_waitdataready(struct mvs_info *mvi, u32 timeout) | 724 | static int mvs_64xx_spi_waitdataready(struct mvs_info *mvi, u32 timeout) |
| 724 | { | 725 | { |
| 725 | void __iomem *regs = mvi->regs_ex; | 726 | void __iomem *regs = mvi->regs_ex; |
| 726 | u32 i, dwTmp; | 727 | u32 i, dwTmp; |
| @@ -735,7 +736,7 @@ int mvs_64xx_spi_waitdataready(struct mvs_info *mvi, u32 timeout) · 8 unmodified lines | |||
| 735 | return -1; | 736 | return -1; |
| 736 | } | 737 | } |
| 737 | 738 | ||
| 738 | void mvs_64xx_fix_dma(struct mvs_info *mvi, u32 phy_mask, | 739 | static void mvs_64xx_fix_dma(struct mvs_info *mvi, u32 phy_mask, |
| 739 | int buf_len, int from, void *prd) | 740 | int buf_len, int from, void *prd) |
| 740 | { | 741 | { |
| 741 | int i; | 742 | int i; |
| @@ -48,8 +48,8 @@ static void mvs_94xx_detect_porttype(struct mvs_info *mvi, int i) · 47 unmodified lines | |||
| 48 | } | 48 | } |
| 49 | } | 49 | } |
| 50 | 50 | ||
| 51 | void set_phy_tuning(struct mvs_info *mvi, int phy_id, | 51 | static void set_phy_tuning(struct mvs_info *mvi, int phy_id, |
| 52 | struct phy_tuning phy_tuning) | 52 | struct phy_tuning phy_tuning) |
| 53 | { | 53 | { |
| 54 | u32 tmp, setting_0 = 0, setting_1 = 0; | 54 | u32 tmp, setting_0 = 0, setting_1 = 0; |
| 55 | u8 i; | 55 | u8 i; |
| @@ -110,8 +110,8 @@ void set_phy_tuning(struct mvs_info *mvi, int phy_id, · 54 unmodified lines | |||
| 110 | } | 110 | } |
| 111 | } | 111 | } |
| 112 | 112 | ||
| 113 | void set_phy_ffe_tuning(struct mvs_info *mvi, int phy_id, | 113 | static void set_phy_ffe_tuning(struct mvs_info *mvi, int phy_id, |
| 114 | struct ffe_control ffe) | 114 | struct ffe_control ffe) |
| 115 | { | 115 | { |
| 116 | u32 tmp; | 116 | u32 tmp; |
| 117 | 117 | ||
| @@ -177,7 +177,7 @@ void set_phy_ffe_tuning(struct mvs_info *mvi, int phy_id, · 59 unmodified lines | |||
| 177 | } | 177 | } |
| 178 | 178 | ||
| 179 | /*Notice: this function must be called when phy is disabled*/ | 179 | /*Notice: this function must be called when phy is disabled*/ |
| 180 | void set_phy_rate(struct mvs_info *mvi, int phy_id, u8 rate) | 180 | static void set_phy_rate(struct mvs_info *mvi, int phy_id, u8 rate) |
| 181 | { | 181 | { |
| 182 | union reg_phy_cfg phy_cfg, phy_cfg_tmp; | 182 | union reg_phy_cfg phy_cfg, phy_cfg_tmp; |
| 183 | mvs_write_port_vsr_addr(mvi, phy_id, VSR_PHY_MODE2); | 183 | mvs_write_port_vsr_addr(mvi, phy_id, VSR_PHY_MODE2); |
| @@ -679,7 +679,8 @@ static void mvs_94xx_command_active(struct mvs_info *mvi, u32 slot_idx) · 495 unmodified lines | |||
| 679 | } | 679 | } |
| 680 | } | 680 | } |
| 681 | 681 | ||
| 682 | void mvs_94xx_clear_srs_irq(struct mvs_info *mvi, u8 reg_set, u8 clear_all) | 682 | static void |
| 683 | mvs_94xx_clear_srs_irq(struct mvs_info *mvi, u8 reg_set, u8 clear_all) | ||
| 683 | { | 684 | { |
| 684 | void __iomem *regs = mvi->regs; | 685 | void __iomem *regs = mvi->regs; |
| 685 | u32 tmp; | 686 | u32 tmp; |
| @@ -906,8 +907,8 @@ static void mvs_94xx_fix_phy_info(struct mvs_info *mvi, int i, · 220 unmodified lines | |||
| 906 | 907 | ||
| 907 | } | 908 | } |
| 908 | 909 | ||
| 909 | void mvs_94xx_phy_set_link_rate(struct mvs_info *mvi, u32 phy_id, | 910 | static void mvs_94xx_phy_set_link_rate(struct mvs_info *mvi, u32 phy_id, |
| 910 | struct sas_phy_linkrates *rates) | 911 | struct sas_phy_linkrates *rates) |
| 911 | { | 912 | { |
| 912 | u32 lrmax = 0; | 913 | u32 lrmax = 0; |
| 913 | u32 tmp; | 914 | u32 tmp; |
| @@ -936,25 +937,25 @@ static void mvs_94xx_clear_active_cmds(struct mvs_info *mvi) · 22 unmodified lines | |||
| 936 | } | 937 | } |
| 937 | 938 | ||
| 938 | 939 | ||
| 939 | u32 mvs_94xx_spi_read_data(struct mvs_info *mvi) | 940 | static u32 mvs_94xx_spi_read_data(struct mvs_info *mvi) |
| 940 | { | 941 | { |
| 941 | void __iomem *regs = mvi->regs_ex - 0x10200; | 942 | void __iomem *regs = mvi->regs_ex - 0x10200; |
| 942 | return mr32(SPI_RD_DATA_REG_94XX); | 943 | return mr32(SPI_RD_DATA_REG_94XX); |
| 943 | } | 944 | } |
| 944 | 945 | ||
| 945 | void mvs_94xx_spi_write_data(struct mvs_info *mvi, u32 data) | 946 | static void mvs_94xx_spi_write_data(struct mvs_info *mvi, u32 data) |
| 946 | { | 947 | { |
| 947 | void __iomem *regs = mvi->regs_ex - 0x10200; | 948 | void __iomem *regs = mvi->regs_ex - 0x10200; |
| 948 | mw32(SPI_RD_DATA_REG_94XX, data); | 949 | mw32(SPI_RD_DATA_REG_94XX, data); |
| 949 | } | 950 | } |
| 950 | 951 | ||
| 951 | 952 | ||
| 952 | int mvs_94xx_spi_buildcmd(struct mvs_info *mvi, | 953 | static int mvs_94xx_spi_buildcmd(struct mvs_info *mvi, |
| 953 | u32 *dwCmd, | 954 | u32 *dwCmd, |
| 954 | u8 cmd, | 955 | u8 cmd, |
| 955 | u8 read, | 956 | u8 read, |
| 956 | u8 length, | 957 | u8 length, |
| 957 | u32 addr | 958 | u32 addr |
| 958 | ) | 959 | ) |
| 959 | { | 960 | { |
| 960 | void __iomem *regs = mvi->regs_ex - 0x10200; | 961 | void __iomem *regs = mvi->regs_ex - 0x10200; |
| @@ -974,7 +975,7 @@ int mvs_94xx_spi_buildcmd(struct mvs_info *mvi, · 13 unmodified lines | |||
| 974 | } | 975 | } |
| 975 | 976 | ||
| 976 | 977 | ||
| 977 | int mvs_94xx_spi_issuecmd(struct mvs_info *mvi, u32 cmd) | 978 | static int mvs_94xx_spi_issuecmd(struct mvs_info *mvi, u32 cmd) |
| 978 | { | 979 | { |
| 979 | void __iomem *regs = mvi->regs_ex - 0x10200; | 980 | void __iomem *regs = mvi->regs_ex - 0x10200; |
| 980 | mw32(SPI_CTRL_REG_94XX, cmd | SPI_CTRL_SpiStart_94XX); | 981 | mw32(SPI_CTRL_REG_94XX, cmd | SPI_CTRL_SpiStart_94XX); |
| @@ -982,7 +983,7 @@ int mvs_94xx_spi_issuecmd(struct mvs_info *mvi, u32 cmd) · 1 unmodified line | |||
| 982 | return 0; | 983 | return 0; |
| 983 | } | 984 | } |
| 984 | 985 | ||
| 985 | int mvs_94xx_spi_waitdataready(struct mvs_info *mvi, u32 timeout) | 986 | static int mvs_94xx_spi_waitdataready(struct mvs_info *mvi, u32 timeout) |
| 986 | { | 987 | { |
| 987 | void __iomem *regs = mvi->regs_ex - 0x10200; | 988 | void __iomem *regs = mvi->regs_ex - 0x10200; |
| 988 | u32 i, dwTmp; | 989 | u32 i, dwTmp; |
| @@ -997,8 +998,8 @@ int mvs_94xx_spi_waitdataready(struct mvs_info *mvi, u32 timeout) · 8 unmodified lines | |||
| 997 | return -1; | 998 | return -1; |
| 998 | } | 999 | } |
| 999 | 1000 | ||
| 1000 | void mvs_94xx_fix_dma(struct mvs_info *mvi, u32 phy_mask, | 1001 | static void mvs_94xx_fix_dma(struct mvs_info *mvi, u32 phy_mask, |
| 1001 | int buf_len, int from, void *prd) | 1002 | int buf_len, int from, void *prd) |
| 1002 | { | 1003 | { |
| 1003 | int i; | 1004 | int i; |
| 1004 | struct mvs_prd *buf_prd = prd; | 1005 | struct mvs_prd *buf_prd = prd; |
| @@ -74,7 +74,7 @@ void mvs_tag_init(struct mvs_info *mvi) · 73 unmodified lines | |||
| 74 | mvs_tag_clear(mvi, i); | 74 | mvs_tag_clear(mvi, i); |
| 75 | } | 75 | } |
| 76 | 76 | ||
| 77 | struct mvs_info *mvs_find_dev_mvi(struct domain_device *dev) | 77 | static struct mvs_info *mvs_find_dev_mvi(struct domain_device *dev) |
| 78 | { | 78 | { |
| 79 | unsigned long i = 0, j = 0, hi = 0; | 79 | unsigned long i = 0, j = 0, hi = 0; |
| 80 | struct sas_ha_struct *sha = dev->port->ha; | 80 | struct sas_ha_struct *sha = dev->port->ha; |
| @@ -102,7 +102,7 @@ struct mvs_info *mvs_find_dev_mvi(struct domain_device *dev) · 21 unmodified lines | |||
| 102 | 102 | ||
| 103 | } | 103 | } |
| 104 | 104 | ||
| 105 | int mvs_find_dev_phyno(struct domain_device *dev, int *phyno) | 105 | static int mvs_find_dev_phyno(struct domain_device *dev, int *phyno) |
| 106 | { | 106 | { |
| 107 | unsigned long i = 0, j = 0, n = 0, num = 0; | 107 | unsigned long i = 0, j = 0, n = 0, num = 0; |
| 108 | struct mvs_device *mvi_dev = (struct mvs_device *)dev->lldd_dev; | 108 | struct mvs_device *mvi_dev = (struct mvs_device *)dev->lldd_dev; |
| @@ -1158,7 +1158,7 @@ void mvs_port_deformed(struct asd_sas_phy *sas_phy) · 1049 unmodified lines | |||
| 1158 | mvs_port_notify_deformed(sas_phy, 1); | 1158 | mvs_port_notify_deformed(sas_phy, 1); |
| 1159 | } | 1159 | } |
| 1160 | 1160 | ||
| 1161 | struct mvs_device *mvs_alloc_dev(struct mvs_info *mvi) | 1161 | static struct mvs_device *mvs_alloc_dev(struct mvs_info *mvi) |
| 1162 | { | 1162 | { |
| 1163 | u32 dev; | 1163 | u32 dev; |
| 1164 | for (dev = 0; dev < MVS_MAX_DEVICES; dev++) { | 1164 | for (dev = 0; dev < MVS_MAX_DEVICES; dev++) { |
| @@ -1175,7 +1175,7 @@ struct mvs_device *mvs_alloc_dev(struct mvs_info *mvi) · 10 unmodified lines | |||
| 1175 | return NULL; | 1175 | return NULL; |
| 1176 | } | 1176 | } |
| 1177 | 1177 | ||
| 1178 | void mvs_free_dev(struct mvs_device *mvi_dev) | 1178 | static void mvs_free_dev(struct mvs_device *mvi_dev) |
| 1179 | { | 1179 | { |
| 1180 | u32 id = mvi_dev->device_id; | 1180 | u32 id = mvi_dev->device_id; |
| 1181 | memset(mvi_dev, 0, sizeof(*mvi_dev)); | 1181 | memset(mvi_dev, 0, sizeof(*mvi_dev)); |
| @@ -1185,7 +1185,7 @@ void mvs_free_dev(struct mvs_device *mvi_dev) · 3 unmodified lines | |||
| 1185 | mvi_dev->taskfileset = MVS_ID_NOT_MAPPED; | 1185 | mvi_dev->taskfileset = MVS_ID_NOT_MAPPED; |
| 1186 | } | 1186 | } |
| 1187 | 1187 | ||
| 1188 | int mvs_dev_found_notify(struct domain_device *dev, int lock) | 1188 | static int mvs_dev_found_notify(struct domain_device *dev, int lock) |
| 1189 | { | 1189 | { |
| 1190 | unsigned long flags = 0; | 1190 | unsigned long flags = 0; |
| 1191 | int res = 0; | 1191 | int res = 0; |
| @@ -1241,7 +1241,7 @@ int mvs_dev_found(struct domain_device *dev) · 49 unmodified lines | |||
| 1241 | return mvs_dev_found_notify(dev, 1); | 1241 | return mvs_dev_found_notify(dev, 1); |
| 1242 | } | 1242 | } |
| 1243 | 1243 | ||
| 1244 | void mvs_dev_gone_notify(struct domain_device *dev) | 1244 | static void mvs_dev_gone_notify(struct domain_device *dev) |
| 1245 | { | 1245 | { |
| 1246 | unsigned long flags = 0; | 1246 | unsigned long flags = 0; |
| 1247 | struct mvs_device *mvi_dev = dev->lldd_dev; | 1247 | struct mvs_device *mvi_dev = dev->lldd_dev; |
| @@ -1611,7 +1611,7 @@ static int mvs_sata_done(struct mvs_info *mvi, struct sas_task *task, · 363 unmodified lines | |||
| 1611 | return stat; | 1611 | return stat; |
| 1612 | } | 1612 | } |
| 1613 | 1613 | ||
| 1614 | void mvs_set_sense(u8 *buffer, int len, int d_sense, | 1614 | static void mvs_set_sense(u8 *buffer, int len, int d_sense, |
| 1615 | int key, int asc, int ascq) | 1615 | int key, int asc, int ascq) |
| 1616 | { | 1616 | { |
| 1617 | memset(buffer, 0, len); | 1617 | memset(buffer, 0, len); |
| @@ -1650,7 +1650,7 @@ void mvs_set_sense(u8 *buffer, int len, int d_sense, · 32 unmodified lines | |||
| 1650 | return; | 1650 | return; |
| 1651 | } | 1651 | } |
| 1652 | 1652 | ||
| 1653 | void mvs_fill_ssp_resp_iu(struct ssp_response_iu *iu, | 1653 | static void mvs_fill_ssp_resp_iu(struct ssp_response_iu *iu, |
| 1654 | u8 key, u8 asc, u8 asc_q) | 1654 | u8 key, u8 asc, u8 asc_q) |
| 1655 | { | 1655 | { |
| 1656 | iu->datapres = 2; | 1656 | iu->datapres = 2; |
| @@ -1,565 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * This driver adapted from Drew Eckhardt's Trantor T128 driver | ||
| 3 | * | ||
| 4 | * Copyright 1993, Drew Eckhardt | ||
| 5 | * Visionary Computing | ||
| 6 | * (Unix and Linux consulting and custom programming) | ||
| 7 | * drew@colorado.edu | ||
| 8 | * +1 (303) 666-5836 | ||
| 9 | * | ||
| 10 | * ( Based on T128 - DISTRIBUTION RELEASE 3. ) | ||
| 11 | * | ||
| 12 | * Modified to work with the Pro Audio Spectrum/Studio 16 | ||
| 13 | * by John Weidman. | ||
| 14 | * | ||
| 15 | * | ||
| 16 | * For more information, please consult | ||
| 17 | * | ||
| 18 | * Media Vision | ||
| 19 | * (510) 770-8600 | ||
| 20 | * (800) 348-7116 | ||
| 21 | */ | ||
| 22 | |||
| 23 | /* | ||
| 24 | * The card is detected and initialized in one of several ways : | ||
| 25 | * 1. Autoprobe (default) - There are many different models of | ||
| 26 | * the Pro Audio Spectrum/Studio 16, and I only have one of | ||
| 27 | * them, so this may require a little tweaking. An interrupt | ||
| 28 | * is triggered to autoprobe for the interrupt line. Note: | ||
| 29 | * with the newer model boards, the interrupt is set via | ||
| 30 | * software after reset using the default_irq for the | ||
| 31 | * current board number. | ||
| 32 | * | ||
| 33 | * 2. With command line overrides - pas16=port,irq may be | ||
| 34 | * used on the LILO command line to override the defaults. | ||
| 35 | * | ||
| 36 | * 3. With the PAS16_OVERRIDE compile time define. This is | ||
| 37 | * specified as an array of address, irq tuples. Ie, for | ||
| 38 | * one board at the default 0x388 address, IRQ10, I could say | ||
| 39 | * -DPAS16_OVERRIDE={{0x388, 10}} | ||
| 40 | * NOTE: Untested. | ||
| 41 | * | ||
| 42 | * 4. When included as a module, with arguments passed on the command line: | ||
| 43 | * pas16_irq=xx the interrupt | ||
| 44 | * pas16_addr=xx the port | ||
| 45 | * e.g. "modprobe pas16 pas16_addr=0x388 pas16_irq=5" | ||
| 46 | * | ||
| 47 | * Note that if the override methods are used, place holders must | ||
| 48 | * be specified for other boards in the system. | ||
| 49 | * | ||
| 50 | * | ||
| 51 | * Configuration notes : | ||
| 52 | * The current driver does not support interrupt sharing with the | ||
| 53 | * sound portion of the card. If you use the same irq for the | ||
| 54 | * scsi port and sound you will have problems. Either use | ||
| 55 | * a different irq for the scsi port or don't use interrupts | ||
| 56 | * for the scsi port. | ||
| 57 | * | ||
| 58 | * If you have problems with your card not being recognized, use | ||
| 59 | * the LILO command line override. Try to get it recognized without | ||
| 60 | * interrupts. Ie, for a board at the default 0x388 base port, | ||
| 61 | * boot: linux pas16=0x388,0 | ||
| 62 | * | ||
| 63 | * NO_IRQ (0) should be specified for no interrupt, | ||
| 64 | * IRQ_AUTO (254) to autoprobe for an IRQ line if overridden | ||
| 65 | * on the command line. | ||
| 66 | */ | ||
| 67 | |||
| 68 | #include <linux/module.h> | ||
| 69 | |||
| 70 | #include <asm/io.h> | ||
| 71 | #include <asm/dma.h> | ||
| 72 | #include <linux/blkdev.h> | ||
| 73 | #include <linux/interrupt.h> | ||
| 74 | #include <linux/init.h> | ||
| 75 | |||
| 76 | #include <scsi/scsi_host.h> | ||
| 77 | #include "pas16.h" | ||
| 78 | #include "NCR5380.h" | ||
| 79 | |||
| 80 | |||
| 81 | static unsigned short pas16_addr; | ||
| 82 | static int pas16_irq; | ||
| 83 | |||
| 84 | |||
| 85 | static const int scsi_irq_translate[] = | ||
| 86 | { 0, 0, 1, 2, 3, 4, 5, 6, 0, 0, 7, 8, 9, 0, 10, 11 }; | ||
| 87 | |||
| 88 | /* The default_irqs array contains values used to set the irq into the | ||
| 89 | * board via software (as must be done on newer model boards without | ||
| 90 | * irq jumpers on the board). The first value in the array will be | ||
| 91 | * assigned to logical board 0, the next to board 1, etc. | ||
| 92 | */ | ||
| 93 | static int default_irqs[] __initdata = | ||
| 94 | { PAS16_DEFAULT_BOARD_1_IRQ, | ||
| 95 | PAS16_DEFAULT_BOARD_2_IRQ, | ||
| 96 | PAS16_DEFAULT_BOARD_3_IRQ, | ||
| 97 | PAS16_DEFAULT_BOARD_4_IRQ | ||
| 98 | }; | ||
| 99 | |||
| 100 | static struct override { | ||
| 101 | unsigned short io_port; | ||
| 102 | int irq; | ||
| 103 | } overrides | ||
| 104 | #ifdef PAS16_OVERRIDE | ||
| 105 | [] __initdata = PAS16_OVERRIDE; | ||
| 106 | #else | ||
| 107 | [4] __initdata = {{0,IRQ_AUTO}, {0,IRQ_AUTO}, {0,IRQ_AUTO}, | ||
| 108 | {0,IRQ_AUTO}}; | ||
| 109 | #endif | ||
| 110 | |||
| 111 | #define NO_OVERRIDES ARRAY_SIZE(overrides) | ||
| 112 | |||
| 113 | static struct base { | ||
| 114 | unsigned short io_port; | ||
| 115 | int noauto; | ||
| 116 | } bases[] __initdata = | ||
| 117 | { {PAS16_DEFAULT_BASE_1, 0}, | ||
| 118 | {PAS16_DEFAULT_BASE_2, 0}, | ||
| 119 | {PAS16_DEFAULT_BASE_3, 0}, | ||
| 120 | {PAS16_DEFAULT_BASE_4, 0} | ||
| 121 | }; | ||
| 122 | |||
| 123 | #define NO_BASES ARRAY_SIZE(bases) | ||
| 124 | |||
| 125 | static const unsigned short pas16_offset[ 8 ] = | ||
| 126 | { | ||
| 127 | 0x1c00, /* OUTPUT_DATA_REG */ | ||
| 128 | 0x1c01, /* INITIATOR_COMMAND_REG */ | ||
| 129 | 0x1c02, /* MODE_REG */ | ||
| 130 | 0x1c03, /* TARGET_COMMAND_REG */ | ||
| 131 | 0x3c00, /* STATUS_REG ro, SELECT_ENABLE_REG wo */ | ||
| 132 | 0x3c01, /* BUS_AND_STATUS_REG ro, START_DMA_SEND_REG wo */ | ||
| 133 | 0x3c02, /* INPUT_DATA_REGISTER ro, (N/A on PAS16 ?) | ||
| 134 | * START_DMA_TARGET_RECEIVE_REG wo | ||
| 135 | */ | ||
| 136 | 0x3c03, /* RESET_PARITY_INTERRUPT_REG ro, | ||
| 137 | * START_DMA_INITIATOR_RECEIVE_REG wo | ||
| 138 | */ | ||
| 139 | }; | ||
| 140 | |||
| 141 | |||
| 142 | /* | ||
| 143 | * Function : enable_board( int board_num, unsigned short port ) | ||
| 144 | * | ||
| 145 | * Purpose : set address in new model board | ||
| 146 | * | ||
| 147 | * Inputs : board_num - logical board number 0-3, port - base address | ||
| 148 | * | ||
| 149 | */ | ||
| 150 | |||
| 151 | static void __init | ||
| 152 | enable_board( int board_num, unsigned short port ) | ||
| 153 | { | ||
| 154 | outb( 0xbc + board_num, MASTER_ADDRESS_PTR ); | ||
| 155 | outb( port >> 2, MASTER_ADDRESS_PTR ); | ||
| 156 | } | ||
| 157 | |||
| 158 | |||
| 159 | |||
| 160 | /* | ||
| 161 | * Function : init_board( unsigned short port, int irq ) | ||
| 162 | * | ||
| 163 | * Purpose : Set the board up to handle the SCSI interface | ||
| 164 | * | ||
| 165 | * Inputs : port - base address of the board, | ||
| 166 | * irq - irq to assign to the SCSI port | ||
| 167 | * force_irq - set it even if it conflicts with sound driver | ||
| 168 | * | ||
| 169 | */ | ||
| 170 | |||
| 171 | static void __init | ||
| 172 | init_board( unsigned short io_port, int irq, int force_irq ) | ||
| 173 | { | ||
| 174 | unsigned int tmp; | ||
| 175 | unsigned int pas_irq_code; | ||
| 176 | |||
| 177 | /* Initialize the SCSI part of the board */ | ||
| 178 | |||
| 179 | outb( 0x30, io_port + P_TIMEOUT_COUNTER_REG ); /* Timeout counter */ | ||
| 180 | outb( 0x01, io_port + P_TIMEOUT_STATUS_REG_OFFSET ); /* Reset TC */ | ||
| 181 | outb( 0x01, io_port + WAIT_STATE ); /* 1 Wait state */ | ||
| 182 | |||
| 183 | inb(io_port + pas16_offset[RESET_PARITY_INTERRUPT_REG]); | ||
| 184 | |||
| 185 | /* Set the SCSI interrupt pointer without mucking up the sound | ||
| 186 | * interrupt pointer in the same byte. | ||
| 187 | */ | ||
| 188 | pas_irq_code = ( irq < 16 ) ? scsi_irq_translate[irq] : 0; | ||
| 189 | tmp = inb( io_port + IO_CONFIG_3 ); | ||
| 190 | |||
| 191 | if( (( tmp & 0x0f ) == pas_irq_code) && pas_irq_code > 0 | ||
| 192 | && !force_irq ) | ||
| 193 | { | ||
| 194 | printk( "pas16: WARNING: Can't use same irq as sound " | ||
| 195 | "driver -- interrupts disabled\n" ); | ||
| 196 | /* Set up the drive parameters, disable 5380 interrupts */ | ||
| 197 | outb( 0x4d, io_port + SYS_CONFIG_4 ); | ||
| 198 | } | ||
| 199 | else | ||
| 200 | { | ||
| 201 | tmp = ( tmp & 0x0f ) | ( pas_irq_code << 4 ); | ||
| 202 | outb( tmp, io_port + IO_CONFIG_3 ); | ||
| 203 | |||
| 204 | /* Set up the drive parameters and enable 5380 interrupts */ | ||
| 205 | outb( 0x6d, io_port + SYS_CONFIG_4 ); | ||
| 206 | } | ||
| 207 | } | ||
| 208 | |||
| 209 | |||
| 210 | /* | ||
| 211 | * Function : pas16_hw_detect( unsigned short board_num ) | ||
| 212 | * | ||
| 213 | * Purpose : determine if a pas16 board is present | ||
| 214 | * | ||
| 215 | * Inputs : board_num - logical board number ( 0 - 3 ) | ||
| 216 | * | ||
| 217 | * Returns : 0 if board not found, 1 if found. | ||
| 218 | */ | ||
| 219 | |||
| 220 | static int __init | ||
| 221 | pas16_hw_detect( unsigned short board_num ) | ||
| 222 | { | ||
| 223 | unsigned char board_rev, tmp; | ||
| 224 | unsigned short io_port = bases[ board_num ].io_port; | ||
| 225 | |||
| 226 | /* See if we can find a PAS16 board at the address associated | ||
| 227 | * with this logical board number. | ||
| 228 | */ | ||
| 229 | |||
| 230 | /* First, attempt to take a newer model board out of reset and | ||
| 231 | * give it a base address. This shouldn't affect older boards. | ||
| 232 | */ | ||
| 233 | enable_board( board_num, io_port ); | ||
| 234 | |||
| 235 | /* Now see if it looks like a PAS16 board */ | ||
| 236 | board_rev = inb( io_port + PCB_CONFIG ); | ||
| 237 | |||
| 238 | if( board_rev == 0xff ) | ||
| 239 | return 0; | ||
| 240 | |||
| 241 | tmp = board_rev ^ 0xe0; | ||
| 242 | |||
| 243 | outb( tmp, io_port + PCB_CONFIG ); | ||
| 244 | tmp = inb( io_port + PCB_CONFIG ); | ||
| 245 | outb( board_rev, io_port + PCB_CONFIG ); | ||
| 246 | |||
| 247 | if( board_rev != tmp ) /* Not a PAS-16 */ | ||
| 248 | return 0; | ||
| 249 | |||
| 250 | if( ( inb( io_port + OPERATION_MODE_1 ) & 0x03 ) != 0x03 ) | ||
| 251 | return 0; /* return if no SCSI interface found */ | ||
| 252 | |||
| 253 | /* Mediavision has some new model boards that return ID bits | ||
| 254 | * that indicate a SCSI interface, but they're not (LMS). We'll | ||
| 255 | * put in an additional test to try to weed them out. | ||
| 256 | */ | ||
| 257 | |||
| 258 | outb(0x01, io_port + WAIT_STATE); /* 1 Wait state */ | ||
| 259 | outb(0x20, io_port + pas16_offset[MODE_REG]); /* Is it really SCSI? */ | ||
| 260 | if (inb(io_port + pas16_offset[MODE_REG]) != 0x20) /* Write to a reg. */ | ||
| 261 | return 0; /* and try to read */ | ||
| 262 | outb(0x00, io_port + pas16_offset[MODE_REG]); /* it back. */ | ||
| 263 | if (inb(io_port + pas16_offset[MODE_REG]) != 0x00) | ||
| 264 | return 0; | ||
| 265 | |||
| 266 | return 1; | ||
| 267 | } | ||
| 268 | |||
| 269 | |||
| 270 | #ifndef MODULE | ||
| 271 | /* | ||
| 272 | * Function : pas16_setup(char *str, int *ints) | ||
| 273 | * | ||
| 274 | * Purpose : LILO command line initialization of the overrides array, | ||
| 275 | * | ||
| 276 | * Inputs : str - unused, ints - array of integer parameters with ints[0] | ||
| 277 | * equal to the number of ints. | ||
| 278 | * | ||
| 279 | */ | ||
| 280 | |||
| 281 | static int __init pas16_setup(char *str) | ||
| 282 | { | ||
| 283 | static int commandline_current; | ||
| 284 | int i; | ||
| 285 | int ints[10]; | ||
| 286 | |||
| 287 | get_options(str, ARRAY_SIZE(ints), ints); | ||
| 288 | if (ints[0] != 2) | ||
| 289 | printk("pas16_setup : usage pas16=io_port,irq\n"); | ||
| 290 | else | ||
| 291 | if (commandline_current < NO_OVERRIDES) { | ||
| 292 | overrides[commandline_current].io_port = (unsigned short) ints[1]; | ||
| 293 | overrides[commandline_current].irq = ints[2]; | ||
| 294 | for (i = 0; i < NO_BASES; ++i) | ||
| 295 | if (bases[i].io_port == (unsigned short) ints[1]) { | ||
| 296 | bases[i].noauto = 1; | ||
| 297 | break; | ||
| 298 | } | ||
| 299 | ++commandline_current; | ||
| 300 | } | ||
| 301 | return 1; | ||
| 302 | } | ||
| 303 | |||
| 304 | __setup("pas16=", pas16_setup); | ||
| 305 | #endif | ||
| 306 | |||
| 307 | /* | ||
| 308 | * Function : int pas16_detect(struct scsi_host_template * tpnt) | ||
| 309 | * | ||
| 310 | * Purpose : detects and initializes PAS16 controllers | ||
| 311 | * that were autoprobed, overridden on the LILO command line, | ||
| 312 | * or specified at compile time. | ||
| 313 | * | ||
| 314 | * Inputs : tpnt - template for this SCSI adapter. | ||
| 315 | * | ||
| 316 | * Returns : 1 if a host adapter was found, 0 if not. | ||
| 317 | * | ||
| 318 | */ | ||
| 319 | |||
| 320 | static int __init pas16_detect(struct scsi_host_template *tpnt) | ||
| 321 | { | ||
| 322 | static int current_override; | ||
| 323 | static unsigned short current_base; | ||
| 324 | struct Scsi_Host *instance; | ||
| 325 | unsigned short io_port; | ||
| 326 | int count; | ||
| 327 | |||
| 328 | if (pas16_addr != 0) { | ||
| 329 | overrides[0].io_port = pas16_addr; | ||
| 330 | /* | ||
| 331 | * This is how we avoid seeing more than | ||
| 332 | * one host adapter at the same I/O port. | ||
| 333 | * Cribbed shamelessly from pas16_setup(). | ||
| 334 | */ | ||
| 335 | for (count = 0; count < NO_BASES; ++count) | ||
| 336 | if (bases[count].io_port == pas16_addr) { | ||
| 337 | bases[count].noauto = 1; | ||
| 338 | break; | ||
| 339 | } | ||
| 340 | } | ||
| 341 | if (pas16_irq != 0) | ||
| 342 | overrides[0].irq = pas16_irq; | ||
| 343 | |||
| 344 | for (count = 0; current_override < NO_OVERRIDES; ++current_override) { | ||
| 345 | io_port = 0; | ||
| 346 | |||
| 347 | if (overrides[current_override].io_port) | ||
| 348 | { | ||
| 349 | io_port = overrides[current_override].io_port; | ||
| 350 | enable_board( current_override, io_port ); | ||
| 351 | init_board( io_port, overrides[current_override].irq, 1 ); | ||
| 352 | } | ||
| 353 | else | ||
| 354 | for (; !io_port && (current_base < NO_BASES); ++current_base) { | ||
| 355 | dprintk(NDEBUG_INIT, "pas16: probing io_port 0x%04x\n", | ||
| 356 | (unsigned int)bases[current_base].io_port); | ||
| 357 | if ( !bases[current_base].noauto && | ||
| 358 | pas16_hw_detect( current_base ) ){ | ||
| 359 | io_port = bases[current_base].io_port; | ||
| 360 | init_board( io_port, default_irqs[ current_base ], 0 ); | ||
| 361 | dprintk(NDEBUG_INIT, "pas16: detected board\n"); | ||
| 362 | } | ||
| 363 | } | ||
| 364 | |||
| 365 | dprintk(NDEBUG_INIT, "pas16: io_port = 0x%04x\n", | ||
| 366 | (unsigned int)io_port); | ||
| 367 | |||
| 368 | if (!io_port) | ||
| 369 | break; | ||
| 370 | |||
| 371 | instance = scsi_register (tpnt, sizeof(struct NCR5380_hostdata)); | ||
| 372 | if(instance == NULL) | ||
| 373 | goto out; | ||
| 374 | |||
| 375 | instance->io_port = io_port; | ||
| 376 | |||
| 377 | if (NCR5380_init(instance, FLAG_DMA_FIXUP | FLAG_LATE_DMA_SETUP)) | ||
| 378 | goto out_unregister; | ||
| 379 | |||
| 380 | NCR5380_maybe_reset_bus(instance); | ||
| 381 | |||
| 382 | if (overrides[current_override].irq != IRQ_AUTO) | ||
| 383 | instance->irq = overrides[current_override].irq; | ||
| 384 | else | ||
| 385 | instance->irq = NCR5380_probe_irq(instance, PAS16_IRQS); | ||
| 386 | |||
| 387 | /* Compatibility with documented NCR5380 kernel parameters */ | ||
| 388 | if (instance->irq == 255) | ||
| 389 | instance->irq = NO_IRQ; | ||
| 390 | |||
| 391 | if (instance->irq != NO_IRQ) | ||
| 392 | if (request_irq(instance->irq, pas16_intr, 0, | ||
| 393 | "pas16", instance)) { | ||
| 394 | printk("scsi%d : IRQ%d not free, interrupts disabled\n", | ||
| 395 | instance->host_no, instance->irq); | ||
| 396 | instance->irq = NO_IRQ; | ||
| 397 | } | ||
| 398 | |||
| 399 | if (instance->irq == NO_IRQ) { | ||
| 400 | printk("scsi%d : interrupts not enabled. for better interactive performance,\n", instance->host_no); | ||
| 401 | printk("scsi%d : please jumper the board for a free IRQ.\n", instance->host_no); | ||
| 402 | /* Disable 5380 interrupts, leave drive params the same */ | ||
| 403 | outb( 0x4d, io_port + SYS_CONFIG_4 ); | ||
| 404 | outb( (inb(io_port + IO_CONFIG_3) & 0x0f), io_port + IO_CONFIG_3 ); | ||
| 405 | } | ||
| 406 | |||
| 407 | dprintk(NDEBUG_INIT, "scsi%d : irq = %d\n", | ||
| 408 | instance->host_no, instance->irq); | ||
| 409 | |||
| 410 | ++current_override; | ||
| 411 | ++count; | ||
| 412 | } | ||
| 413 | return count; | ||
| 414 | |||
| 415 | out_unregister: | ||
| 416 | scsi_unregister(instance); | ||
| 417 | out: | ||
| 418 | return count; | ||
| 419 | } | ||
| 420 | |||
| 421 | /* | ||
| 422 | * Function : int pas16_biosparam(Disk *disk, struct block_device *dev, int *ip) | ||
| 423 | * | ||
| 424 | * Purpose : Generates a BIOS / DOS compatible H-C-S mapping for | ||
| 425 | * the specified device / size. | ||
| 426 | * | ||
| 427 | * Inputs : size = size of device in sectors (512 bytes), dev = block device | ||
| 428 | * major / minor, ip[] = {heads, sectors, cylinders} | ||
| 429 | * | ||
| 430 | * Returns : always 0 (success), initializes ip | ||
| 431 | * | ||
| 432 | */ | ||
| 433 | |||
| 434 | /* | ||
| 435 | * XXX Most SCSI boards use this mapping, I could be incorrect. Some one | ||
| 436 | * using hard disks on a trantor should verify that this mapping corresponds | ||
| 437 | * to that used by the BIOS / ASPI driver by running the linux fdisk program | ||
| 438 | * and matching the H_C_S coordinates to what DOS uses. | ||
| 439 | */ | ||
| 440 | |||
| 441 | static int pas16_biosparam(struct scsi_device *sdev, struct block_device *dev, | ||
| 442 | sector_t capacity, int *ip) | ||
| 443 | { | ||
| 444 | int size = capacity; | ||
| 445 | ip[0] = 64; | ||
| 446 | ip[1] = 32; | ||
| 447 | ip[2] = size >> 11; /* I think I have it as /(32*64) */ | ||
| 448 | if( ip[2] > 1024 ) { /* yes, >, not >= */ | ||
| 449 | ip[0]=255; | ||
| 450 | ip[1]=63; | ||
| 451 | ip[2]=size/(63*255); | ||
| 452 | if( ip[2] > 1023 ) /* yes >1023... */ | ||
| 453 | ip[2] = 1023; | ||
| 454 | } | ||
| 455 | |||
| 456 | return 0; | ||
| 457 | } | ||
| 458 | |||
| 459 | /* | ||
| 460 | * Function : int pas16_pread (struct Scsi_Host *instance, | ||
| 461 | * unsigned char *dst, int len) | ||
| 462 | * | ||
| 463 | * Purpose : Fast 5380 pseudo-dma read function, transfers len bytes to | ||
| 464 | * dst | ||
| 465 | * | ||
| 466 | * Inputs : dst = destination, len = length in bytes | ||
| 467 | * | ||
| 468 | * Returns : 0 on success, non zero on a failure such as a watchdog | ||
| 469 | * timeout. | ||
| 470 | */ | ||
| 471 | |||
| 472 | static inline int pas16_pread(struct Scsi_Host *instance, | ||
| 473 | unsigned char *dst, int len) | ||
| 474 | { | ||
| 475 | register unsigned char *d = dst; | ||
| 476 | register unsigned short reg = (unsigned short) (instance->io_port + | ||
| 477 | P_DATA_REG_OFFSET); | ||
| 478 | register int i = len; | ||
| 479 | int ii = 0; | ||
| 480 | |||
| 481 | while ( !(inb(instance->io_port + P_STATUS_REG_OFFSET) & P_ST_RDY) ) | ||
| 482 | ++ii; | ||
| 483 | |||
| 484 | insb( reg, d, i ); | ||
| 485 | |||
| 486 | if ( inb(instance->io_port + P_TIMEOUT_STATUS_REG_OFFSET) & P_TS_TIM) { | ||
| 487 | outb( P_TS_CT, instance->io_port + P_TIMEOUT_STATUS_REG_OFFSET); | ||
| 488 | printk("scsi%d : watchdog timer fired in NCR5380_pread()\n", | ||
| 489 | instance->host_no); | ||
| 490 | return -1; | ||
| 491 | } | ||
| 492 | return 0; | ||
| 493 | } | ||
| 494 | |||
| 495 | /* | ||
| 496 | * Function : int pas16_pwrite (struct Scsi_Host *instance, | ||
| 497 | * unsigned char *src, int len) | ||
| 498 | * | ||
| 499 | * Purpose : Fast 5380 pseudo-dma write function, transfers len bytes from | ||
| 500 | * src | ||
| 501 | * | ||
| 502 | * Inputs : src = source, len = length in bytes | ||
| 503 | * | ||
| 504 | * Returns : 0 on success, non zero on a failure such as a watchdog | ||
| 505 | * timeout. | ||
| 506 | */ | ||
| 507 | |||
| 508 | static inline int pas16_pwrite(struct Scsi_Host *instance, | ||
| 509 | unsigned char *src, int len) | ||
| 510 | { | ||
| 511 | register unsigned char *s = src; | ||
| 512 | register unsigned short reg = (instance->io_port + P_DATA_REG_OFFSET); | ||
| 513 | register int i = len; | ||
| 514 | int ii = 0; | ||
| 515 | |||
| 516 | while ( !((inb(instance->io_port + P_STATUS_REG_OFFSET)) & P_ST_RDY) ) | ||
| 517 | ++ii; | ||
| 518 | |||
| 519 | outsb( reg, s, i ); | ||
| 520 | |||
| 521 | if (inb(instance->io_port + P_TIMEOUT_STATUS_REG_OFFSET) & P_TS_TIM) { | ||
| 522 | outb( P_TS_CT, instance->io_port + P_TIMEOUT_STATUS_REG_OFFSET); | ||
| 523 | printk("scsi%d : watchdog timer fired in NCR5380_pwrite()\n", | ||
| 524 | instance->host_no); | ||
| 525 | return -1; | ||
| 526 | } | ||
| 527 | return 0; | ||
| 528 | } | ||
| 529 | |||
| 530 | #include "NCR5380.c" | ||
| 531 | |||
| 532 | static int pas16_release(struct Scsi_Host *shost) | ||
| 533 | { | ||
| 534 | if (shost->irq != NO_IRQ) | ||
| 535 | free_irq(shost->irq, shost); | ||
| 536 | NCR5380_exit(shost); | ||
| 537 | scsi_unregister(shost); | ||
| 538 | return 0; | ||
| 539 | } | ||
| 540 | |||
| 541 | static struct scsi_host_template driver_template = { | ||
| 542 | .name = "Pro Audio Spectrum-16 SCSI", | ||
| 543 | .detect = pas16_detect, | ||
| 544 | .release = pas16_release, | ||
| 545 | .proc_name = "pas16", | ||
| 546 | .info = pas16_info, | ||
| 547 | .queuecommand = pas16_queue_command, | ||
| 548 | .eh_abort_handler = pas16_abort, | ||
| 549 | .eh_bus_reset_handler = pas16_bus_reset, | ||
| 550 | .bios_param = pas16_biosparam, | ||
| 551 | .can_queue = 32, | ||
| 552 | .this_id = 7, | ||
| 553 | .sg_tablesize = SG_ALL, | ||
| 554 | .cmd_per_lun = 2, | ||
| 555 | .use_clustering = DISABLE_CLUSTERING, | ||
| 556 | .cmd_size = NCR5380_CMD_SIZE, | ||
| 557 | .max_sectors = 128, | ||
| 558 | }; | ||
| 559 | #include "scsi_module.c" | ||
| 560 | |||
| 561 | #ifdef MODULE | ||
| 562 | module_param(pas16_addr, ushort, 0); | ||
| 563 | module_param(pas16_irq, int, 0); | ||
| 564 | #endif | ||
| 565 | MODULE_LICENSE("GPL"); | ||
| @@ -1,121 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * This driver adapted from Drew Eckhardt's Trantor T128 driver | ||
| 3 | * | ||
| 4 | * Copyright 1993, Drew Eckhardt | ||
| 5 | * Visionary Computing | ||
| 6 | * (Unix and Linux consulting and custom programming) | ||
| 7 | * drew@colorado.edu | ||
| 8 | * +1 (303) 666-5836 | ||
| 9 | * | ||
| 10 | * ( Based on T128 - DISTRIBUTION RELEASE 3. ) | ||
| 11 | * | ||
| 12 | * Modified to work with the Pro Audio Spectrum/Studio 16 | ||
| 13 | * by John Weidman. | ||
| 14 | * | ||
| 15 | * | ||
| 16 | * For more information, please consult | ||
| 17 | * | ||
| 18 | * Media Vision | ||
| 19 | * (510) 770-8600 | ||
| 20 | * (800) 348-7116 | ||
| 21 | */ | ||
| 22 | |||
| 23 | |||
| 24 | #ifndef PAS16_H | ||
| 25 | #define PAS16_H | ||
| 26 | |||
| 27 | #define PAS16_DEFAULT_BASE_1 0x388 | ||
| 28 | #define PAS16_DEFAULT_BASE_2 0x384 | ||
| 29 | #define PAS16_DEFAULT_BASE_3 0x38c | ||
| 30 | #define PAS16_DEFAULT_BASE_4 0x288 | ||
| 31 | |||
| 32 | #define PAS16_DEFAULT_BOARD_1_IRQ 10 | ||
| 33 | #define PAS16_DEFAULT_BOARD_2_IRQ 12 | ||
| 34 | #define PAS16_DEFAULT_BOARD_3_IRQ 14 | ||
| 35 | #define PAS16_DEFAULT_BOARD_4_IRQ 15 | ||
| 36 | |||
| 37 | |||
| 38 | /* | ||
| 39 | * The Pro Audio Spectrum boards are I/O mapped. They use a Zilog 5380 | ||
| 40 | * SCSI controller, which is the equivalent of NCR's 5380. "Pseudo-DMA" | ||
| 41 | * architecture is used, where a PAL drives the DMA signals on the 5380 | ||
| 42 | * allowing fast, blind transfers with proper handshaking. | ||
| 43 | */ | ||
| 44 | |||
| 45 | |||
| 46 | /* The Time-out Counter register is used to safe-guard against a stuck | ||
| 47 | * bus (in the case of RDY driven handshake) or a stuck byte (if 16-Bit | ||
| 48 | * DMA conversion is used). The counter uses a 28.224MHz clock | ||
| 49 | * divided by 14 as its clock source. In the case of a stuck byte in | ||
| 50 | * the holding register, an interrupt is generated (and mixed with the | ||
| 51 | * one with the drive) using the CD-ROM interrupt pointer. | ||
| 52 | */ | ||
| 53 | |||
| 54 | #define P_TIMEOUT_COUNTER_REG 0x4000 | ||
| 55 | #define P_TC_DISABLE 0x80 /* Set to 0 to enable timeout int. */ | ||
| 56 | /* Bits D6-D0 contain timeout count */ | ||
| 57 | |||
| 58 | |||
| 59 | #define P_TIMEOUT_STATUS_REG_OFFSET 0x4001 | ||
| 60 | #define P_TS_TIM 0x80 /* check timeout status */ | ||
| 61 | /* Bits D6-D4 N/U */ | ||
| 62 | #define P_TS_ARM_DRQ_INT 0x08 /* Arm DRQ Int. When set high, | ||
| 63 | * the next rising edge will | ||
| 64 | * cause a CD-ROM interrupt. | ||
| 65 | * When set low, the interrupt | ||
| 66 | * will be cleared. There is | ||
| 67 | * no status available for | ||
| 68 | * this interrupt. | ||
| 69 | */ | ||
| 70 | #define P_TS_ENABLE_TO_ERR_INTERRUPT /* Enable timeout error int. */ | ||
| 71 | #define P_TS_ENABLE_WAIT /* Enable Wait */ | ||
| 72 | |||
| 73 | #define P_TS_CT 0x01 /* clear timeout. Note: writing | ||
| 74 | * to this register clears the | ||
| 75 | * timeout error int. or status | ||
| 76 | */ | ||
| 77 | |||
| 78 | |||
| 79 | /* | ||
| 80 | * The data register reads/writes to/from the 5380 in pseudo-DMA mode | ||
| 81 | */ | ||
| 82 | |||
| 83 | #define P_DATA_REG_OFFSET 0x5c00 /* rw */ | ||
| 84 | |||
| 85 | #define P_STATUS_REG_OFFSET 0x5c01 /* ro */ | ||
| 86 | #define P_ST_RDY 0x80 /* 5380 DDRQ Status */ | ||
| 87 | |||
| 88 | #define P_IRQ_STATUS 0x5c03 | ||
| 89 | #define P_IS_IRQ 0x80 /* DIRQ status */ | ||
| 90 | |||
| 91 | #define PCB_CONFIG 0x803 | ||
| 92 | #define MASTER_ADDRESS_PTR 0x9a01 /* Fixed position - no relo */ | ||
| 93 | #define SYS_CONFIG_4 0x8003 | ||
| 94 | #define WAIT_STATE 0xbc00 | ||
| 95 | #define OPERATION_MODE_1 0xec03 | ||
| 96 | #define IO_CONFIG_3 0xf002 | ||
| 97 | |||
| 98 | #define NCR5380_implementation_fields /* none */ | ||
| 99 | |||
| 100 | #define PAS16_io_port(reg) (instance->io_port + pas16_offset[(reg)]) | ||
| 101 | |||
| 102 | #define NCR5380_read(reg) ( inb(PAS16_io_port(reg)) ) | ||
| 103 | #define NCR5380_write(reg, value) ( outb((value),PAS16_io_port(reg)) ) | ||
| 104 | |||
| 105 | #define NCR5380_dma_xfer_len(instance, cmd, phase) (cmd->transfersize) | ||
| 106 | #define NCR5380_dma_recv_setup pas16_pread | ||
| 107 | #define NCR5380_dma_send_setup pas16_pwrite | ||
| 108 | #define NCR5380_dma_residual(instance) (0) | ||
| 109 | |||
| 110 | #define NCR5380_intr pas16_intr | ||
| 111 | #define NCR5380_queue_command pas16_queue_command | ||
| 112 | #define NCR5380_abort pas16_abort | ||
| 113 | #define NCR5380_bus_reset pas16_bus_reset | ||
| 114 | #define NCR5380_info pas16_info | ||
| 115 | |||
| 116 | /* 15 14 12 10 7 5 3 | ||
| 117 | 1101 0100 1010 1000 */ | ||
| 118 | |||
| 119 | #define PAS16_IRQS 0xd4a8 | ||
| 120 | |||
| 121 | #endif /* PAS16_H */ | ||
| @@ -4492,8 +4492,8 @@ pm8001_chip_phy_start_req(struct pm8001_hba_info *pm8001_ha, u8 phy_id) · 4491 unmodified lines | |||
| 4492 | * @num: the inbound queue number | 4492 | * @num: the inbound queue number |
| 4493 | * @phy_id: the phy id which we wanted to start up. | 4493 | * @phy_id: the phy id which we wanted to start up. |
| 4494 | */ | 4494 | */ |
| 4495 | int pm8001_chip_phy_stop_req(struct pm8001_hba_info *pm8001_ha, | 4495 | static int pm8001_chip_phy_stop_req(struct pm8001_hba_info *pm8001_ha, |
| 4496 | u8 phy_id) | 4496 | u8 phy_id) |
| 4497 | { | 4497 | { |
| 4498 | struct phy_stop_req payload; | 4498 | struct phy_stop_req payload; |
| 4499 | struct inbound_queue_table *circularQ; | 4499 | struct inbound_queue_table *circularQ; |
| @@ -527,7 +527,7 @@ void pm8001_ccb_task_free(struct pm8001_hba_info *pm8001_ha, · 526 unmodified lines | |||
| 527 | * pm8001_alloc_dev - find a empty pm8001_device | 527 | * pm8001_alloc_dev - find a empty pm8001_device |
| 528 | * @pm8001_ha: our hba card information | 528 | * @pm8001_ha: our hba card information |
| 529 | */ | 529 | */ |
| 530 | struct pm8001_device *pm8001_alloc_dev(struct pm8001_hba_info *pm8001_ha) | 530 | static struct pm8001_device *pm8001_alloc_dev(struct pm8001_hba_info *pm8001_ha) |
| 531 | { | 531 | { |
| 532 | u32 dev; | 532 | u32 dev; |
| 533 | for (dev = 0; dev < PM8001_MAX_DEVICES; dev++) { | 533 | for (dev = 0; dev < PM8001_MAX_DEVICES; dev++) { |
| @@ -306,7 +306,7 @@ static int pmcraid_change_queue_depth(struct scsi_device *scsi_dev, int depth) · 305 unmodified lines | |||
| 306 | * Return Value | 306 | * Return Value |
| 307 | * None | 307 | * None |
| 308 | */ | 308 | */ |
| 309 | void pmcraid_init_cmdblk(struct pmcraid_cmd *cmd, int index) | 309 | static void pmcraid_init_cmdblk(struct pmcraid_cmd *cmd, int index) |
| 310 | { | 310 | { |
| 311 | struct pmcraid_ioarcb *ioarcb = &(cmd->ioa_cb->ioarcb); | 311 | struct pmcraid_ioarcb *ioarcb = &(cmd->ioa_cb->ioarcb); |
| 312 | dma_addr_t dma_addr = cmd->ioa_cb_bus_addr; | 312 | dma_addr_t dma_addr = cmd->ioa_cb_bus_addr; |
| @@ -401,7 +401,7 @@ static struct pmcraid_cmd *pmcraid_get_free_cmd( · 88 unmodified lines | |||
| 401 | * Return Value: | 401 | * Return Value: |
| 402 | * nothing | 402 | * nothing |
| 403 | */ | 403 | */ |
| 404 | void pmcraid_return_cmd(struct pmcraid_cmd *cmd) | 404 | static void pmcraid_return_cmd(struct pmcraid_cmd *cmd) |
| 405 | { | 405 | { |
| 406 | struct pmcraid_instance *pinstance = cmd->drv_inst; | 406 | struct pmcraid_instance *pinstance = cmd->drv_inst; |
| 407 | unsigned long lock_flags; | 407 | unsigned long lock_flags; |
| @@ -1710,7 +1710,7 @@ static struct pmcraid_ioasc_error *pmcraid_get_error_info(u32 ioasc) · 1302 unmodified lines | |||
| 1710 | * @ioasc: ioasc code | 1710 | * @ioasc: ioasc code |
| 1711 | * @cmd: pointer to command that resulted in 'ioasc' | 1711 | * @cmd: pointer to command that resulted in 'ioasc' |
| 1712 | */ | 1712 | */ |
| 1713 | void pmcraid_ioasc_logger(u32 ioasc, struct pmcraid_cmd *cmd) | 1713 | static void pmcraid_ioasc_logger(u32 ioasc, struct pmcraid_cmd *cmd) |
| 1714 | { | 1714 | { |
| 1715 | struct pmcraid_ioasc_error *error_info = pmcraid_get_error_info(ioasc); | 1715 | struct pmcraid_ioasc_error *error_info = pmcraid_get_error_info(ioasc); |
| 1716 | 1716 | ||
| @@ -3137,7 +3137,7 @@ static int pmcraid_eh_host_reset_handler(struct scsi_cmnd *scmd) · 1420 unmodified lines | |||
| 3137 | * returns pointer pmcraid_ioadl_desc, initialized to point to internal | 3137 | * returns pointer pmcraid_ioadl_desc, initialized to point to internal |
| 3138 | * or external IOADLs | 3138 | * or external IOADLs |
| 3139 | */ | 3139 | */ |
| 3140 | struct pmcraid_ioadl_desc * | 3140 | static struct pmcraid_ioadl_desc * |
| 3141 | pmcraid_init_ioadls(struct pmcraid_cmd *cmd, int sgcount) | 3141 | pmcraid_init_ioadls(struct pmcraid_cmd *cmd, int sgcount) |
| 3142 | { | 3142 | { |
| 3143 | struct pmcraid_ioadl_desc *ioadl; | 3143 | struct pmcraid_ioadl_desc *ioadl; |
| @@ -278,16 +278,6 @@ · 277 unmodified lines | |||
| 278 | struct req_que; | 278 | struct req_que; |
| 279 | struct qla_tgt_sess; | 279 | struct qla_tgt_sess; |
| 280 | 280 | ||
| 281 | /* | ||
| 282 | * (sd.h is not exported, hence local inclusion) | ||
| 283 | * Data Integrity Field tuple. | ||
| 284 | */ | ||
| 285 | struct sd_dif_tuple { | ||
| 286 | __be16 guard_tag; /* Checksum */ | ||
| 287 | __be16 app_tag; /* Opaque storage */ | ||
| 288 | __be32 ref_tag; /* Target LBA or indirect LBA */ | ||
| 289 | }; | ||
| 290 | |||
| 291 | /* | 281 | /* |
| 292 | * SCSI Request Block | 282 | * SCSI Request Block |
| 293 | */ | 283 | */ |
| @@ -1828,7 +1828,7 @@ qla2x00_handle_dif_error(srb_t *sp, struct sts_entry_24xx *sts24) · 1827 unmodified lines | |||
| 1828 | if (scsi_prot_sg_count(cmd)) { | 1828 | if (scsi_prot_sg_count(cmd)) { |
| 1829 | uint32_t i, j = 0, k = 0, num_ent; | 1829 | uint32_t i, j = 0, k = 0, num_ent; |
| 1830 | struct scatterlist *sg; | 1830 | struct scatterlist *sg; |
| 1831 | struct sd_dif_tuple *spt; | 1831 | struct t10_pi_tuple *spt; |
| 1832 | 1832 | ||
| 1833 | /* Patch the corresponding protection tags */ | 1833 | /* Patch the corresponding protection tags */ |
| 1834 | scsi_for_each_prot_sg(cmd, sg, | 1834 | scsi_for_each_prot_sg(cmd, sg, |
| @@ -899,12 +899,12 @@ qla2x00_wait_for_hba_ready(scsi_qla_host_t *vha) · 898 unmodified lines | |||
| 899 | struct qla_hw_data *ha = vha->hw; | 899 | struct qla_hw_data *ha = vha->hw; |
| 900 | scsi_qla_host_t *base_vha = pci_get_drvdata(ha->pdev); | 900 | scsi_qla_host_t *base_vha = pci_get_drvdata(ha->pdev); |
| 901 | 901 | ||
| 902 | while (((qla2x00_reset_active(vha)) || ha->dpc_active || | 902 | while ((qla2x00_reset_active(vha) || ha->dpc_active || |
| 903 | ha->flags.mbox_busy) || | 903 | ha->flags.mbox_busy) || |
| 904 | test_bit(FX00_RESET_RECOVERY, &vha->dpc_flags) || | 904 | test_bit(FX00_RESET_RECOVERY, &vha->dpc_flags) || |
| 905 | test_bit(FX00_TARGET_SCAN, &vha->dpc_flags)) { | 905 | test_bit(FX00_TARGET_SCAN, &vha->dpc_flags)) { |
| 906 | if (test_bit(UNLOADING, &base_vha->dpc_flags)) | 906 | if (test_bit(UNLOADING, &base_vha->dpc_flags)) |
| 907 | break; | 907 | break; |
| 908 | msleep(1000); | 908 | msleep(1000); |
| 909 | } | 909 | } |
| 910 | } | 910 | } |
| @@ -4694,7 +4694,7 @@ retry_unlock: · 3783 unmodified lines | |||
| 4694 | qla83xx_wait_logic(); | 4694 | qla83xx_wait_logic(); |
| 4695 | retry++; | 4695 | retry++; |
| 4696 | ql_dbg(ql_dbg_p3p, base_vha, 0xb064, | 4696 | ql_dbg(ql_dbg_p3p, base_vha, 0xb064, |
| 4697 | "Failed to release IDC lock, retyring=%d\n", retry); | 4697 | "Failed to release IDC lock, retrying=%d\n", retry); |
| 4698 | goto retry_unlock; | 4698 | goto retry_unlock; |
| 4699 | } | 4699 | } |
| 4700 | } else if (retry < 10) { | 4700 | } else if (retry < 10) { |
| @@ -4702,7 +4702,7 @@ retry_unlock: · 1 unmodified line | |||
| 4702 | qla83xx_wait_logic(); | 4702 | qla83xx_wait_logic(); |
| 4703 | retry++; | 4703 | retry++; |
| 4704 | ql_dbg(ql_dbg_p3p, base_vha, 0xb065, | 4704 | ql_dbg(ql_dbg_p3p, base_vha, 0xb065, |
| 4705 | "Failed to read drv-lockid, retyring=%d\n", retry); | 4705 | "Failed to read drv-lockid, retrying=%d\n", retry); |
| 4706 | goto retry_unlock; | 4706 | goto retry_unlock; |
| 4707 | } | 4707 | } |
| 4708 | 4708 | ||
| @@ -4718,7 +4718,7 @@ retry_unlock2: · 9 unmodified lines | |||
| 4718 | qla83xx_wait_logic(); | 4718 | qla83xx_wait_logic(); |
| 4719 | retry++; | 4719 | retry++; |
| 4720 | ql_dbg(ql_dbg_p3p, base_vha, 0xb066, | 4720 | ql_dbg(ql_dbg_p3p, base_vha, 0xb066, |
| 4721 | "Failed to release IDC lock, retyring=%d\n", retry); | 4721 | "Failed to release IDC lock, retrying=%d\n", retry); |
| 4722 | goto retry_unlock2; | 4722 | goto retry_unlock2; |
| 4723 | } | 4723 | } |
| 4724 | } | 4724 | } |
| @@ -1843,7 +1843,7 @@ static uint32_t ql4_84xx_poll_wait_for_ready(struct scsi_qla_host *ha, · 1842 unmodified lines | |||
| 1843 | return rval; | 1843 | return rval; |
| 1844 | } | 1844 | } |
| 1845 | 1845 | ||
| 1846 | uint32_t ql4_84xx_ipmdio_rd_reg(struct scsi_qla_host *ha, uint32_t addr1, | 1846 | static uint32_t ql4_84xx_ipmdio_rd_reg(struct scsi_qla_host *ha, uint32_t addr1, |
| 1847 | uint32_t addr3, uint32_t mask, uint32_t addr, | 1847 | uint32_t addr3, uint32_t mask, uint32_t addr, |
| 1848 | uint32_t *data_ptr) | 1848 | uint32_t *data_ptr) |
| 1849 | { | 1849 | { |
| @@ -42,6 +42,7 @@ · 41 unmodified lines | |||
| 42 | #include <linux/atomic.h> | 42 | #include <linux/atomic.h> |
| 43 | #include <linux/hrtimer.h> | 43 | #include <linux/hrtimer.h> |
| 44 | #include <linux/uuid.h> | 44 | #include <linux/uuid.h> |
| 45 | #include <linux/t10-pi.h> | ||
| 45 | 46 | ||
| 46 | #include <net/checksum.h> | 47 | #include <net/checksum.h> |
| 47 | 48 | ||
| @@ -627,7 +628,7 @@ static LIST_HEAD(sdebug_host_list); · 579 unmodified lines | |||
| 627 | static DEFINE_SPINLOCK(sdebug_host_list_lock); | 628 | static DEFINE_SPINLOCK(sdebug_host_list_lock); |
| 628 | 629 | ||
| 629 | static unsigned char *fake_storep; /* ramdisk storage */ | 630 | static unsigned char *fake_storep; /* ramdisk storage */ |
| 630 | static struct sd_dif_tuple *dif_storep; /* protection info */ | 631 | static struct t10_pi_tuple *dif_storep; /* protection info */ |
| 631 | static void *map_storep; /* provisioning map */ | 632 | static void *map_storep; /* provisioning map */ |
| 632 | 633 | ||
| 633 | static unsigned long map_size; | 634 | static unsigned long map_size; |
| @@ -682,7 +683,7 @@ static void *fake_store(unsigned long long lba) · 48 unmodified lines | |||
| 682 | return fake_storep + lba * sdebug_sector_size; | 683 | return fake_storep + lba * sdebug_sector_size; |
| 683 | } | 684 | } |
| 684 | 685 | ||
| 685 | static struct sd_dif_tuple *dif_store(sector_t sector) | 686 | static struct t10_pi_tuple *dif_store(sector_t sector) |
| 686 | { | 687 | { |
| 687 | sector = sector_div(sector, sdebug_store_sectors); | 688 | sector = sector_div(sector, sdebug_store_sectors); |
| 688 | 689 | ||
| @@ -1349,7 +1350,7 @@ static int resp_inquiry(struct scsi_cmnd *scp, struct sdebug_dev_info *devip) · 660 unmodified lines | |||
| 1349 | } else if (0x86 == cmd[2]) { /* extended inquiry */ | 1350 | } else if (0x86 == cmd[2]) { /* extended inquiry */ |
| 1350 | arr[1] = cmd[2]; /*sanity */ | 1351 | arr[1] = cmd[2]; /*sanity */ |
| 1351 | arr[3] = 0x3c; /* number of following entries */ | 1352 | arr[3] = 0x3c; /* number of following entries */ |
| 1352 | if (sdebug_dif == SD_DIF_TYPE3_PROTECTION) | 1353 | if (sdebug_dif == T10_PI_TYPE3_PROTECTION) |
| 1353 | arr[4] = 0x4; /* SPT: GRD_CHK:1 */ | 1354 | arr[4] = 0x4; /* SPT: GRD_CHK:1 */ |
| 1354 | else if (have_dif_prot) | 1355 | else if (have_dif_prot) |
| 1355 | arr[4] = 0x5; /* SPT: GRD_CHK:1, REF_CHK:1 */ | 1356 | arr[4] = 0x5; /* SPT: GRD_CHK:1, REF_CHK:1 */ |
| @@ -2430,7 +2431,7 @@ static __be16 dif_compute_csum(const void *buf, int len) · 1074 unmodified lines | |||
| 2430 | return csum; | 2431 | return csum; |
| 2431 | } | 2432 | } |
| 2432 | 2433 | ||
| 2433 | static int dif_verify(struct sd_dif_tuple *sdt, const void *data, | 2434 | static int dif_verify(struct t10_pi_tuple *sdt, const void *data, |
| 2434 | sector_t sector, u32 ei_lba) | 2435 | sector_t sector, u32 ei_lba) |
| 2435 | { | 2436 | { |
| 2436 | __be16 csum = dif_compute_csum(data, sdebug_sector_size); | 2437 | __be16 csum = dif_compute_csum(data, sdebug_sector_size); |
| @@ -2442,13 +2443,13 @@ static int dif_verify(struct sd_dif_tuple *sdt, const void *data, · 5 unmodified lines | |||
| 2442 | be16_to_cpu(csum)); | 2443 | be16_to_cpu(csum)); |
| 2443 | return 0x01; | 2444 | return 0x01; |
| 2444 | } | 2445 | } |
| 2445 | if (sdebug_dif == SD_DIF_TYPE1_PROTECTION && | 2446 | if (sdebug_dif == T10_PI_TYPE1_PROTECTION && |
| 2446 | be32_to_cpu(sdt->ref_tag) != (sector & 0xffffffff)) { | 2447 | be32_to_cpu(sdt->ref_tag) != (sector & 0xffffffff)) { |
| 2447 | pr_err("REF check failed on sector %lu\n", | 2448 | pr_err("REF check failed on sector %lu\n", |
| 2448 | (unsigned long)sector); | 2449 | (unsigned long)sector); |
| 2449 | return 0x03; | 2450 | return 0x03; |
| 2450 | } | 2451 | } |
| 2451 | if (sdebug_dif == SD_DIF_TYPE2_PROTECTION && | 2452 | if (sdebug_dif == T10_PI_TYPE2_PROTECTION && |
| 2452 | be32_to_cpu(sdt->ref_tag) != ei_lba) { | 2453 | be32_to_cpu(sdt->ref_tag) != ei_lba) { |
| 2453 | pr_err("REF check failed on sector %lu\n", | 2454 | pr_err("REF check failed on sector %lu\n", |
| 2454 | (unsigned long)sector); | 2455 | (unsigned long)sector); |
| @@ -2504,7 +2505,7 @@ static int prot_verify_read(struct scsi_cmnd *SCpnt, sector_t start_sec, · 49 unmodified lines | |||
| 2504 | unsigned int sectors, u32 ei_lba) | 2505 | unsigned int sectors, u32 ei_lba) |
| 2505 | { | 2506 | { |
| 2506 | unsigned int i; | 2507 | unsigned int i; |
| 2507 | struct sd_dif_tuple *sdt; | 2508 | struct t10_pi_tuple *sdt; |
| 2508 | sector_t sector; | 2509 | sector_t sector; |
| 2509 | 2510 | ||
| 2510 | for (i = 0; i < sectors; i++, ei_lba++) { | 2511 | for (i = 0; i < sectors; i++, ei_lba++) { |
| @@ -2580,13 +2581,13 @@ static int resp_read_dt0(struct scsi_cmnd *scp, struct sdebug_dev_info *devip) · 69 unmodified lines | |||
| 2580 | break; | 2581 | break; |
| 2581 | } | 2582 | } |
| 2582 | if (unlikely(have_dif_prot && check_prot)) { | 2583 | if (unlikely(have_dif_prot && check_prot)) { |
| 2583 | if (sdebug_dif == SD_DIF_TYPE2_PROTECTION && | 2584 | if (sdebug_dif == T10_PI_TYPE2_PROTECTION && |
| 2584 | (cmd[1] & 0xe0)) { | 2585 | (cmd[1] & 0xe0)) { |
| 2585 | mk_sense_invalid_opcode(scp); | 2586 | mk_sense_invalid_opcode(scp); |
| 2586 | return check_condition_result; | 2587 | return check_condition_result; |
| 2587 | } | 2588 | } |
| 2588 | if ((sdebug_dif == SD_DIF_TYPE1_PROTECTION || | 2589 | if ((sdebug_dif == T10_PI_TYPE1_PROTECTION || |
| 2589 | sdebug_dif == SD_DIF_TYPE3_PROTECTION) && | 2590 | sdebug_dif == T10_PI_TYPE3_PROTECTION) && |
| 2590 | (cmd[1] & 0xe0) == 0) | 2591 | (cmd[1] & 0xe0) == 0) |
| 2591 | sdev_printk(KERN_ERR, scp->device, "Unprotected RD " | 2592 | sdev_printk(KERN_ERR, scp->device, "Unprotected RD " |
| 2592 | "to DIF device\n"); | 2593 | "to DIF device\n"); |
| @@ -2696,7 +2697,7 @@ static int prot_verify_write(struct scsi_cmnd *SCpnt, sector_t start_sec, · 103 unmodified lines | |||
| 2696 | unsigned int sectors, u32 ei_lba) | 2697 | unsigned int sectors, u32 ei_lba) |
| 2697 | { | 2698 | { |
| 2698 | int ret; | 2699 | int ret; |
| 2699 | struct sd_dif_tuple *sdt; | 2700 | struct t10_pi_tuple *sdt; |
| 2700 | void *daddr; | 2701 | void *daddr; |
| 2701 | sector_t sector = start_sec; | 2702 | sector_t sector = start_sec; |
| 2702 | int ppage_offset; | 2703 | int ppage_offset; |
| @@ -2722,7 +2723,7 @@ static int prot_verify_write(struct scsi_cmnd *SCpnt, sector_t start_sec, · 19 unmodified lines | |||
| 2722 | } | 2723 | } |
| 2723 | 2724 | ||
| 2724 | for (ppage_offset = 0; ppage_offset < piter.length; | 2725 | for (ppage_offset = 0; ppage_offset < piter.length; |
| 2725 | ppage_offset += sizeof(struct sd_dif_tuple)) { | 2726 | ppage_offset += sizeof(struct t10_pi_tuple)) { |
| 2726 | /* If we're at the end of the current | 2727 | /* If we're at the end of the current |
| 2727 | * data page advance to the next one | 2728 | * data page advance to the next one |
| 2728 | */ | 2729 | */ |
| @@ -2893,13 +2894,13 @@ static int resp_write_dt0(struct scsi_cmnd *scp, struct sdebug_dev_info *devip) · 164 unmodified lines | |||
| 2893 | break; | 2894 | break; |
| 2894 | } | 2895 | } |
| 2895 | if (unlikely(have_dif_prot && check_prot)) { | 2896 | if (unlikely(have_dif_prot && check_prot)) { |
| 2896 | if (sdebug_dif == SD_DIF_TYPE2_PROTECTION && | 2897 | if (sdebug_dif == T10_PI_TYPE2_PROTECTION && |
| 2897 | (cmd[1] & 0xe0)) { | 2898 | (cmd[1] & 0xe0)) { |
| 2898 | mk_sense_invalid_opcode(scp); | 2899 | mk_sense_invalid_opcode(scp); |
| 2899 | return check_condition_result; | 2900 | return check_condition_result; |
| 2900 | } | 2901 | } |
| 2901 | if ((sdebug_dif == SD_DIF_TYPE1_PROTECTION || | 2902 | if ((sdebug_dif == T10_PI_TYPE1_PROTECTION || |
| 2902 | sdebug_dif == SD_DIF_TYPE3_PROTECTION) && | 2903 | sdebug_dif == T10_PI_TYPE3_PROTECTION) && |
| 2903 | (cmd[1] & 0xe0) == 0) | 2904 | (cmd[1] & 0xe0) == 0) |
| 2904 | sdev_printk(KERN_ERR, scp->device, "Unprotected WR " | 2905 | sdev_printk(KERN_ERR, scp->device, "Unprotected WR " |
| 2905 | "to DIF device\n"); | 2906 | "to DIF device\n"); |
| @@ -3135,13 +3136,13 @@ static int resp_comp_write(struct scsi_cmnd *scp, · 229 unmodified lines | |||
| 3135 | num = cmd[13]; /* 1 to a maximum of 255 logical blocks */ | 3136 | num = cmd[13]; /* 1 to a maximum of 255 logical blocks */ |
| 3136 | if (0 == num) | 3137 | if (0 == num) |
| 3137 | return 0; /* degenerate case, not an error */ | 3138 | return 0; /* degenerate case, not an error */ |
| 3138 | if (sdebug_dif == SD_DIF_TYPE2_PROTECTION && | 3139 | if (sdebug_dif == T10_PI_TYPE2_PROTECTION && |
| 3139 | (cmd[1] & 0xe0)) { | 3140 | (cmd[1] & 0xe0)) { |
| 3140 | mk_sense_invalid_opcode(scp); | 3141 | mk_sense_invalid_opcode(scp); |
| 3141 | return check_condition_result; | 3142 | return check_condition_result; |
| 3142 | } | 3143 | } |
| 3143 | if ((sdebug_dif == SD_DIF_TYPE1_PROTECTION || | 3144 | if ((sdebug_dif == T10_PI_TYPE1_PROTECTION || |
| 3144 | sdebug_dif == SD_DIF_TYPE3_PROTECTION) && | 3145 | sdebug_dif == T10_PI_TYPE3_PROTECTION) && |
| 3145 | (cmd[1] & 0xe0) == 0) | 3146 | (cmd[1] & 0xe0) == 0) |
| 3146 | sdev_printk(KERN_ERR, scp->device, "Unprotected WR " | 3147 | sdev_printk(KERN_ERR, scp->device, "Unprotected WR " |
| 3147 | "to DIF device\n"); | 3148 | "to DIF device\n"); |
| @@ -4939,12 +4940,11 @@ static int __init scsi_debug_init(void) · 1791 unmodified lines | |||
| 4939 | } | 4940 | } |
| 4940 | 4941 | ||
| 4941 | switch (sdebug_dif) { | 4942 | switch (sdebug_dif) { |
| 4942 | 4943 | case T10_PI_TYPE0_PROTECTION: | |
| 4943 | case SD_DIF_TYPE0_PROTECTION: | ||
| 4944 | break; | 4944 | break; |
| 4945 | case SD_DIF_TYPE1_PROTECTION: | 4945 | case T10_PI_TYPE1_PROTECTION: |
| 4946 | case SD_DIF_TYPE2_PROTECTION: | 4946 | case T10_PI_TYPE2_PROTECTION: |
| 4947 | case SD_DIF_TYPE3_PROTECTION: | 4947 | case T10_PI_TYPE3_PROTECTION: |
| 4948 | have_dif_prot = true; | 4948 | have_dif_prot = true; |
| 4949 | break; | 4949 | break; |
| 4950 | 4950 | ||
| @@ -5026,7 +5026,7 @@ static int __init scsi_debug_init(void) · 75 unmodified lines | |||
| 5026 | if (sdebug_dix) { | 5026 | if (sdebug_dix) { |
| 5027 | int dif_size; | 5027 | int dif_size; |
| 5028 | 5028 | ||
| 5029 | dif_size = sdebug_store_sectors * sizeof(struct sd_dif_tuple); | 5029 | dif_size = sdebug_store_sectors * sizeof(struct t10_pi_tuple); |
| 5030 | dif_storep = vmalloc(dif_size); | 5030 | dif_storep = vmalloc(dif_size); |
| 5031 | 5031 | ||
| 5032 | pr_err("dif_storep %u bytes @ %p\n", dif_size, dif_storep); | 5032 | pr_err("dif_storep %u bytes @ %p\n", dif_size, dif_storep); |
| @@ -5480,19 +5480,19 @@ static int sdebug_driver_probe(struct device * dev) · 447 unmodified lines | |||
| 5480 | 5480 | ||
| 5481 | switch (sdebug_dif) { | 5481 | switch (sdebug_dif) { |
| 5482 | 5482 | ||
| 5483 | case SD_DIF_TYPE1_PROTECTION: | 5483 | case T10_PI_TYPE1_PROTECTION: |
| 5484 | hprot = SHOST_DIF_TYPE1_PROTECTION; | 5484 | hprot = SHOST_DIF_TYPE1_PROTECTION; |
| 5485 | if (sdebug_dix) | 5485 | if (sdebug_dix) |
| 5486 | hprot |= SHOST_DIX_TYPE1_PROTECTION; | 5486 | hprot |= SHOST_DIX_TYPE1_PROTECTION; |
| 5487 | break; | 5487 | break; |
| 5488 | 5488 | ||
| 5489 | case SD_DIF_TYPE2_PROTECTION: | 5489 | case T10_PI_TYPE2_PROTECTION: |
| 5490 | hprot = SHOST_DIF_TYPE2_PROTECTION; | 5490 | hprot = SHOST_DIF_TYPE2_PROTECTION; |
| 5491 | if (sdebug_dix) | 5491 | if (sdebug_dix) |
| 5492 | hprot |= SHOST_DIX_TYPE2_PROTECTION; | 5492 | hprot |= SHOST_DIX_TYPE2_PROTECTION; |
| 5493 | break; | 5493 | break; |
| 5494 | 5494 | ||
| 5495 | case SD_DIF_TYPE3_PROTECTION: | 5495 | case T10_PI_TYPE3_PROTECTION: |
| 5496 | hprot = SHOST_DIF_TYPE3_PROTECTION; | 5496 | hprot = SHOST_DIF_TYPE3_PROTECTION; |
| 5497 | if (sdebug_dix) | 5497 | if (sdebug_dix) |
| 5498 | hprot |= SHOST_DIX_TYPE3_PROTECTION; | 5498 | hprot |= SHOST_DIX_TYPE3_PROTECTION; |
| @@ -86,12 +86,14 @@ extern void scsi_device_unbusy(struct scsi_device *sdev); · 85 unmodified lines | |||
| 86 | extern void scsi_queue_insert(struct scsi_cmnd *cmd, int reason); | 86 | extern void scsi_queue_insert(struct scsi_cmnd *cmd, int reason); |
| 87 | extern void scsi_io_completion(struct scsi_cmnd *, unsigned int); | 87 | extern void scsi_io_completion(struct scsi_cmnd *, unsigned int); |
| 88 | extern void scsi_run_host_queues(struct Scsi_Host *shost); | 88 | extern void scsi_run_host_queues(struct Scsi_Host *shost); |
| 89 | extern void scsi_requeue_run_queue(struct work_struct *work); | ||
| 89 | extern struct request_queue *scsi_alloc_queue(struct scsi_device *sdev); | 90 | extern struct request_queue *scsi_alloc_queue(struct scsi_device *sdev); |
| 90 | extern struct request_queue *scsi_mq_alloc_queue(struct scsi_device *sdev); | 91 | extern struct request_queue *scsi_mq_alloc_queue(struct scsi_device *sdev); |
| 91 | extern int scsi_mq_setup_tags(struct Scsi_Host *shost); | 92 | extern int scsi_mq_setup_tags(struct Scsi_Host *shost); |
| 92 | extern void scsi_mq_destroy_tags(struct Scsi_Host *shost); | 93 | extern void scsi_mq_destroy_tags(struct Scsi_Host *shost); |
| 93 | extern int scsi_init_queue(void); | 94 | extern int scsi_init_queue(void); |
| 94 | extern void scsi_exit_queue(void); | 95 | extern void scsi_exit_queue(void); |
| 96 | extern void scsi_evt_thread(struct work_struct *work); | ||
| 95 | struct request_queue; | 97 | struct request_queue; |
| 96 | struct request; | 98 | struct request; |
| 97 | extern struct kmem_cache *scsi_sdb_cache; | 99 | extern struct kmem_cache *scsi_sdb_cache; |
| @@ -217,8 +217,6 @@ static struct scsi_device *scsi_alloc_sdev(struct scsi_target *starget, · 216 unmodified lines | |||
| 217 | struct scsi_device *sdev; | 217 | struct scsi_device *sdev; |
| 218 | int display_failure_msg = 1, ret; | 218 | int display_failure_msg = 1, ret; |
| 219 | struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); | 219 | struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); |
| 220 | extern void scsi_evt_thread(struct work_struct *work); | ||
| 221 | extern void scsi_requeue_run_queue(struct work_struct *work); | ||
| 222 | 220 | ||
| 223 | sdev = kzalloc(sizeof(*sdev) + shost->transportt->device_size, | 221 | sdev = kzalloc(sizeof(*sdev) + shost->transportt->device_size, |
| 224 | GFP_ATOMIC); | 222 | GFP_ATOMIC); |
| @@ -52,6 +52,7 @@ · 51 unmodified lines | |||
| 52 | #include <linux/slab.h> | 52 | #include <linux/slab.h> |
| 53 | #include <linux/pm_runtime.h> | 53 | #include <linux/pm_runtime.h> |
| 54 | #include <linux/pr.h> | 54 | #include <linux/pr.h> |
| 55 | #include <linux/t10-pi.h> | ||
| 55 | #include <asm/uaccess.h> | 56 | #include <asm/uaccess.h> |
| 56 | #include <asm/unaligned.h> | 57 | #include <asm/unaligned.h> |
| 57 | 58 | ||
| @@ -314,7 +315,7 @@ protection_type_store(struct device *dev, struct device_attribute *attr, · 256 unmodified lines | |||
| 314 | if (err) | 315 | if (err) |
| 315 | return err; | 316 | return err; |
| 316 | 317 | ||
| 317 | if (val >= 0 && val <= SD_DIF_TYPE3_PROTECTION) | 318 | if (val >= 0 && val <= T10_PI_TYPE3_PROTECTION) |
| 318 | sdkp->protection_type = val; | 319 | sdkp->protection_type = val; |
| 319 | 320 | ||
| 320 | return count; | 321 | return count; |
| @@ -332,7 +333,7 @@ protection_mode_show(struct device *dev, struct device_attribute *attr, · 11 unmodified lines | |||
| 332 | dif = scsi_host_dif_capable(sdp->host, sdkp->protection_type); | 333 | dif = scsi_host_dif_capable(sdp->host, sdkp->protection_type); |
| 333 | dix = scsi_host_dix_capable(sdp->host, sdkp->protection_type); | 334 | dix = scsi_host_dix_capable(sdp->host, sdkp->protection_type); |
| 334 | 335 | ||
| 335 | if (!dix && scsi_host_dix_capable(sdp->host, SD_DIF_TYPE0_PROTECTION)) { | 336 | if (!dix && scsi_host_dix_capable(sdp->host, T10_PI_TYPE0_PROTECTION)) { |
| 336 | dif = 0; | 337 | dif = 0; |
| 337 | dix = 1; | 338 | dix = 1; |
| 338 | } | 339 | } |
| @@ -608,7 +609,7 @@ static unsigned char sd_setup_protect_cmnd(struct scsi_cmnd *scmd, · 269 unmodified lines | |||
| 608 | scmd->prot_flags |= SCSI_PROT_GUARD_CHECK; | 609 | scmd->prot_flags |= SCSI_PROT_GUARD_CHECK; |
| 609 | } | 610 | } |
| 610 | 611 | ||
| 611 | if (dif != SD_DIF_TYPE3_PROTECTION) { /* DIX/DIF Type 0, 1, 2 */ | 612 | if (dif != T10_PI_TYPE3_PROTECTION) { /* DIX/DIF Type 0, 1, 2 */ |
| 612 | scmd->prot_flags |= SCSI_PROT_REF_INCREMENT; | 613 | scmd->prot_flags |= SCSI_PROT_REF_INCREMENT; |
| 613 | 614 | ||
| 614 | if (bio_integrity_flagged(bio, BIP_CTRL_NOCHECK) == false) | 615 | if (bio_integrity_flagged(bio, BIP_CTRL_NOCHECK) == false) |
| @@ -1031,7 +1032,7 @@ static int sd_setup_read_write_cmnd(struct scsi_cmnd *SCpnt) · 416 unmodified lines | |||
| 1031 | else | 1032 | else |
| 1032 | protect = 0; | 1033 | protect = 0; |
| 1033 | 1034 | ||
| 1034 | if (protect && sdkp->protection_type == SD_DIF_TYPE2_PROTECTION) { | 1035 | if (protect && sdkp->protection_type == T10_PI_TYPE2_PROTECTION) { |
| 1035 | SCpnt->cmnd = mempool_alloc(sd_cdb_pool, GFP_ATOMIC); | 1036 | SCpnt->cmnd = mempool_alloc(sd_cdb_pool, GFP_ATOMIC); |
| 1036 | 1037 | ||
| 1037 | if (unlikely(SCpnt->cmnd == NULL)) { | 1038 | if (unlikely(SCpnt->cmnd == NULL)) { |
| @@ -1997,7 +1998,7 @@ static int sd_read_protection_type(struct scsi_disk *sdkp, unsigned char *buffer · 959 unmodified lines | |||
| 1997 | 1998 | ||
| 1998 | type = ((buffer[12] >> 1) & 7) + 1; /* P_TYPE 0 = Type 1 */ | 1999 | type = ((buffer[12] >> 1) & 7) + 1; /* P_TYPE 0 = Type 1 */ |
| 1999 | 2000 | ||
| 2000 | if (type > SD_DIF_TYPE3_PROTECTION) | 2001 | if (type > T10_PI_TYPE3_PROTECTION) |
| 2001 | ret = -ENODEV; | 2002 | ret = -ENODEV; |
| 2002 | else if (scsi_host_dif_capable(sdp->host, type)) | 2003 | else if (scsi_host_dif_capable(sdp->host, type)) |
| 2003 | ret = 1; | 2004 | ret = 1; |
| @@ -156,27 +156,6 @@ static inline unsigned int logical_to_bytes(struct scsi_device *sdev, sector_t b · 155 unmodified lines | |||
| 156 | return blocks * sdev->sector_size; | 156 | return blocks * sdev->sector_size; |
| 157 | } | 157 | } |
| 158 | 158 | ||
| 159 | /* | ||
| 160 | * A DIF-capable target device can be formatted with different | ||
| 161 | * protection schemes. Currently 0 through 3 are defined: | ||
| 162 | * | ||
| 163 | * Type 0 is regular (unprotected) I/O | ||
| 164 | * | ||
| 165 | * Type 1 defines the contents of the guard and reference tags | ||
| 166 | * | ||
| 167 | * Type 2 defines the contents of the guard and reference tags and | ||
| 168 | * uses 32-byte commands to seed the latter | ||
| 169 | * | ||
| 170 | * Type 3 defines the contents of the guard tag only | ||
| 171 | */ | ||
| 172 | |||
| 173 | enum sd_dif_target_protection_types { | ||
| 174 | SD_DIF_TYPE0_PROTECTION = 0x0, | ||
| 175 | SD_DIF_TYPE1_PROTECTION = 0x1, | ||
| 176 | SD_DIF_TYPE2_PROTECTION = 0x2, | ||
| 177 | SD_DIF_TYPE3_PROTECTION = 0x3, | ||
| 178 | }; | ||
| 179 | |||
| 180 | /* | 159 | /* |
| 181 | * Look up the DIX operation based on whether the command is read or | 160 | * Look up the DIX operation based on whether the command is read or |
| 182 | * write and whether dix and dif are enabled. | 161 | * write and whether dix and dif are enabled. |
| @@ -239,15 +218,6 @@ static inline unsigned int sd_prot_flag_mask(unsigned int prot_op) · 56 unmodified lines | |||
| 239 | return flag_mask[prot_op]; | 218 | return flag_mask[prot_op]; |
| 240 | } | 219 | } |
| 241 | 220 | ||
| 242 | /* | ||
| 243 | * Data Integrity Field tuple. | ||
| 244 | */ | ||
| 245 | struct sd_dif_tuple { | ||
| 246 | __be16 guard_tag; /* Checksum */ | ||
| 247 | __be16 app_tag; /* Opaque storage */ | ||
| 248 | __be32 ref_tag; /* Target LBA or indirect LBA */ | ||
| 249 | }; | ||
| 250 | |||
| 251 | #ifdef CONFIG_BLK_DEV_INTEGRITY | 221 | #ifdef CONFIG_BLK_DEV_INTEGRITY |
| 252 | 222 | ||
| 253 | extern void sd_dif_config_host(struct scsi_disk *); | 223 | extern void sd_dif_config_host(struct scsi_disk *); |
| @@ -60,14 +60,14 @@ void sd_dif_config_host(struct scsi_disk *sdkp) · 59 unmodified lines | |||
| 60 | 60 | ||
| 61 | /* Enable DMA of protection information */ | 61 | /* Enable DMA of protection information */ |
| 62 | if (scsi_host_get_guard(sdkp->device->host) & SHOST_DIX_GUARD_IP) { | 62 | if (scsi_host_get_guard(sdkp->device->host) & SHOST_DIX_GUARD_IP) { |
| 63 | if (type == SD_DIF_TYPE3_PROTECTION) | 63 | if (type == T10_PI_TYPE3_PROTECTION) |
| 64 | bi.profile = &t10_pi_type3_ip; | 64 | bi.profile = &t10_pi_type3_ip; |
| 65 | else | 65 | else |
| 66 | bi.profile = &t10_pi_type1_ip; | 66 | bi.profile = &t10_pi_type1_ip; |
| 67 | 67 | ||
| 68 | bi.flags |= BLK_INTEGRITY_IP_CHECKSUM; | 68 | bi.flags |= BLK_INTEGRITY_IP_CHECKSUM; |
| 69 | } else | 69 | } else |
| 70 | if (type == SD_DIF_TYPE3_PROTECTION) | 70 | if (type == T10_PI_TYPE3_PROTECTION) |
| 71 | bi.profile = &t10_pi_type3_crc; | 71 | bi.profile = &t10_pi_type3_crc; |
| 72 | else | 72 | else |
| 73 | bi.profile = &t10_pi_type1_crc; | 73 | bi.profile = &t10_pi_type1_crc; |
| @@ -82,7 +82,7 @@ void sd_dif_config_host(struct scsi_disk *sdkp) · 8 unmodified lines | |||
| 82 | if (!sdkp->ATO) | 82 | if (!sdkp->ATO) |
| 83 | goto out; | 83 | goto out; |
| 84 | 84 | ||
| 85 | if (type == SD_DIF_TYPE3_PROTECTION) | 85 | if (type == T10_PI_TYPE3_PROTECTION) |
| 86 | bi.tag_size = sizeof(u16) + sizeof(u32); | 86 | bi.tag_size = sizeof(u16) + sizeof(u32); |
| 87 | else | 87 | else |
| 88 | bi.tag_size = sizeof(u16); | 88 | bi.tag_size = sizeof(u16); |
| @@ -121,7 +121,7 @@ void sd_dif_prepare(struct scsi_cmnd *scmd) · 32 unmodified lines | |||
| 121 | 121 | ||
| 122 | sdkp = scsi_disk(scmd->request->rq_disk); | 122 | sdkp = scsi_disk(scmd->request->rq_disk); |
| 123 | 123 | ||
| 124 | if (sdkp->protection_type == SD_DIF_TYPE3_PROTECTION) | 124 | if (sdkp->protection_type == T10_PI_TYPE3_PROTECTION) |
| 125 | return; | 125 | return; |
| 126 | 126 | ||
| 127 | phys = scsi_prot_ref_tag(scmd); | 127 | phys = scsi_prot_ref_tag(scmd); |
| @@ -172,7 +172,7 @@ void sd_dif_complete(struct scsi_cmnd *scmd, unsigned int good_bytes) · 44 unmodified lines | |||
| 172 | 172 | ||
| 173 | sdkp = scsi_disk(scmd->request->rq_disk); | 173 | sdkp = scsi_disk(scmd->request->rq_disk); |
| 174 | 174 | ||
| 175 | if (sdkp->protection_type == SD_DIF_TYPE3_PROTECTION || good_bytes == 0) | 175 | if (sdkp->protection_type == T10_PI_TYPE3_PROTECTION || good_bytes == 0) |
| 176 | return; | 176 | return; |
| 177 | 177 | ||
| 178 | intervals = good_bytes / scsi_prot_interval(scmd); | 178 | intervals = good_bytes / scsi_prot_interval(scmd); |
| @@ -79,18 +79,7 @@ static void sg_proc_cleanup(void); · 78 unmodified lines | |||
| 79 | */ | 79 | */ |
| 80 | #define SG_MAX_CDB_SIZE 252 | 80 | #define SG_MAX_CDB_SIZE 252 |
| 81 | 81 | ||
| 82 | /* | 82 | #define SG_DEFAULT_TIMEOUT mult_frac(SG_DEFAULT_TIMEOUT_USER, HZ, USER_HZ) |
| 83 | * Suppose you want to calculate the formula muldiv(x,m,d)=int(x * m / d) | ||
| 84 | * Then when using 32 bit integers x * m may overflow during the calculation. | ||
| 85 | * Replacing muldiv(x) by muldiv(x)=((x % d) * m) / d + int(x / d) * m | ||
| 86 | * calculates the same, but prevents the overflow when both m and d | ||
| 87 | * are "small" numbers (like HZ and USER_HZ). | ||
| 88 | * Of course an overflow is inavoidable if the result of muldiv doesn't fit | ||
| 89 | * in 32 bits. | ||
| 90 | */ | ||
| 91 | #define MULDIV(X,MUL,DIV) ((((X % DIV) * MUL) / DIV) + ((X / DIV) * MUL)) | ||
| 92 | |||
| 93 | #define SG_DEFAULT_TIMEOUT MULDIV(SG_DEFAULT_TIMEOUT_USER, HZ, USER_HZ) | ||
| 94 | 83 | ||
| 95 | int sg_big_buff = SG_DEF_RESERVED_SIZE; | 84 | int sg_big_buff = SG_DEF_RESERVED_SIZE; |
| 96 | /* N.B. This variable is readable and writeable via | 85 | /* N.B. This variable is readable and writeable via |
| @@ -884,10 +873,11 @@ sg_ioctl(struct file *filp, unsigned int cmd_in, unsigned long arg) · 787 unmodified lines | |||
| 884 | return result; | 873 | return result; |
| 885 | if (val < 0) | 874 | if (val < 0) |
| 886 | return -EIO; | 875 | return -EIO; |
| 887 | if (val >= MULDIV (INT_MAX, USER_HZ, HZ)) | 876 | if (val >= mult_frac((s64)INT_MAX, USER_HZ, HZ)) |
| 888 | val = MULDIV (INT_MAX, USER_HZ, HZ); | 877 | val = min_t(s64, mult_frac((s64)INT_MAX, USER_HZ, HZ), |
| 878 | INT_MAX); | ||
| 889 | sfp->timeout_user = val; | 879 | sfp->timeout_user = val; |
| 890 | sfp->timeout = MULDIV (val, HZ, USER_HZ); | 880 | sfp->timeout = mult_frac(val, HZ, USER_HZ); |
| 891 | 881 | ||
| 892 | return 0; | 882 | return 0; |
| 893 | case SG_GET_TIMEOUT: /* N.B. User receives timeout as return value */ | 883 | case SG_GET_TIMEOUT: /* N.B. User receives timeout as return value */ |
| @@ -0,0 +1,54 @@ | |||
| 1 | # | ||
| 2 | # Kernel configuration file for the SMARTPQI | ||
| 3 | # | ||
| 4 | # Copyright (c) 2016 Microsemi Corporation | ||
| 5 | # Copyright (c) 2016 PMC-Sierra, Inc. | ||
| 6 | # (mailto:esc.storagedev@microsemi.com) | ||
| 7 | |||
| 8 | # This program is free software; you can redistribute it and/or | ||
| 9 | # modify it under the terms of the GNU General Public License | ||
| 10 | # as published by the Free Software Foundation; version 2 | ||
| 11 | # of the License. | ||
| 12 | |||
| 13 | # This program is distributed in the hope that it will be useful, | ||
| 14 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 15 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 16 | # GNU General Public License for more details. | ||
| 17 | |||
| 18 | # NO WARRANTY | ||
| 19 | # THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR | ||
| 20 | # CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT | ||
| 21 | # LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, | ||
| 22 | # MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is | ||
| 23 | # solely responsible for determining the appropriateness of using and | ||
| 24 | # distributing the Program and assumes all risks associated with its | ||
| 25 | # exercise of rights under this Agreement, including but not limited to | ||
| 26 | # the risks and costs of program errors, damage to or loss of data, | ||
| 27 | # programs or equipment, and unavailability or interruption of operations. | ||
| 28 | |||
| 29 | # DISCLAIMER OF LIABILITY | ||
| 30 | # NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY | ||
| 31 | # DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | ||
| 32 | # DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND | ||
| 33 | # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR | ||
| 34 | # TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE | ||
| 35 | # USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED | ||
| 36 | # HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES | ||
| 37 | |||
| 38 | config SCSI_SMARTPQI | ||
| 39 | tristate "Microsemi PQI Driver" | ||
| 40 | depends on PCI && SCSI && !S390 | ||
| 41 | select SCSI_SAS_ATTRS | ||
| 42 | select RAID_ATTRS | ||
| 43 | ---help--- | ||
| 44 | This driver supports Microsemi PQI controllers. | ||
| 45 | |||
| 46 | <http://www.microsemi.com> | ||
| 47 | |||
| 48 | To compile this driver as a module, choose M here: the | ||
| 49 | module will be called smartpqi. | ||
| 50 | |||
| 51 | Note: the aacraid driver will not manage a smartpqi | ||
| 52 | controller. You need to enable smartpqi for smartpqi | ||
| 53 | controllers. For more information, please see | ||
| 54 | Documentation/scsi/smartpqi.txt | ||
| @@ -0,0 +1,3 @@ | |||
| 1 | ccflags-y += -I. | ||
| 2 | obj-m += smartpqi.o | ||
| 3 | smartpqi-objs := smartpqi_init.o smartpqi_sis.o smartpqi_sas_transport.o | ||
| @@ -0,0 +1,1136 @@ | |||
| 1 | /* | ||
| 2 | * driver for Microsemi PQI-based storage controllers | ||
| 3 | * Copyright (c) 2016 Microsemi Corporation | ||
| 4 | * Copyright (c) 2016 PMC-Sierra, Inc. | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or modify | ||
| 7 | * it under the terms of the GNU General Public License as published by | ||
| 8 | * the Free Software Foundation; version 2 of the License. | ||
| 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, GOOD TITLE or | ||
| 13 | * NON INFRINGEMENT. See the GNU General Public License for more details. | ||
| 14 | * | ||
| 15 | * Questions/Comments/Bugfixes to esc.storagedev@microsemi.com | ||
| 16 | * | ||
| 17 | */ | ||
| 18 | |||
| 19 | #if !defined(_SMARTPQI_H) | ||
| 20 | #define _SMARTPQI_H | ||
| 21 | |||
| 22 | #pragma pack(1) | ||
| 23 | |||
| 24 | #define PQI_DEVICE_SIGNATURE "PQI DREG" | ||
| 25 | |||
| 26 | /* This structure is defined by the PQI specification. */ | ||
| 27 | struct pqi_device_registers { | ||
| 28 | __le64 signature; | ||
| 29 | u8 function_and_status_code; | ||
| 30 | u8 reserved[7]; | ||
| 31 | u8 max_admin_iq_elements; | ||
| 32 | u8 max_admin_oq_elements; | ||
| 33 | u8 admin_iq_element_length; /* in 16-byte units */ | ||
| 34 | u8 admin_oq_element_length; /* in 16-byte units */ | ||
| 35 | __le16 max_reset_timeout; /* in 100-millisecond units */ | ||
| 36 | u8 reserved1[2]; | ||
| 37 | __le32 legacy_intx_status; | ||
| 38 | __le32 legacy_intx_mask_set; | ||
| 39 | __le32 legacy_intx_mask_clear; | ||
| 40 | u8 reserved2[28]; | ||
| 41 | __le32 device_status; | ||
| 42 | u8 reserved3[4]; | ||
| 43 | __le64 admin_iq_pi_offset; | ||
| 44 | __le64 admin_oq_ci_offset; | ||
| 45 | __le64 admin_iq_element_array_addr; | ||
| 46 | __le64 admin_oq_element_array_addr; | ||
| 47 | __le64 admin_iq_ci_addr; | ||
| 48 | __le64 admin_oq_pi_addr; | ||
| 49 | u8 admin_iq_num_elements; | ||
| 50 | u8 admin_oq_num_elements; | ||
| 51 | __le16 admin_queue_int_msg_num; | ||
| 52 | u8 reserved4[4]; | ||
| 53 | __le32 device_error; | ||
| 54 | u8 reserved5[4]; | ||
| 55 | __le64 error_details; | ||
| 56 | __le32 device_reset; | ||
| 57 | __le32 power_action; | ||
| 58 | u8 reserved6[104]; | ||
| 59 | }; | ||
| 60 | |||
| 61 | /* | ||
| 62 | * controller registers | ||
| 63 | * | ||
| 64 | * These are defined by the PMC implementation. | ||
| 65 | * | ||
| 66 | * Some registers (those named sis_*) are only used when in | ||
| 67 | * legacy SIS mode before we transition the controller into | ||
| 68 | * PQI mode. There are a number of other SIS mode registers, | ||
| 69 | * but we don't use them, so only the SIS registers that we | ||
| 70 | * care about are defined here. The offsets mentioned in the | ||
| 71 | * comments are the offsets from the PCIe BAR 0. | ||
| 72 | */ | ||
| 73 | struct pqi_ctrl_registers { | ||
| 74 | u8 reserved[0x20]; | ||
| 75 | __le32 sis_host_to_ctrl_doorbell; /* 20h */ | ||
| 76 | u8 reserved1[0x34 - (0x20 + sizeof(__le32))]; | ||
| 77 | __le32 sis_interrupt_mask; /* 34h */ | ||
| 78 | u8 reserved2[0x9c - (0x34 + sizeof(__le32))]; | ||
| 79 | __le32 sis_ctrl_to_host_doorbell; /* 9Ch */ | ||
| 80 | u8 reserved3[0xa0 - (0x9c + sizeof(__le32))]; | ||
| 81 | __le32 sis_ctrl_to_host_doorbell_clear; /* A0h */ | ||
| 82 | u8 reserved4[0xb0 - (0xa0 + sizeof(__le32))]; | ||
| 83 | __le32 sis_driver_scratch; /* B0h */ | ||
| 84 | u8 reserved5[0xbc - (0xb0 + sizeof(__le32))]; | ||
| 85 | __le32 sis_firmware_status; /* BCh */ | ||
| 86 | u8 reserved6[0x1000 - (0xbc + sizeof(__le32))]; | ||
| 87 | __le32 sis_mailbox[8]; /* 1000h */ | ||
| 88 | u8 reserved7[0x4000 - (0x1000 + (sizeof(__le32) * 8))]; | ||
| 89 | /* | ||
| 90 | * The PQI spec states that the PQI registers should be at | ||
| 91 | * offset 0 from the PCIe BAR 0. However, we can't map | ||
| 92 | * them at offset 0 because that would break compatibility | ||
| 93 | * with the SIS registers. So we map them at offset 4000h. | ||
| 94 | */ | ||
| 95 | struct pqi_device_registers pqi_registers; /* 4000h */ | ||
| 96 | }; | ||
| 97 | |||
| 98 | #define PQI_DEVICE_REGISTERS_OFFSET 0x4000 | ||
| 99 | |||
| 100 | enum pqi_io_path { | ||
| 101 | RAID_PATH = 0, | ||
| 102 | AIO_PATH = 1 | ||
| 103 | }; | ||
| 104 | |||
| 105 | struct pqi_sg_descriptor { | ||
| 106 | __le64 address; | ||
| 107 | __le32 length; | ||
| 108 | __le32 flags; | ||
| 109 | }; | ||
| 110 | |||
| 111 | /* manifest constants for the flags field of pqi_sg_descriptor */ | ||
| 112 | #define CISS_SG_LAST 0x40000000 | ||
| 113 | #define CISS_SG_CHAIN 0x80000000 | ||
| 114 | |||
| 115 | struct pqi_iu_header { | ||
| 116 | u8 iu_type; | ||
| 117 | u8 reserved; | ||
| 118 | __le16 iu_length; /* in bytes - does not include the length */ | ||
| 119 | /* of this header */ | ||
| 120 | __le16 response_queue_id; /* specifies the OQ where the */ | ||
| 121 | /* response IU is to be delivered */ | ||
| 122 | u8 work_area[2]; /* reserved for driver use */ | ||
| 123 | }; | ||
| 124 | |||
| 125 | /* | ||
| 126 | * According to the PQI spec, the IU header is only the first 4 bytes of our | ||
| 127 | * pqi_iu_header structure. | ||
| 128 | */ | ||
| 129 | #define PQI_REQUEST_HEADER_LENGTH 4 | ||
| 130 | |||
| 131 | struct pqi_general_admin_request { | ||
| 132 | struct pqi_iu_header header; | ||
| 133 | __le16 request_id; | ||
| 134 | u8 function_code; | ||
| 135 | union { | ||
| 136 | struct { | ||
| 137 | u8 reserved[33]; | ||
| 138 | __le32 buffer_length; | ||
| 139 | struct pqi_sg_descriptor sg_descriptor; | ||
| 140 | } report_device_capability; | ||
| 141 | |||
| 142 | struct { | ||
| 143 | u8 reserved; | ||
| 144 | __le16 queue_id; | ||
| 145 | u8 reserved1[2]; | ||
| 146 | __le64 element_array_addr; | ||
| 147 | __le64 ci_addr; | ||
| 148 | __le16 num_elements; | ||
| 149 | __le16 element_length; | ||
| 150 | u8 queue_protocol; | ||
| 151 | u8 reserved2[23]; | ||
| 152 | __le32 vendor_specific; | ||
| 153 | } create_operational_iq; | ||
| 154 | |||
| 155 | struct { | ||
| 156 | u8 reserved; | ||
| 157 | __le16 queue_id; | ||
| 158 | u8 reserved1[2]; | ||
| 159 | __le64 element_array_addr; | ||
| 160 | __le64 pi_addr; | ||
| 161 | __le16 num_elements; | ||
| 162 | __le16 element_length; | ||
| 163 | u8 queue_protocol; | ||
| 164 | u8 reserved2[3]; | ||
| 165 | __le16 int_msg_num; | ||
| 166 | __le16 coalescing_count; | ||
| 167 | __le32 min_coalescing_time; | ||
| 168 | __le32 max_coalescing_time; | ||
| 169 | u8 reserved3[8]; | ||
| 170 | __le32 vendor_specific; | ||
| 171 | } create_operational_oq; | ||
| 172 | |||
| 173 | struct { | ||
| 174 | u8 reserved; | ||
| 175 | __le16 queue_id; | ||
| 176 | u8 reserved1[50]; | ||
| 177 | } delete_operational_queue; | ||
| 178 | |||
| 179 | struct { | ||
| 180 | u8 reserved; | ||
| 181 | __le16 queue_id; | ||
| 182 | u8 reserved1[46]; | ||
| 183 | __le32 vendor_specific; | ||
| 184 | } change_operational_iq_properties; | ||
| 185 | |||
| 186 | } data; | ||
| 187 | }; | ||
| 188 | |||
| 189 | struct pqi_general_admin_response { | ||
| 190 | struct pqi_iu_header header; | ||
| 191 | __le16 request_id; | ||
| 192 | u8 function_code; | ||
| 193 | u8 status; | ||
| 194 | union { | ||
| 195 | struct { | ||
| 196 | u8 status_descriptor[4]; | ||
| 197 | __le64 iq_pi_offset; | ||
| 198 | u8 reserved[40]; | ||
| 199 | } create_operational_iq; | ||
| 200 | |||
| 201 | struct { | ||
| 202 | u8 status_descriptor[4]; | ||
| 203 | __le64 oq_ci_offset; | ||
| 204 | u8 reserved[40]; | ||
| 205 | } create_operational_oq; | ||
| 206 | } data; | ||
| 207 | }; | ||
| 208 | |||
| 209 | struct pqi_iu_layer_descriptor { | ||
| 210 | u8 inbound_spanning_supported : 1; | ||
| 211 | u8 reserved : 7; | ||
| 212 | u8 reserved1[5]; | ||
| 213 | __le16 max_inbound_iu_length; | ||
| 214 | u8 outbound_spanning_supported : 1; | ||
| 215 | u8 reserved2 : 7; | ||
| 216 | u8 reserved3[5]; | ||
| 217 | __le16 max_outbound_iu_length; | ||
| 218 | }; | ||
| 219 | |||
| 220 | struct pqi_device_capability { | ||
| 221 | __le16 data_length; | ||
| 222 | u8 reserved[6]; | ||
| 223 | u8 iq_arbitration_priority_support_bitmask; | ||
| 224 | u8 maximum_aw_a; | ||
| 225 | u8 maximum_aw_b; | ||
| 226 | u8 maximum_aw_c; | ||
| 227 | u8 max_arbitration_burst : 3; | ||
| 228 | u8 reserved1 : 4; | ||
| 229 | u8 iqa : 1; | ||
| 230 | u8 reserved2[2]; | ||
| 231 | u8 iq_freeze : 1; | ||
| 232 | u8 reserved3 : 7; | ||
| 233 | __le16 max_inbound_queues; | ||
| 234 | __le16 max_elements_per_iq; | ||
| 235 | u8 reserved4[4]; | ||
| 236 | __le16 max_iq_element_length; | ||
| 237 | __le16 min_iq_element_length; | ||
| 238 | u8 reserved5[2]; | ||
| 239 | __le16 max_outbound_queues; | ||
| 240 | __le16 max_elements_per_oq; | ||
| 241 | __le16 intr_coalescing_time_granularity; | ||
| 242 | __le16 max_oq_element_length; | ||
| 243 | __le16 min_oq_element_length; | ||
| 244 | u8 reserved6[24]; | ||
| 245 | struct pqi_iu_layer_descriptor iu_layer_descriptors[32]; | ||
| 246 | }; | ||
| 247 | |||
| 248 | #define PQI_MAX_EMBEDDED_SG_DESCRIPTORS 4 | ||
| 249 | |||
| 250 | struct pqi_raid_path_request { | ||
| 251 | struct pqi_iu_header header; | ||
| 252 | __le16 request_id; | ||
| 253 | __le16 nexus_id; | ||
| 254 | __le32 buffer_length; | ||
| 255 | u8 lun_number[8]; | ||
| 256 | __le16 protocol_specific; | ||
| 257 | u8 data_direction : 2; | ||
| 258 | u8 partial : 1; | ||
| 259 | u8 reserved1 : 4; | ||
| 260 | u8 fence : 1; | ||
| 261 | __le16 error_index; | ||
| 262 | u8 reserved2; | ||
| 263 | u8 task_attribute : 3; | ||
| 264 | u8 command_priority : 4; | ||
| 265 | u8 reserved3 : 1; | ||
| 266 | u8 reserved4 : 2; | ||
| 267 | u8 additional_cdb_bytes_usage : 3; | ||
| 268 | u8 reserved5 : 3; | ||
| 269 | u8 cdb[32]; | ||
| 270 | struct pqi_sg_descriptor | ||
| 271 | sg_descriptors[PQI_MAX_EMBEDDED_SG_DESCRIPTORS]; | ||
| 272 | }; | ||
| 273 | |||
| 274 | struct pqi_aio_path_request { | ||
| 275 | struct pqi_iu_header header; | ||
| 276 | __le16 request_id; | ||
| 277 | u8 reserved1[2]; | ||
| 278 | __le32 nexus_id; | ||
| 279 | __le32 buffer_length; | ||
| 280 | u8 data_direction : 2; | ||
| 281 | u8 partial : 1; | ||
| 282 | u8 memory_type : 1; | ||
| 283 | u8 fence : 1; | ||
| 284 | u8 encryption_enable : 1; | ||
| 285 | u8 reserved2 : 2; | ||
| 286 | u8 task_attribute : 3; | ||
| 287 | u8 command_priority : 4; | ||
| 288 | u8 reserved3 : 1; | ||
| 289 | __le16 data_encryption_key_index; | ||
| 290 | __le32 encrypt_tweak_lower; | ||
| 291 | __le32 encrypt_tweak_upper; | ||
| 292 | u8 cdb[16]; | ||
| 293 | __le16 error_index; | ||
| 294 | u8 num_sg_descriptors; | ||
| 295 | u8 cdb_length; | ||
| 296 | u8 lun_number[8]; | ||
| 297 | u8 reserved4[4]; | ||
| 298 | struct pqi_sg_descriptor | ||
| 299 | sg_descriptors[PQI_MAX_EMBEDDED_SG_DESCRIPTORS]; | ||
| 300 | }; | ||
| 301 | |||
| 302 | struct pqi_io_response { | ||
| 303 | struct pqi_iu_header header; | ||
| 304 | __le16 request_id; | ||
| 305 | __le16 error_index; | ||
| 306 | u8 reserved2[4]; | ||
| 307 | }; | ||
| 308 | |||
| 309 | struct pqi_general_management_request { | ||
| 310 | struct pqi_iu_header header; | ||
| 311 | __le16 request_id; | ||
| 312 | union { | ||
| 313 | struct { | ||
| 314 | u8 reserved[2]; | ||
| 315 | __le32 buffer_length; | ||
| 316 | struct pqi_sg_descriptor sg_descriptors[3]; | ||
| 317 | } report_event_configuration; | ||
| 318 | |||
| 319 | struct { | ||
| 320 | __le16 global_event_oq_id; | ||
| 321 | __le32 buffer_length; | ||
| 322 | struct pqi_sg_descriptor sg_descriptors[3]; | ||
| 323 | } set_event_configuration; | ||
| 324 | } data; | ||
| 325 | }; | ||
| 326 | |||
| 327 | struct pqi_event_descriptor { | ||
| 328 | u8 event_type; | ||
| 329 | u8 reserved; | ||
| 330 | __le16 oq_id; | ||
| 331 | }; | ||
| 332 | |||
| 333 | struct pqi_event_config { | ||
| 334 | u8 reserved[2]; | ||
| 335 | u8 num_event_descriptors; | ||
| 336 | u8 reserved1; | ||
| 337 | struct pqi_event_descriptor descriptors[1]; | ||
| 338 | }; | ||
| 339 | |||
| 340 | #define PQI_MAX_EVENT_DESCRIPTORS 255 | ||
| 341 | |||
| 342 | struct pqi_event_response { | ||
| 343 | struct pqi_iu_header header; | ||
| 344 | u8 event_type; | ||
| 345 | u8 reserved2 : 7; | ||
| 346 | u8 request_acknowlege : 1; | ||
| 347 | __le16 event_id; | ||
| 348 | __le32 additional_event_id; | ||
| 349 | u8 data[16]; | ||
| 350 | }; | ||
| 351 | |||
| 352 | struct pqi_event_acknowledge_request { | ||
| 353 | struct pqi_iu_header header; | ||
| 354 | u8 event_type; | ||
| 355 | u8 reserved2; | ||
| 356 | __le16 event_id; | ||
| 357 | __le32 additional_event_id; | ||
| 358 | }; | ||
| 359 | |||
| 360 | struct pqi_task_management_request { | ||
| 361 | struct pqi_iu_header header; | ||
| 362 | __le16 request_id; | ||
| 363 | __le16 nexus_id; | ||
| 364 | u8 reserved[4]; | ||
| 365 | u8 lun_number[8]; | ||
| 366 | __le16 protocol_specific; | ||
| 367 | __le16 outbound_queue_id_to_manage; | ||
| 368 | __le16 request_id_to_manage; | ||
| 369 | u8 task_management_function; | ||
| 370 | u8 reserved2 : 7; | ||
| 371 | u8 fence : 1; | ||
| 372 | }; | ||
| 373 | |||
| 374 | #define SOP_TASK_MANAGEMENT_LUN_RESET 0x8 | ||
| 375 | |||
| 376 | struct pqi_task_management_response { | ||
| 377 | struct pqi_iu_header header; | ||
| 378 | __le16 request_id; | ||
| 379 | __le16 nexus_id; | ||
| 380 | u8 additional_response_info[3]; | ||
| 381 | u8 response_code; | ||
| 382 | }; | ||
| 383 | |||
| 384 | struct pqi_aio_error_info { | ||
| 385 | u8 status; | ||
| 386 | u8 service_response; | ||
| 387 | u8 data_present; | ||
| 388 | u8 reserved; | ||
| 389 | __le32 residual_count; | ||
| 390 | __le16 data_length; | ||
| 391 | __le16 reserved1; | ||
| 392 | u8 data[256]; | ||
| 393 | }; | ||
| 394 | |||
| 395 | struct pqi_raid_error_info { | ||
| 396 | u8 data_in_result; | ||
| 397 | u8 data_out_result; | ||
| 398 | u8 reserved[3]; | ||
| 399 | u8 status; | ||
| 400 | __le16 status_qualifier; | ||
| 401 | __le16 sense_data_length; | ||
| 402 | __le16 response_data_length; | ||
| 403 | __le32 data_in_transferred; | ||
| 404 | __le32 data_out_transferred; | ||
| 405 | u8 data[256]; | ||
| 406 | }; | ||
| 407 | |||
| 408 | #define PQI_REQUEST_IU_TASK_MANAGEMENT 0x13 | ||
| 409 | #define PQI_REQUEST_IU_RAID_PATH_IO 0x14 | ||
| 410 | #define PQI_REQUEST_IU_AIO_PATH_IO 0x15 | ||
| 411 | #define PQI_REQUEST_IU_GENERAL_ADMIN 0x60 | ||
| 412 | #define PQI_REQUEST_IU_REPORT_VENDOR_EVENT_CONFIG 0x72 | ||
| 413 | #define PQI_REQUEST_IU_SET_VENDOR_EVENT_CONFIG 0x73 | ||
| 414 | #define PQI_REQUEST_IU_ACKNOWLEDGE_VENDOR_EVENT 0xf6 | ||
| 415 | |||
| 416 | #define PQI_RESPONSE_IU_GENERAL_MANAGEMENT 0x81 | ||
| 417 | #define PQI_RESPONSE_IU_TASK_MANAGEMENT 0x93 | ||
| 418 | #define PQI_RESPONSE_IU_GENERAL_ADMIN 0xe0 | ||
| 419 | #define PQI_RESPONSE_IU_RAID_PATH_IO_SUCCESS 0xf0 | ||
| 420 | #define PQI_RESPONSE_IU_AIO_PATH_IO_SUCCESS 0xf1 | ||
| 421 | #define PQI_RESPONSE_IU_RAID_PATH_IO_ERROR 0xf2 | ||
| 422 | #define PQI_RESPONSE_IU_AIO_PATH_IO_ERROR 0xf3 | ||
| 423 | #define PQI_RESPONSE_IU_AIO_PATH_DISABLED 0xf4 | ||
| 424 | #define PQI_RESPONSE_IU_VENDOR_EVENT 0xf5 | ||
| 425 | |||
| 426 | #define PQI_GENERAL_ADMIN_FUNCTION_REPORT_DEVICE_CAPABILITY 0x0 | ||
| 427 | #define PQI_GENERAL_ADMIN_FUNCTION_CREATE_IQ 0x10 | ||
| 428 | #define PQI_GENERAL_ADMIN_FUNCTION_CREATE_OQ 0x11 | ||
| 429 | #define PQI_GENERAL_ADMIN_FUNCTION_DELETE_IQ 0x12 | ||
| 430 | #define PQI_GENERAL_ADMIN_FUNCTION_DELETE_OQ 0x13 | ||
| 431 | #define PQI_GENERAL_ADMIN_FUNCTION_CHANGE_IQ_PROPERTY 0x14 | ||
| 432 | |||
| 433 | #define PQI_GENERAL_ADMIN_STATUS_SUCCESS 0x0 | ||
| 434 | |||
| 435 | #define PQI_IQ_PROPERTY_IS_AIO_QUEUE 0x1 | ||
| 436 | |||
| 437 | #define PQI_GENERAL_ADMIN_IU_LENGTH 0x3c | ||
| 438 | #define PQI_PROTOCOL_SOP 0x0 | ||
| 439 | |||
| 440 | #define PQI_DATA_IN_OUT_GOOD 0x0 | ||
| 441 | #define PQI_DATA_IN_OUT_UNDERFLOW 0x1 | ||
| 442 | #define PQI_DATA_IN_OUT_BUFFER_ERROR 0x40 | ||
| 443 | #define PQI_DATA_IN_OUT_BUFFER_OVERFLOW 0x41 | ||
| 444 | #define PQI_DATA_IN_OUT_BUFFER_OVERFLOW_DESCRIPTOR_AREA 0x42 | ||
| 445 | #define PQI_DATA_IN_OUT_BUFFER_OVERFLOW_BRIDGE 0x43 | ||
| 446 | #define PQI_DATA_IN_OUT_PCIE_FABRIC_ERROR 0x60 | ||
| 447 | #define PQI_DATA_IN_OUT_PCIE_COMPLETION_TIMEOUT 0x61 | ||
| 448 | #define PQI_DATA_IN_OUT_PCIE_COMPLETER_ABORT_RECEIVED 0x62 | ||
| 449 | #define PQI_DATA_IN_OUT_PCIE_UNSUPPORTED_REQUEST_RECEIVED 0x63 | ||
| 450 | #define PQI_DATA_IN_OUT_PCIE_ECRC_CHECK_FAILED 0x64 | ||
| 451 | #define PQI_DATA_IN_OUT_PCIE_UNSUPPORTED_REQUEST 0x65 | ||
| 452 | #define PQI_DATA_IN_OUT_PCIE_ACS_VIOLATION 0x66 | ||
| 453 | #define PQI_DATA_IN_OUT_PCIE_TLP_PREFIX_BLOCKED 0x67 | ||
| 454 | #define PQI_DATA_IN_OUT_PCIE_POISONED_MEMORY_READ 0x6F | ||
| 455 | #define PQI_DATA_IN_OUT_ERROR 0xf0 | ||
| 456 | #define PQI_DATA_IN_OUT_PROTOCOL_ERROR 0xf1 | ||
| 457 | #define PQI_DATA_IN_OUT_HARDWARE_ERROR 0xf2 | ||
| 458 | #define PQI_DATA_IN_OUT_UNSOLICITED_ABORT 0xf3 | ||
| 459 | #define PQI_DATA_IN_OUT_ABORTED 0xf4 | ||
| 460 | #define PQI_DATA_IN_OUT_TIMEOUT 0xf5 | ||
| 461 | |||
| 462 | #define CISS_CMD_STATUS_SUCCESS 0x0 | ||
| 463 | #define CISS_CMD_STATUS_TARGET_STATUS 0x1 | ||
| 464 | #define CISS_CMD_STATUS_DATA_UNDERRUN 0x2 | ||
| 465 | #define CISS_CMD_STATUS_DATA_OVERRUN 0x3 | ||
| 466 | #define CISS_CMD_STATUS_INVALID 0x4 | ||
| 467 | #define CISS_CMD_STATUS_PROTOCOL_ERROR 0x5 | ||
| 468 | #define CISS_CMD_STATUS_HARDWARE_ERROR 0x6 | ||
| 469 | #define CISS_CMD_STATUS_CONNECTION_LOST 0x7 | ||
| 470 | #define CISS_CMD_STATUS_ABORTED 0x8 | ||
| 471 | #define CISS_CMD_STATUS_ABORT_FAILED 0x9 | ||
| 472 | #define CISS_CMD_STATUS_UNSOLICITED_ABORT 0xa | ||
| 473 | #define CISS_CMD_STATUS_TIMEOUT 0xb | ||
| 474 | #define CISS_CMD_STATUS_UNABORTABLE 0xc | ||
| 475 | #define CISS_CMD_STATUS_TMF 0xd | ||
| 476 | #define CISS_CMD_STATUS_AIO_DISABLED 0xe | ||
| 477 | |||
| 478 | #define PQI_NUM_EVENT_QUEUE_ELEMENTS 32 | ||
| 479 | #define PQI_EVENT_OQ_ELEMENT_LENGTH sizeof(struct pqi_event_response) | ||
| 480 | |||
| 481 | #define PQI_EVENT_TYPE_HOTPLUG 0x1 | ||
| 482 | #define PQI_EVENT_TYPE_HARDWARE 0x2 | ||
| 483 | #define PQI_EVENT_TYPE_PHYSICAL_DEVICE 0x4 | ||
| 484 | #define PQI_EVENT_TYPE_LOGICAL_DEVICE 0x5 | ||
| 485 | #define PQI_EVENT_TYPE_AIO_STATE_CHANGE 0xfd | ||
| 486 | #define PQI_EVENT_TYPE_AIO_CONFIG_CHANGE 0xfe | ||
| 487 | #define PQI_EVENT_TYPE_HEARTBEAT 0xff | ||
| 488 | |||
| 489 | #pragma pack() | ||
| 490 | |||
| 491 | #define PQI_ERROR_BUFFER_ELEMENT_LENGTH \ | ||
| 492 | sizeof(struct pqi_raid_error_info) | ||
| 493 | |||
| 494 | /* these values are based on our implementation */ | ||
| 495 | #define PQI_ADMIN_IQ_NUM_ELEMENTS 8 | ||
| 496 | #define PQI_ADMIN_OQ_NUM_ELEMENTS 20 | ||
| 497 | #define PQI_ADMIN_IQ_ELEMENT_LENGTH 64 | ||
| 498 | #define PQI_ADMIN_OQ_ELEMENT_LENGTH 64 | ||
| 499 | |||
| 500 | #define PQI_OPERATIONAL_IQ_ELEMENT_LENGTH 128 | ||
| 501 | #define PQI_OPERATIONAL_OQ_ELEMENT_LENGTH 16 | ||
| 502 | |||
| 503 | #define PQI_MIN_MSIX_VECTORS 1 | ||
| 504 | #define PQI_MAX_MSIX_VECTORS 64 | ||
| 505 | |||
| 506 | /* these values are defined by the PQI spec */ | ||
| 507 | #define PQI_MAX_NUM_ELEMENTS_ADMIN_QUEUE 255 | ||
| 508 | #define PQI_MAX_NUM_ELEMENTS_OPERATIONAL_QUEUE 65535 | ||
| 509 | #define PQI_QUEUE_ELEMENT_ARRAY_ALIGNMENT 64 | ||
| 510 | #define PQI_QUEUE_ELEMENT_LENGTH_ALIGNMENT 16 | ||
| 511 | #define PQI_ADMIN_INDEX_ALIGNMENT 64 | ||
| 512 | #define PQI_OPERATIONAL_INDEX_ALIGNMENT 4 | ||
| 513 | |||
| 514 | #define PQI_MIN_OPERATIONAL_QUEUE_ID 1 | ||
| 515 | #define PQI_MAX_OPERATIONAL_QUEUE_ID 65535 | ||
| 516 | |||
| 517 | #define PQI_AIO_SERV_RESPONSE_COMPLETE 0 | ||
| 518 | #define PQI_AIO_SERV_RESPONSE_FAILURE 1 | ||
| 519 | #define PQI_AIO_SERV_RESPONSE_TMF_COMPLETE 2 | ||
| 520 | #define PQI_AIO_SERV_RESPONSE_TMF_SUCCEEDED 3 | ||
| 521 | #define PQI_AIO_SERV_RESPONSE_TMF_REJECTED 4 | ||
| 522 | #define PQI_AIO_SERV_RESPONSE_TMF_INCORRECT_LUN 5 | ||
| 523 | |||
| 524 | #define PQI_AIO_STATUS_IO_ERROR 0x1 | ||
| 525 | #define PQI_AIO_STATUS_IO_ABORTED 0x2 | ||
| 526 | #define PQI_AIO_STATUS_NO_PATH_TO_DEVICE 0x3 | ||
| 527 | #define PQI_AIO_STATUS_INVALID_DEVICE 0x4 | ||
| 528 | #define PQI_AIO_STATUS_AIO_PATH_DISABLED 0xe | ||
| 529 | #define PQI_AIO_STATUS_UNDERRUN 0x51 | ||
| 530 | #define PQI_AIO_STATUS_OVERRUN 0x75 | ||
| 531 | |||
| 532 | typedef u32 pqi_index_t; | ||
| 533 | |||
| 534 | /* SOP data direction flags */ | ||
| 535 | #define SOP_NO_DIRECTION_FLAG 0 | ||
| 536 | #define SOP_WRITE_FLAG 1 /* host writes data to Data-Out */ | ||
| 537 | /* buffer */ | ||
| 538 | #define SOP_READ_FLAG 2 /* host receives data from Data-In */ | ||
| 539 | /* buffer */ | ||
| 540 | #define SOP_BIDIRECTIONAL 3 /* data is transferred from the */ | ||
| 541 | /* Data-Out buffer and data is */ | ||
| 542 | /* transferred to the Data-In buffer */ | ||
| 543 | |||
| 544 | #define SOP_TASK_ATTRIBUTE_SIMPLE 0 | ||
| 545 | #define SOP_TASK_ATTRIBUTE_HEAD_OF_QUEUE 1 | ||
| 546 | #define SOP_TASK_ATTRIBUTE_ORDERED 2 | ||
| 547 | #define SOP_TASK_ATTRIBUTE_ACA 4 | ||
| 548 | |||
| 549 | #define SOP_TMF_COMPLETE 0x0 | ||
| 550 | #define SOP_TMF_FUNCTION_SUCCEEDED 0x8 | ||
| 551 | |||
| 552 | /* additional CDB bytes usage field codes */ | ||
| 553 | #define SOP_ADDITIONAL_CDB_BYTES_0 0 /* 16-byte CDB */ | ||
| 554 | #define SOP_ADDITIONAL_CDB_BYTES_4 1 /* 20-byte CDB */ | ||
| 555 | #define SOP_ADDITIONAL_CDB_BYTES_8 2 /* 24-byte CDB */ | ||
| 556 | #define SOP_ADDITIONAL_CDB_BYTES_12 3 /* 28-byte CDB */ | ||
| 557 | #define SOP_ADDITIONAL_CDB_BYTES_16 4 /* 32-byte CDB */ | ||
| 558 | |||
| 559 | /* | ||
| 560 | * The purpose of this structure is to obtain proper alignment of objects in | ||
| 561 | * an admin queue pair. | ||
| 562 | */ | ||
| 563 | struct pqi_admin_queues_aligned { | ||
| 564 | __aligned(PQI_QUEUE_ELEMENT_ARRAY_ALIGNMENT) | ||
| 565 | u8 iq_element_array[PQI_ADMIN_IQ_ELEMENT_LENGTH] | ||
| 566 | [PQI_ADMIN_IQ_NUM_ELEMENTS]; | ||
| 567 | __aligned(PQI_QUEUE_ELEMENT_ARRAY_ALIGNMENT) | ||
| 568 | u8 oq_element_array[PQI_ADMIN_OQ_ELEMENT_LENGTH] | ||
| 569 | [PQI_ADMIN_OQ_NUM_ELEMENTS]; | ||
| 570 | __aligned(PQI_ADMIN_INDEX_ALIGNMENT) pqi_index_t iq_ci; | ||
| 571 | __aligned(PQI_ADMIN_INDEX_ALIGNMENT) pqi_index_t oq_pi; | ||
| 572 | }; | ||
| 573 | |||
| 574 | struct pqi_admin_queues { | ||
| 575 | void *iq_element_array; | ||
| 576 | void *oq_element_array; | ||
| 577 | volatile pqi_index_t *iq_ci; | ||
| 578 | volatile pqi_index_t *oq_pi; | ||
| 579 | dma_addr_t iq_element_array_bus_addr; | ||
| 580 | dma_addr_t oq_element_array_bus_addr; | ||
| 581 | dma_addr_t iq_ci_bus_addr; | ||
| 582 | dma_addr_t oq_pi_bus_addr; | ||
| 583 | __le32 __iomem *iq_pi; | ||
| 584 | pqi_index_t iq_pi_copy; | ||
| 585 | __le32 __iomem *oq_ci; | ||
| 586 | pqi_index_t oq_ci_copy; | ||
| 587 | struct task_struct *task; | ||
| 588 | u16 int_msg_num; | ||
| 589 | }; | ||
| 590 | |||
| 591 | struct pqi_queue_group { | ||
| 592 | struct pqi_ctrl_info *ctrl_info; /* backpointer */ | ||
| 593 | u16 iq_id[2]; | ||
| 594 | u16 oq_id; | ||
| 595 | u16 int_msg_num; | ||
| 596 | void *iq_element_array[2]; | ||
| 597 | void *oq_element_array; | ||
| 598 | dma_addr_t iq_element_array_bus_addr[2]; | ||
| 599 | dma_addr_t oq_element_array_bus_addr; | ||
| 600 | __le32 __iomem *iq_pi[2]; | ||
| 601 | pqi_index_t iq_pi_copy[2]; | ||
| 602 | volatile pqi_index_t *iq_ci[2]; | ||
| 603 | volatile pqi_index_t *oq_pi; | ||
| 604 | dma_addr_t iq_ci_bus_addr[2]; | ||
| 605 | dma_addr_t oq_pi_bus_addr; | ||
| 606 | __le32 __iomem *oq_ci; | ||
| 607 | pqi_index_t oq_ci_copy; | ||
| 608 | spinlock_t submit_lock[2]; /* protect submission queue */ | ||
| 609 | struct list_head request_list[2]; | ||
| 610 | }; | ||
| 611 | |||
| 612 | struct pqi_event_queue { | ||
| 613 | u16 oq_id; | ||
| 614 | u16 int_msg_num; | ||
| 615 | void *oq_element_array; | ||
| 616 | volatile pqi_index_t *oq_pi; | ||
| 617 | dma_addr_t oq_element_array_bus_addr; | ||
| 618 | dma_addr_t oq_pi_bus_addr; | ||
| 619 | __le32 __iomem *oq_ci; | ||
| 620 | pqi_index_t oq_ci_copy; | ||
| 621 | }; | ||
| 622 | |||
| 623 | #define PQI_DEFAULT_QUEUE_GROUP 0 | ||
| 624 | #define PQI_MAX_QUEUE_GROUPS PQI_MAX_MSIX_VECTORS | ||
| 625 | |||
| 626 | struct pqi_encryption_info { | ||
| 627 | u16 data_encryption_key_index; | ||
| 628 | u32 encrypt_tweak_lower; | ||
| 629 | u32 encrypt_tweak_upper; | ||
| 630 | }; | ||
| 631 | |||
| 632 | #define PQI_MAX_OUTSTANDING_REQUESTS ((u32)~0) | ||
| 633 | #define PQI_MAX_TRANSFER_SIZE (4 * 1024U * 1024U) | ||
| 634 | |||
| 635 | #define RAID_MAP_MAX_ENTRIES 1024 | ||
| 636 | |||
| 637 | #define PQI_PHYSICAL_DEVICE_BUS 0 | ||
| 638 | #define PQI_RAID_VOLUME_BUS 1 | ||
| 639 | #define PQI_HBA_BUS 2 | ||
| 640 | #define PQI_MAX_BUS PQI_HBA_BUS | ||
| 641 | |||
| 642 | #pragma pack(1) | ||
| 643 | |||
| 644 | struct report_lun_header { | ||
| 645 | __be32 list_length; | ||
| 646 | u8 extended_response; | ||
| 647 | u8 reserved[3]; | ||
| 648 | }; | ||
| 649 | |||
| 650 | struct report_log_lun_extended_entry { | ||
| 651 | u8 lunid[8]; | ||
| 652 | u8 volume_id[16]; | ||
| 653 | }; | ||
| 654 | |||
| 655 | struct report_log_lun_extended { | ||
| 656 | struct report_lun_header header; | ||
| 657 | struct report_log_lun_extended_entry lun_entries[1]; | ||
| 658 | }; | ||
| 659 | |||
| 660 | struct report_phys_lun_extended_entry { | ||
| 661 | u8 lunid[8]; | ||
| 662 | __be64 wwid; | ||
| 663 | u8 device_type; | ||
| 664 | u8 device_flags; | ||
| 665 | u8 lun_count; /* number of LUNs in a multi-LUN device */ | ||
| 666 | u8 redundant_paths; | ||
| 667 | u32 aio_handle; | ||
| 668 | }; | ||
| 669 | |||
| 670 | /* for device_flags field of struct report_phys_lun_extended_entry */ | ||
| 671 | #define REPORT_PHYS_LUN_DEV_FLAG_NON_DISK 0x1 | ||
| 672 | #define REPORT_PHYS_LUN_DEV_FLAG_AIO_ENABLED 0x8 | ||
| 673 | |||
| 674 | struct report_phys_lun_extended { | ||
| 675 | struct report_lun_header header; | ||
| 676 | struct report_phys_lun_extended_entry lun_entries[1]; | ||
| 677 | }; | ||
| 678 | |||
| 679 | struct raid_map_disk_data { | ||
| 680 | u32 aio_handle; | ||
| 681 | u8 xor_mult[2]; | ||
| 682 | u8 reserved[2]; | ||
| 683 | }; | ||
| 684 | |||
| 685 | /* constants for flags field of RAID map */ | ||
| 686 | #define RAID_MAP_ENCRYPTION_ENABLED 0x1 | ||
| 687 | |||
| 688 | struct raid_map { | ||
| 689 | __le32 structure_size; /* size of entire structure in bytes */ | ||
| 690 | __le32 volume_blk_size; /* bytes / block in the volume */ | ||
| 691 | __le64 volume_blk_cnt; /* logical blocks on the volume */ | ||
| 692 | u8 phys_blk_shift; /* shift factor to convert between */ | ||
| 693 | /* units of logical blocks and */ | ||
| 694 | /* physical disk blocks */ | ||
| 695 | u8 parity_rotation_shift; /* shift factor to convert between */ | ||
| 696 | /* units of logical stripes and */ | ||
| 697 | /* physical stripes */ | ||
| 698 | __le16 strip_size; /* blocks used on each disk / stripe */ | ||
| 699 | __le64 disk_starting_blk; /* first disk block used in volume */ | ||
| 700 | __le64 disk_blk_cnt; /* disk blocks used by volume / disk */ | ||
| 701 | __le16 data_disks_per_row; /* data disk entries / row in the map */ | ||
| 702 | __le16 metadata_disks_per_row; /* mirror/parity disk entries / row */ | ||
| 703 | /* in the map */ | ||
| 704 | __le16 row_cnt; /* rows in each layout map */ | ||
| 705 | __le16 layout_map_count; /* layout maps (1 map per */ | ||
| 706 | /* mirror parity group) */ | ||
| 707 | __le16 flags; | ||
| 708 | __le16 data_encryption_key_index; | ||
| 709 | u8 reserved[16]; | ||
| 710 | struct raid_map_disk_data disk_data[RAID_MAP_MAX_ENTRIES]; | ||
| 711 | }; | ||
| 712 | |||
| 713 | #pragma pack() | ||
| 714 | |||
| 715 | #define RAID_CTLR_LUNID "\0\0\0\0\0\0\0\0" | ||
| 716 | |||
| 717 | struct pqi_scsi_dev { | ||
| 718 | int devtype; /* as reported by INQUIRY commmand */ | ||
| 719 | u8 device_type; /* as reported by */ | ||
| 720 | /* BMIC_IDENTIFY_PHYSICAL_DEVICE */ | ||
| 721 | /* only valid for devtype = TYPE_DISK */ | ||
| 722 | int bus; | ||
| 723 | int target; | ||
| 724 | int lun; | ||
| 725 | u8 scsi3addr[8]; | ||
| 726 | __be64 wwid; | ||
| 727 | u8 volume_id[16]; | ||
| 728 | u8 is_physical_device : 1; | ||
| 729 | u8 target_lun_valid : 1; | ||
| 730 | u8 expose_device : 1; | ||
| 731 | u8 no_uld_attach : 1; | ||
| 732 | u8 aio_enabled : 1; /* only valid for physical disks */ | ||
| 733 | u8 device_gone : 1; | ||
| 734 | u8 new_device : 1; | ||
| 735 | u8 keep_device : 1; | ||
| 736 | u8 volume_offline : 1; | ||
| 737 | u8 vendor[8]; /* bytes 8-15 of inquiry data */ | ||
| 738 | u8 model[16]; /* bytes 16-31 of inquiry data */ | ||
| 739 | u64 sas_address; | ||
| 740 | u8 raid_level; | ||
| 741 | u16 queue_depth; /* max. queue_depth for this device */ | ||
| 742 | u16 advertised_queue_depth; | ||
| 743 | u32 aio_handle; | ||
| 744 | u8 volume_status; | ||
| 745 | u8 active_path_index; | ||
| 746 | u8 path_map; | ||
| 747 | u8 bay; | ||
| 748 | u8 box[8]; | ||
| 749 | u16 phys_connector[8]; | ||
| 750 | int offload_configured; /* I/O accel RAID offload configured */ | ||
| 751 | int offload_enabled; /* I/O accel RAID offload enabled */ | ||
| 752 | int offload_enabled_pending; | ||
| 753 | int offload_to_mirror; /* Send next I/O accelerator RAID */ | ||
| 754 | /* offload request to mirror drive. */ | ||
| 755 | struct raid_map *raid_map; /* I/O accelerator RAID map */ | ||
| 756 | |||
| 757 | struct pqi_sas_port *sas_port; | ||
| 758 | struct scsi_device *sdev; | ||
| 759 | |||
| 760 | struct list_head scsi_device_list_entry; | ||
| 761 | struct list_head new_device_list_entry; | ||
| 762 | struct list_head add_list_entry; | ||
| 763 | struct list_head delete_list_entry; | ||
| 764 | }; | ||
| 765 | |||
| 766 | /* VPD inquiry pages */ | ||
| 767 | #define SCSI_VPD_SUPPORTED_PAGES 0x0 /* standard page */ | ||
| 768 | #define SCSI_VPD_DEVICE_ID 0x83 /* standard page */ | ||
| 769 | #define CISS_VPD_LV_DEVICE_GEOMETRY 0xc1 /* vendor-specific page */ | ||
| 770 | #define CISS_VPD_LV_OFFLOAD_STATUS 0xc2 /* vendor-specific page */ | ||
| 771 | #define CISS_VPD_LV_STATUS 0xc3 /* vendor-specific page */ | ||
| 772 | |||
| 773 | #define VPD_PAGE (1 << 8) | ||
| 774 | |||
| 775 | #pragma pack(1) | ||
| 776 | |||
| 777 | /* structure for CISS_VPD_LV_STATUS */ | ||
| 778 | struct ciss_vpd_logical_volume_status { | ||
| 779 | u8 peripheral_info; | ||
| 780 | u8 page_code; | ||
| 781 | u8 reserved; | ||
| 782 | u8 page_length; | ||
| 783 | u8 volume_status; | ||
| 784 | u8 reserved2[3]; | ||
| 785 | __be32 flags; | ||
| 786 | }; | ||
| 787 | |||
| 788 | #pragma pack() | ||
| 789 | |||
| 790 | /* constants for volume_status field of ciss_vpd_logical_volume_status */ | ||
| 791 | #define CISS_LV_OK 0 | ||
| 792 | #define CISS_LV_FAILED 1 | ||
| 793 | #define CISS_LV_NOT_CONFIGURED 2 | ||
| 794 | #define CISS_LV_DEGRADED 3 | ||
| 795 | #define CISS_LV_READY_FOR_RECOVERY 4 | ||
| 796 | #define CISS_LV_UNDERGOING_RECOVERY 5 | ||
| 797 | #define CISS_LV_WRONG_PHYSICAL_DRIVE_REPLACED 6 | ||
| 798 | #define CISS_LV_PHYSICAL_DRIVE_CONNECTION_PROBLEM 7 | ||
| 799 | #define CISS_LV_HARDWARE_OVERHEATING 8 | ||
| 800 | #define CISS_LV_HARDWARE_HAS_OVERHEATED 9 | ||
| 801 | #define CISS_LV_UNDERGOING_EXPANSION 10 | ||
| 802 | #define CISS_LV_NOT_AVAILABLE 11 | ||
| 803 | #define CISS_LV_QUEUED_FOR_EXPANSION 12 | ||
| 804 | #define CISS_LV_DISABLED_SCSI_ID_CONFLICT 13 | ||
| 805 | #define CISS_LV_EJECTED 14 | ||
| 806 | #define CISS_LV_UNDERGOING_ERASE 15 | ||
| 807 | /* state 16 not used */ | ||
| 808 | #define CISS_LV_READY_FOR_PREDICTIVE_SPARE_REBUILD 17 | ||
| 809 | #define CISS_LV_UNDERGOING_RPI 18 | ||
| 810 | #define CISS_LV_PENDING_RPI 19 | ||
| 811 | #define CISS_LV_ENCRYPTED_NO_KEY 20 | ||
| 812 | /* state 21 not used */ | ||
| 813 | #define CISS_LV_UNDERGOING_ENCRYPTION 22 | ||
| 814 | #define CISS_LV_UNDERGOING_ENCRYPTION_REKEYING 23 | ||
| 815 | #define CISS_LV_ENCRYPTED_IN_NON_ENCRYPTED_CONTROLLER 24 | ||
| 816 | #define CISS_LV_PENDING_ENCRYPTION 25 | ||
| 817 | #define CISS_LV_PENDING_ENCRYPTION_REKEYING 26 | ||
| 818 | #define CISS_LV_NOT_SUPPORTED 27 | ||
| 819 | #define CISS_LV_STATUS_UNAVAILABLE 255 | ||
| 820 | |||
| 821 | /* constants for flags field of ciss_vpd_logical_volume_status */ | ||
| 822 | #define CISS_LV_FLAGS_NO_HOST_IO 0x1 /* volume not available for */ | ||
| 823 | /* host I/O */ | ||
| 824 | |||
| 825 | /* for SAS hosts and SAS expanders */ | ||
| 826 | struct pqi_sas_node { | ||
| 827 | struct device *parent_dev; | ||
| 828 | struct list_head port_list_head; | ||
| 829 | }; | ||
| 830 | |||
| 831 | struct pqi_sas_port { | ||
| 832 | struct list_head port_list_entry; | ||
| 833 | u64 sas_address; | ||
| 834 | struct sas_port *port; | ||
| 835 | int next_phy_index; | ||
| 836 | struct list_head phy_list_head; | ||
| 837 | struct pqi_sas_node *parent_node; | ||
| 838 | struct sas_rphy *rphy; | ||
| 839 | }; | ||
| 840 | |||
| 841 | struct pqi_sas_phy { | ||
| 842 | struct list_head phy_list_entry; | ||
| 843 | struct sas_phy *phy; | ||
| 844 | struct pqi_sas_port *parent_port; | ||
| 845 | bool added_to_port; | ||
| 846 | }; | ||
| 847 | |||
| 848 | struct pqi_io_request { | ||
| 849 | atomic_t refcount; | ||
| 850 | u16 index; | ||
| 851 | void (*io_complete_callback)(struct pqi_io_request *io_request, | ||
| 852 | void *context); | ||
| 853 | void *context; | ||
| 854 | int status; | ||
| 855 | struct scsi_cmnd *scmd; | ||
| 856 | void *error_info; | ||
| 857 | struct pqi_sg_descriptor *sg_chain_buffer; | ||
| 858 | dma_addr_t sg_chain_buffer_dma_handle; | ||
| 859 | void *iu; | ||
| 860 | struct list_head request_list_entry; | ||
| 861 | }; | ||
| 862 | |||
| 863 | /* for indexing into the pending_events[] field of struct pqi_ctrl_info */ | ||
| 864 | #define PQI_EVENT_HEARTBEAT 0 | ||
| 865 | #define PQI_EVENT_HOTPLUG 1 | ||
| 866 | #define PQI_EVENT_HARDWARE 2 | ||
| 867 | #define PQI_EVENT_PHYSICAL_DEVICE 3 | ||
| 868 | #define PQI_EVENT_LOGICAL_DEVICE 4 | ||
| 869 | #define PQI_EVENT_AIO_STATE_CHANGE 5 | ||
| 870 | #define PQI_EVENT_AIO_CONFIG_CHANGE 6 | ||
| 871 | #define PQI_NUM_SUPPORTED_EVENTS 7 | ||
| 872 | |||
| 873 | struct pqi_event { | ||
| 874 | bool pending; | ||
| 875 | u8 event_type; | ||
| 876 | __le16 event_id; | ||
| 877 | __le32 additional_event_id; | ||
| 878 | }; | ||
| 879 | |||
| 880 | #define PQI_RESERVED_IO_SLOTS_LUN_RESET 1 | ||
| 881 | #define PQI_RESERVED_IO_SLOTS_EVENT_ACK PQI_NUM_SUPPORTED_EVENTS | ||
| 882 | #define PQI_RESERVED_IO_SLOTS_SYNCHRONOUS_REQUESTS 3 | ||
| 883 | #define PQI_RESERVED_IO_SLOTS \ | ||
| 884 | (PQI_RESERVED_IO_SLOTS_LUN_RESET + PQI_RESERVED_IO_SLOTS_EVENT_ACK + \ | ||
| 885 | PQI_RESERVED_IO_SLOTS_SYNCHRONOUS_REQUESTS) | ||
| 886 | |||
| 887 | struct pqi_ctrl_info { | ||
| 888 | unsigned int ctrl_id; | ||
| 889 | struct pci_dev *pci_dev; | ||
| 890 | char firmware_version[11]; | ||
| 891 | void __iomem *iomem_base; | ||
| 892 | struct pqi_ctrl_registers __iomem *registers; | ||
| 893 | struct pqi_device_registers __iomem *pqi_registers; | ||
| 894 | u32 max_sg_entries; | ||
| 895 | u32 config_table_offset; | ||
| 896 | u32 config_table_length; | ||
| 897 | u16 max_inbound_queues; | ||
| 898 | u16 max_elements_per_iq; | ||
| 899 | u16 max_iq_element_length; | ||
| 900 | u16 max_outbound_queues; | ||
| 901 | u16 max_elements_per_oq; | ||
| 902 | u16 max_oq_element_length; | ||
| 903 | u32 max_transfer_size; | ||
| 904 | u32 max_outstanding_requests; | ||
| 905 | u32 max_io_slots; | ||
| 906 | unsigned int scsi_ml_can_queue; | ||
| 907 | unsigned short sg_tablesize; | ||
| 908 | unsigned int max_sectors; | ||
| 909 | u32 error_buffer_length; | ||
| 910 | void *error_buffer; | ||
| 911 | dma_addr_t error_buffer_dma_handle; | ||
| 912 | size_t sg_chain_buffer_length; | ||
| 913 | unsigned int num_queue_groups; | ||
| 914 | unsigned int num_active_queue_groups; | ||
| 915 | u16 num_elements_per_iq; | ||
| 916 | u16 num_elements_per_oq; | ||
| 917 | u16 max_inbound_iu_length_per_firmware; | ||
| 918 | u16 max_inbound_iu_length; | ||
| 919 | unsigned int max_sg_per_iu; | ||
| 920 | void *admin_queue_memory_base; | ||
| 921 | u32 admin_queue_memory_length; | ||
| 922 | dma_addr_t admin_queue_memory_base_dma_handle; | ||
| 923 | void *queue_memory_base; | ||
| 924 | u32 queue_memory_length; | ||
| 925 | dma_addr_t queue_memory_base_dma_handle; | ||
| 926 | struct pqi_admin_queues admin_queues; | ||
| 927 | struct pqi_queue_group queue_groups[PQI_MAX_QUEUE_GROUPS]; | ||
| 928 | struct pqi_event_queue event_queue; | ||
| 929 | int max_msix_vectors; | ||
| 930 | int num_msix_vectors_enabled; | ||
| 931 | int num_msix_vectors_initialized; | ||
| 932 | u32 msix_vectors[PQI_MAX_MSIX_VECTORS]; | ||
| 933 | void *intr_data[PQI_MAX_MSIX_VECTORS]; | ||
| 934 | int event_irq; | ||
| 935 | struct Scsi_Host *scsi_host; | ||
| 936 | |||
| 937 | struct mutex scan_mutex; | ||
| 938 | u8 inbound_spanning_supported : 1; | ||
| 939 | u8 outbound_spanning_supported : 1; | ||
| 940 | u8 pqi_mode_enabled : 1; | ||
| 941 | u8 controller_online : 1; | ||
| 942 | u8 heartbeat_timer_started : 1; | ||
| 943 | |||
| 944 | struct list_head scsi_device_list; | ||
| 945 | spinlock_t scsi_device_list_lock; | ||
| 946 | |||
| 947 | struct delayed_work rescan_work; | ||
| 948 | struct delayed_work update_time_work; | ||
| 949 | |||
| 950 | struct pqi_sas_node *sas_host; | ||
| 951 | u64 sas_address; | ||
| 952 | |||
| 953 | struct pqi_io_request *io_request_pool; | ||
| 954 | u16 next_io_request_slot; | ||
| 955 | |||
| 956 | struct pqi_event pending_events[PQI_NUM_SUPPORTED_EVENTS]; | ||
| 957 | struct work_struct event_work; | ||
| 958 | |||
| 959 | atomic_t num_interrupts; | ||
| 960 | int previous_num_interrupts; | ||
| 961 | unsigned int num_heartbeats_requested; | ||
| 962 | struct timer_list heartbeat_timer; | ||
| 963 | |||
| 964 | struct semaphore sync_request_sem; | ||
| 965 | struct semaphore lun_reset_sem; | ||
| 966 | }; | ||
| 967 | |||
| 968 | enum pqi_ctrl_mode { | ||
| 969 | UNKNOWN, | ||
| 970 | PQI_MODE | ||
| 971 | }; | ||
| 972 | |||
| 973 | /* | ||
| 974 | * assume worst case: SATA queue depth of 31 minus 4 internal firmware commands | ||
| 975 | */ | ||
| 976 | #define PQI_PHYSICAL_DISK_DEFAULT_MAX_QUEUE_DEPTH 27 | ||
| 977 | |||
| 978 | /* 0 = no limit */ | ||
| 979 | #define PQI_LOGICAL_DRIVE_DEFAULT_MAX_QUEUE_DEPTH 0 | ||
| 980 | |||
| 981 | /* CISS commands */ | ||
| 982 | #define CISS_READ 0xc0 | ||
| 983 | #define CISS_REPORT_LOG 0xc2 /* Report Logical LUNs */ | ||
| 984 | #define CISS_REPORT_PHYS 0xc3 /* Report Physical LUNs */ | ||
| 985 | #define CISS_GET_RAID_MAP 0xc8 | ||
| 986 | |||
| 987 | /* constants for CISS_REPORT_LOG/CISS_REPORT_PHYS commands */ | ||
| 988 | #define CISS_REPORT_LOG_EXTENDED 0x1 | ||
| 989 | #define CISS_REPORT_PHYS_EXTENDED 0x2 | ||
| 990 | |||
| 991 | /* BMIC commands */ | ||
| 992 | #define BMIC_IDENTIFY_CONTROLLER 0x11 | ||
| 993 | #define BMIC_IDENTIFY_PHYSICAL_DEVICE 0x15 | ||
| 994 | #define BMIC_READ 0x26 | ||
| 995 | #define BMIC_WRITE 0x27 | ||
| 996 | #define BMIC_SENSE_CONTROLLER_PARAMETERS 0x64 | ||
| 997 | #define BMIC_SENSE_SUBSYSTEM_INFORMATION 0x66 | ||
| 998 | #define BMIC_WRITE_HOST_WELLNESS 0xa5 | ||
| 999 | #define BMIC_CACHE_FLUSH 0xc2 | ||
| 1000 | |||
| 1001 | #define SA_CACHE_FLUSH 0x01 | ||
| 1002 | |||
| 1003 | #define MASKED_DEVICE(lunid) ((lunid)[3] & 0xc0) | ||
| 1004 | #define CISS_GET_BUS(lunid) ((lunid)[7] & 0x3f) | ||
| 1005 | #define CISS_GET_LEVEL_2_TARGET(lunid) ((lunid)[6]) | ||
| 1006 | #define CISS_GET_DRIVE_NUMBER(lunid) \ | ||
130 more lines aren’t shown here.
This diff is large: its 6304 lines aren’t shown here.
This diff is large: its 351 lines aren’t shown here.
This diff is large: its 405 lines aren’t shown here.
This diff is large: its 35 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 408 lines aren’t shown here.
This diff is large: its 98 lines aren’t shown here.
This diff is large: its 1972 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 20 lines aren’t shown here.
This diff is large: its 1211 lines aren’t shown here.
This diff is large: its 81 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 1658 lines aren’t shown here.
This diff is large: its 27 lines aren’t shown here.
This diff is large: its 34 lines aren’t shown here.